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