/*
 * Copyright (c) 2011 NTT DATA Corporation
 */

package jp.terasoluna.batch.functionsample.b005;


import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 業務ロジックの実行直前・実行直後に ログを出力するためのインタセプタ。
 * 
 * <p>
 * ログ出力の実処理は、OperationLoggerが行う。
 * </p>
 * 
 * <p>
 * このインタセプタの適用先を変更する場合は、
 * bean要素"blogicLoggingAutoProxy"を編集すること。
 * </p>
 * 
 */
public class BLogicLoggingInterceptor extends LoggingInterceptor {
    /**
     * Log。
     */
    private static Log logger = LogFactory
            .getLog(BLogicLoggingInterceptor.class);

    /**
     * ログクラスを取得し、ログ出力の判定を行う。
     * 
     * @param invocation 本来呼び出されるメソッド
     * @return 本来呼び出されるメソッドの結果
     * @throws Throwable 例外
     */
    public Object invoke(MethodInvocation invocation) throws Throwable {
        OperationLogger operationLogger = getOperationLogger();

        // 開始ログの出力
        if (logger.isTraceEnabled()) {
            logger.trace("Start:" + getInvocationDescription(invocation));
        }

        // 操作ログ(開始)の出力
        if (operationLogger != null) {
            try {
                operationLogger.logStartBLogic(invocation.getThis().getClass(),
                        invocation.getMethod(), invocation.getArguments());
            } catch (Throwable logEx) {
                // 監査ログ書き出し失敗時に警告ログを出力する。
                logger.warn("Logging start BLogic failed.", logEx);
            }
        }

        try {
            // 本来呼び出されるメソッドを呼び出す
            Object rval = invocation.proceed();

            // 終了ログの出力
            if (logger.isTraceEnabled()) {
                logger.trace("End:" + getInvocationDescription(invocation));
            }

            // 操作ログ(終了)の出力
            if (operationLogger != null) {
                try {
                    operationLogger.logEndBLogic(invocation.getThis()
                            .getClass(), invocation.getMethod(), invocation
                            .getArguments(), rval);
                } catch (Throwable logEx) {
                    // 監査ログ書き出し失敗時に警告ログを出力する。
                    logger.warn("Logging end BLogic failed.", logEx);
                }
            }
            // 結果の返却
            return rval;

        } catch (Throwable ex) {
            // 例外が発生した際のログ出力
            if (logger.isTraceEnabled()) {
                logger.trace("Exception thrown in:"
                        + getInvocationDescription(invocation), ex);
            }

            // 操作ログ(例外)の出力
            if (operationLogger != null) {
                try {
                    operationLogger.logExceptionBLogic(invocation.getThis()
                            .getClass(), invocation.getMethod(), invocation
                            .getArguments(), ex);
                } catch (Throwable logEx) {
                    // 監査ログ書き出し失敗時に警告ログを出力する。
                    logger.warn("Logging exception BLogic failed.", logEx);
                }
            }
            throw ex;
        }
    }

}
