001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.hayabusa.filter;
017
018 import org.opengion.fukurou.util.FileUtil;
019 import org.opengion.fukurou.util.Closer;
020
021 import java.io.PrintWriter;
022 import java.io.BufferedOutputStream;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.io.File;
026 import java.io.ByteArrayOutputStream;
027 import javax.servlet.ServletOutputStream;
028 import javax.servlet.ServletResponse;
029
030 /**
031 * FileFilter で使用する、File圧縮するServletOutputStreamクラスです?
032 *
033 * @og.group フィルター処?
034 *
035 * @version 4.0
036 * @author Kazuhiko Hasegawa
037 * @since JDK5.0,
038 */
039 public class FileResponseStream extends ServletOutputStream {
040 /** ?出力ストリー?*/
041 protected ByteArrayOutputStream filestream = null;
042 /** クローズ判?*/
043 protected boolean isClosed = false;
044 /** レスポンスオブジェク?*/
045 // protected ServletResponse response = null; // 5.5.2.6 (2012/05/25)
046 /** サーブレ?出力ストリー?*/
047 protected ServletOutputStream output = null;
048
049 private final String filename ;
050
051 /**
052 * コンストラクター
053 *
054 * @param response レスポンス
055 * @param filename ファイル?
056 * @throws IOException 入出力エラーが発生したと?
057 */
058 public FileResponseStream( final ServletResponse response,final String filename ) throws IOException {
059 // 4.3.4.4 (2009/01/01)
060 // super();
061 this.filename = filename;
062 isClosed = false;
063 // this.response = response; // 5.5.2.6 (2012/05/25)
064 this.output = response.getOutputStream();
065 filestream = new ByteArrayOutputStream();
066 }
067
068 /**
069 * こ?ストリー?閉じ、このストリー?関連するすべてのシス?リソースを解放します?
070 *
071 * close の汎用規?は、close は出力ストリー?閉じます?閉じられたストリー??
072 * 出力??実行できません。また?それを開き直すことはできません?
073 *
074 * @og.rev 5.6.4.2 (2013/05/17) fileDownload のエンコード?、UTF-8 ではなく?UnicodeLittle でセーブする?
075 *
076 * @throws IOException 入出力エラーが発生したと?
077 */
078 @Override
079 public void close() throws IOException {
080 if(isClosed) {
081 // System.out.println( "already been closed !" );
082 // throw new IOException("This output stream has already been closed");
083 return ;
084 }
085 try {
086 filestream.flush();
087
088 // 5.6.4.2 (2013/05/17) ファイル名が fileDownload で始まる?合?、Streamのままセーブする?
089 if( filename.indexOf( "fileDownload:" ) >= 0 ) {
090 BufferedOutputStream toStream = new BufferedOutputStream( new FileOutputStream( filename.replace( "fileDownload:","" ) ) );
091 filestream.writeTo( toStream );
092 Closer.ioClose( toStream );
093 }
094 else {
095 String msg = filestream.toString( "UTF-8" );
096 FileResponseTransform trans = new FileResponseTransform();
097 msg = trans.replace( filename,msg );
098
099 PrintWriter writer = FileUtil.getPrintWriter( new File( filename ), "UTF-8" );
100 writer.print( msg );
101 Closer.ioClose( writer );
102 }
103 System.out.println( filename + " Saved" );
104
105 output.flush();
106 }
107 catch( Throwable th ) {
108 System.out.println( filename + " Error! " + th );
109 }
110 finally {
111 isClosed = true;
112 Closer.ioClose( filestream );
113 Closer.ioClose( output );
114 }
115 }
116
117 /**
118 * こ?出力ストリー?フラ?ュし?バッファに入って?出力バイトをすべて強制?き込みますに?
119 *
120 * flush の汎用規?は、それまでに書き込まれたバイトが出力ストリー??
121 * 実?よってバッファに入れられて?場合に flush を呼び出すと、それらのバイト?
122 * ただちにそ?目??転送?に書き込まれます?
123 *
124 * @og.rev 5.1.7.0 (2010/06/01) isClosed == true の場合に Exception でなく?return にする?
125 * @throws IOException 入出力エラーが発生したと?
126 */
127 @Override
128 public void flush() throws IOException {
129 if(isClosed) {
130 // throw new IOException("Cannot flush a closed output stream");
131 return ;
132 }
133 filestream.flush();
134 output.flush();
135 }
136
137 /**
138 * こ?出力ストリー??されたバイトを書き込みます?
139 *
140 * write の汎用規?は? バイトが
141 * 出力ストリー?書き込まれます?書き込まれるバイト?、引数 b の下?8 ビットです?
142 * b の上?24 ビット?無視されます?
143 *
144 * @og.rev 5.1.7.0 (2010/06/01) isClosed == true の場合に Exception でなく?return にする?
145 *
146 * @param bt byte??タ
147 * @throws IOException 入出力エラーが発生したと?
148 */
149 @Override
150 public void write(final int bt) throws IOException {
151 if(isClosed) {
152 // throw new IOException("Cannot write to a closed output stream");
153 return ;
154 }
155 filestream.write((byte)bt);
156 output.write((byte)bt);
157 }
158
159 /**
160 * ?されたバイト?列からこの出力ストリー? b.length バイトを書き込みます?
161 *
162 * write(b) の汎用規?は、write(b) の効果? write(b, 0, b.length) を呼び出?
163 * 場合とまったく同じです?
164 *
165 * @param bt バイト??
166 * @throws IOException 入出力エラーが発生したと?
167 */
168 @Override
169 public void write(final byte[] bt) throws IOException {
170 write(bt, 0, bt.length);
171 }
172
173 /**
174 * オフセ? off から始まる指定?バイト?列からこの出力ストリー? len バイトを書き込みます?
175 *
176 * write(b, off, len) の汎用規?は???b ????バイトが出力ストリー??に
177 * 書き込まれます?こ?処???に書き込まれるバイト?要?b[off]、最後に書き込まれる
178 * バイト?要?b[off+len-1] です?
179 *
180 * @og.rev 5.1.7.0 (2010/06/01) isClosed == true の場合に Exception でなく?return にする?
181 *
182 * @param bt バイト??
183 * @param off オフセ?数
184 * @param len 書き込みバイト数
185 * @throws IOException 入出力エラーが発生したと?
186 */
187 @Override
188 public void write(final byte bt[], final int off, final int len) throws IOException {
189 if(isClosed) {
190 // throw new IOException("Cannot write to a closed output stream");
191 return ;
192 }
193 output.write(bt, off, len);
194 filestream.write(bt, off, len);
195 }
196
197 /**
198 * すでにストリー?閉じられて?かど?を返します?
199 *
200 * @return すでにストリー?閉じられて?かど?
201 */
202 public boolean closed() {
203 return isClosed;
204 }
205
206 /**
207 * Checks if a non-blocking write will succeed. If this returns
208 * <code>false</code>, it will cause a callback to
209 * WriteListener#onWritePossible() when the buffer has emptied. If
210 * this method returns <code>false</code> no further data must be written
211 * until the contain calls WriteListener#onWritePossible().
212 *
213 * @og.rev 5.6.8.2 (2013/09/20) 新規追?Tomcat8 / Servlet 3.1 で追?れた abstract メソ?)
214 *
215 * @return true:書き込み可能/false:不可 (true if data can be written, else false)
216 *
217 * @since Servlet 3.1
218 */
219 //@Override
220 public boolean isReady() { return false; }
221
222 /**
223 * Sets the WriteListener for this ServletOutputStream and
224 * thereby switches to non-blocking IO. It is only valid to switch to
225 * non-blocking IO within async processing or HTTP upgrade processing.
226 *
227 * @og.rev 5.6.8.2 (2013/09/20) 新規追?Tomcat8 / Servlet 3.1 で追?れた abstract メソ?)
228 *
229 * @param listener The non-blocking IO write listener
230 *
231 * @throws IllegalStateException If this method is called if neither
232 * async nor HTTP upgrade is in progress or
233 * if the WriteListener has already
234 * been set
235 * @throws NullPointerException If listener is null
236 *
237 * @since Servlet 3.1
238 */
239 //@Override
240 // public void setWriteListener( final javax.servlet.WriteListener listener ) {
241 // // 何も実?な??
242 // }
243 }