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 */ 016package org.opengion.hayabusa.filter; 017 018import org.opengion.fukurou.util.FileUtil; 019import org.opengion.fukurou.util.Closer; 020 021import java.io.PrintWriter; 022import java.io.BufferedOutputStream; 023import java.io.FileOutputStream; 024import java.io.IOException; 025import java.io.File; 026import java.io.ByteArrayOutputStream; 027import javax.servlet.ServletOutputStream; 028import 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 */ 039public class FileResponseStream extends ServletOutputStream { 040 /** 内部出力ストリーム */ 041 protected ByteArrayOutputStream filestream = null; 042 /** クローズ判定 */ 043 protected boolean isClosed = false; 044 /** サーブレット出力ストリーム */ 045 protected ServletOutputStream output = null; 046 047 private final String filename ; 048 049 /** 050 * コンストラクター 051 * 052 * @param response レスポンス 053 * @param filename ファイル名 054 * @throws IOException 入出力エラーが発生したとき 055 */ 056 public FileResponseStream( final ServletResponse response,final String filename ) throws IOException { 057 // 4.3.4.4 (2009/01/01) 058 this.filename = filename; 059 isClosed = false; 060 this.output = response.getOutputStream(); 061 filestream = new ByteArrayOutputStream(); 062 } 063 064 /** 065 * このストリームを閉じ、このストリームに関連するすべてのシステムリソースを解放します。 066 * 067 * close の汎用規約では、close は出力ストリームを閉じます。閉じられたストリームは 068 * 出力処理を実行できません。また、それを開き直すことはできません。 069 * 070 * @og.rev 5.6.4.2 (2013/05/17) fileDownload のエンコードは、UTF-8 ではなく、UnicodeLittle でセーブする。 071 * 072 * @throws IOException 入出力エラーが発生したとき 073 */ 074 @Override 075 public void close() throws IOException { 076 if(isClosed) { 077 return ; 078 } 079 try { 080 filestream.flush(); 081 082 // 5.6.4.2 (2013/05/17) ファイル名が fileDownload で始まる場合は、Streamのままセーブする。 083 if( filename.indexOf( "fileDownload:" ) >= 0 ) { 084 BufferedOutputStream toStream = new BufferedOutputStream( new FileOutputStream( filename.replace( "fileDownload:","" ) ) ); 085 filestream.writeTo( toStream ); 086 Closer.ioClose( toStream ); 087 } 088 else { 089 String msg = filestream.toString( "UTF-8" ); 090 FileResponseTransform trans = new FileResponseTransform(); 091 msg = trans.replace( filename,msg ); 092 093 PrintWriter writer = FileUtil.getPrintWriter( new File( filename ), "UTF-8" ); 094 writer.print( msg ); 095 Closer.ioClose( writer ); 096 } 097 System.out.println( filename + " Saved" ); 098 099 output.flush(); 100 } 101 catch( Throwable th ) { 102 System.out.println( filename + " Error! " + th ); 103 } 104 finally { 105 isClosed = true; 106 Closer.ioClose( filestream ); 107 Closer.ioClose( output ); 108 } 109 } 110 111 /** 112 * この出力ストリームをフラッシュし、バッファに入っている出力バイトをすべて強制的書き込みますに。 113 * 114 * flush の汎用規約では、それまでに書き込まれたバイトが出力ストリームの 115 * 実装によってバッファに入れられている場合に flush を呼び出すと、それらのバイトは 116 * ただちにその目的の転送先に書き込まれます。 117 * 118 * @og.rev 5.1.7.0 (2010/06/01) isClosed == true の場合に Exception でなく、return にする。 119 * @throws IOException 入出力エラーが発生したとき 120 */ 121 @Override 122 public void flush() throws IOException { 123 if(isClosed) { 124 return ; 125 } 126 filestream.flush(); 127 output.flush(); 128 } 129 130 /** 131 * この出力ストリームに指定されたバイトを書き込みます。 132 * 133 * write の汎用規約では、1 バイトが 134 * 出力ストリームに書き込まれます。書き込まれるバイトは、引数 b の下位 8 ビットです。 135 * b の上位 24 ビットは無視されます。 136 * 137 * @og.rev 5.1.7.0 (2010/06/01) isClosed == true の場合に Exception でなく、return にする。 138 * 139 * @param bt byteデータ 140 * @throws IOException 入出力エラーが発生したとき 141 */ 142 @Override 143 public void write(final int bt) throws IOException { 144 if(isClosed) { 145 return ; 146 } 147 filestream.write((byte)bt); 148 output.write((byte)bt); 149 } 150 151 /** 152 * 指定されたバイト配列からこの出力ストリームに b.length バイトを書き込みます。 153 * 154 * write(b) の汎用規約では、write(b) の効果は write(b, 0, b.length) を呼び出す 155 * 場合とまったく同じです。 156 * 157 * @param bt バイト配列 158 * @throws IOException 入出力エラーが発生したとき 159 */ 160 @Override 161 public void write(final byte[] bt) throws IOException { 162 write(bt, 0, bt.length); 163 } 164 165 /** 166 * オフセット off から始まる指定のバイト配列からこの出力ストリームに len バイトを書き込みます。 167 * 168 * write(b, off, len) の汎用規約では、配列 b 内の一定のバイトが出力ストリームに順番に 169 * 書き込まれます。この処理で最初に書き込まれるバイトは要素 b[off]、最後に書き込まれる 170 * バイトは要素 b[off+len-1] です。 171 * 172 * @og.rev 5.1.7.0 (2010/06/01) isClosed == true の場合に Exception でなく、return にする。 173 * 174 * @param bt バイト配列 175 * @param off オフセット数 176 * @param len 書き込みバイト数 177 * @throws IOException 入出力エラーが発生したとき 178 */ 179 @Override 180 public void write(final byte bt[], final int off, final int len) throws IOException { 181 if(isClosed) { 182 return ; 183 } 184 output.write(bt, off, len); 185 filestream.write(bt, off, len); 186 } 187 188 /** 189 * すでにストリームが閉じられているかどうかを返します。 190 * 191 * @return すでにストリームが閉じられているかどうか 192 */ 193 public boolean closed() { 194 return isClosed; 195 } 196 197 /** 198 * Checks if a non-blocking write will succeed. If this returns 199 * <code>false</code>, it will cause a callback to 200 * WriteListener#onWritePossible() when the buffer has emptied. If 201 * this method returns <code>false</code> no further data must be written 202 * until the contain calls WriteListener#onWritePossible(). 203 * 204 * @og.rev 5.6.8.2 (2013/09/20) 新規追加(Tomcat8 / Servlet 3.1 で追加された abstract メソッド) 205 * 206 * @return true:書き込み可能/false:不可 (true if data can be written, else false) 207 * 208 * @since Servlet 3.1 209 */ 210 @Override 211 public boolean isReady() { return false; } 212 213 /** 214 * Sets the WriteListener for this ServletOutputStream and 215 * thereby switches to non-blocking IO. It is only valid to switch to 216 * non-blocking IO within async processing or HTTP upgrade processing. 217 * 218 * @og.rev 5.6.8.2 (2013/09/20) 新規追加(Tomcat8 / Servlet 3.1 で追加された abstract メソッド) 219 * 220 * @param listener The non-blocking IO write listener 221 * 222 * @throws IllegalStateException If this method is called if neither 223 * async nor HTTP upgrade is in progress or 224 * if the WriteListener has already 225 * been set 226 * @throws NullPointerException If listener is null 227 * 228 * @since Servlet 3.1 229 */ 230 @Override 231 public void setWriteListener( final javax.servlet.WriteListener listener ) { 232 // 何も実装しない。 233 } 234}