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 }