    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.process;
    017
    018import org.opengion.fukurou.util.Argument;
    019import org.opengion.fukurou.util.Closer ;
    020import org.opengion.fukurou.util.FileUtil ;
    021import org.opengion.fukurou.util.StringUtil ;
    022import org.opengion.fukurou.util.LogWriter;
    023import org.opengion.fukurou.mail.MailTX ;
    024
    025import java.util.Map ;
    026import java.util.LinkedHashMap ;
    027import java.io.PrintWriter ;
    028import java.io.StringWriter ;
    029
    030/**
    031 * Process_Logger は、画面出力、ファイルログ、エラーメールを管理する、
    032 * ロギング関係の LoggerProcess インターフェースの実装クラスです。
    033 *
    034 * MainProcess で使用されるログと、各種 Process で使用されるディスプレイを
    035 * 管理します。また、エラー発生時の、メール送信機能も、ここで用意します。
    036 *
    037 * 引数文字列中にスペースを含む場合は、ダブルコーテーション("") で括って下さい。
    038 * 引数文字列の 『=』の前後には、スペースは挟めません。必ず、-key=value の様に
    039 * 繋げてください。
    040 *
    041 * @og.formSample
    042 *  Process_Logger -logFile=ABC.txt -dispFile=System.out
    043 *
    044 *   [ -logFile=ログ出力先指定  ] ： -logFile=[ファイル名/System.out/System.err] (初期値:null)
    045 *   [ -dispFile=画面出力先指定 ] ： -dispFile=[ファイル名/System.out/System.err](初期値:null)
    046 *   [ -host=メールサーバ       ] ： -host=メールサーバー
    047 *   [ -from=送信From           ] ： -from=送信元アドレス
    048 *   [ -to=受信To               ] ： -to=送信先アドレスをカンマ区切りで並べる
    049 *   [ -charset=ｷｬﾗｸﾀｾｯﾄ        ] ： -charset=メール送信時のキャラクタセット [ISO-2022-JP / Windows-31J]
    050 *   [ -subject=タイトル        ] ： -subject=タイトル
    051 *   [ -message=本文雛形        ] ： -message=本文雛形文章
    052 *   [ -msgFile=本文雛形ﾌｧｲﾙ    ] ： -msgFile=本文を格納しているファイルのアドレス
    053 *   [ -{&#064;XXXX}=YYYY       ] ： メッセージ本文の {&#064;XXXX} 文字列を、YYYY 文字列に変換します。
    054 *
    055 * @version  4.0
    056 * @author   Kazuhiko Hasegawa
    057 * @since    JDK5.0,
    058 */
    059public class Process_Logger extends AbstractProcess implements LoggerProcess {
    060
    061        private String logFile          = null;         // ログ出力先
    062        private String dispFile         = null;         // 画面出力先
    063
    064        private PrintWriter logWriter = null;
    065        private PrintWriter dispWriter = null;
    066
    067        /** メール送信時のデフォルトキャラクタセット {@value}  */
    068        public static final String DEFAULT_CHARSET = "ISO-2022-JP" ;
    069        private String host = "mail.opengion.org";
    070        private String from = "DUMMY@DUMMY";
    071        private String to   = null;
    072        private String subject     = null;                      // 5.3.1.0 (2011/03/10)
    073        private boolean useErrMail = false;
    074
    075        private static final Map<String,String> mustProparty   ;  // ［プロパティ］必須チェック用 Map
    076        private static final Map<String,String> usableProparty ;  // ［プロパティ］整合性チェック Map
    077
    078        static {
    079                mustProparty = new LinkedHashMap<String,String>();
    080
    081                usableProparty = new LinkedHashMap<String,String>();
    082                usableProparty.put( "logFile",          "ログ出力先指定のファイル名を指定します(初期値:null)" +
    083                                                                                        CR + "『System.out』,『System.err』は特殊な名称です。" );
    084                usableProparty.put( "dispFile",         "画面出力先指定のファイル名を指定します(初期値:null)" +
    085                                                                                        CR + "『System.out』,『System.err』は特殊な名称です。" );
    086                usableProparty.put( "host",             "メールサーバー" );
    087                usableProparty.put( "from",             "送信元アドレス" );
    088                usableProparty.put( "to",               "送信先アドレスをカンマ区切りで並べる" );
    089                usableProparty.put( "charset",  "メール送信時のキャラクタセット [ISO-2022-JP / Windows-31J]" );
    090                usableProparty.put( "subject",  "タイトル" );
    091                usableProparty.put( "message",  "本文雛形文章" );
    092                usableProparty.put( "msgFile",  "本文雛形を格納しているファイルのアドレス" );
    093                usableProparty.put( "{@",               "{@XXXX}=YYYY 汎用文字変換" +
    094                                                                        CR + "メッセージ本文の {@XXXX} 文字列を、YYYY 文字列に変換します。"  );
    095                usableProparty.put( "{@ARG.",   "{@ARG.XXX} 予約文字変換 上記引数を割り当てます。" );
    096                usableProparty.put( "{@DATE.",  "{@DATE.XXX} 予約文字変換 の文字を変換します。" +
    097                                                                        CR + "(SimpleDateFormat 形式の日付、時刻等)" );
    098                usableProparty.put( "{@ENV.",   "{@ENV.XXX} 予約文字変換 ｼｽﾃﾑﾌﾟﾛﾊﾟﾃｨｰの文字を変換します。" +
    099                                                                        CR + "(java -Dkey=value オプションで引き渡します。)" );
    100        }
    101
    102        /**
    103         * デフォルトコンストラクター。
    104         * このクラスは、動的作成されます。デフォルトコンストラクターで、
    105         * super クラスに対して、必要な初期化を行っておきます。
    106         *
    107         */
    108        public Process_Logger() {
    109                super( "org.opengion.fukurou.process.Process_Logger",mustProparty,usableProparty );
    110        }
    111
    112        /**
    113         * プロセスの初期化を行います。初めに一度だけ、呼び出されます。
    114         * 初期処理(ファイルオープン、ＤＢオープン等)に使用します。
    115         *
    116         * @og.rev 5.3.4.0 (2011/04/01) タイトル追加
    117         *
    118         * @param   paramProcess データベースの接続先情報などを持っているオブジェクト
    119         */
    120        public void init( final ParamProcess paramProcess ) {
    121                Argument arg = getArgument();
    122
    123                logFile  = arg.getProparty( "logFile"  );       // ログ出力先
    124                dispFile = arg.getProparty( "dispFile" );       // 画面出力先
    125
    126                if( logWriter == null && logFile != null ) {
    127                        logWriter = FileUtil.getLogWriter( logFile );
    128                }
    129
    130                if( dispWriter == null && dispFile != null ) {
    131                        dispWriter = FileUtil.getLogWriter( dispFile );
    132                }
    133
    134                host = arg.getProparty( "host",host );  // メールサーバー
    135                from = arg.getProparty( "from",from );  // 送信元アドレス
    136                to   = arg.getProparty( "to"  ,to   );  // 送信先アドレス
    137                subject    = arg.getProparty( "subject" );              // 5.3.4.0 (2011/04/01) タイトル
    138                useErrMail = ( host != null ) && ( from != null ) && ( to != null ) ;
    139        }
    140
    141        /**
    142         * プロセスの終了を行います。最後に一度だけ、呼び出されます。
    143         * 終了処理(ファイルクローズ、ＤＢクローズ等)に使用します。
    144         *
    145         * @param   isOK トータルで、OKだったかどうか[true:成功/false:失敗]
    146         */
    147        public void end( final boolean isOK ) {
    148                if( logWriter != null ) {
    149                        logWriter.flush();
    150                        Closer.ioClose( logWriter );
    151                }
    152
    153                if( dispWriter != null ) {
    154                        dispWriter.flush();
    155                        Closer.ioClose( dispWriter );
    156                }
    157        }
    158
    159        /**
    160         * ログファイルにメッセージを表示します。
    161         *
    162         * @param       msg     表示するメッセージ
    163         */
    164        @Override
    165        public void logging( final String msg ) {
    166                if( logWriter != null ) {
    167                        logWriter.println( msg ) ;
    168                }
    169        }
    170
    171        /**
    172         * ディスプレイにメッセージを表示します。
    173         *
    174         * @param       msg     表示するメッセージ
    175         */
    176        @Override
    177        public void println( final String msg ) {
    178                if( dispWriter != null ) {
    179                        dispWriter.println( msg ) ;
    180                }
    181        }
    182
    183        /**
    184         * エラーログにメッセージを表示します。
    185         * ここに書き込まれたメッセージは、通常ログと、特殊ログの
    186         * 両方に書き込まれます。
    187         * 特殊ログとは、メール連絡等のことです。
    188         *
    189         * @param       msg     表示するメッセージ
    190         * @param       th      Throwable例外オブジェクト
    191         */
    192        public void errLog( final String msg,final Throwable th ) {
    193                String sendMsg = msg;
    194                if( logWriter != null ) {
    195                        if( th != null ) {
    196                                StringWriter errMsg = new StringWriter();
    197                                errMsg.append( msg ).append( CR );
    198                                th.printStackTrace( new PrintWriter( errMsg ) );
    199                                sendMsg = errMsg.toString();
    200                        }
    201                        logWriter.println( sendMsg ) ;
    202                }
    203                println( sendMsg ) ;
    204                if( useErrMail ) { sendmail( sendMsg ) ; }
    205        }
    206
    207        /**
    208         * メール送信を行います。
    209         *
    210         * @og.rev 5.3.4.0 (2011/04/01) タイトル追加
    211         *
    212         * @param       msg     送信するメッセージ
    213         */
    214        private void sendmail( final String msg ) {
    215
    216                Argument arg = getArgument();
    217
    218                String charset = arg.getProparty( "charset", DEFAULT_CHARSET );
    219                MailTX mail = new MailTX( host,charset );
    220                mail.setFrom( from );
    221                mail.setTo( StringUtil.csv2Array( to ) );
    222//              mail.setSubject( arg.getProparty( "subject" ) );
    223                mail.setSubject( subject );                                                                     // 5.3.4.0 (2011/04/01)
    224
    225                String message = arg.getFileProparty("message","msgFile",false);
    226
    227                // {@XXX} 変換は、Argument クラスの機能を使う。
    228                message = arg.changeParam( message );
    229                message = message + CR + msg ;
    230                mail.setMessage( message );
    231                mail.sendmail();
    232        }
    233
    234        /**
    235         * ログ出力用のPrintWriterを設定します。
    236         * 通常は、引数の -logFile=XXXX で指定しますが、直接 PrintWriter を
    237         * 渡す必要があるケース(JSPなどで使用するケース)で使用します。
    238         * 引数より、こちらの設定のほうが、優先されます。
    239         * ※ JspWriter を渡す場合の PrintWriter は、flushing および、close 処理を
    240         * 行わない NonFlushPrintWriter を設定してください。
    241         *
    242         * @param  logWriter    ログ出力用のPrintWriter
    243         */
    244        public void setLoggingWriter( final PrintWriter logWriter ) {
    245                this.logWriter = logWriter;
    246        }
    247
    248        /**
    249         * 画面表示用のPrintWriterを設定します。
    250         * 通常は、引数の -dispFile=XXXX で指定しますが、直接 PrintWriter を
    251         * 渡す必要があるケース(JSPなどで使用するケース)で使用します。
    252         * 引数より、こちらの設定のほうが、優先されます。
    253         * ※ JspWriter を渡す場合の PrintWriter は、flushing および、close 処理を
    254         * 行わない NonFlushPrintWriter を設定してください。
    255         *
    256         * @param  dispWriter   画面表示用のPrintWriter
    257         */
    258        public void setDisplayWriter( final PrintWriter dispWriter ) {
    259                this.dispWriter = dispWriter;
    260        }
    261
    262        /**
    263         * プロセスの処理結果のレポート表現を返します。
    264         * 処理プログラム名、入力件数、出力件数などの情報です。
    265         * この文字列をそのまま、標準出力に出すことで、結果レポートと出来るような
    266         * 形式で出してください。
    267         *
    268         * @og.rev 5.3.4.0 (2011/04/01) タイトル追加
    269         *
    270         * @return   処理結果のレポート
    271         */
    272        public String report() {
    273                return "[" + getClass().getName() + "]" + CR
    274                                + TAB + "Subject      : " + subject + CR
    275                                + TAB + "Log     File : " + logFile + CR
    276                                + TAB + "Display File : " + dispFile ;
    277        }
    278
    279        /**
    280         * このクラスの使用方法を返します。
    281         *
    282         * @return      このクラスの使用方法
    283         */
    284        public String usage() {
    285                StringBuilder buf = new StringBuilder();
    286
    287                buf.append( "Process_Logger は、画面出力、ファイルログ、エラーメールを管理する、"                         ).append( CR );
    288                buf.append( "ロギング関係の LoggerProcess インターフェースの実装クラスです。"                           ).append( CR );
    289                buf.append( CR );
    290                buf.append( "MainProcess で使用されるログと、各種 Process で使用されるディスプレイを"            ).append( CR );
    291                buf.append( "管理します。また、エラー発生時の、メール送信機能も、ここで用意します。"               ).append( CR );
    292                buf.append( CR );
    293                buf.append( "引数文字列中に空白を含む場合は、ダブルコーテーション(\"\") で括って下さい。" ).append( CR );
    294                buf.append( "引数文字列の 『=』の前後には、空白は挟めません。必ず、-key=value の様に"                ).append( CR );
    295                buf.append( "繋げてください。"                                                                                                                          ).append( CR );
    296                buf.append( CR ).append( CR );
    297
    298                buf.append( getArgument().usage() ).append( CR );
    299
    300                return buf.toString();
    301        }
    302
    303        /**
    304         * このクラスは、main メソッドから実行できません。
    305         *
    306         * @param       args    コマンド引数配列
    307         */
    308        public static void main( final String[] args ) {
    309                LogWriter.log( new Process_Logger().usage() );
    310        }
    311}