/**
 * Copyright (c) 2007-2014 Kaazing Corporation. All rights reserved.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.kaazing.test.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.log4j.PropertyConfigurator;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

/**
 * This class can be used to print out a message at the start and end of each test method in a JUnit test class
 * by including the following at the start of the class:
    @Rule
    public MethodRule testExecutionTrace = new MethodExecutionTrace();
 */
public class MethodExecutionTrace extends TestWatcher {

    /**
     * Use this constructor to set up a particular log4j configuration using a properties file,
     * or null if you do not want to load any log4j configuration properties.
     * See gateway.server src/test/resources/log4j-trace.properties for an example.
     * @param log4jConfigPropertiesFileName
     */
    public MethodExecutionTrace(String log4jPropertiesResourceName) {
        MemoryAppender.initialize();
        if (log4jPropertiesResourceName != null) {
            // Initialize log4j using a properties file available on the class path
            Properties log4j = new Properties();
            InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(log4jPropertiesResourceName);
            if (in == null) {
                throw new RuntimeException(String.format("Could not load resource %s", log4jPropertiesResourceName));
            }
            try {
                log4j.load(in);
            } catch (IOException e) {
                throw new RuntimeException(String.format("Could not load resource %s", log4jPropertiesResourceName), e);
            }
            PropertyConfigurator.configure(log4j);
        }
    }

    /**
     * This constructor will configure log4j using the log4j-trace.properties file from the
     * test.util jar, which uses MemoryAppender so failed tests will print out the trace level log messages
     * to help diagnose the failure.
     */
    public MethodExecutionTrace() {
        this("log4j-trace.properties");
    }

    @Override
    public void starting(Description description) {
        System.out.println(description.getDisplayName() + " starting");
    }

    @Override
    public void failed(Throwable e, Description description) {
        if (e instanceof AssumptionViolatedException) {
            System.out.println(String.format("%s skipped programmatically with reason: %s",
                    getFullMethodName(description) , e.getMessage()));
        }
        else {
            System.out.println(getFullMethodName(description) + " FAILED with exception " + e);
            e.printStackTrace(System.out);
            System.out.println("=================== BEGIN STORED LOG MESSAGES ===========================");
            MemoryAppender.printAllMessages();
            System.out.println("=================== END STORED LOG MESSAGES ===========================");
        }
    }

    @Override
    public void succeeded(Description description) {
            System.out.println(getFullMethodName(description) + " " + "success");
    }

    private String getFullMethodName(Description description) {
        return description.getTestClass().getSimpleName() + "." + description.getMethodName();
    }
}

@@ -1340,17 +1340,24 @@
 e class:
-%0A
+%3Cpre%3E%0A *
     @Rul
@@ -1358,16 +1358,18 @@
   @Rule%0A
+ *
     publ
@@ -1437,65 +1437,822 @@
 ;%0A *
-/%0Apublic class MethodExecutionTrace extends TestWatcher %7B
+ %3C/pre%3E%0A * It can also be chained with other rules, for example:%3Cpre%3E%0A *    private MethodRule trace = new MethodExecutionTrace();%0A *    @Rule%0A *    public TestRule chain = outerRule(trace).around(robot).around(gateway);%0A * %3C/pre%3E%0A */%0Apublic class MethodExecutionTrace extends TestWatcher %7B%0A%0A    /**%0A     * This constructor will configure log4j using the log4j-trace.properties file from the%0A     * test.util jar, which uses MemoryAppender so failed tests will print out the trace level log messages%0A     * to help diagnose the failure.%0A     */%0A    public MethodExecutionTrace() %7B%0A        // TODO: consider using or exposing programmatic configuration instead,%0A        // see https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/BasicConfigurator.html instead%0A        this(%22log4j-trace.properties%22);%0A    %7D
 %0A%0A  
@@ -2355,16 +2355,43 @@
 file
-,
 %0A     *
+ available on the classpath,
  or 
@@ -2445,16 +2445,23 @@
 guration
+%0A     *
  propert
@@ -2467,92 +2467,8 @@
 ties
-.%0A     * See gateway.server src/test/resources/log4j-trace.properties for an example
 .%0A  
@@ -2484,22 +2484,16 @@
 am log4j
-Config
 Properti
@@ -2498,11 +2498,15 @@
 ties
-Fil
+Resourc
 eNam
@@ -2802,24 +2802,46 @@
 operties();%0A
+            try (%0A    
             
@@ -2952,18 +2952,37 @@
 rceName)
-;
 %0A
+            ) %7B%0A    
         
@@ -2995,32 +2995,36 @@
  (in == null) %7B%0A
+    
                 
@@ -3129,32 +3129,36 @@
 ));%0A            
+    
 %7D%0A            tr
@@ -3159,43 +3159,80 @@
     
-try %7B%0A                log4j.load(in
+    log4j.load(in);%0A                PropertyConfigurator.configure(log4j
 );%0A 
@@ -3415,396 +3415,9 @@
     
-    PropertyConfigurator.configure(log4j);%0A        %7D%0A    %7D%0A%0A    /**%0A     * This constructor will configure log4j using the log4j-trace.properties file from the%0A     * test.util jar, which uses MemoryAppender so failed tests will print out the trace level log messages%0A     * to help diagnose the failure.%0A     */%0A    public MethodExecutionTrace() %7B%0A        this(%22log4j-trace.properties%22);
+%7D
 %0A   

Apply code review feedback to MethodExecutionTrace in test.util.