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         * デフォルトコンストラクターをprivateにして、
063         * オブジェクトの生成をさせないようにする。
064         *
065         */
066        private Closer() {}
067
068        /**
069         * io関連の close 処理時の IOException を無視して、close 処理を行います。
070         * ここでは、処理中のエラーは、System.err に出力するだけで無視します。
071         *
072         * これにより、try ~ catch ~ finally 処理で、close を finally 処理から
073         * 例外を送出させなくてすむようになります。
074         * 引数が、null の場合は、何も処理しません。(正常:trueを返します。)
075         *
076         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
077         *
078         * @param obj Closeableインターフェースを実装したIO関連オブジェクト
079         *
080         * @return 正常:true/異常:false
081         */
082        public static boolean ioClose( final Closeable obj ) {
083                boolean isOK = true;
084
085                try {
086                        if( obj != null ) { obj.close(); }
087                }
088                catch( final IOException ex ) {
089                        isOK = false;
090                        logWriter( IO_CLOSE_ERR , obj.toString() , ex );
091                }
092                catch( final RuntimeException ex ) {
093                        isOK = false;
094                        logWriter( UNNONE_ERR , obj.toString() , ex );
095                }
096
097                return isOK;
098        }
099
100        /**
101         * Connection オブジェクトを commit します。
102         * ここでは、処理中のエラーは、System.err に出力するだけで無視します。
103         *
104         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
105         *
106         * @param conn コネクションオブジェクト
107         *
108         * @return 正常:true/異常:false
109         */
110        public static boolean commit( final Connection conn ) {
111                boolean isOK = true;
112
113                try {
114                        if( conn != null ) { conn.commit(); }
115                }
116                catch( final SQLException ex ) {
117                        logWriter( COMMIT_ERR , ex.getSQLState() , ex );
118                }
119                catch( final RuntimeException ex ) {
120                        isOK = false;
121                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
122                }
123
124                return isOK;
125        }
126
127        /**
128         * Connection オブジェクトをrollbackします。
129         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
130         *
131         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
132         * @og.rev 8.1.0.4 (2022/01/28) Connection#isClosed で先に判定する。
133         *
134         * @param conn コネクションオブジェクト
135         *
136         * @return 正常:true/異常:false
137         */
138        public static boolean rollback( final Connection conn ) {
139                boolean isOK = true;
140
141                try {
142//                      if( conn != null ) { conn.rollback(); }
143                        if( conn != null && !conn.isClosed() ) { conn.rollback(); }     // 8.1.0.4 (2022/01/28)
144                }
145                catch( final SQLException ex ) {
146                        logWriter( ROLLBACK_ERR , ex.getSQLState() , ex );
147                }
148                catch( final RuntimeException ex ) {
149                        isOK = false;
150                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
151                }
152
153                return isOK;
154        }
155
156        /**
157         * Connection オブジェクトをcloseします。
158         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
159         *
160         * ここでは、現実の Connection の close() メソッドを呼び出しますので、
161         * キャッシュ等で使用しているコネクションには適用しないでください。
162         *
163         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
164         * @og.rev 5.5.5.0 (2012/07/28) commit追加
165         * @og.rev 5.9.4.0 (201601//08) commit前にvalidのチェックを行う(10秒でタイムアウト)
166         *
167         * @param conn コネクションオブジェクト
168         *
169         * @return 正常:true/異常:false
170         */
171        public static boolean connClose( final Connection conn ) {
172                boolean isOK = true;
173
174                try {
175                        if( conn != null && ! conn.isClosed() ) {
176                                if( conn.isValid(10) ){         // 5.9.4.0 (2016/01/08)
177                                        conn.commit();                  // 5.5.5.0 (2012/07/28)
178                                }
179                                conn.close();
180                        }
181                }
182                catch( final SQLException ex ) {
183                        logWriter( CONN_CLOSE_ERR , ex.getSQLState() , ex );
184                }
185                catch( final RuntimeException ex ) {
186                        isOK = false;
187                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
188                }
189
190                return isOK;
191        }
192
193        /**
194         * Statement オブジェクトをクローズします。
195         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
196         *
197         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
198         * @og.rev 8.1.0.3 (2022/01/21) isClosed()チェック他
199         *
200         * @param stmt Statementオブジェクト
201         *
202         * @return 正常:true/異常:false
203         */
204        public static boolean stmtClose( final Statement stmt ) {
205                boolean isOK = true;
206
207                try {
208//                      if( stmt != null ) { stmt.close(); }
209                        if( stmt != null && !stmt.isClosed() ) { stmt.close(); }        // 8.1.0.3 (2022/01/21)
210                }
211                catch( final SQLException ex ) {
212                        logWriter( STMT_CLOSE_ERR , ex.getSQLState() , ex );
213                }
214                catch( final RuntimeException ex ) {
215                        isOK = false;
216                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
217                }
218
219                return isOK;
220        }
221
222        /**
223         * ResultSet オブジェクトをクローズします。
224         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
225         *
226         * @og.rev 4.0.0.0 (2007/02/08) 新規追加
227         * @og.rev 8.1.0.3 (2022/01/21) isClosed()チェック他
228         *
229         * @param result ResultSetオブジェクト
230         *
231         * @return 正常:true/異常:false
232         */
233        public static boolean resultClose( final ResultSet result ) {
234                boolean isOK = true;
235
236                try {
237//                      if( result != null ) { result.close(); }
238                        if( result != null && !result.isClosed() ) { result.close(); }  // 8.1.0.3 (2022/01/21)
239                }
240                catch( final SQLException ex ) {
241                        logWriter( RESULT_CLOSE_ERR , ex.getSQLState() , ex );
242                }
243                catch( final RuntimeException ex ) {
244                        isOK = false;
245                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
246                }
247
248                return isOK;
249        }
250
251        /**
252         * ZipFile オブジェクトをクローズします。
253         * Jar ファイルも、このメソッドでクローズします。
254         * ここでは、処理中のエラーは、標準出力に出力するだけで無視します。
255         *
256         * @og.rev 5.5.2.6 (2012/05/25) findbugs対応に伴い、新規追加
257         *
258         * @param zipFile ZipFileオブジェクト
259         *
260         * @return 正常:true/異常:false
261         */
262        public static boolean zipClose( final ZipFile zipFile ) {
263                boolean isOK = true;
264
265                try {
266                        if( zipFile != null ) { zipFile.close(); }
267                }
268                catch( final IOException ex ) {
269                        logWriter( ZIP_CLOSE_ERR , zipFile.getName() , ex );
270                }
271                catch( final RuntimeException ex ) {
272                        isOK = false;
273                        logWriter( UNNONE_ERR , ex.getMessage() , ex );
274                }
275
276                return isOK;
277        }
278
279        /**
280         * AutoCloseable オブジェクトをクローズします。
281         * これは、Java1.7 で導入された、try-with-resourcesブロックの終了時に自動的に呼び出される
282         * close() メソッドを、使用します。
283         * 基本的には、try-with-resourcesブロックを使用すべきですが、Exception を発生させたくないため
284         * ここで、close() する処理を残しておきます。
285         * ちなみに、IO系や、SQL系も、AutoCloseable を継承していますが、独自のエラーメッセージを出せないため、
286         * エラーの内容がわかっている場合は、個々に適したクロースメソッドを呼び出してください。
287         *
288         * @og.rev 6.4.2.0 (2016/01/29) エラー処理を統一的に行います。
289         *
290         * @param autoClose AutoCloseableオブジェクト
291         *
292         * @return 正常:true/異常:false
293         */
294        public static boolean autoClose( final AutoCloseable autoClose ) {
295                boolean isOK = true;
296
297                try {
298                        if( autoClose != null ) { autoClose.close(); }
299                }
300                catch( final Throwable th ) {
301                        isOK = false;
302                        logWriter( UNNONE_ERR , th.getMessage() , th );
303                }
304
305                return isOK;
306        }
307
308        /**
309         * Exception 発生時の処理を、統一します。
310         * ここでは、LogWriter に、書き出します。
311         *
312         * @og.rev 6.4.2.0 (2016/01/29) エラー処理を統一的に行います。
313         *
314         * @param msg  エラー時のメッセージ
315         * @param cmnt コメント
316         * @param th   Throwableオブジェクト
317         */
318        private static void logWriter( final String msg , final String cmnt , final Throwable th ) {
319                final String errMsg = msg + th.getMessage() + ":" + cmnt + CR;
320                LogWriter.log( errMsg );
321                LogWriter.log( th );
322        }
323}