/*
 * Copyright 2010 Outerthought bvba
 *
 * Licensed 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.lilyproject.hadooptestfw;

import java.io.IOException;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;

public class TestHelper {
    private static Logger ROOT_LOGGER;

    private TestHelper() {
    }

    private static synchronized void init() {
        if (ROOT_LOGGER == null) {
            JavaLoggingToLog4jRedirector.activate();

            ROOT_LOGGER = Logger.getRootLogger();
            ROOT_LOGGER.removeAllAppenders();
            ROOT_LOGGER.setLevel(Level.INFO);
        }
    }

    public static void setupFileLogging() throws IOException {
        init();

        final String LAYOUT = "[%t] %-5p %c - %m%n";

        FileAppender appender = new FileAppender();
        appender.setLayout(new PatternLayout(LAYOUT));

        // Maven sets a property basedir, but if the testcases are run outside Maven (e.g. by an IDE),
        // then fall back to the working directory
        String targetDir = System.getProperty("basedir");
        if (targetDir == null) {
            targetDir = System.getProperty("user.dir");
        }
        String logFileName = targetDir + "/target/log.txt";

        System.out.println("Log output will go to " + logFileName);

        appender.setFile(logFileName, false, false, 0);

        appender.activateOptions();
        ROOT_LOGGER.addAppender(appender);
    }

    public static void setupConsoleLogging(String defaultLevel, final String... debugCategories) {
        init();

        final String CONSOLE_LAYOUT = "[%-5p][%d{ABSOLUTE}][%-10.10t] %c - %m%n";

        ConsoleAppender consoleAppender = new ConsoleAppender();
        consoleAppender.setLayout(new PatternLayout(CONSOLE_LAYOUT));

        final boolean debugLoggingEnabled = System.getProperty("lily.test.log") != null;

        final Level DEFAULT_LEVEL = Level.toLevel(defaultLevel);

        consoleAppender.addFilter(new Filter() {
            @Override
            public int decide(LoggingEvent loggingEvent) {
                if (debugLoggingEnabled) {
                    // This is slow, but it's only for when testcase debug output is enabled
                    for (String debugCat : debugCategories) {
                        if (loggingEvent.getLoggerName().startsWith(debugCat)) {
                            return loggingEvent.getLevel().isGreaterOrEqual(Level.DEBUG) ? Filter.ACCEPT : Filter.DENY;
                        }
                    }
                }

                return loggingEvent.getLevel().isGreaterOrEqual(DEFAULT_LEVEL) ? Filter.ACCEPT : Filter.DENY;
            }
        });

        consoleAppender.activateOptions();
        ROOT_LOGGER.addAppender(consoleAppender);


        for (String debugCat : debugCategories) {
            Logger.getLogger(debugCat).setLevel(Level.DEBUG);
        }
    }

    public static void setupOtherDefaults() {
        // Some categories which are too chatty on INFO level
        Logger.getLogger("org.apache.hadoop.hdfs.server.datanode.DataNode.clienttrace").setLevel(Level.WARN);
        Logger.getLogger("org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit").setLevel(Level.WARN);
        Logger.getLogger("org.apache.hadoop.hbase.master.BaseScanner").setLevel(Level.WARN);
    }

    /**
     * Sets up logging such that errors are logged to the console, and info level
     * logging is sent to a file in target directory.
     *
     * <p>Additionally a set of categories can be specified that will be logged
     * as debug output to the console when a system property -Dlily.test.log is present.
     */
    public static void setupLogging(final String... debugCategories) throws IOException {
        setupFileLogging();
        setupConsoleLogging("WARN", debugCategories);
        setupOtherDefaults();
    }
}

@@ -4551,11 +4551,217 @@
 );%0A    %7D
+%0A%0A    public static void setLogLevel(String level, String... categories) %7B%0A        for (String category : categories) %7B%0A            Logger.getLogger(category).setLevel(Level.toLevel(level));%0A        %7D%0A    %7D
 %0A%7D%0A

Add util method to set log levels