001package com.streamconverter.command.rule; 002 003import com.streamconverter.context.ExecutionContext; 004import java.util.Objects; 005 006/** 007 * MDC設定用のルール 008 * 009 * <p>XMLやJSONなどから抽出した値を、ExecutionContextの共有コンテキストに設定します。 010 * 共有コンテキストに設定された値は、全ての並列実行中のコマンドから即座にアクセス可能になり、 applyToMDC()呼び出し時にMDCに反映されます。 011 * 012 * <p><b>使用例:</b> 013 * 014 * <pre>{@code 015 * // ExecutionContextを作成 016 * ExecutionContext context = ExecutionContext.create(); 017 * 018 * // MdcSetupRuleを使用してXMLからuserIdを抽出してMDCに設定 019 * IStreamCommand xmlNavigate = new XmlNavigateCommand( 020 * TreePath.of("request", "userId"), 021 * new MdcSetupRule(context, "userId") 022 * ); 023 * 024 * // パイプライン実行 025 * StreamConverter.createWithContext(context, xmlNavigate, otherCommands...) 026 * .run(inputStream, outputStream); 027 * 028 * // 全てのコマンドのログに [userId:USER12345] が出力される 029 * }</pre> 030 * 031 * <p><b>スレッドセーフ性:</b> このルールはスレッドセーフです。複数のスレッドから同時に呼び出されても、 032 * ExecutionContextの共有コンテキスト(ConcurrentHashMap)により安全に動作します。 033 */ 034public class MdcSetupRule implements IRule { 035 036 private final ExecutionContext context; 037 private final String mdcKey; 038 039 /** 040 * MdcSetupRuleを作成します 041 * 042 * @param context ExecutionContextインスタンス 043 * @param mdcKey MDCキー名(共有コンテキストのキーとして使用される) 044 * @throws NullPointerException contextまたはmdcKeyがnullの場合 045 */ 046 public MdcSetupRule(ExecutionContext context, String mdcKey) { 047 this.context = Objects.requireNonNull(context, "context cannot be null"); 048 this.mdcKey = Objects.requireNonNull(mdcKey, "mdcKey cannot be null"); 049 } 050 051 /** 052 * 抽出された値を共有コンテキストに設定します 053 * 054 * <p>このメソッドは値を変更せずそのまま返しますが、副作用として ExecutionContextの共有コンテキストに値を設定します。 MDCへの同期はLogback 055 * TurboFilterが自動的に行うため、呼び出し側は同期を意識する必要がありません。 056 * 057 * @param extractedValue 抽出された値(nullの場合は共有コンテキストから削除) 058 * @return 入力値をそのまま返す 059 */ 060 @Override 061 public String apply(String extractedValue) { 062 context.setSharedContext(mdcKey, extractedValue); 063 return extractedValue; 064 } 065 066 /** 067 * このルールが使用するMDCキー名を取得します 068 * 069 * @return MDCキー名 070 */ 071 public String getMdcKey() { 072 return mdcKey; 073 } 074 075 @Override 076 public String toString() { 077 return String.format("MdcSetupRule{mdcKey='%s'}", mdcKey); 078 } 079}