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 @Override 033 public void write(Object obj) throws IOException { 034 byte[] bytes = null; 035 InputStream is=null; 036 if(Decision.isBinary(obj)){ 037 bytes=Caster.toBinary(obj,null); 038 } 039 else if(obj instanceof FileStreamWrapper) { 040 is=((FileStreamWrapper)obj).getResource().getInputStream(); 041 } 042 else if(obj instanceof Resource) { 043 is=((Resource)obj).getInputStream(); 044 } 045 else if(Decision.isSimpleValue(obj)){ 046 String str = Caster.toString(obj,null); 047 if(str!=null) bytes=str.getBytes(charset); 048 } 049 050 if(bytes!=null){ 051 if(seekable)getRAF().write(bytes); 052 else _getOS().write(bytes); 053 } 054 else if(is!=null){ 055 if(seekable)writeToRAF(is, getRAF()); 056 else IOUtil.copy(is, _getOS(),true,false); 057 } 058 else 059 throw new IOException("can't write down object of type ["+Caster.toTypeName(obj)+"] to resource ["+res+"]"); 060 061 062 063 064 } 065 066 public void close() throws IOException { 067 if(bos!=null)bos.close(); 068 if(raf!=null)raf.close(); 069 } 070 071 @Override 072 public String getMode() { 073 return append?"append":"write"; 074 } 075 076 @Override 077 public void skip(int len) throws PageException { 078 if(seekable){ 079 try { 080 getRAF().skipBytes(len); 081 } catch (IOException e) { 082 throw Caster.toPageException(e); 083 } 084 } 085 else throw Caster.toPageException(new IOException("skip is only supported when you have set argument seekable of function fileOpen to true")); 086 } 087 public void seek(long pos) throws PageException { 088 if(seekable){ 089 try { 090 getRAF().seek(pos); 091 } catch (IOException e) { 092 throw Caster.toPageException(e); 093 } 094 } 095 else throw Caster.toPageException(new IOException("seek is only supported when you have set argument seekable of function fileOpen to true")); 096 } 097 098 public static void writeToRAF(InputStream is, RandomAccessFile raf) throws IOException { 099 100 byte[] buffer = new byte[2048]; 101 int tmp=0; 102 103 while ((tmp = is.read(buffer)) != -1) { 104 raf.write(buffer, 0, tmp); 105 } 106 } 107 108 private RandomAccessFile getRAF() throws IOException { 109 if(raf==null){ 110 if(!(res instanceof File)) 111 throw new IOException("only resources for local filesytem support seekable"); 112 113 raf = new RandomAccessFile((File)res,"rw"); 114 if(append)raf.seek(res.length()); 115 } 116 return raf; 117 } 118 119 private BufferedOutputStream _getOS() throws IOException{ 120 if(bos==null) 121 bos = IOUtil.toBufferedOutputStream(res.getOutputStream(append)); 122 return bos; 123 } 124 }