001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.functions.file;
020
021import java.io.File;
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.RandomAccessFile;
025
026import lucee.commons.io.res.Resource;
027import lucee.runtime.exp.PageException;
028import lucee.runtime.op.Caster;
029import lucee.runtime.op.Decision;
030
031public class FileStreamWrapperReadWrite extends FileStreamWrapper {
032        
033        //private BufferedOutputStream bos;
034        private String charset;
035        private boolean seekable;
036        private RandomAccessFile raf;
037        private boolean isEOF;
038
039        public FileStreamWrapperReadWrite(Resource res, String charset,boolean seekable) {
040                super(res);
041                
042                this.charset=charset;
043                this.seekable=seekable;
044        }
045        
046
047        @Override
048        public void write(Object obj) throws IOException {
049                byte[] bytes = null;
050                InputStream is=null;
051                if(Decision.isBinary(obj)){
052                        bytes=Caster.toBinary(obj,null);
053                }
054                else if(obj instanceof FileStreamWrapper) {
055                        is=((FileStreamWrapper)obj).getResource().getInputStream();
056                }
057                else if(obj instanceof Resource) {
058                        is=((Resource)obj).getInputStream();
059                }
060                else {//if(Decision.isSimpleValue(obj)){
061                        String str = Caster.toString(obj,false,null);
062                        if(str!=null) bytes=str.getBytes(charset);
063                }
064                
065                if(bytes!=null){
066                        getRAF().write(bytes);
067                }
068                else if(is!=null){
069                        writeToRAF(is, getRAF());
070                }
071                else
072                        throw new IOException("can't write down object of type ["+Caster.toTypeName(obj)+"] to resource ["+res+"]");
073                
074                
075                
076                
077        }
078
079        public void close() throws IOException {
080                if(raf!=null)raf.close();
081        }
082
083        @Override
084        public String getMode() {
085                return "readwrite";
086        }
087        
088        @Override
089        public Object read(int len) throws IOException {
090                byte[] barr=new byte[len];
091                len=getRAF().read(barr);
092                if(len!=barr.length) {
093                        byte[] rtn=new byte[len];
094                        for(int i=0;i<len;i++) {
095                                rtn[i]=barr[i];
096                        }
097                        barr=rtn;
098                        isEOF=true;
099                }
100                return barr;
101        }
102
103
104
105        @Override
106        public boolean isEndOfFile() {
107                return isEOF;
108        }
109
110        @Override
111        public long getSize() {
112                return res.length();
113        }
114        
115        @Override
116        public void skip(int len) throws PageException {
117                try {
118                        getRAF().skipBytes(len);
119                } catch (IOException e) {
120                        throw Caster.toPageException(e);
121                }
122        }
123        public void seek(long pos) throws PageException {
124                try {
125                        getRAF().seek(pos);
126                } catch (IOException e) {
127                        throw Caster.toPageException(e);
128                }
129        }
130        
131        public static void writeToRAF(InputStream is, RandomAccessFile raf) throws IOException   {  
132        
133        byte[] buffer = new byte[2048];  
134        int tmp=0;  
135   
136        while ((tmp = is.read(buffer)) != -1)   {  
137          raf.write(buffer, 0, tmp);  
138        }   
139    } 
140        
141        private RandomAccessFile getRAF() throws IOException {
142                if(raf==null){
143                        if(!(res instanceof File))
144                                throw new IOException("only resources for local filesytem support seekable");
145                        raf = new RandomAccessFile((File)res,"rw");
146                        
147                }
148                return raf;
149        }
150        
151        
152        
153        
154        
155        
156        
157        
158        
159        
160        
161        
162        
163        
164        
165
166        
167}