001    package railo.runtime.functions.file;
002    
003    import java.io.BufferedReader;
004    import java.io.File;
005    import java.io.IOException;
006    import java.io.RandomAccessFile;
007    
008    import railo.commons.io.IOUtil;
009    import railo.commons.io.res.Resource;
010    import railo.runtime.exp.PageException;
011    import railo.runtime.exp.PageRuntimeException;
012    import railo.runtime.op.Caster;
013    
014    public class FileStreamWrapperRead extends FileStreamWrapper {
015            
016    
017            private BufferedReader br;
018            private String charset;
019            private boolean seekable;
020            private RandomAccessFile raf;
021    
022            /**
023             * Constructor of the class
024             * @param res
025             * @param charset
026             * @throws IOException
027             */
028            public FileStreamWrapperRead(Resource res, String charset,boolean seekable) {
029                    super(res);
030                    this.charset=charset;
031                    this.seekable=seekable;
032            }
033            
034            /**
035             *
036             * @see railo.runtime.functions.file.FileStreamWrapper#read(int)
037             */
038            public Object read(int len) throws IOException {
039                    if(seekable) {
040                            byte[] barr=new byte[len];
041                len = getRAF().read(barr);
042                if(len==-1) throw new IOException("End of file reached");
043                return new String(barr, 0, len, charset);
044                    }
045                    
046                    char[] carr=new char[len];
047                    len = _getBR().read(carr);
048                    if(len==-1) throw new IOException("End of file reached");
049                    
050                    return new String(carr,0,len);
051            }
052    
053            /**
054             *
055             * @see railo.runtime.functions.file.FileStreamWrapper#readLine()
056             */
057            public String readLine() throws IOException {
058                    if(seekable) {
059                            return getRAF().readLine();
060                    }
061                    
062                    if(!_getBR().ready())
063                            throw new IOException(" End of file reached");
064                    return _getBR().readLine();
065            }
066    
067            /**
068             * @see railo.runtime.functions.file.FileStreamWrapper#close()
069             */
070            public void close() throws IOException {
071                    super.setStatus(FileStreamWrapper.STATE_CLOSE);
072                    if(br!=null)br.close();
073                    if(raf!=null)raf.close();
074            }
075    
076            /**
077             * @see railo.runtime.functions.file.FileStreamWrapper#getMode()
078             */
079            public String getMode() {
080                    return "read";
081            }
082    
083            public boolean isEndOfFile() {
084                    if(seekable){
085                            long pos=0;
086                            try {
087                                    pos = getRAF().getFilePointer();
088                            } catch (IOException ioe) {
089                                    throw new PageRuntimeException(Caster.toPageException(ioe));
090                            }
091                            try {
092                                    if(raf.read()==-1) return true;
093                                    raf.seek(pos);
094                            } 
095                            catch (IOException e) {
096                                    return true;
097                            }
098                            return false;
099                    }
100                    
101                    try {
102                            return !_getBR().ready();
103                    } catch (IOException e) {
104                            return true;
105                    }
106            }
107    
108            /**
109             * @see railo.runtime.functions.file.FileStreamWrapper#getSize()
110             */
111            public long getSize() {
112                    return res.length();
113            }
114    
115            /**
116             * @see railo.runtime.functions.file.FileStreamWrapper#skip(long)
117             */
118            public void skip(int len) throws PageException {
119                    if(seekable){
120                            try {
121                                    getRAF().skipBytes(len);
122                            } catch (IOException e) {
123                                    throw Caster.toPageException(e);
124                            }
125                            return;
126                    }
127                    
128                    try {
129                            _getBR().skip(len);
130                            return;
131                    } 
132                    catch (IOException e) {}
133                            
134                    throw Caster.toPageException(new IOException("skip is only supported when you have set argument seekable of function fileOpen to true"));
135            }
136            public void seek(long pos) throws PageException {
137                    if(seekable){
138                            try {
139                                    getRAF().seek(pos);
140                            } catch (IOException e) {
141                                    throw Caster.toPageException(e);
142                            }
143                    }
144                    else throw Caster.toPageException(new IOException("seek is only supported when you have set argument seekable of function fileOpen to true"));
145            }
146    
147            private RandomAccessFile getRAF() throws IOException {
148                    if(raf==null){
149                            if(!(res instanceof File))
150                                    throw new IOException("only resources for local filesytem support seekable");
151                            
152                            raf = new RandomAccessFile((File)res,"r");
153                    }
154                    return raf;
155            }
156    
157    
158            private BufferedReader _getBR() throws IOException {
159                    if(br==null){
160                            br = IOUtil.toBufferedReader(IOUtil.getReader(res.getInputStream(),charset));
161                    }
162                    return br;
163            }
164    }