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    }