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