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