001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.functions.file;
020
021import java.io.BufferedInputStream;
022import java.io.File;
023import java.io.IOException;
024import java.io.RandomAccessFile;
025
026import lucee.commons.io.IOUtil;
027import lucee.commons.io.res.Resource;
028import lucee.runtime.exp.PageException;
029import lucee.runtime.op.Caster;
030
031public class FileStreamWrapperReadBinary extends FileStreamWrapper {
032        
033
034
035        private BufferedInputStream bis;
036        private boolean isEOF;
037        private boolean seekable;
038        private RandomAccessFile raf;
039
040        /**
041         * Constructor of the class
042         * @param res
043         * @param charset
044         * @throws IOException
045         */
046        public FileStreamWrapperReadBinary(Resource res,boolean seekable) {
047                super(res);
048                this.seekable=seekable;
049        }
050        
051
052
053
054        @Override
055        public Object read(int len) throws IOException {
056                byte[] barr=new byte[len];
057                len=seekable?getRAF().read(barr):_getBIS().read(barr);
058                if(len!=barr.length) {
059                        byte[] rtn=new byte[len];
060                        for(int i=0;i<len;i++) {
061                                rtn[i]=barr[i];
062                        }
063                        barr=rtn;
064                        isEOF=true;
065                }
066                return barr;
067        }
068
069        @Override
070        public void close() throws IOException {
071                super.setStatus(FileStreamWrapper.STATE_CLOSE);
072                if(bis!=null)bis.close();
073                if(raf!=null)raf.close();
074        }
075
076        @Override
077        public String getMode() {
078                return "readBinary";
079        }
080
081        public boolean isEndOfFile() {
082                return isEOF;
083        }
084
085        @Override
086        public long getSize() {
087                return res.length();
088        }
089        
090        @Override
091        public void skip(int len) throws PageException {
092                if(seekable){
093                        try {
094                                getRAF().skipBytes(len);
095                        } catch (IOException e) {
096                                throw Caster.toPageException(e);
097                        }
098                        return;
099                }
100                
101                try {
102                        _getBIS().skip(len);
103                        return;
104                } 
105                catch (IOException e) {}
106                        
107                throw Caster.toPageException(new IOException("skip is only supported when you have set argument seekable of function fileOpen to true"));
108        }
109        public void seek(long pos) throws PageException {
110                if(seekable){
111                        try {
112                                getRAF().seek(pos);
113                        } catch (IOException e) {
114                                throw Caster.toPageException(e);
115                        }
116                }
117                else throw Caster.toPageException(new IOException("seek is only supported when you have set argument seekable of function fileOpen to true"));
118        }
119        
120        private RandomAccessFile getRAF() throws IOException {
121                if(raf==null){
122                        if(!(res instanceof File))
123                                throw new IOException("only resources for local filesytem support seekable");
124                        
125                        raf = new RandomAccessFile((File)res,"r");
126                }
127                return raf;
128        }
129        
130
131        private BufferedInputStream _getBIS() throws IOException {
132                if(bis==null)bis = IOUtil.toBufferedInputStream(res.getInputStream());
133                return bis;
134        }
135}