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