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    }