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