
nablarch.core.log.LogUtil Maven / Gradle / Ivy
The newest version!
package nablarch.core.log;
import java.lang.reflect.Array;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import nablarch.core.util.StringUtil;
import nablarch.core.util.annotation.Published;
/**
* ログ出力の実装を助けるユーティリティ。
* @author Kiyohito Itoh
*/
public final class LogUtil {
/** 隠蔽コンストラクタ */
private LogUtil() {
}
/** システムプロパティから起動プロセスを識別する文字列を取得する際に使用するキー */
private static final String SYSTEM_PROP_BOOT_PROCESS = "nablarch.bootProcess";
/** 実行時IDの日時(ミリ秒)をフォーマットする際に使用するフォーマッタ */
private static final DateFormat EXECUTION_ID_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");
/** 実行時IDの連番(4桁)に使用する値 */
private static int executionIdSequence = 1;
/**
* 実行時IDを生成する。
*
* 実行時IDは下記のフォーマットで生成する。
*
* 起動プロセス+日時("yyyyMMddHHmmssSSS")+連番(4桁)
*
* 起動プロセスは{@link #getBootProcess()}から取得する。
*
* @return 実行時ID
*/
public static synchronized String generateExecutionId() {
String bootProcess = getBootProcess();
String date = EXECUTION_ID_DATE_FORMAT.format(new Date());
String sequence = StringUtil.lpad(String.valueOf(executionIdSequence++), 4, '0');
if (executionIdSequence == 10000) {
executionIdSequence = 1;
}
return bootProcess + date + sequence;
}
/**
* システムプロパティ("nablarch.bootProcess")から起動プロセスを識別する文字列を取得する。
* @return 起動プロセスを識別する文字列。指定がない場合はブランク
*/
public static String getBootProcess() {
return System.getProperty(SYSTEM_PROP_BOOT_PROCESS, "");
}
/**
* プレースホルダ($名前$形式)検索用のパターンを作成する。
* @param replacements 置き換え文字($名前$形式)
* @return プレースホルダ($名前$形式)検索用のパターン
*/
public static Pattern createReplacementsPattern(Set replacements) {
StringBuilder pattern = new StringBuilder();
for (String replacement : replacements) {
if (pattern.length() != 0) {
pattern.append("|");
}
pattern.append(replacement.replace("$", "\\$"));
}
return Pattern.compile("(" + pattern.toString() + ")");
}
/**
* フォーマット文字列からフォーマット済みのログ出力項目を生成する。
* 指定されたログ出力項目のキーをプレースホルダ($名前$形式)検索用のパターンに使用する。
* @param ログ出力項目の取得に使用するコンテキストの型
* @param logItems ログ出力項目
* @param format フォーマット文字列
* @return フォーマット済みのログ出力項目
*/
public static LogItem[] createFormattedLogItems(Map> logItems, String format) {
Pattern pattern = createReplacementsPattern(logItems.keySet());
return createFormattedLogItems(logItems, format, pattern);
}
/**
* フォーマット文字列からフォーマット済みのログ出力項目を生成する。
* プレースホルダでない固定文字列には、{@link FixedStringItem}を使用する。
* @param ログ出力項目の取得に使用するコンテキストの型
* @param logItems ログ出力項目
* @param format フォーマット文字列
* @param pattern プレースホルダのパターン
* @return フォーマット済みのログ出力項目
*/
@SuppressWarnings("unchecked")
public static LogItem[] createFormattedLogItems(Map> logItems, String format, Pattern pattern) {
List> logItemList = new ArrayList>();
int beginIndex = 0;
int endIndex = -1;
Matcher matcher = pattern.matcher(format);
while (matcher.find()) {
endIndex = matcher.start(1);
if (beginIndex < endIndex) {
logItemList.add((LogItem) new FixedStringItem(format.substring(beginIndex, endIndex)));
}
String subSequence = matcher.group(1);
LogItem logItem = logItems.get(subSequence);
logItemList.add(logItem != null ? logItem : (LogItem) new FixedStringItem(subSequence));
beginIndex = matcher.end(1);
}
endIndex = format.length();
if (beginIndex < endIndex) {
logItemList.add((LogItem) new FixedStringItem(format.substring(beginIndex, endIndex)));
}
LogItem[] logItemArray = new LogItem[logItemList.size()];
logItemList.toArray(logItemArray);
return logItemArray;
}
/**
* フォーマット済みのログ出力項目を使用してメッセージをフォーマットする。
* @param ログ出力項目の取得に使用するコンテキストの型
* @param logItems フォーマット済みのログ出力項目
* @param context ログ出力項目の取得に使用するコンテキスト
* @return フォーマット済みのメッセージ
*/
public static String formatMessage(LogItem[] logItems, T context) {
StringBuilder sb = new StringBuilder();
for (LogItem logItem : logItems) {
sb.append(logItem.get(context));
}
return sb.toString();
}
/** デフォルトの{@link MapValueEditor} */
private static final BasicMapValueEditor DEFAULT_MAP_VALUE_EDITOR = new BasicMapValueEditor();
/**
* マップをダンプした文字列を返す。
* @param マップの値の型
* @param map マップ
* @param separator マップエントリのセパレータ
* @return マップをダンプした文字列
*/
public static String dumpMap(Map map, String separator) {
return dumpMap(map, separator, DEFAULT_MAP_VALUE_EDITOR, null);
}
/**
* マップをダンプした文字列を返す。
* @param マップの値の型
* @param map マップ
* @param separator マップエントリのセパレータ
* @param excludeKeyPattern ダンプから除外するキーのパターン。指定しない場合はnull
* @return マップをダンプした文字列
*/
public static String dumpMap(Map map, String separator, Pattern excludeKeyPattern) {
return dumpMap(map, separator, DEFAULT_MAP_VALUE_EDITOR, excludeKeyPattern);
}
/**
* マップをダンプした文字列を返す。
* @param マップの値の型
* @param map マップ
* @param separator マップエントリのセパレータ
* @param valueEditor {@link MapValueEditor}
* @return マップをダンプした文字列
*/
public static String dumpMap(Map map, String separator, MapValueEditor valueEditor) {
return dumpMap(map, separator, valueEditor, null);
}
/**
* マップをダンプした文字列を返す。
* @param マップの値の型
* @param map マップ
* @param separator マップエントリのセパレータ
* @param valueEditor {@link MapValueEditor}
* @param excludeKeyPattern ダンプから除外するキーのパターン。指定しない場合はnull
* @return マップをダンプした文字列
*/
private static String dumpMap(Map map, String separator, MapValueEditor valueEditor, Pattern excludeKeyPattern) {
if (map == null) {
return "null";
}
if (map.isEmpty()) {
return "{}";
}
StringBuilder sb = new StringBuilder();
boolean appendSeparator = false;
for (Map.Entry param : map.entrySet()) {
String key = param.getKey();
if (key == null) {
key = "null";
}
if (excludeKeyPattern != null && excludeKeyPattern.matcher(key).matches()) {
continue;
}
if (appendSeparator) {
sb.append(",").append(separator);
} else {
appendSeparator = true;
}
sb.append(key).append(" = [").append(valueEditor.edit(key, param.getValue())).append("]");
}
if (sb.length() == 0) {
return "{}";
}
return "{" + (separator.contains(Logger.LS) ? separator : "") + sb.toString() + "}";
}
/**
* マップの値を編集するインタフェース。
* マップをダンプする処理({@link LogUtil#dumpMap(Map, String, MapValueEditor)})で使用する。
* @author Kiyohito Itoh
*/
public static interface MapValueEditor {
/**
* マップの値を編集する。
*
* @param key マップのキー
* @param value マップの値
* @return 編集後のマップの値
*/
String edit(String key, Object value);
}
/**
* マップの値を編集するインタフェースの基本実装クラス。
* @author Kiyohito Itoh
*/
public static class BasicMapValueEditor implements MapValueEditor {
/**
* マップの編集処理を行う。
*
* マップの値に応じて下記の通り処理する。
* null:"null"
* 配列:["要素1","要素2"・・・,"要素n"](要素毎に{@link Object#toString()})
* Collection型:["要素1","要素2"・・・,"要素n"](要素毎に{@link Object#toString()})
* 上記以外:{@link Object#toString()}
*
*
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public String edit(String key, Object value) {
if (value == null) {
return getNullValue();
} else if (value.getClass().isArray()) {
StringBuilder sb = new StringBuilder();
if (value instanceof Object[]) {
Object[] values = (Object[]) value;
for (int i = 0; i < values.length; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(editValue(key, values[i]));
}
} else {
final int length = Array.getLength(value);
for (int i = 0; i < length; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(editValue(key, Array.get(value, i)));
}
}
return sb.toString();
} else if (value instanceof Collection) {
StringBuilder sb = new StringBuilder();
Iterator
© 2015 - 2025 Weber Informatics LLC | Privacy Policy