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