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            @Override
035            public Object read(int len) throws IOException {
036                    if(seekable) {
037                            byte[] barr=new byte[len];
038                len = getRAF().read(barr);
039                if(len==-1) throw new IOException("End of file reached");
040                return new String(barr, 0, len, charset);
041                    }
042                    
043                    char[] carr=new char[len];
044                    len = _getBR().read(carr);
045                    if(len==-1) throw new IOException("End of file reached");
046                    
047                    return new String(carr,0,len);
048            }
049    
050            @Override
051            public String readLine() throws IOException {
052                    if(seekable) {
053                            return getRAF().readLine();
054                    }
055                    
056                    if(!_getBR().ready())
057                            throw new IOException(" End of file reached");
058                    return _getBR().readLine();
059            }
060    
061            @Override
062            public void close() throws IOException {
063                    super.setStatus(FileStreamWrapper.STATE_CLOSE);
064                    if(br!=null)br.close();
065                    if(raf!=null)raf.close();
066            }
067    
068            @Override
069            public String getMode() {
070                    return "read";
071            }
072    
073            public boolean isEndOfFile() {
074                    if(seekable){
075                            long pos=0;
076                            try {
077                                    pos = getRAF().getFilePointer();
078                            } catch (IOException ioe) {
079                                    throw new PageRuntimeException(Caster.toPageException(ioe));
080                            }
081                            try {
082                                    if(raf.read()==-1) return true;
083                                    raf.seek(pos);
084                            } 
085                            catch (IOException e) {
086                                    return true;
087                            }
088                            return false;
089                    }
090                    
091                    try {
092                            return !_getBR().ready();
093                    } catch (IOException e) {
094                            return true;
095                    }
096            }
097    
098            @Override
099            public long getSize() {
100                    return res.length();
101            }
102    
103            @Override
104            public void skip(int len) throws PageException {
105                    if(seekable){
106                            try {
107                                    getRAF().skipBytes(len);
108                            } catch (IOException e) {
109                                    throw Caster.toPageException(e);
110                            }
111                            return;
112                    }
113                    
114                    try {
115                            _getBR().skip(len);
116                            return;
117                    } 
118                    catch (IOException e) {}
119                            
120                    throw Caster.toPageException(new IOException("skip is only supported when you have set argument seekable of function fileOpen to true"));
121            }
122            public void seek(long pos) throws PageException {
123                    if(seekable){
124                            try {
125                                    getRAF().seek(pos);
126                            } catch (IOException e) {
127                                    throw Caster.toPageException(e);
128                            }
129                    }
130                    else throw Caster.toPageException(new IOException("seek is only supported when you have set argument seekable of function fileOpen to true"));
131            }
132    
133            private RandomAccessFile getRAF() throws IOException {
134                    if(raf==null){
135                            if(!(res instanceof File))
136                                    throw new IOException("only resources for local filesytem support seekable");
137                            
138                            raf = new RandomAccessFile((File)res,"r");
139                    }
140                    return raf;
141            }
142    
143    
144            private BufferedReader _getBR() throws IOException {
145                    if(br==null){
146                            br = IOUtil.toBufferedReader(IOUtil.getReader(res.getInputStream(),charset));
147                    }
148                    return br;
149            }
150    }