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