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.BufferedWriter;
019import java.io.File;
020import java.io.FileWriter;
021import java.io.IOException;
022import java.io.PrintWriter;
023
024import java.io.OutputStreamWriter;                                      // 7.1.0.1 (2020/02/07)
025import java.io.FileOutputStream;                                        // 7.1.0.1 (2020/02/07)
026
027/**
028 * Logを書き込む為の PrintWriter を管理するクラスです。
029 *
030 * 実際の Log の書き込みには、LogSender を利用して下さい。
031 *
032 * @og.rev 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system
033 *
034 * @og.group エラー処理
035 *
036 * @version  4.0
037 * @author   Kazuhiko Hasegawa
038 * @since    JDK5.0,
039 */
040public final class LogWriter {
041        private static PrintWriter writer ;
042        private static String      encode ;                                     // 7.1.0.1 (2020/02/07) "UTF-8" など
043        private static final Object LOCK = new Object();        // 6.3.9.0 (2015/11/06) synchronizedブロック
044
045        private static String logFileUrl        ;                               // 4.1.0.1 (2008/01/23)
046
047        /**
048         * デフォルトコンストラクター
049         * private にして、コンストラクターの作成をさせない様にしています。
050         *
051         */
052        private LogWriter() {}
053
054        /**
055         * Logファイルの出力先を設定します。
056         *
057         * このファイル名は、日付フォーマット変数を含むことができます。
058         *
059         * @og.rev 4.1.0.1 (2008/01/23) 新規作成
060         * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD)
061         * @og.rev 6.4.2.0 (2016/01/29) 出力先変更時は、既存の Writer をclose() してからにする。
062         * @og.rev 7.1.0.1 (2020/02/07) ログファイルのエンコードを指定します。
063         *
064         * @param   url 出力先
065         * @param   enc エンコード
066         * @see         org.opengion.fukurou.system.DateSet#changeString(String)
067         */
068//      public static void init( final String url ) {
069        public static void init( final String url,final String enc ) {
070                synchronized( LOCK ) {
071                        close();
072                        logFileUrl = url;
073                        encode     = enc;               // 7.1.0.1 (2020/02/07)
074                }
075        }
076
077        /**
078         * Logを書き出します。
079         *
080         * @og.rev 4.1.0.1 (2008/01/23) 出力時間を出力する。
081         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
082         * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD)
083         *
084         * @param   message メッセージ
085         */
086        public static void log( final String message ) {
087                synchronized( LOCK ) {
088                        if( writer == null ) { writer = getPrintWriter(); }
089                }
090                writer.println( "[WriteTime= " + DateSet.getDate( "yyyy/MM/dd HH:mm:ss.SSS" ) + "] " + message );       // 5.5.7.2 (2012/10/09) HybsDateUtil を利用
091                writer.flush();
092        }
093
094        /**
095         * 例外のスタックトレースをLogWriterのPrintWriterに書き出します。
096         *
097         * @og.rev 4.1.0.1 (2008/01/23) 新規作成
098         * @og.rev 4.3.4.5 (2009/01/08) nullチェック追加
099         * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD)
100         * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
101         *
102         * @param   th スタックトレースの取得元Throwableオブジェクト
103         */
104        public static void log( final Throwable th ) {
105                synchronized( LOCK ) {
106                        if( writer == null ) { writer = getPrintWriter(); }
107                }
108                writer.println( ThrowUtil.ogStackTrace( th ) );                         // 6.4.2.0 (2016/01/29)
109        }
110
111        /**
112         * PrintWriter を close() します。
113         *
114         * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD)
115         */
116        public static void close() {
117                synchronized( LOCK ) {
118                        if( writer != null ) { writer.close(); }
119                        writer = null;
120                }
121        }
122
123        /**
124         * 追加モードで作成した PrintWriter を取得します。
125         * PrintWriter は、シングルトーンとして唯一存在させています。
126         *
127         * @og.rev 4.1.0.1 (2008/01/23) ログファイル出力先を外部から指定する。
128         * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD)
129         * @og.rev 7.1.0.1 (2020/02/07) ログファイルのエンコードを指定します。
130         *
131         * @return 追加モードで作成したPrintWriter
132         * @og.rtnNotNull
133         */
134        private static PrintWriter getPrintWriter() {
135                if( logFileUrl == null || logFileUrl.isEmpty() ) {
136                        return new PrintWriter( System.err );
137                }
138                else {
139                        // 日付フォームのファイル名を変換します。
140                        final DateSet dateSet = new DateSet();
141                        final String timeFileUrl = dateSet.changeString( logFileUrl );          // 6.3.9.0 (2015/11/06) 日付フォーマットは、作成都度行う事とする。
142
143                        try {
144                                final File logFile = new File( timeFileUrl );
145                                // 7.1.0.1 (2020/02/07) ログファイルのエンコードを指定します。
146        //                      return new PrintWriter( new BufferedWriter( new FileWriter( logFile, true ) ) );
147                                if( encode == null || encode.isEmpty() ) {
148                                        return new PrintWriter( new BufferedWriter( new FileWriter( logFile, true ) ) );
149                                }
150                                else {
151                                        return new PrintWriter( new BufferedWriter( new OutputStreamWriter( new FileOutputStream( logFile, true ), encode ) ) );        // 7.1.0.1 (2020/02/07)
152                                }
153                        }
154                        catch( final IOException ex ) {
155                                final String errMsg = "ログライターが作成できません。[" + timeFileUrl + "]";
156                                throw new OgRuntimeException( errMsg, ex );
157                        }
158                }
159        }
160}