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.fukurou.system;                                                            // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
017
018import java.io.IOException;
019import java.io.Closeable;
020import java.sql.Connection;
021import java.sql.ResultSet;
022import java.sql.Statement;
023import java.sql.SQLException;
024import java.util.zip.ZipFile;           // 5.5.2.6 (2012/05/25)
025
026import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
027
028/**
029 * Closer.java は、共通的に使用される close処理を集約した、クラスです。
030 *
031 * 各種 close() 処理では、Exception が発生しても、どうすることも出来ない
032 * ケースが多々あります。また、close() 処理中の Exception の為だけに、
033 * try ~ catch 節を用意しなければならず、finally 節内からの さらなる
034 * throw など、コーディング上、本流以外の箇所で、色々と問題が発生します。
035 * ここでは、とりあえず、LogWriter.log するだけにしていますが、
036 * 将来的には、エラーを別ファイルにセーブしたり、データベースに書き込んだり
037 * 出来ると思います。
038 *
039 * また、close 処理とは異なりますが、commit や、rollback など、finally 節に
040 * 書き込んで、必ず処理したいが、Exception 発生時に、どうしようもない処理も、
041 * ここに集約していきます。
042 *
043 * @og.rev 6.4.2.0 (2016/01/29) エラー処理を統一的に行います。
044 * @og.rev 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
045 *
046 * @version  4.0
047 * @author       Kazuhiko Hasegawa
048 * @since    JDK5.0,
049 */
050public final class Closer {
051        // 6.4.2.0 (2016/01/29) エラー処理を統一的に行います。
052        private static final String IO_CLOSE_ERR        = "ストリーム close 処理でエラーが発生しました。" ;
053        private static final String COMMIT_ERR          = "Connection を commit することが出来ません。" ;
054        private static final String ROLLBACK_ERR        = "Connection を rollback することが出来ません。" ;
055        private static final String CONN_CLOSE_ERR      = "Connection を close することが出来ません。" ;
056        private static final String STMT_CLOSE_ERR      = "Statement を close することが出来ません。" ;
057        private static final String RESULT_CLOSE_ERR= "ResultSet を close することが出来ません。" ;
058        private static final String ZIP_CLOSE_ERR       = "ZipFile/JarFile を close することが出来ません。" ;
059        private static final String UNNONE_ERR          = "予期せぬエラーが発生しました。" ;
060
061        /**
062         * すべてが staticメソッドなので、コンストラクタを呼び出さなくしておきます。
063         *
064         */
065        private Closer() {}
066
067        /**
068         * io関連の close 処理時の IOException を無視して、close 処理を行います。
069         * ここでは、処理中のエラーは、System.err に出力するだけで無視します。
070         *
071         * これにより、try ~ catch ~ finally 処理で、close を finally 処理から
072         * 例外を送出させなくてすむようになります。
073         * 引数が、null の場合は、何も処理しません。(正常:trueを返します。)
074         *
075         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
076         *
077         * @param obj Closeableインターフェースを実装したIO関連オブジェクト
078         *
079         * @return 正常:true/異常:false
080         */
081        public static boolean ioClose( final Closeable obj ) {
082                boolean isOK = true;
083
084                try {
085                        if( obj != null ) { obj.close(); }
086                }
087                catch( final IOException ex ) {
088                        isOK = false;
089                        logWriter( IO_CLOSE_ERR , obj.toString() , ex );
090                }
091                catch( final RuntimeException ex ) {
092                        isOK = false;
093                        logWriter( UNNONE_ERR , obj.toString() , ex );
094                }
095
096                return isOK;
097        }
098
099        /**
100         * Connection オブジェクトを commit します。
101         * ここでは、処理中のエラーは、System.err に出力するだけで無視します。
102         *
103         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
104         *
105         * @param conn コネクションオブジェクト
106         *
107         * @return 正常:true/異常:false
108         */
109        public static boolean commit( final Connection conn ) {
110                boolean isOK = true;
111
112                try {
113                        if( conn != null ) { conn.commit(); }
114                }
115                catch( final SQLException ex ) {
116                        logWriter( COMMIT_ERR , ex.getSQLState() , ex );
117                }
118                catch( final RuntimeException ex ) {
119                        isOK = false;
120                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
121                }
122
123                return isOK;
124        }
125
126        /**
127         * Connection オブジェクトをrollbackします。
128         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
129         *
130         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
131         *
132         * @param conn コネクションオブジェクト
133         *
134         * @return 正常:true/異常:false
135         */
136        public static boolean rollback( final Connection conn ) {
137                boolean isOK = true;
138
139                try {
140                        if( conn != null ) { conn.rollback(); }
141                }
142                catch( final SQLException ex ) {
143                        logWriter( ROLLBACK_ERR , ex.getSQLState() , ex );
144                }
145                catch( final RuntimeException ex ) {
146                        isOK = false;
147                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
148                }
149
150                return isOK;
151        }
152
153        /**
154         * Connection オブジェクトをcloseします。
155         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
156         *
157         * ここでは、現実の Connection の close() メソッドを呼び出しますので、
158         * キャッシュ等で使用しているコネクションには適用しないでください。
159         *
160         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
161         * @og.rev 5.5.5.0 (2012/07/28) commit追加
162         * @og.rev 5.9.4.0 (201601//08) commit前にvalidのチェックを行う(10秒でタイムアウト)
163         *
164         * @param conn コネクションオブジェクト
165         *
166         * @return 正常:true/異常:false
167         */
168        public static boolean connClose( final Connection conn ) {
169                boolean isOK = true;
170
171                try {
172                        if( conn != null && ! conn.isClosed() ) { 
173                                if( conn.isValid(10) ){         // 5.9.4.0 (2016/01/08)
174                                        conn.commit();                  // 5.5.5.0 (2012/07/28)
175                                }
176                                conn.close();
177                        }
178                }
179                catch( final SQLException ex ) {
180                        logWriter( CONN_CLOSE_ERR , ex.getSQLState() , ex );
181                }
182                catch( final RuntimeException ex ) {
183                        isOK = false;
184                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
185                }
186
187                return isOK;
188        }
189
190        /**
191         * Statement オブジェクトをクローズします。
192         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
193         *
194         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
195         *
196         * @param stmt Statementオブジェクト
197         *
198         * @return 正常:true/異常:false
199         */
200        public static boolean stmtClose( final Statement stmt ) {
201                boolean isOK = true;
202
203                try {
204                        if( stmt != null ) { stmt.close(); }
205                }
206                catch( final SQLException ex ) {
207                        logWriter( STMT_CLOSE_ERR , ex.getSQLState() , ex );
208                }
209                catch( final RuntimeException ex ) {
210                        isOK = false;
211                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
212                }
213
214                return isOK;
215        }
216
217        /**
218         * ResultSet オブジェクトをクローズします。
219         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
220         *
221         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
222         *
223         * @param result ResultSetオブジェクト
224         *
225         * @return 正常:true/異常:false
226         */
227        public static boolean resultClose( final ResultSet result ) {
228                boolean isOK = true;
229
230                try {
231                        if( result != null ) { result.close(); }
232                }
233                catch( final SQLException ex ) {
234                        logWriter( RESULT_CLOSE_ERR , ex.getSQLState() , ex );
235                }
236                catch( final RuntimeException ex ) {
237                        isOK = false;
238                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
239                }
240
241                return isOK;
242        }
243
244        /**
245         * ZipFile オブジェクトをクローズします。
246         * Jar ファイルも、このメソッドでクローズします。
247         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
248         *
249         * @og.rev 5.5.2.6 (2012/05/25) findbugs対応に伴い、新規追加
250         *
251         * @param zipFile ZipFileオブジェクト
252         *
253         * @return 正常:true/異常:false
254         */
255        public static boolean zipClose( final ZipFile zipFile ) {
256                boolean isOK = true;
257
258                try {
259                        if( zipFile != null ) { zipFile.close(); }
260                }
261                catch( final IOException ex ) {
262                        logWriter( ZIP_CLOSE_ERR , zipFile.getName() , ex );
263                }
264                catch( final RuntimeException ex ) {
265                        isOK = false;
266                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
267                }
268
269                return isOK;
270        }
271
272        /**
273         * AutoCloseable オブジェクトをクローズします。
274         * これは、Java1.7 で導入された、try-with-resourcesブロックの終了時に自動的に呼び出される
275         * close() メソッドを、使用します。
276         * 基本的には、try-with-resourcesブロックを使用すべきですが、Exception を発生させたくないため
277         * ここで、close() する処理を残しておきます。
278         * ちなみに、IO系や、SQL系も、AutoCloseable を継承していますが、独自のエラーメッセージを出せないため、
279         * エラーの内容がわかっている場合は、個々に適したクロースメソッドを呼び出してください。
280         *
281         * @og.rev 6.4.2.0 (2016/01/29) エラー処理を統一的に行います。
282         *
283         * @param autoClose AutoCloseableオブジェクト
284         *
285         * @return 正常:true/異常:false
286         */
287        public static boolean autoClose( final AutoCloseable autoClose ) {
288                boolean isOK = true;
289
290                try {
291                        if( autoClose != null ) { autoClose.close(); }
292                }
293                catch( final Throwable th ) {
294                        isOK = false;
295                        logWriter( UNNONE_ERR , th.getMessage() , th );
296                }
297
298                return isOK;
299        }
300
301        /**
302         * Exception 発生時の処理を、統一します。
303         * ここでは、LogWriter に、書き出します。
304         *
305         * @og.rev 6.4.2.0 (2016/01/29) エラー処理を統一的に行います。
306         *
307         * @param msg  エラー時のメッセージ
308         * @param cmnt コメント
309         * @param th   Throwableオブジェクト
310         */
311        private static void logWriter( final String msg , final String cmnt , final Throwable th ) {
312                final String errMsg = msg + th.getMessage() + ":" + cmnt + CR;
313                LogWriter.log( errMsg );
314                LogWriter.log( th );
315        }
316}