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