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            public boolean isReady() { return false; }
200    
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    //      public void setWriteListener( final javax.servlet.WriteListener listener ) {
219    //              // 何も実?な??
220    //      }
221    }