001 package railo.runtime.functions.file; 002 003 import java.io.BufferedOutputStream; 004 import java.io.File; 005 import java.io.IOException; 006 import java.io.InputStream; 007 import java.io.RandomAccessFile; 008 009 import railo.commons.io.IOUtil; 010 import railo.commons.io.res.Resource; 011 import railo.runtime.exp.PageException; 012 import railo.runtime.op.Caster; 013 import railo.runtime.op.Decision; 014 015 public class FileStreamWrapperWrite extends FileStreamWrapper { 016 017 private BufferedOutputStream bos; 018 private boolean append; 019 private String charset; 020 private boolean seekable; 021 private RandomAccessFile raf; 022 023 public FileStreamWrapperWrite(Resource res, String charset,boolean append,boolean seekable) { 024 super(res); 025 026 this.charset=charset; 027 this.append=append; 028 this.seekable=seekable; 029 } 030 031 032 /** 033 * @see railo.runtime.functions.file.FileStreamWrapper#write(java.lang.Object) 034 */ 035 public void write(Object obj) throws IOException { 036 byte[] bytes = null; 037 InputStream is=null; 038 if(Decision.isBinary(obj)){ 039 bytes=Caster.toBinary(obj,null); 040 } 041 else if(obj instanceof FileStreamWrapper) { 042 is=((FileStreamWrapper)obj).getResource().getInputStream(); 043 } 044 else if(obj instanceof Resource) { 045 is=((Resource)obj).getInputStream(); 046 } 047 else if(Decision.isSimpleValue(obj)){ 048 String str = Caster.toString(obj,null); 049 if(str!=null) bytes=str.getBytes(charset); 050 } 051 052 if(bytes!=null){ 053 if(seekable)getRAF().write(bytes); 054 else _getOS().write(bytes); 055 } 056 else if(is!=null){ 057 if(seekable)writeToRAF(is, getRAF()); 058 else IOUtil.copy(is, _getOS(),true,false); 059 } 060 else 061 throw new IOException("can't write down object of type ["+Caster.toTypeName(obj)+"] to resource ["+res+"]"); 062 063 064 065 066 } 067 068 public void close() throws IOException { 069 if(bos!=null)bos.close(); 070 if(raf!=null)raf.close(); 071 } 072 073 /** 074 * 075 * @see railo.runtime.functions.file.FileStreamWrapper#getMode() 076 */ 077 public String getMode() { 078 return append?"append":"write"; 079 } 080 081 /** 082 * @see railo.runtime.functions.file.FileStreamWrapper#skip(long) 083 */ 084 public void skip(int len) throws PageException { 085 if(seekable){ 086 try { 087 getRAF().skipBytes(len); 088 } catch (IOException e) { 089 throw Caster.toPageException(e); 090 } 091 } 092 else throw Caster.toPageException(new IOException("skip is only supported when you have set argument seekable of function fileOpen to true")); 093 } 094 public void seek(long pos) throws PageException { 095 if(seekable){ 096 try { 097 getRAF().seek(pos); 098 } catch (IOException e) { 099 throw Caster.toPageException(e); 100 } 101 } 102 else throw Caster.toPageException(new IOException("seek is only supported when you have set argument seekable of function fileOpen to true")); 103 } 104 105 public static void writeToRAF(InputStream is, RandomAccessFile raf) throws IOException { 106 107 byte[] buffer = new byte[2048]; 108 int tmp=0; 109 110 while ((tmp = is.read(buffer)) != -1) { 111 raf.write(buffer, 0, tmp); 112 } 113 } 114 115 private RandomAccessFile getRAF() throws IOException { 116 if(raf==null){ 117 if(!(res instanceof File)) 118 throw new IOException("only resources for local filesytem support seekable"); 119 120 raf = new RandomAccessFile((File)res,"rw"); 121 if(append)raf.seek(res.length()); 122 } 123 return raf; 124 } 125 126 private BufferedOutputStream _getOS() throws IOException{ 127 if(bos==null) 128 bos = IOUtil.toBufferedOutputStream(res.getOutputStream(append)); 129 return bos; 130 } 131 }