[maven-release-plugin]  copy for tag org.apache.sling.commons.log-4.0.0

git-svn-id: https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.commons.log-4.0.0@1572506 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..066727e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+Apache Sling Commons Log
+========================
+
+The "log" project packages the [Logback][2] library to manage logging
+in OSGi environment. It provide some useful extension to the default
+Logback feature set to enable better integration with OSGi. The SLF4j
+API bundle must be installed along with this bundle to provide full SLF4J
+logging support.
+  
+The Logging bundle should be installed as one of the first modules in
+the OSGi framework and - provided the framework supports start levels -
+be set to start at start level 1. This ensures the Logging bundle is
+loaded as early as possible thus providing services to the framework
+and preparing logging.
+
+For more details refer to the [Logging Documentation][1]
+
+Getting Started
+===============
+
+You can compile and package the jar using the following command:
+
+    mvn package -Pide,coverage
+
+It would build the module and also produce a test coverage report also
+prepare bundle jar which is suitable to be used to run integration test
+from within IDE.
+
+[1]: http://sling.apache.org/documentation/development/logging.html
+[2]: http://logback.qos.ch/
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 83e2632..0000000
--- a/README.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-Apache Sling SLF4J Implementation
-
-
-=======================================
-Welcome to Sling - SLF4J Implementation
-=======================================
-
-The "log" project implements the SLF4J SPI and thus operates as the backend
-for the SLF4J API. The SLF4j API bundle must be installed along with this
-bundle to provide full SLF4J logging support.
-  
-The Logging bundle should be installed as one of the first modules in
-the OSGi framework and - provided the framework supports start levels -
-be set to start at start level 1. This ensures the Logging bundle is
-loaded as early as possible thus providing services to the framework
-and preparing logging.
-
-See the Apache Sling web site (http://sling.apache.org) for
-documentation and other information. You are welcome to join the
-Sling mailing lists (http://sling.apache.org/site/project-information.html)
-to discuss this component and to use the Sling issue tracker
-(http://issues.apache.org/jira/browse/SLING) to report issues or request
-new features.
-
-Apache Sling is a project of the Apache Software Foundation
-(http://www.apache.org).
-
-License (see also LICENSE)
-==========================
-
-Collective work: Copyright 2007 The Apache Software Foundation.
-
-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.
-
-Getting Started
-===============
-
-This component uses a Maven 2 (http://maven.apache.org/) build
-environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/)
-2.0.7 or later. We recommend to use the latest Maven version.
-
-If you have Maven 2 installed, you can compile and
-package the jar using the following command:
-
-    mvn package
-
-See the Maven 2 documentation for other build features.
-
-The latest source code for this component is available in the
-Subversion (http://subversion.tigris.org/) source repository of
-the Apache Software Foundation. If you have Subversion installed,
-you can checkout the latest source using the following command:
-
-    svn checkout http://svn.apache.org/repos/asf/sling/trunk/commons/log
-
-See the Subversion documentation for other source control features.
diff --git a/pom.xml b/pom.xml
index 4dc9de7..36f8227 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
 
   <properties>
     <slf4j.version>1.6.4</slf4j.version>
-    <logback.version>1.0.13</logback.version>
+    <logback.version>1.1.0</logback.version>
     <sling.java.version>6</sling.java.version>
     <pax-exam.version>3.0.0</pax-exam.version>
 
@@ -104,12 +104,8 @@
             </Bundle-DocURL>
             <_exportcontents>
               org.slf4j.impl;version=${slf4j.version},
-              ch.qos.logback.core;
-              ch.qos.logback.core.filter;
-              ch.qos.logback.core.spi;
-              ch.qos.logback.classic;
-              ch.qos.logback.classic.turbo;
-              ch.qos.logback.classic.spi;version=${logback.version}
+              ch.qos.logback.classic*;
+              ch.qos.logback.core*;
             </_exportcontents>
             <Import-Package>
               !org.slf4j.impl,
@@ -161,7 +157,6 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
-        <version>1.8</version>
         <executions>
           <execution>
             <id>reserve-network-port</id>
@@ -218,7 +213,6 @@
       <!-- integration tests run with pax-exam -->
       <plugin>
         <artifactId>maven-failsafe-plugin</artifactId>
-        <version>2.12</version>
         <executions>
           <execution>
             <goals>
diff --git a/src/main/appended-resources/META-INF/NOTICE b/src/main/appended-resources/META-INF/NOTICE
index a899950..2fed022 100644
--- a/src/main/appended-resources/META-INF/NOTICE
+++ b/src/main/appended-resources/META-INF/NOTICE
@@ -7,3 +7,6 @@
 
 This product includes software from http://www.slf4j.org/
 Licensed under the MIT License
+
+This product includes software from https://github.com/dyve/jquery-autocomplete
+Licensed under the Apache License 2.0.
diff --git a/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java b/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java
deleted file mode 100644
index 83298a5..0000000
--- a/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/**
- * Logback: the reliable, generic, fast and flexible logging framework.
- * Copyright (C) 1999-2013, QOS.ch. All rights reserved.
- *
- * This program and the accompanying materials are dual-licensed under
- * either the terms of the Eclipse Public License v1.0 as published by
- * the Eclipse Foundation
- *
- *   or (per the licensee's choosing)
- *
- * under the terms of the GNU Lesser General Public License version 2.1
- * as published by the Free Software Foundation.
- */
-package ch.qos.logback.classic.spi;
-
-import java.net.URL;
-import java.security.CodeSource;
-import java.util.HashMap;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.Version;
-import sun.reflect.Reflection;
-// import java.security.AccessControlException; import java.security.AccessController;import java.security.PrivilegedAction;
-/**
- * Given a classname locate associated PackageInfo (jar name, version name).
- *
- * @author James Strachan
- * @Ceki G&uuml;lc&uuml;
- */
-public class PackagingDataCalculator {
-
-  final static StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0];
-
-  HashMap<String, ClassPackagingData> cache = new HashMap<String, ClassPackagingData>();
-
-  private static boolean GET_CALLER_CLASS_METHOD_AVAILABLE = false; //private static boolean HAS_GET_CLASS_LOADER_PERMISSION = false;
-
-  static {
-    // if either the Reflection class or the getCallerClass method
-    // are unavailable, then we won't invoke Reflection.getCallerClass()
-    // This approach ensures that this class will *run* on JDK's lacking
-    // sun.reflect.Reflection class. However, this class will *not compile*
-    // on JDKs lacking sun.reflect.Reflection.
-    try {
-      Reflection.getCallerClass(2);
-      GET_CALLER_CLASS_METHOD_AVAILABLE = true;
-    } catch (NoClassDefFoundError e) {
-    } catch (NoSuchMethodError e) {
-    } catch (Throwable e) {
-      System.err.println("Unexpected exception");
-      e.printStackTrace();
-    }
-  }
-
-
-  public void calculate(IThrowableProxy tp) {
-    while (tp != null) {
-      populateFrames(tp.getStackTraceElementProxyArray());
-      IThrowableProxy[] suppressed = tp.getSuppressed();
-      if(suppressed != null) {
-        for(IThrowableProxy current:suppressed) {
-          populateFrames(current.getStackTraceElementProxyArray());
-        }
-      }
-      tp = tp.getCause();
-    }
-  }
-
-  void populateFrames(StackTraceElementProxy[] stepArray) {
-    // in the initial part of this method we populate package information for
-    // common stack frames
-    final Throwable t = new Throwable("local stack reference");
-    final StackTraceElement[] localteSTEArray = t.getStackTrace();
-    final int commonFrames = STEUtil.findNumberOfCommonFrames(localteSTEArray,
-            stepArray);
-    final int localFirstCommon = localteSTEArray.length - commonFrames;
-    final int stepFirstCommon = stepArray.length - commonFrames;
-
-    ClassLoader lastExactClassLoader = null;
-    ClassLoader firsExactClassLoader = null;
-
-    int missfireCount = 0;
-    for (int i = 0; i < commonFrames; i++) {
-      Class callerClass = null;
-      if (GET_CALLER_CLASS_METHOD_AVAILABLE) {
-        callerClass = Reflection.getCallerClass(localFirstCommon + i
-                - missfireCount + 1);
-      }
-      StackTraceElementProxy step = stepArray[stepFirstCommon + i];
-      String stepClassname = step.ste.getClassName();
-
-      if (callerClass != null && stepClassname.equals(callerClass.getName())) {
-        // see also LBCLASSIC-263
-        lastExactClassLoader = callerClass.getClassLoader();
-        if (firsExactClassLoader == null) {
-          firsExactClassLoader = lastExactClassLoader;
-        }
-        ClassPackagingData pi = calculateByExactType(callerClass);
-        step.setClassPackagingData(pi);
-      } else {
-        missfireCount++;
-        ClassPackagingData pi = computeBySTEP(step, lastExactClassLoader);
-        step.setClassPackagingData(pi);
-      }
-    }
-    populateUncommonFrames(commonFrames, stepArray, firsExactClassLoader);
-  }
-
-  void populateUncommonFrames(int commonFrames,
-                              StackTraceElementProxy[] stepArray, ClassLoader firstExactClassLoader) {
-    int uncommonFrames = stepArray.length - commonFrames;
-    for (int i = 0; i < uncommonFrames; i++) {
-      StackTraceElementProxy step = stepArray[i];
-      ClassPackagingData pi = computeBySTEP(step, firstExactClassLoader);
-      step.setClassPackagingData(pi);
-    }
-  }
-
-  private ClassPackagingData calculateByExactType(Class type) {
-    String className = type.getName();
-    ClassPackagingData cpd = cache.get(className);
-    if (cpd != null) {
-      return cpd;
-    }
-    String version = getImplementationVersion(type);
-    String codeLocation = getCodeLocation(type);
-    cpd = new ClassPackagingData(codeLocation, version);
-    cache.put(className, cpd);
-    return cpd;
-  }
-
-  private ClassPackagingData computeBySTEP(StackTraceElementProxy step,
-                                           ClassLoader lastExactClassLoader) {
-    String className = step.ste.getClassName();
-    ClassPackagingData cpd = cache.get(className);
-    if (cpd != null) {
-      return cpd;
-    }
-    Class type = bestEffortLoadClass(lastExactClassLoader, className);
-    String version = getImplementationVersion(type);
-    String codeLocation = getCodeLocation(type);
-    cpd = new ClassPackagingData(codeLocation, version, false);
-    cache.put(className, cpd);
-    return cpd;
-  }
-
-  String getImplementationVersion(Class type) {
-    if (type == null) {
-      return "na";
-    }
-
-    Bundle b = FrameworkUtil.getBundle(type);
-    if(b != null){
-      final Version version = b.getVersion();
-      return version == org.osgi.framework.Version.emptyVersion ? "na" : version.toString();
-    }
-
-    Package aPackage = type.getPackage();
-    if (aPackage != null) {
-      String v = aPackage.getImplementationVersion();
-      if (v == null) {
-        return "na";
-      } else {
-        return v;
-      }
-    }
-    return "na";
-
-  }
-
-  String getCodeLocation(Class type) {
-    try {
-      if (type != null) {
-
-        Bundle b = FrameworkUtil.getBundle(type);
-        if(b != null){
-            return b.getSymbolicName();
-        }
-        // file:/C:/java/maven-2.0.8/repo/com/icegreen/greenmail/1.3/greenmail-1.3.jar
-        CodeSource codeSource = type.getProtectionDomain().getCodeSource();
-        if (codeSource != null) {
-          URL resource = codeSource.getLocation();
-          if (resource != null) {
-            String locationStr = resource.toString();
-            // now lets remove all but the file name
-            String result = getCodeLocation(locationStr, '/');
-            if (result != null) {
-              return result;
-            }
-            return getCodeLocation(locationStr, '\\');
-          }
-        }
-      }
-    } catch (Exception e) {
-      // ignore
-    }
-    return "na";
-  }
-
-  private String getCodeLocation(String locationStr, char separator) {
-    int idx = locationStr.lastIndexOf(separator);
-    if (isFolder(idx, locationStr)) {
-      idx = locationStr.lastIndexOf(separator, idx - 1);
-      return locationStr.substring(idx + 1);
-    } else if (idx > 0) {
-      return locationStr.substring(idx + 1);
-    }
-    return null;
-  }
-
-  private boolean isFolder(int idx, String text) {
-    return (idx != -1 && idx + 1 == text.length());
-  }
-
-  private Class loadClass(ClassLoader cl, String className) {
-    if (cl == null) {
-      return null;
-    }
-    try {
-      return cl.loadClass(className);
-    } catch (ClassNotFoundException e1) {
-      return null;
-    } catch (NoClassDefFoundError e1) {
-      return null;
-    } catch (Exception e) {
-      e.printStackTrace(); // this is unexpected
-      return null;
-    }
-
-  }
-
-  /**
-   * @param lastGuaranteedClassLoader may be null
-   * @param className
-   * @return
-   */
-  private Class bestEffortLoadClass(ClassLoader lastGuaranteedClassLoader,
-                                    String className) {
-    Class result = loadClass(lastGuaranteedClassLoader, className);
-    if (result != null) {
-      return result;
-    }
-    ClassLoader tccl = Thread.currentThread().getContextClassLoader();
-    if (tccl != lastGuaranteedClassLoader) {
-      result = loadClass(tccl, className);
-    }
-    if (result != null) {
-      return result;
-    }
-
-    try {
-      return Class.forName(className);
-    } catch (ClassNotFoundException e1) {
-      return null;
-    } catch (NoClassDefFoundError e1) {
-      return null;
-    } catch (Exception e) {
-      e.printStackTrace(); // this is unexpected
-      return null;
-    }
-  }
-
-}
diff --git a/src/main/java/ch/qos/logback/classic/util/LoggerNameUtil.java b/src/main/java/ch/qos/logback/classic/util/LoggerNameUtil.java
deleted file mode 100644
index ec0797e..0000000
--- a/src/main/java/ch/qos/logback/classic/util/LoggerNameUtil.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
-* Logback: the reliable, generic, fast and flexible logging framework.
-* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
-*
-* This program and the accompanying materials are dual-licensed under
-* either the terms of the Eclipse Public License v1.0 as published by
-* the Eclipse Foundation
-*
-* or (per the licensee's choosing)
-*
-* under the terms of the GNU Lesser General Public License version 2.1
-* as published by the Free Software Foundation.
-*/
-package ch.qos.logback.classic.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import ch.qos.logback.core.CoreConstants;
-
-/**
- * Utility class for analysing logger names.
- * Locally overriding the class for SLING-3037
- */
-public class LoggerNameUtil {
-
-
-  public static int getFirstSeparatorIndexOf(String name) {
-    return getSeparatorIndexOf(name, 0);
-  }
-
-  /**
-   * Get the position of the separator character, if any, starting at position
-   * 'fromIndex'.
-   *
-   * @param name
-   * @param fromIndex
-   * @return
-   */
-  public static int getSeparatorIndexOf(String name, int fromIndex) {
-      int dotIndex = name.indexOf(CoreConstants.DOT, fromIndex);
-      int dollarIndex = name.indexOf(CoreConstants.DOLLAR, fromIndex);
-      if (dotIndex == -1 && dollarIndex == -1) return -1;
-      if (dotIndex == -1) return dollarIndex;
-      if (dollarIndex == -1) return dotIndex;
-      return dotIndex < dollarIndex ? dotIndex : dollarIndex;
-  }
-
-  public static List<String> computeNameParts(String loggerName) {
-    List<String> partList = new ArrayList<String>();
-
-    int fromIndex = 0;
-    while(true) {
-      int index = getSeparatorIndexOf(loggerName, fromIndex);
-      if(index == -1) {
-       partList.add(loggerName.substring(fromIndex));
-       break;
-      }
-      partList.add(loggerName.substring(fromIndex, index));
-      fromIndex = index+1;
-    }
-    return partList;
-  }
-}
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/Activator.java b/src/main/java/org/apache/sling/commons/log/logback/internal/Activator.java
index ad0ba6b..ebaff94 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/Activator.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/Activator.java
@@ -23,26 +23,22 @@
 import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.core.status.ErrorStatus;
+import ch.qos.logback.core.util.StatusPrinter;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.slf4j.bridge.SLF4JBridgeHandler;
-
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.core.status.ErrorStatus;
-import ch.qos.logback.core.util.StatusPrinter;
 
 public class Activator implements BundleActivator {
-    private static final String JUL_SUPPORT = "org.apache.sling.commons.log.julenabled";
 
     private LogbackManager logManager;
 
     private BundleContext context;
 
     private Timer timer;
-    private boolean bridgeHandlerInstalled;
     private long startTime;
     private static final AtomicInteger counter = new AtomicInteger();
     public static final long INIT_TASK_PERIOD_MSEC = 1;
@@ -64,10 +60,6 @@
     }
 
     public void stop(BundleContext context) throws Exception {
-        if(bridgeHandlerInstalled){
-            SLF4JBridgeHandler.uninstall();
-        }
-
         if(timer != null){
             timer.cancel();
             timer = null;
@@ -80,30 +72,6 @@
     }
 
     private void initializeLogbackManager(boolean immediateInit) throws InvalidSyntaxException {
-        // SLING-2373
-        if (Boolean.parseBoolean(context.getProperty(JUL_SUPPORT))) {
-            // In config one must enable the LevelChangePropagator
-            // http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
-            // make sure configuration is empty unless explicitly set
-            if (System.getProperty("java.util.logging.config.file") == null
-                    && System.getProperty("java.util.logging.config.class") == null) {
-                final Thread ct = Thread.currentThread();
-                final ClassLoader old = ct.getContextClassLoader();
-                try {
-                    ct.setContextClassLoader(getClass().getClassLoader());
-                    System.setProperty("java.util.logging.config.class",
-                            "org.apache.sling.commons.log.internal.Activator.DummyLogManagerConfiguration");
-                    java.util.logging.LogManager.getLogManager().reset();
-                } finally {
-                    ct.setContextClassLoader(old);
-                    System.clearProperty("java.util.logging.config.class");
-                }
-            }
-
-            SLF4JBridgeHandler.install();
-            bridgeHandlerInstalled = true;
-        }
-
         logManager = new LogbackManager(context);
         
         final Logger log = LoggerFactory.getLogger(getClass());
@@ -139,14 +107,4 @@
     private static boolean isSlf4jInitialized(){
         return LoggerFactory.getILoggerFactory() instanceof LoggerContext;
     }
-
-
-    /**
-     * The <code>DummyLogManagerConfiguration</code> class is used as JUL
-     * LogginManager configurator to preven reading platform default
-     * configuration which just duplicate log output to be redirected to SLF4J.
-     */
-    @SuppressWarnings("UnusedDeclaration")
-    public static class DummyLogManagerConfiguration {
-    }
 }
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfig.java b/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfig.java
index 3dba508..37bd4c8 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfig.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfig.java
@@ -19,6 +19,7 @@
 package org.apache.sling.commons.log.logback.internal;
 
 import java.text.MessageFormat;
+import java.util.Collections;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -53,7 +54,7 @@
         this.logWriterProvider = logWriterProvider;
         this.configPid = configPid;
         this.pattern = pattern;
-        this.categories = categories;
+        this.categories = Collections.unmodifiableSet(categories);
         this.logLevel = logLevel;
         this.logWriterName = logWriterName;
         this.loggerContext = loggerContext;
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfigManager.java b/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfigManager.java
index b1c1afd..1d4accd 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfigManager.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/LogConfigManager.java
@@ -29,14 +29,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.sling.commons.log.logback.internal.config.ConfigAdminSupport;
-import org.apache.sling.commons.log.logback.internal.config.ConfigurationException;
-import org.apache.sling.commons.log.logback.internal.util.LoggerSpecificEncoder;
-import org.apache.sling.commons.log.logback.internal.util.Util;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import ch.qos.logback.classic.ClassicConstants;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
@@ -47,6 +40,13 @@
 import ch.qos.logback.core.OutputStreamAppender;
 import ch.qos.logback.core.joran.action.ActionConst;
 import ch.qos.logback.core.util.ContextUtil;
+import org.apache.sling.commons.log.logback.internal.config.ConfigAdminSupport;
+import org.apache.sling.commons.log.logback.internal.config.ConfigurationException;
+import org.apache.sling.commons.log.logback.internal.util.LoggerSpecificEncoder;
+import org.apache.sling.commons.log.logback.internal.util.Util;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class LogConfigManager implements LogbackResetListener, LogConfig.LogWriterProvider {
 
@@ -60,6 +60,8 @@
 
     public static final String LOG_FILE_SIZE = "org.apache.sling.commons.log.file.size";
 
+    public static final String LOG_FILE_BUFFERED = "org.apache.sling.commons.log.file.buffered";
+
     public static final String LOG_PATTERN = "org.apache.sling.commons.log.pattern";
 
     public static final String LOG_PATTERN_DEFAULT = "%d{dd.MM.yyyy HH:mm:ss.SSS} *%level* [%thread] %logger %msg%n";
@@ -68,6 +70,10 @@
 
     public static final String LOG_ADDITIV = "org.apache.sling.commons.log.additiv";
 
+    public static final String LOG_PACKAGING_DATA = "org.apache.sling.commons.log.packagingDataEnabled";
+
+    public static final String LOG_MAX_CLALLER_DEPTH = "org.apache.sling.commons.log.maxCallerDataDepth";
+
     public static final String LOG_LEVEL_DEFAULT = "INFO";
 
     public static final int LOG_FILE_NUMBER_DEFAULT = 5;
@@ -80,7 +86,7 @@
 
     public static final String FACTORY_PID_CONFIGS = PID + ".factory.config";
 
-    private static final String DEFAULT_CONSOLE_APPENDER_NAME = "org.apache.sling.commons.log.CONSOLE";
+    public static final String DEFAULT_CONSOLE_APPENDER_NAME = "org.apache.sling.commons.log.CONSOLE";
 
     private final LoggerContext loggerContext;
 
@@ -118,6 +124,10 @@
 
     private File logbackConfigFile;
 
+    private boolean packagingDataEnabled;
+
+    private int maxCallerDataDepth;
+
     /**
      * Logs a message an optional stack trace to error output. This method is
      * used by the logging system in case of errors writing to the correct
@@ -204,6 +214,14 @@
         return logbackConfigFile;
     }
 
+    public Iterable<LogConfig> getLogConfigs() {
+        return configByPid.values();
+    }
+
+    public Iterable<LogWriter> getLogWriters(){
+        return writerByFileName.values();
+    }
+
     public Appender<ILoggingEvent> getDefaultAppender() {
         OutputStreamAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
         appender.setName(DEFAULT_CONSOLE_APPENDER_NAME);
@@ -279,13 +297,11 @@
                 if (appender != null) {
                     logger.setAdditive(config.isAdditive());
                     logger.addAppender(appender);
+                    contextUtil.addInfo("Registering appender "+appender.getName()+ "("+appender.getClass()+
+                            ") with logger "+logger.getName());
                 }
             }
         }
-
-        // Remove the default console appender that we attached at start of
-        // reset
-        context.getLogger(Logger.ROOT_LOGGER_NAME).detachAppender(DEFAULT_CONSOLE_APPENDER_NAME);
     }
 
 
@@ -404,7 +420,10 @@
                 fileSize = fileSizeProp.toString();
             }
 
-            LogWriter newWriter = new LogWriter(pid, getAppnderName(logFileName), fileNum, fileSize, logFileName);
+            boolean bufferedLogging = Util.toBoolean(configuration.get(LogConfigManager.LOG_FILE_BUFFERED), false);
+
+            LogWriter newWriter = new LogWriter(pid, getAppnderName(logFileName), fileNum,
+                    fileSize, logFileName, bufferedLogging);
             if (oldWriter != null) {
                 writerByFileName.remove(oldWriter.getFileName());
             }
@@ -551,13 +570,22 @@
         }
     }
 
+    public boolean isPackagingDataEnabled() {
+        return packagingDataEnabled;
+    }
+
+    public int getMaxCallerDataDepth() {
+        return maxCallerDataDepth;
+    }
+
     // ---------- ManagedService interface -------------------------------------
 
     private Dictionary<String, String> getBundleConfiguration(BundleContext bundleContext) {
         Dictionary<String, String> config = new Hashtable<String, String>();
 
         final String[] props = {
-            LOG_LEVEL, LOG_FILE, LOG_FILE_NUMBER, LOG_FILE_SIZE, LOG_PATTERN, LOGBACK_FILE
+            LOG_LEVEL, LOG_FILE, LOG_FILE_NUMBER, LOG_FILE_SIZE, LOG_PATTERN, LOGBACK_FILE,
+            LOG_PACKAGING_DATA
         };
         for (String prop : props) {
             String value = bundleContext.getProperty(prop);
@@ -576,12 +604,14 @@
 
     private void processGlobalConfig(Dictionary<String, String> configuration) {
         String fileName = configuration.get(LOGBACK_FILE);
-        if (fileName != null) {
+        if (fileName != null && !fileName.isEmpty()) {
             File file = new File(getAbsoluteFilePath(fileName));
             final String path = file.getAbsolutePath();
             if (!file.exists()) {
-                log.warn("Logback configuration file [{}]does not exist.", path);
-            } else if (!file.canRead()) {
+                log.warn("Logback configuration file [{}] does not exist.", path);
+            } if (!file.isFile()) {
+                log.warn("Logback configuration file [{}] is not a file.", path);
+            }else if (!file.canRead()) {
                 log.warn("Logback configuration [{}]file cannot be read", path);
             } else {
                 synchronized (configLock) {
@@ -589,6 +619,18 @@
                 }
             }
         }
+
+        //Process packaging data
+        Object packagingData = configuration.get(LOG_PACKAGING_DATA);
+        if (packagingData != null) {
+            packagingDataEnabled = Boolean.valueOf(packagingData.toString());
+        } else {
+            //Defaults to false i.e. disabled in OSGi env
+            packagingDataEnabled = false;
+        }
+
+        maxCallerDataDepth = Util.toInteger(configuration.get(LOG_MAX_CLALLER_DEPTH),
+                ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH);
     }
 
     // ---------- Internal helpers ---------------------------------------------
@@ -601,7 +643,7 @@
         return new LogWriter(getAppnderName(logWriterName),logWriterName, defaultWriter.getLogNumber(), defaultWriter.getLogRotation());
     }
 
-    private LogWriter getDefaultWriter() {
+    public LogWriter getDefaultWriter() {
         return writerByPid.get(LogConfigManager.PID);
     }
 
@@ -613,9 +655,7 @@
         return getDefaultConfig().createLayout();
     }
 
-    private Iterable<LogConfig> getLogConfigs() {
-        return configByPid.values();
-    }
+
 
     /**
      * Returns the <code>logFileName</code> argument converted into an absolute
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/LogWriter.java b/src/main/java/org/apache/sling/commons/log/logback/internal/LogWriter.java
index b800bf9..e4e4b63 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/LogWriter.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/LogWriter.java
@@ -27,10 +27,11 @@
 import ch.qos.logback.core.Context;
 import ch.qos.logback.core.OutputStreamAppender;
 import ch.qos.logback.core.encoder.Encoder;
+import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
 import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
 import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
 import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
-
+import org.apache.sling.commons.log.logback.internal.util.SlingContextUtil;
 import org.apache.sling.commons.log.logback.internal.util.SlingRollingFileAppender;
 
 /**
@@ -72,7 +73,9 @@
 
     private final String appenderName;
 
-    public LogWriter(String configurationPID, String appenderName, int logNumber, String logRotation, String fileName) {
+    private final boolean bufferedLogging;
+
+    public LogWriter(String configurationPID, String appenderName, int logNumber, String logRotation, String fileName, boolean bufferedLogging) {
         this.appenderName = appenderName;
         if (fileName == null || fileName.length() == 0) {
             fileName = FILE_NAME_CONSOLE;
@@ -90,16 +93,21 @@
         this.fileName = fileName;
         this.logNumber = logNumber;
         this.logRotation = logRotation;
+        this.bufferedLogging = bufferedLogging;
     }
 
     public LogWriter(String appenderName,String fileName, int logNumber, String logRotation) {
-        this(null, appenderName, logNumber, logRotation, fileName);
+        this(null, appenderName, logNumber, logRotation, fileName, false);
     }
 
     public String getConfigurationPID() {
         return configurationPID;
     }
 
+    public String getImplicitConfigPID(){
+        return LogConfigManager.PID;
+    }
+
     public String getFileName() {
         return fileName;
     }
@@ -121,12 +129,14 @@
     }
 
     public Appender<ILoggingEvent> createAppender(final Context context, final Encoder<ILoggingEvent> encoder) {
-
+        SlingContextUtil ctxUtil = new SlingContextUtil(context, this);
         OutputStreamAppender<ILoggingEvent> appender;
         if (FILE_NAME_CONSOLE.equals(fileName)) {
             appender = new ConsoleAppender<ILoggingEvent>();
             appender.setName(FILE_NAME_CONSOLE);
         } else {
+            ctxUtil.addInfo("Configuring appender "+getFileName());
+
             SlingRollingFileAppender<ILoggingEvent> rollingAppender = new SlingRollingFileAppender<ILoggingEvent>();
             rollingAppender.setAppend(true);
             rollingAppender.setFile(getFileName());
@@ -183,12 +193,15 @@
                 rollingAppender.setRollingPolicy(pol);
             } else {
                 TimeBasedRollingPolicy<ILoggingEvent> policy = new TimeBasedRollingPolicy<ILoggingEvent>();
-                policy.setFileNamePattern(createFileNamePattern(getFileName(), getLogRotation()));
+                String fileNamePattern = createFileNamePattern(getFileName(), getLogRotation());
+                policy.setFileNamePattern(fileNamePattern);
                 policy.setMaxHistory(getLogNumber());
                 policy.setContext(context);
                 policy.setParent(rollingAppender);
                 policy.start();
                 rollingAppender.setTriggeringPolicy(policy);
+
+                ctxUtil.addInfo("Configured TimeBasedRollingPolicy with pattern "+ fileNamePattern);
             }
 
             rollingAppender.setLogWriter(this);
@@ -197,9 +210,19 @@
             appender = rollingAppender;
         }
 
+        if(bufferedLogging && encoder instanceof LayoutWrappingEncoder){
+            ((LayoutWrappingEncoder) encoder).setImmediateFlush(false);
+            ctxUtil.addInfo("Setting immediateFlush to false");
+        } else{
+            ctxUtil.addInfo("immediateFlush property not modified. Defaults to true");
+        }
+
         appender.setContext(context);
         appender.setEncoder(encoder);
         appender.start();
+
+        ctxUtil.addInfo("Completed configuring appender with name "+getFileName());
+
         return appender;
     }
 
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java b/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java
index 2e85234..7af2c94 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java
@@ -13,13 +13,13 @@
 import java.util.Properties;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.gaffer.GafferUtil;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.jul.LevelChangePropagator;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.classic.spi.LoggerContextAwareBase;
 import ch.qos.logback.classic.spi.LoggerContextListener;
@@ -34,8 +34,9 @@
 import ch.qos.logback.core.status.StatusListener;
 import ch.qos.logback.core.status.StatusListenerAsList;
 import ch.qos.logback.core.status.StatusUtil;
-import ch.qos.logback.core.util.StatusPrinter;
 import org.apache.sling.commons.log.logback.internal.AppenderTracker.AppenderInfo;
+import org.apache.sling.commons.log.logback.internal.util.SlingRollingFileAppender;
+import org.apache.sling.commons.log.logback.internal.util.SlingStatusPrinter;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -45,18 +46,36 @@
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.LoggerFactory;
+import org.slf4j.bridge.SLF4JBridgeHandler;
 
 public class LogbackManager extends LoggerContextAwareBase {
+    private static final String JUL_SUPPORT = "org.apache.sling.commons.log.julenabled";
+
+    //These properties should have been defined in SlingLogPanel
+    //But we need them while registering ServiceFactory and hence
+    //would not want to load SlingLogPanel class for registration
+    //purpose as we need to run in cases where Servlet classes
+    //are not available
+    static final String APP_ROOT = "slinglog";
+
+    static final String RES_LOC = APP_ROOT + "/res/ui";
+
+    public static final String[] CSS_REFS = {
+            RES_LOC + "/jquery.autocomplete.css",
+            RES_LOC + "/prettify.css",
+            RES_LOC + "/log.css",
+    };
+
     private static final String PREFIX = "org.apache.sling.commons.log";
 
     private static final String DEBUG = PREFIX + "." + "debug";
 
-    private static final String PLUGIN_URL = "slinglog";
-
     private static final String PRINTER_URL = "slinglogs";
 
     private static final String RESET_EVENT_TOPIC = "org/apache/sling/commons/log/RESET";
 
+    private final BundleContext bundleContext;
+
     private final String rootDir;
 
     private final String contextName = "sling";
@@ -78,7 +97,9 @@
 
     private final Semaphore resetLock = new Semaphore(1);
 
-    private final AtomicBoolean configChanged = new AtomicBoolean();
+    private final Object configChangedFlagLock = new Object();
+
+    private boolean configChanged = false;
 
     private final AppenderTracker appenderTracker;
 
@@ -89,8 +110,11 @@
     private final TurboFilterTracker turboFilterTracker;
 
     private final List<ServiceRegistration> registrations = new ArrayList<ServiceRegistration>();
+
     private final List<ServiceTracker> serviceTrackers = new ArrayList<ServiceTracker>();
 
+    private final boolean bridgeHandlerInstalled;
+
     /**
      * Time at which reset started. Used as the threshold for logging error
      * messages from status printer
@@ -98,27 +122,30 @@
     private volatile long resetStartTime;
 
     public LogbackManager(BundleContext bundleContext) throws InvalidSyntaxException {
-        final long startTime = System.currentTimeMillis();
+        this.bundleContext = bundleContext;
+
         setLoggerContext((LoggerContext) LoggerFactory.getILoggerFactory());
+
         this.log = LoggerFactory.getLogger(getClass());
         this.rootDir = getRootDir(bundleContext);
-
         this.debug = Boolean.parseBoolean(bundleContext.getProperty(DEBUG));
+        this.bridgeHandlerInstalled = installSlf4jBridgeHandler(bundleContext);
 
         this.appenderTracker = new AppenderTracker(bundleContext, getLoggerContext());
         this.configSourceTracker = new ConfigSourceTracker(bundleContext, this);
         this.filterTracker = new FilterTracker(bundleContext,this);
         this.turboFilterTracker = new TurboFilterTracker(bundleContext,getLoggerContext());
-        // TODO Make it configurable
-        // TODO: what should it be ?
+
         getLoggerContext().setName(contextName);
         this.logConfigManager = new LogConfigManager(getLoggerContext(), bundleContext, rootDir, this);
 
+        resetListeners.add(new LevelChangePropagatorChecker());
         resetListeners.add(logConfigManager);
         resetListeners.add(appenderTracker);
         resetListeners.add(configSourceTracker);
         resetListeners.add(filterTracker);
         resetListeners.add(turboFilterTracker);
+        resetListeners.add(new RootLoggerListener()); //Should be invoked at last
 
         //Record trackers for shutdown later
         serviceTrackers.add(appenderTracker);
@@ -127,15 +154,18 @@
         serviceTrackers.add(turboFilterTracker);
 
         getLoggerContext().addListener(osgiIntegrationListener);
+        registerWebConsoleSupport();
+        registerEventHandler();
 
-        configure();
-        registerWebConsoleSupport(bundleContext);
-        registerEventHandler(bundleContext);
-        StatusPrinter.printInCaseOfErrorsOrWarnings(getLoggerContext(), startTime);
         started = true;
+        configChanged();
     }
 
     public void shutdown() {
+        if(bridgeHandlerInstalled){
+            SLF4JBridgeHandler.uninstall();
+        }
+
         logConfigManager.close();
 
         for(ServiceTracker tracker : serviceTrackers){
@@ -151,21 +181,90 @@
         getLoggerContext().stop();
     }
 
+    //-------------------------------------- Config reset handling ----------
+
     public void configChanged() {
         if (!started) {
             return;
         }
 
-        if (resetLock.tryAcquire()) {
-            scheduleConfigReload();
-        } else {
-            configChanged.set(true);
-            addInfo("LoggerContext reset in progress. Marking config changed to true");
+        /*
+        Logback reset cannot be done concurrently. So when Logback is being reset
+        we note down any new request for reset. Later when the thread which performs
+        reset finishes, then it checks if any request for reset pending. if yes
+        then it again tries to reschedules a job to perform reset in rescheduleIfConfigChanged
+
+        Logback reset is done under a lock 'resetLock' so that Logback
+        is not reconfigured concurrently. Only the thread which acquires the
+        'resetLock' can submit the task for reload (actual reload done async)
+
+        Once the reload is done the lock is released in LoggerReconfigurer#run
+
+        The way locking works is any thread which changes config
+        invokes configChanged. Here two things are possible
+
+        1. Log reset in progress i.e. resetLock already acquired
+           In this case the thread would just set the 'configChanged' flag to true
+
+        2. No reset in progress. Thread would acquire the  resetLock and submit the
+          job to reset Logback
+
+
+        Any such change is synchronized with configChangedFlagLock such that a request
+         for config changed is not missed
+        */
+
+        synchronized (configChangedFlagLock){
+            if (resetLock.tryAcquire()) {
+                configChanged = false;
+                scheduleConfigReload();
+            } else {
+                configChanged = true;
+                addInfo("LoggerContext reset in progress. Marking config changed to true");
+            }
         }
     }
 
+    private void rescheduleIfConfigChanged(){
+        synchronized (configChangedFlagLock){
+            //If config changed then only acquire a lock
+            //and proceed to reload
+            if(configChanged){
+                if(resetLock.tryAcquire()){
+                    configChanged = false;
+                    scheduleConfigReload();
+                }
+                //else some other thread acquired the resetlock
+                //and reset is in progress. That job would
+                //eventually call rescheduleIfConfigChanged again
+                //and configChanged request would be taken care of
+            }
+        }
+    }
+
+    private void scheduleConfigReload() {
+        getLoggerContext().getExecutorService().submit(new Runnable() {
+            @Override
+            public void run() {
+                // TODO Might be better to run a job to monitor refreshRequirement
+                try {
+                    addInfo("Performing configuration");
+                    configure();
+                } catch (Exception e) {
+                    log.warn("Error occurred while re-configuring logger", e);
+                    addError("Error occurred while re-configuring logger", e);
+                } finally {
+                    resetLock.release();
+                    addInfo("Re configuration done");
+                    rescheduleIfConfigChanged();
+                }
+            }
+        });
+    }
+
     public void fireResetCompleteListeners(){
         for(LogbackResetListener listener : resetListeners){
+            addInfo("Firing reset listener - onResetComplete "+listener.getClass());
             listener.onResetComplete(getLoggerContext());
         }
     }
@@ -190,6 +289,10 @@
         return getClass().getClassLoader().getResource("logback-empty.xml");
     }
 
+    public String getRootDir() {
+        return rootDir;
+    }
+
     private void configure() {
         ConfiguratorCallback cb = new DefaultCallback();
 
@@ -203,6 +306,7 @@
     }
 
     private void configure(ConfiguratorCallback cb) {
+        long startTime = System.currentTimeMillis();
         StatusListener statusListener = new StatusListenerAsList();
         if (debug) {
             statusListener = new OnConsoleStatusListener();
@@ -226,13 +330,14 @@
             success = true;
         } catch (Throwable t) {
             //Need to catch any error as Logback must work in all scenarios
-            addError("Error configuring Logback", t);
+            //The error would be dumped to sysout in later call to Status printer
+            addError("Error occurred while configuring Logback", t);
         } finally {
             if(!success){
                 cb.fallbackConfiguration(eventList, createConfigurator(), statusListener);
             }
             getStatusManager().remove(statusListener);
-            StatusPrinter.printInCaseOfErrorsOrWarnings(getLoggerContext(), resetStartTime);
+            SlingStatusPrinter.printInCaseOfErrorsOrWarnings(getLoggerContext(), resetStartTime, startTime, success);
         }
     }
 
@@ -251,10 +356,6 @@
         }
     }
 
-    private void scheduleConfigReload() {
-        getLoggerContext().getExecutorService().submit(new LoggerReconfigurer());
-    }
-
     private String getRootDir(BundleContext bundleContext) {
         String rootDir = bundleContext.getProperty("sling.home");
         if (rootDir == null) {
@@ -264,31 +365,84 @@
         return rootDir;
     }
 
-    private class LoggerReconfigurer implements Runnable {
+    //~-------------------------------------------------- Slf4j Bridge Handler Support
 
-        public void run() {
-            // TODO Might be better to run a job to monitor refreshRequirement
-            boolean configChanged = false;
-            try {
-                addInfo("Performing configuration");
-                configure();
-                configChanged = LogbackManager.this.configChanged.getAndSet(false);
-                if (configChanged) {
-                    scheduleConfigReload();
+    /**
+     * Installs the Slf4j BridgeHandler to route the JUL logs through Slf4j
+     *
+     * @return true only if the BridgeHandler is installed.
+     */
+    private static boolean installSlf4jBridgeHandler(BundleContext bundleContext){
+        // SLING-2373
+        if (Boolean.parseBoolean(bundleContext.getProperty(JUL_SUPPORT))) {
+            // In config one must enable the LevelChangePropagator
+            // http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
+            // make sure configuration is empty unless explicitly set
+            if (System.getProperty("java.util.logging.config.file") == null
+                    && System.getProperty("java.util.logging.config.class") == null) {
+                final Thread ct = Thread.currentThread();
+                final ClassLoader old = ct.getContextClassLoader();
+                try {
+                    ct.setContextClassLoader(LogbackManager.class.getClassLoader());
+                    System.setProperty("java.util.logging.config.class",
+                            DummyLogManagerConfiguration.class.getName());
+                    java.util.logging.LogManager.getLogManager().reset();
+                } finally {
+                    ct.setContextClassLoader(old);
+                    System.clearProperty("java.util.logging.config.class");
                 }
-            } catch (Exception e) {
-                log.warn("Error occurred while re-configuring logger", e);
-                addError("Error occurred while re-configuring logger", e);
-            } finally {
-                if (!configChanged) {
-                    resetLock.release();
-                    addInfo("Re configuration done");
+            }
+
+            SLF4JBridgeHandler.install();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * It checks if LevelChangePropagator is installed or not. If not then
+     * it installs the propagator when Slf4j Bridge Handler is installed
+     */
+    private class LevelChangePropagatorChecker implements LogbackResetListener {
+
+        @Override
+        public void onResetStart(LoggerContext context) {
+
+        }
+
+        @Override
+        public void onResetComplete(LoggerContext context) {
+            List<LoggerContextListener> listenerList = context.getCopyOfListenerList();
+            boolean levelChangePropagatorInstalled = false;
+            for (LoggerContextListener listener : listenerList) {
+                if (listener instanceof LevelChangePropagator) {
+                    levelChangePropagatorInstalled = true;
+                    break;
                 }
             }
+
+            //http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
+            if (!levelChangePropagatorInstalled
+                    && bridgeHandlerInstalled) {
+                LevelChangePropagator propagator = new LevelChangePropagator();
+                propagator.setContext(context);
+                propagator.start();
+                context.addListener(propagator);
+                addInfo("Slf4j bridge handler found to be enabled. Installing the LevelChangePropagator");
+            }
         }
     }
 
-    // ~-------------------------------LogggerContextListener
+    /**
+     * The <code>DummyLogManagerConfiguration</code> class is used as JUL
+     * LogginManager configurator to preven reading platform default
+     * configuration which just duplicate log output to be redirected to SLF4J.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    public static class DummyLogManagerConfiguration {
+    }
+
+    // ~-------------------------------LoggerContextListener
 
     private class OsgiIntegrationListener implements LoggerContextListener {
 
@@ -307,20 +461,24 @@
             addInfo("OsgiIntegrationListener : context reset detected. Adding LogManager to context map and firing"
                 + " listeners");
 
+            context.setPackagingDataEnabled(logConfigManager.isPackagingDataEnabled());
+            context.setMaxCallerDataDepth(logConfigManager.getMaxCallerDataDepth());
+
             // Attach a console appender to handle logging untill we configure
-            // one. This would be removed in LogConfigManager.reset
+            // one. This would be removed in RootLoggerListener.reset
             final Logger rootLogger = getLoggerContext().getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
             rootLogger.setLevel(Level.INFO);
             rootLogger.addAppender(logConfigManager.getDefaultAppender());
 
-
             // Now record the time of reset with a default appender attached to
             // root logger. We also add a milli second extra to account for logs which would have
             // got fired in same duration
             resetStartTime = System.currentTimeMillis() + TimeUnit.MILLISECONDS.toMillis(1);
+            addInfo("Registered a default console based logger");
 
             context.putObject(LogbackManager.class.getName(), LogbackManager.this);
             for (LogbackResetListener l : resetListeners) {
+                addInfo("Firing reset listener - onResetStart "+l.getClass());
                 l.onResetStart(context);
             }
         }
@@ -333,6 +491,31 @@
 
     }
 
+    private class RootLoggerListener implements LogbackResetListener {
+
+        @Override
+        public void onResetStart(LoggerContext context) {
+
+        }
+
+        @Override
+        public void onResetComplete(LoggerContext context) {
+            // Remove the default console appender that we attached at start of
+            // reset
+            ch.qos.logback.classic.Logger root = context.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+            Iterator<Appender<ILoggingEvent>> appenderItr = root.iteratorForAppenders();
+
+            //Root logger has at least 1 appender associated with it. Remove the one added by us
+            if (appenderItr.hasNext()) {
+                root.detachAppender(LogConfigManager.DEFAULT_CONSOLE_APPENDER_NAME);
+                addInfo("Found appender attached with root logger. Detaching the default console based logger");
+            } else {
+                addInfo("No appender was found to be associated with root logger. Registering " +
+                        "a Console based logger");
+            }
+        }
+    }
+
     // ~--------------------------------Configurator Base
 
     private class SlingConfigurator extends JoranConfigurator {
@@ -432,19 +615,45 @@
     public LoggerStateContext determineLoggerState() {
         final List<Logger> loggers = getLoggerContext().getLoggerList();
         final LoggerStateContext ctx = new LoggerStateContext(loggers);
-        for (Logger logger : loggers) {
-            if (logger.iteratorForAppenders().hasNext() || logger.getLevel() != null) {
-                ctx.loggerInfos.add(logger);
-            }
 
+        //Distinguish between Logger configured via
+        //1. OSGi Config - The ones configured via ConfigAdmin
+        //2. Other means - Configured via Logback config or any other means
+        for (LogConfig lc : logConfigManager.getLogConfigs()) {
+            for (String category : lc.getCategories()) {
+                ctx.osgiConfiguredLoggers.put(category, lc);
+            }
+        }
+
+        for (Logger logger : loggers) {
+            boolean hasOnlySlingRollingAppenders = true;
             Iterator<Appender<ILoggingEvent>> itr = logger.iteratorForAppenders();
             while (itr.hasNext()) {
                 Appender<ILoggingEvent> a = itr.next();
                 if (a.getName() != null && !ctx.appenders.containsKey(a.getName())) {
                     ctx.appenders.put(a.getName(), a);
                 }
+
+                if(!(a instanceof SlingRollingFileAppender)){
+                    hasOnlySlingRollingAppenders = false;
+                }
             }
+
+            if(logger.getLevel() == null){
+                continue;
+            }
+
+            boolean configuredViaOSGiConfig =
+                    ctx.osgiConfiguredLoggers.containsKey(logger.getName());
+            if (!configuredViaOSGiConfig
+                    || (configuredViaOSGiConfig && !hasOnlySlingRollingAppenders))
+                    {
+                ctx.nonOSgiConfiguredLoggers.add(logger);
+            }
+
         }
+
+
         return ctx;
     }
 
@@ -456,7 +665,9 @@
         /**
          * List of logger which have explicitly defined level or appenders set
          */
-        final List<Logger> loggerInfos = new ArrayList<Logger>();
+        final List<Logger> nonOSgiConfiguredLoggers = new ArrayList<Logger>();
+
+        final Map<String,LogConfig> osgiConfiguredLoggers = new HashMap<String, LogConfig>();
 
         final Map<String, Appender<ILoggingEvent>> appenders = new HashMap<String, Appender<ILoggingEvent>>();
 
@@ -507,20 +718,18 @@
         }
     }
 
-    private void registerWebConsoleSupport(BundleContext context) {
-        final ServiceFactory serviceFactory = new PluginServiceFactory(PLUGIN_URL);
+    private void registerWebConsoleSupport() {
+        final ServiceFactory serviceFactory = new PluginServiceFactory();
 
         Properties pluginProps = new Properties();
         pluginProps.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
         pluginProps.put(Constants.SERVICE_DESCRIPTION, "Sling Log Support");
-        pluginProps.put("felix.webconsole.label", PLUGIN_URL);
+        pluginProps.put("felix.webconsole.label", APP_ROOT);
         pluginProps.put("felix.webconsole.title", "Log Support");
         pluginProps.put("felix.webconsole.category", "Sling");
-        pluginProps.put("felix.webconsole.css", new String[] {
-            "/" + PLUGIN_URL + "/res/ui/prettify.css", "/" + PLUGIN_URL + "/res/ui/log.css"
-        });
+        pluginProps.put("felix.webconsole.css", CSS_REFS);
 
-        registrations.add(context.registerService("javax.servlet.Servlet", serviceFactory, pluginProps));
+        registrations.add(bundleContext.registerService("javax.servlet.Servlet", serviceFactory, pluginProps));
 
         Properties printerProps = new Properties();
         printerProps.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
@@ -530,23 +739,17 @@
         printerProps.put("felix.webconsole.configprinter.modes", "always");
 
         // TODO need to see to add support for Inventory Feature
-        registrations.add(context.registerService(SlingConfigurationPrinter.class.getName(),
+        registrations.add(bundleContext.registerService(SlingConfigurationPrinter.class.getName(),
             new SlingConfigurationPrinter(this), printerProps));
     }
 
     private class PluginServiceFactory implements ServiceFactory {
         private Object instance;
 
-        private final String label;
-
-        private PluginServiceFactory(String label) {
-            this.label = label;
-        }
-
         public Object getService(Bundle bundle, ServiceRegistration registration) {
             synchronized (this) {
                 if (this.instance == null) {
-                    this.instance = new SlingLogPanel(LogbackManager.this, label);
+                    this.instance = new SlingLogPanel(LogbackManager.this,bundleContext);
                 }
                 return instance;
             }
@@ -556,7 +759,7 @@
         }
     }
 
-    private void registerEventHandler(BundleContext bundleContext) {
+    private void registerEventHandler() {
         Properties props = new Properties();
         props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
         props.put(Constants.SERVICE_DESCRIPTION, "Sling Log Reset Event Handler");
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/SlingConfigurationPrinter.java b/src/main/java/org/apache/sling/commons/log/logback/internal/SlingConfigurationPrinter.java
index c275210..bcd3535 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/SlingConfigurationPrinter.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/SlingConfigurationPrinter.java
@@ -20,6 +20,7 @@
 
 import java.io.File;
 import java.io.FileReader;
+import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.MalformedURLException;
@@ -30,12 +31,16 @@
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.FileAppender;
+import ch.qos.logback.core.rolling.RollingFileAppender;
+import ch.qos.logback.core.status.Status;
+import ch.qos.logback.core.util.CachingDateFormatter;
 
 /**
  * The <code>SlingConfigurationPrinter</code> is an Apache Felix Web Console
  * plugin to display the currently configured log files.
  */
 public class SlingConfigurationPrinter {
+    private static final CachingDateFormatter SDF = new CachingDateFormatter("yyyy-MM-dd HH:mm:ss");
     private final LogbackManager logbackManager;
 
     public SlingConfigurationPrinter(LogbackManager logbackManager) {
@@ -48,6 +53,7 @@
     @SuppressWarnings("UnusedDeclaration")
     public void printConfiguration(PrintWriter printWriter) {
         LogbackManager.LoggerStateContext ctx = logbackManager.determineLoggerState();
+        dumpLogbackStatus(logbackManager, printWriter);
         for (Appender<ILoggingEvent> appender : ctx.getAllAppenders()) {
             if (appender instanceof FileAppender) {
                 final File file = new File(((FileAppender) appender).getFile());
@@ -69,7 +75,7 @@
                         if (fr != null) {
                             try {
                                 fr.close();
-                            } catch (IOException ignoreCloseException) {
+                            } catch (IOException ignored) {
                             }
                         }
                     }
@@ -80,8 +86,10 @@
     }
 
     /**
-     * TODO Need to see how to implement this with LogBack as we cannot get
-     * information about all rolled over policy
+     * Attempts to determine all log files created even via rotation.
+     * if some complex rotation logic is used where rotated file get different names
+     * or get created in different directory then those files would not be
+     * included
      * 
      * @see org.apache.felix.webconsole.AttachmentProvider#getAttachments(String)
      */
@@ -93,15 +101,7 @@
             LogbackManager.LoggerStateContext ctx = logbackManager.determineLoggerState();
             for (Appender<ILoggingEvent> appender : ctx.getAllAppenders()) {
                 if (appender instanceof FileAppender) {
-                    final File file = new File(((FileAppender) appender).getFile());
-                    // TODO With LogBack there is no straightforward way to get
-                    // information
-                    // about rolled over files
-                    // final File[] files =
-                    // writer.getFileRotator().getRotatedFiles(writer.getFile());
-                    final File[] files = new File[] {
-                        file
-                    };
+                    final File[] files = getRotatedFiles((FileAppender) appender);
                     for (File f : files) {
                         try {
                             urls.add(f.toURI().toURL());
@@ -118,4 +118,55 @@
         return null;
     }
 
+    private static File[] getRotatedFiles(FileAppender app) {
+        final File file = new File(app.getFile());
+
+        //If RollingFileAppender then make an attempt to list files
+        //This might not work in all cases if complex rolling patterns
+        //are used in Logback
+        if (app instanceof RollingFileAppender) {
+            final File dir = file.getParentFile();
+            final String baseName = file.getName();
+            return dir.listFiles(new FilenameFilter() {
+                public boolean accept(File dir, String name) {
+                    return name.startsWith(baseName);
+                }
+            });
+        }
+
+        //Not a RollingFileAppender then just return the actual file
+        return new File[]{file};
+    }
+
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    private static void dumpLogbackStatus(LogbackManager logbackManager, PrintWriter pw) {
+        List<Status> statusList = logbackManager.getStatusManager().getCopyOfStatusList();
+        pw.println("Logback Status");
+        pw.println("--------------------------------------------------");
+        for (Status s : statusList) {
+            pw.printf("%s *%s* %s - %s %n",
+                    SDF.format(s.getDate()),
+                    statusLevelAsString(s),
+                    SlingLogPanel.abbreviatedOrigin(s),
+                    s.getMessage());
+            if (s.getThrowable() != null) {
+                s.getThrowable().printStackTrace(pw);
+            }
+        }
+
+        pw.println();
+    }
+
+    private static String statusLevelAsString(Status s) {
+        switch (s.getEffectiveLevel()) {
+            case Status.INFO:
+                return "INFO";
+            case Status.WARN:
+                return "WARN";
+            case Status.ERROR:
+                return "ERROR";
+        }
+        return null;
+    }
+
 }
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java b/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java
index 540f7db..1e352da 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java
@@ -27,13 +27,19 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.classic.turbo.TurboFilter;
@@ -45,20 +51,26 @@
 import ch.qos.logback.core.util.CachingDateFormatter;
 import org.apache.sling.commons.log.logback.internal.AppenderTracker.AppenderInfo;
 import org.apache.sling.commons.log.logback.internal.LogbackManager.LoggerStateContext;
+import org.apache.sling.commons.log.logback.internal.config.ConfigurationException;
 import org.apache.sling.commons.log.logback.internal.util.SlingRollingFileAppender;
 import org.apache.sling.commons.log.logback.internal.util.Util;
 import org.apache.sling.commons.log.logback.internal.util.XmlUtil;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.InputSource;
 
 import static org.apache.sling.commons.log.logback.internal.ConfigSourceTracker.ConfigSourceInfo;
+import static org.apache.sling.commons.log.logback.internal.LogbackManager.APP_ROOT;
+import static org.apache.sling.commons.log.logback.internal.LogbackManager.RES_LOC;
 
 /**
  * The <code>SlingLogPanel</code> is a Felix Web Console plugin to display the
  * current active log bundle configuration.
- * <p>
+ * <p/>
  * In future revisions of this plugin, the configuration may probably even be
  * modified through this panel.
  */
@@ -68,7 +80,18 @@
 
     private final CachingDateFormatter SDF = new CachingDateFormatter("yyyy-MM-dd HH:mm:ss");
 
+    private static final String[] LEVEL_NAMES = {
+            Level.ERROR.levelStr,
+            Level.WARN.levelStr,
+            Level.INFO.levelStr,
+            Level.DEBUG.levelStr,
+            Level.TRACE.levelStr,
+    };
+
+    private static final String PACKAGE_SEPARATOR = ".";
+
     private final LogbackManager logbackManager;
+    private final BundleContext bundleContext;
 
     private final String labelRes;
 
@@ -76,9 +99,10 @@
 
     private static final org.slf4j.Logger log = LoggerFactory.getLogger(SlingLogPanel.class);
 
-    public SlingLogPanel(final LogbackManager logbackManager, String label) {
+    public SlingLogPanel(final LogbackManager logbackManager, BundleContext bundleContext) {
         this.logbackManager = logbackManager;
-        this.labelRes = '/' + label + '/';
+        this.bundleContext = bundleContext;
+        this.labelRes = '/' + APP_ROOT + '/';
         this.labelResLen = labelRes.length() - 1;
     }
 
@@ -92,32 +116,161 @@
 
         final LoggerStateContext ctx = logbackManager.determineLoggerState();
         appendLoggerStatus(pw, ctx);
-        appendLoggerData(pw, ctx);
+        appendOsgiConfiguredLoggerData(pw, consoleAppRoot);
+        appendOtherLoggerData(pw, ctx);
         addAppenderData(pw, consoleAppRoot, ctx);
-        appendTurboFilterData(pw, consoleAppRoot,ctx);
+        appendTurboFilterData(pw, consoleAppRoot, ctx);
         appendLogbackMainConfig(pw);
         appendLogbackFragments(pw, consoleAppRoot);
         appendLogbackStatus(pw, ctx);
-        enablePrettifier(pw, pluginRoot);
+        addScriptBlock(pw, ctx);
     }
 
+    @Override
+    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp)
+            throws ServletException, IOException {
+        // check if a configuration should be deleted
+        boolean isDelete = req.getParameter("delete") != null;
+        // get the configuration pid
+        String pid = req.getParameter("pid");
+        try {
+            if (isDelete) {
+                // in delete mode remove the logger with the given pid
+                removeLogger(pid);
+            } else {
+                // get the logger parameters and configure the logger
+                // if the given pid is empty a new logger with be created
+                String logger = req.getParameter("logger");
+                String logLevel = req.getParameter("loglevel");
+                String logFile = req.getParameter("logfile");
+                String[] loggers = req.getParameterValues("logger");
+                if (null != logger) {
+                    configureLogger(pid, logLevel, loggers, logFile);
+                }
+            }
+        } catch (ConfigurationException e) {
+            internalFailure("", e);
+        }
+        // send the redirect back to the logpanel
+        final String consoleAppRoot = (String) req
+                .getAttribute("felix.webconsole.appRoot");
+        resp.sendRedirect(consoleAppRoot + "/" + APP_ROOT);
+    }
 
-    private void enablePrettifier(PrintWriter pw, String pluginRoot) {
-        pw.printf("<script type=\"text/javascript\" src=\"%s/res/ui/prettify.js\"></script>", pluginRoot);
+    private void addScriptBlock(PrintWriter pw, LoggerStateContext ctx) {
+        pw.println("<script type=\"text/javascript\" src=\"" + RES_LOC + "/slinglog.js\"></script>");
+        pw.println("<script type=\"text/javascript\" src=\"" + RES_LOC + "/jquery.autocomplete.min.js\"></script>");
+        pw.println("<script type=\"text/javascript\" src=\"" + RES_LOC + "/prettify.js\"></script>");
+
+        pw.println("<script type=\"text/javascript\">$(document).ready(function() { initializeSlingLogPanel(); });</script>");
+        pw.println("<script>");
+        // write all present loggers as script variable so the autocomplete script can search over them
+        pw.println("var loggers=[");
+        Set<String> loggers = new TreeSet<String>();
+
+        for (Logger logger : ctx.loggerContext.getLoggerList()) {
+            loggers.add(logger.getName());
+        }
+
+        Set<String> packageList = new TreeSet<String>();
+        for (String logger : loggers) {
+            int pos = logger.lastIndexOf(PACKAGE_SEPARATOR);
+            if (pos != -1) {
+                String pack = logger.substring(0, pos);
+                packageList.add(pack);
+            }
+        }
+        loggers.addAll(packageList);
+        for (Iterator<String> loggerIt = loggers.iterator(); loggerIt.hasNext(); ) {
+            String logger = loggerIt.next();
+            pw.print("'" + logger + "'");
+            if (loggerIt.hasNext()) {
+                pw.print(",");
+            }
+        }
+        pw.println("];");
+        pw.println("</script>");
         pw.println("<script>$(document).ready(prettyPrint);</script>");
-
     }
 
     private void appendLoggerStatus(PrintWriter pw, LoggerStateContext ctx) {
         pw.printf(
-            "<p class='statline'>Log Service Stats: %d categories, %d appenders(s), %d Dynamic appenders(s)</p>%n",
-            ctx.getNumberOfLoggers(), ctx.getNumOfAppenders(), ctx.getNumOfDynamicAppenders());
+                "<p class='statline'>Log Service Stats: %d categories, %d appender, %d Dynamic appenders</p>%n",
+                ctx.getNumberOfLoggers(), ctx.getNumOfAppenders(), ctx.getNumOfDynamicAppenders());
     }
 
-    private void appendLoggerData(PrintWriter pw, LoggerStateContext ctx) {
+    private void appendOsgiConfiguredLoggerData(PrintWriter pw, String consoleAppRoot) {
         pw.println("<div class='table'>");
 
-        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>Logger</div>");
+        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>Logger (Configured via OSGi Config)</div>");
+
+        pw.println("<form method='POST'><table id=\"loggerConfig\" class='tablesorter nicetable ui-widget'>");
+
+        pw.println("<thead class='ui-widget-header'>");
+        pw.println("<tr>");
+        pw.println("<th>Log Level</th>");
+        pw.println("<th>Log File</th>");
+        pw.println("<th>Logger</th>");
+        pw.println("<th width=\"20%\">" + getConfigColTitle(consoleAppRoot) + "</th>");
+        pw.println("</tr>");
+        pw.println("</thead>");
+        pw.println("<tbody class='ui-widget-content'>");
+
+        final LogConfigManager configManager = logbackManager.getLogConfigManager();
+        String rootPath = logbackManager.getRootDir();
+        boolean shortenPaths = areAllLogfilesInSameFolder(configManager.getLogWriters(), rootPath);
+        for (LogConfig logConfig : configManager.getLogConfigs()) {
+            pw.println("<tr id=\"" + logConfig.getConfigPid() + "\">");
+            pw.println("<td><span class=\"logLevels\" data-currentloglevel=\""
+                    + logConfig.getLogLevel().levelStr + "\">" + logConfig.getLogLevel().levelStr
+                    + "</span></td>");
+            pw.println("<td><span class=\"logFile\">" + getPath(logConfig.getLogWriterName(), rootPath, shortenPaths) + "</span></td>");
+
+            pw.println("<td><span class=\"loggers\">");
+            String sep = "";
+            for (String cat : logConfig.getCategories()) {
+                pw.println(sep + "<span class=\"logger\">" + cat + "</span>");
+                sep = "<br />";
+            }
+            pw.println("</td>");
+
+            String pid = logConfig.getConfigPid();
+            String url = createUrl(consoleAppRoot, "configMgr", pid, true);
+            if (logConfig.getCategories().contains(Logger.ROOT_LOGGER_NAME)) {
+                url = createUrl(consoleAppRoot, "configMgr", pid, false);
+            }
+            pw.println("<td>" + url + "</td>");
+            pw.println("</tr>");
+        }
+
+        pw.println("</tbody><tfoot>");
+        pw.println("<tr id=\"newlogger\">");
+        pw.println("<td><span id=\"allLogLevels\" class=\"logLevels\" data-loglevels=\"");
+        String sep = "";
+        for (String levelName : LEVEL_NAMES) {
+            pw.print(sep + levelName);
+            sep = ",";
+        }
+
+        pw.println("\"></span></td>");
+        pw.println("<td><span id=\"defaultLogfile\" data-defaultlogfile=\""
+                + getPath(configManager.getDefaultWriter().getFileName(), rootPath, shortenPaths)
+                + "\" class=\"logFile\"></span></td>");
+        pw.println("<td><span class=\"loggers\"></span></td>");
+        pw.println("<td><input type='submit' class=\"configureLink\" value='Add new Logger' /></td></tr></tfoot>");
+
+        pw.println("</table></form>");
+        pw.println("</div>");
+    }
+
+    private void appendOtherLoggerData(PrintWriter pw, LoggerStateContext ctx) {
+        if (ctx.nonOSgiConfiguredLoggers.isEmpty()) {
+            return;
+        }
+
+        pw.println("<div class='table'>");
+
+        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>Logger (Configured via other means)</div>");
 
         pw.println("<table class='nicetable ui-widget'>");
 
@@ -127,12 +280,11 @@
         pw.println("<th>Additivity</th>");
         pw.println("<th>Name</th>");
         pw.println("<th>Appender</th>");
-        // pw.println("<th>" + cfgColTitle + "</th>");
         pw.println("</tr>");
         pw.println("</thead>");
         pw.println("<tbody class='ui-widget-content'>");
 
-        for (Logger logger : ctx.loggerInfos) {
+        for (Logger logger : ctx.nonOSgiConfiguredLoggers) {
             pw.println("<tr>");
             pw.println("<td>" + logger.getLevel() + "</td>");
             pw.println("<td>" + Boolean.toString(logger.isAdditive()) + "</td>");
@@ -144,12 +296,11 @@
             while (itr.hasNext()) {
                 Appender<ILoggingEvent> a = itr.next();
                 pw.print("<li>");
-                pw.println(getName(a));
+                pw.print(getName(a));
                 pw.print("</li>");
             }
             pw.println("</ul>");
             pw.println("</td>");
-
             pw.println("</tr>");
         }
 
@@ -185,8 +336,8 @@
         pw.println("</div>");
     }
 
-    private void appendTurboFilterData(PrintWriter pw, String consoleAppRoot,LoggerStateContext ctx) {
-        if(ctx.loggerContext.getTurboFilterList().isEmpty()){
+    private void appendTurboFilterData(PrintWriter pw, String consoleAppRoot, LoggerStateContext ctx) {
+        if (ctx.loggerContext.getTurboFilterList().isEmpty()) {
             return;
         }
 
@@ -205,7 +356,7 @@
         pw.println("<tbody class='ui-widget-content'>");
 
 
-        for(TurboFilter tf : ctx.loggerContext.getTurboFilterList()){
+        for (TurboFilter tf : ctx.loggerContext.getTurboFilterList()) {
             pw.println("<tr>");
             pw.println("<td>" + getName(tf) + "</td>");
             pw.println("<td>" + formatPid(consoleAppRoot, tf, ctx) + "</td>");
@@ -348,7 +499,7 @@
      * resources are accessed like <code>/system/console/abc/res/logo.gif</code>
      * , the code here will try load resource <code>/res/logo.gif</code> from
      * the bundle, providing the plugin.
-     * 
+     *
      * @param path the path to read.
      * @return the URL of the resource or <code>null</code> if not found.
      */
@@ -359,10 +510,135 @@
                 : null;
     }
 
+    /**
+     * Checks if all log files are in the same folder, then the path can displayed shortened in the panel.
+     *
+     * @param logWriters list of log writers
+     * @param rootPath   root path
+     * @return true if all logfiles are in the same folder
+     */
+    private boolean areAllLogfilesInSameFolder(final Iterable<LogWriter> logWriters, final String rootPath) {
+        String lastPath = null;
+        for (final LogWriter writer : logWriters) {
+            String path = getPath(writer.getFileName(), null, false);
+            if (!path.startsWith(rootPath)) {
+                return false;
+            }
+            path = path.substring(0, rootPath.length());
+            if (lastPath == null) {
+                lastPath = path;
+            } else if (!path.equals(lastPath)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Configures the logger with the given pid. If the pid is empty a new logger configuration is created.
+     *
+     * @param pid      configuration pid of the logger
+     * @param logLevel the log level to set
+     * @param loggers  list of logger categories to set
+     * @param logFile  log file (relative path is ok)
+     * @throws IOException            when an existing configuration couldn't be updated or a configuration couldn't be created.
+     * @throws ConfigurationException when mandatory parameters where not specified
+     */
+    private void configureLogger(final String pid, final String logLevel, final String[] loggers, final String logFile)
+            throws IOException, ConfigurationException {
+        // try to get the configadmin service reference
+        ServiceReference sr = this.bundleContext
+                .getServiceReference(ConfigurationAdmin.class.getName());
+        if (sr != null) {
+            try {
+                if (logLevel == null) {
+                    throw new ConfigurationException(LogConfigManager.LOG_LEVEL,
+                            "Log level has to be specified.");
+                }
+                if (loggers == null) {
+                    throw new ConfigurationException(LogConfigManager.LOG_LOGGERS,
+                            "Logger categories have to be specified.");
+                }
+                if (logFile == null) {
+                    throw new ConfigurationException(LogConfigManager.LOG_FILE,
+                            "LogFile name has to be specified.");
+                }
+                // try to get the configadmin
+                final ConfigurationAdmin configAdmin = (ConfigurationAdmin) this.bundleContext
+                        .getService(sr);
+                if (configAdmin != null) {
+                    Configuration config;
+                    if (pid == null || pid.length() == 0) {
+                        config = configAdmin.createFactoryConfiguration(LogConfigManager.FACTORY_PID_CONFIGS);
+                    } else {
+                        config = configAdmin.getConfiguration(pid);
+                    }
+                    if (config != null) {
+                        Dictionary<String, Object> dict = new Hashtable<String, Object>();
+                        dict.put(LogConfigManager.LOG_LEVEL, logLevel.toLowerCase());
+                        dict.put(LogConfigManager.LOG_LOGGERS, loggers);
+                        dict.put(LogConfigManager.LOG_FILE, logFile);
+                        config.update(dict);
+                    }
+                }
+            } finally {
+                // release the configadmin reference
+                this.bundleContext.ungetService(sr);
+            }
+        }
+    }
+
+
+    /**
+     * Removes the logger configuration with the given pid in the configadmin.
+     *
+     * @param pid pid of the configuration to delete
+     * @throws ConfigurationException when there is no configuration for this pid
+     */
+    private void removeLogger(final String pid)
+            throws ConfigurationException {
+        // try to get the configadmin service reference
+        ServiceReference sr = this.bundleContext
+                .getServiceReference(ConfigurationAdmin.class.getName());
+        if (sr != null) {
+            try {
+                if (pid == null) {
+                    throw new ConfigurationException(LogConfigManager.PID,
+                            "PID has to be specified.");
+                }
+                // try to get the configadmin
+                final ConfigurationAdmin configAdmin = (ConfigurationAdmin) this.bundleContext
+                        .getService(sr);
+                if (configAdmin != null) {
+                    try {
+                        Configuration config = configAdmin.getConfiguration(pid);
+                        if (config != null) {
+                            config.delete();
+                        } else {
+                            throw new ConfigurationException(LogConfigManager.PID,
+                                    "No configuration for this PID:" + pid);
+                        }
+                    } catch (IOException ioe) {
+                        internalFailure(
+                                "Cannot delete configuration for pid " + pid,
+                                ioe);
+                    }
+                }
+            } finally {
+                // release the configadmin reference
+                this.bundleContext.ungetService(sr);
+            }
+        }
+    }
+
+    private void internalFailure(String msg, Exception e) {
+        logbackManager.getLogConfigManager().internalFailure(msg, e);
+    }
+
     private static String getName(TurboFilter tf) {
-        if(tf.getName() != null){
+        if (tf.getName() != null) {
             return String.format("%s (%s)", tf.getName(), tf.getClass().getName());
-        } else{
+        } else {
             return tf.getClass().getName();
         }
     }
@@ -384,18 +660,22 @@
             return String.format("File : [%s] %s", appender.getName(), ((FileAppender) appender).getFile());
         }
 
-        return String.format("%s (%s)", appender.getName(), appender.getClass().getName());
+        final String appenderName = appender.getName();
+        if(appenderName == null){
+            return appender.getClass().getName();
+        } else {
+            return String.format("%s (%s)", appender.getName(), appender.getClass().getName());
+        }
     }
 
     private static String formatPid(final String consoleAppRoot, final Appender<ILoggingEvent> appender,
-            final LoggerStateContext ctx) {
+                                    final LoggerStateContext ctx) {
         if (appender instanceof SlingRollingFileAppender) {
             final LogWriter lw = ((SlingRollingFileAppender) appender).getLogWriter();
+            String pid = lw.getConfigurationPID();
             if (lw.isImplicit()) {
-                return "[implicit]";
+                pid = lw.getImplicitConfigPID();
             }
-
-            final String pid = lw.getConfigurationPID();
             return createUrl(consoleAppRoot, "configMgr", pid);
         } else if (ctx.isDynamicAppender(appender)) {
             final AppenderInfo ai = ctx.dynamicAppenders.get(appender);
@@ -412,16 +692,35 @@
     }
 
     private static String createUrl(String consoleAppRoot, String subContext, String pid) {
+        return createUrl(consoleAppRoot, subContext, pid, false);
+    }
+
+    private static String createUrl(String consoleAppRoot, String subContext, String pid, boolean inlineEditable) {
         // no recent web console, so just render the pid as the link
         if (consoleAppRoot == null) {
             return "<a href=\"" + subContext + "/" + pid + "\">" + pid + "</a>";
         }
 
         // recent web console has app root and hence we can use an image
-        return "<a href=\"" + subContext + "/" + pid + "\"><img src=\"" + consoleAppRoot
-            + "/res/imgs/component_configure.png\" border=\"0\" /></a>";
+        String classAttr = "class=\"configureLink\"";
+        if (!inlineEditable) {
+            classAttr = "";
+        }
+
+        return "<a " + classAttr + " href=\"" + subContext + "/" + pid + "\"><img src=\"" + consoleAppRoot
+                + "/res/imgs/component_configure.png\" border=\"0\" /></a>";
     }
 
+    private static String getPath(String path, final String rootPath, final boolean shortenPaths) {
+        if (shortenPaths && path != null) {
+            // if the shortenPath parameter is set (all log files are in the same folder)
+            // remove the root path (root log file folder) from the paths
+            path = path.substring(rootPath.length() + 1);
+        }
+        return (path != null) ? path : "[stdout]";
+    }
+
+
     // ~------------------------------------------------Status Manager
     // Based on ch.qos.logback.core.status.ViewStatusMessagesServletBase
 
@@ -437,7 +736,7 @@
         return null;
     }
 
-    private static String abbreviatedOrigin(Status s) {
+    static String abbreviatedOrigin(Status s) {
         Object o = s.getOrigin();
         if (o == null) {
             return null;
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/util/SlingContextUtil.java b/src/main/java/org/apache/sling/commons/log/logback/internal/util/SlingContextUtil.java
new file mode 100644
index 0000000..5ddcad7
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/util/SlingContextUtil.java
@@ -0,0 +1,40 @@
+/*
+ * 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.apache.sling.commons.log.logback.internal.util;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+/**
+ * Custom util such that origin can be customized
+ */
+public class SlingContextUtil extends ContextAwareBase {
+    private final Object origin;
+
+    public SlingContextUtil(Context context, Object origin) {
+        this.origin = origin;
+        setContext(context);
+    }
+
+    @Override
+    protected Object getDeclaredOrigin() {
+        return origin;
+    }
+}
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/util/SlingStatusPrinter.java b/src/main/java/org/apache/sling/commons/log/logback/internal/util/SlingStatusPrinter.java
new file mode 100644
index 0000000..e5fa4e4
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/util/SlingStatusPrinter.java
@@ -0,0 +1,101 @@
+/*
+ * 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.apache.sling.commons.log.logback.internal.util;
+
+import java.io.PrintStream;
+import java.util.List;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.CoreConstants;
+import ch.qos.logback.core.status.ErrorStatus;
+import ch.qos.logback.core.status.Status;
+import ch.qos.logback.core.status.StatusManager;
+import ch.qos.logback.core.status.StatusUtil;
+import ch.qos.logback.core.util.StatusPrinter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Custom StatusPrinter similar to Logback StatusPrinter to account for changes required
+ * for SLING-3410
+ */
+public class SlingStatusPrinter {
+
+    /**
+     * Based on StatusPrinter. printInCaseOfErrorsOrWarnings. This has been adapted
+     * to print more context i.e. some message from before the error message to better understand
+     * the failure scenario
+     *
+     * @param threshold   time since which the message have to be checked for errors/warnings
+     * @param msgSince    time form which we are interested in the message logs
+     * @param initSuccess flag indicating if Logback configuration failed or not
+     */
+    public static void printInCaseOfErrorsOrWarnings(Context context, long threshold,
+                                                     long msgSince, boolean initSuccess) {
+        if (context == null) {
+            throw new IllegalArgumentException("Context argument cannot be null");
+        }
+        PrintStream ps = System.out;
+        StatusManager sm = context.getStatusManager();
+        if (sm == null) {
+            ps.println("WARN: Context named \"" + context.getName()
+                    + "\" has no status manager");
+        } else {
+            StatusUtil statusUtil = new StatusUtil(context);
+            if (statusUtil.getHighestLevel(threshold) >= ErrorStatus.WARN) {
+                List<Status> filteredList =
+                        StatusUtil.filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), msgSince);
+                print(filteredList, initSuccess);
+            }
+        }
+    }
+
+    private static void print(List<Status> statusList, boolean initSuccess) {
+        if (statusList == null) {
+            return;
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        if (initSuccess) {
+            sb.append("While (re)configuring Logback transient issues were observed. " +
+                    "More details are provided below.");
+            sb.append(CoreConstants.LINE_SEPARATOR);
+        }
+
+        String prefix = "";
+        if(initSuccess){
+            prefix = "*Logback Status* ";
+        }
+
+        for (Status s : statusList) {
+            StatusPrinter.buildStr(sb, prefix, s);
+        }
+
+        //In case logging system completely fails then log the message in System out
+        //otherwise make it part of 'normal' logs
+        if (!initSuccess) {
+            System.out.println(sb.toString());
+        } else {
+            Logger logger = LoggerFactory.getLogger(SlingStatusPrinter.class);
+            logger.info(sb.toString());
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/util/Util.java b/src/main/java/org/apache/sling/commons/log/logback/internal/util/Util.java
index 87181fd..90efb5f 100644
--- a/src/main/java/org/apache/sling/commons/log/logback/internal/util/Util.java
+++ b/src/main/java/org/apache/sling/commons/log/logback/internal/util/Util.java
@@ -76,4 +76,71 @@
         }
     }
 
+    //-------------Taken from org.apache.sling.commons.osgi.PropertiesUtil
+
+    /**
+     * Returns the boolean value of the parameter or the
+     * <code>defaultValue</code> if the parameter is <code>null</code>.
+     * If the parameter is not a <code>Boolean</code> it is converted
+     * by calling <code>Boolean.valueOf</code> on the string value of the
+     * object.
+     * @param propValue the property value or <code>null</code>
+     * @param defaultValue the default boolean value
+     */
+    public static boolean toBoolean(Object propValue, boolean defaultValue) {
+        propValue = toObject(propValue);
+        if (propValue instanceof Boolean) {
+            return (Boolean) propValue;
+        } else if (propValue != null) {
+            return Boolean.valueOf(String.valueOf(propValue));
+        }
+
+        return defaultValue;
+    }
+
+    /**
+     * Returns the parameter as an integer or the
+     * <code>defaultValue</code> if the parameter is <code>null</code> or if
+     * the parameter is not an <code>Integer</code> and cannot be converted to
+     * an <code>Integer</code> from the parameter's string value.
+     * @param propValue the property value or <code>null</code>
+     * @param defaultValue the default integer value
+     */
+    public static int toInteger(Object propValue, int defaultValue) {
+        propValue = toObject(propValue);
+        if (propValue instanceof Integer) {
+            return (Integer) propValue;
+        } else if (propValue != null) {
+            try {
+                return Integer.valueOf(String.valueOf(propValue));
+            } catch (NumberFormatException nfe) {
+                // don't care, fall through to default value
+            }
+        }
+
+        return defaultValue;
+    }
+
+    /**
+     * Returns the parameter as a single value. If the
+     * parameter is neither an array nor a <code>java.util.Collection</code> the
+     * parameter is returned unmodified. If the parameter is a non-empty array,
+     * the first array element is returned. If the property is a non-empty
+     * <code>java.util.Collection</code>, the first collection element is returned.
+     * Otherwise <code>null</code> is returned.
+     * @param propValue the parameter to convert.
+     */
+    public static Object toObject(Object propValue) {
+        if (propValue == null) {
+            return null;
+        } else if (propValue.getClass().isArray()) {
+            Object[] prop = (Object[]) propValue;
+            return prop.length > 0 ? prop[0] : null;
+        } else if (propValue instanceof Collection<?>) {
+            Collection<?> prop = (Collection<?>) propValue;
+            return prop.isEmpty() ? null : prop.iterator().next();
+        } else {
+            return propValue;
+        }
+    }
 }
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
index 848ef05..aefa58f 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -17,6 +17,8 @@
 #  under the License.
 #
 
+# suppress inspection "UnusedProperty" for whole file
+
 log.name = Apache Sling Logging Configuration
 log.description = Global configuration setup for the Sling OSGi LogService \
  implementation. See http://sling.apache.org/site/logging.html for more \
@@ -48,12 +50,8 @@
   pattern. The default is "'.'yyyy-MM-dd" (daily log rotation).
 
 log.pattern.name = Message Pattern
-log.pattern.description = Message Pattern for formatting the log messages. \
- This is a java.text.MessageFormat pattern supporting up to six arguments: \
- {0} The timestamp of type java.util.Date, {1} the log marker, {2} the name \
- of the current thread, {3} the name of the logger, {4} the debug level and \
- {5} the actual debug message. If the log call includes a Throwable, the \
- stacktrace is just appended to the message.
+log.pattern.description = Message Pattern for formatting the log messages. For \
+  complete details refer to http://logback.qos.ch/manual/layouts.html#ClassicPatternLayout
  
 log.factory.writer.name = Apache Sling Logging Writer Configuration
 log.factory.writer.description = Configure a Logger Writer for Sling Logging. \
@@ -70,4 +68,19 @@
  configuration. Each logger name applies for any child category unless configured \
  otherwise. E.g. a logger name of org.apache.sling applies to logger \
  org.apache.sling.commons unless there is a different configuration for \
- org.apache.sling.commons. 
+ org.apache.sling.commons.
+
+log.config.packagingData.name = Packaging Data
+log.config.packagingData.description = Include the packaging data which provide \
+  details about jar name and version of jar from which the class is loaded as part \
+  of stacktrace. See http://logback.qos.ch/reasonsToSwitch.html#packagingData
+
+log.config.maxCallerDataDepth.name = Max Caller Depth
+log.config.maxCallerDataDepth.description = The stack data depth computed during caller data \
+  extraction. See http://logback.qos.ch/manual/layouts.html#caller
+
+log.file.buffered.name = Buffered Logging
+log.file.buffered.description = By default logging events are immediately written to disk \
+  and will not be lost in case your application exits without properly closing appenders. \
+  If set to true  and if appenders are not closed properly when your application exits, then \
+  logging events not yet written to disk may be lost. See http://logback.qos.ch/manual/encoders.html#immediateFlush
\ No newline at end of file
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.xml b/src/main/resources/OSGI-INF/metatype/metatype.xml
index 459d4e0..348f736 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.xml
+++ b/src/main/resources/OSGI-INF/metatype/metatype.xml
@@ -44,12 +44,22 @@
             description="%log.file.size.description" />
         <metatype:AD id="org.apache.sling.commons.log.pattern"
             type="String"
-            default="{0\,date\,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3} {5}"
+            default="%d{dd.MM.yyyy HH:mm:ss.SSS} *%level* [%thread] %logger %msg%n"
             name="%log.pattern.name"
             description="%log.pattern.description" />
-      <metatype:AD id="org.apache.sling.commons.log.configurationFile"
-             type="String"  name="%log.config.file.name"
+        <metatype:AD id="org.apache.sling.commons.log.configurationFile"
+             type="String"
+             name="%log.config.file.name"
              description="%log.config.file.description" />
+        <metatype:AD id="org.apache.sling.commons.log.packagingDataEnabled"
+             type="Boolean"
+             name="%log.config.packagingData.name"
+             description="%log.config.packagingData.description" />
+        <metatype:AD id="org.apache.sling.commons.log.maxCallerDataDepth"
+             type="Integer"
+             default="7"
+             name="%log.config.maxCallerDataDepth.name"
+             description="%log.config.maxCallerDataDepth.description" />
     </metatype:OCD>
     <metatype:Designate pid="org.apache.sling.commons.log.LogManager">
         <metatype:Object
@@ -70,6 +80,9 @@
         <metatype:AD id="org.apache.sling.commons.log.file.size"
             type="String" default="'.'yyyy-MM-dd" name="%log.file.size.name"
             description="%log.file.size.description" />
+        <metatype:AD id="org.apache.sling.commons.log.file.buffered"
+             type="Boolean" default="false" name="%log.file.buffered.name"
+             description="%log.file.buffered.description" />
     </metatype:OCD>
     <metatype:Designate
         pid="org.apache.sling.commons.log.LogManager.factory.writer"
diff --git a/src/main/resources/res/ui/jquery.autocomplete.css b/src/main/resources/res/ui/jquery.autocomplete.css
new file mode 100644
index 0000000..9a95dc7
--- /dev/null
+++ b/src/main/resources/res/ui/jquery.autocomplete.css
@@ -0,0 +1,38 @@
+/**
+ * @fileOverview CSS for jquery-autocomplete, the jQuery Autocompleter
+ * @author <a href="mailto:dylan@dyve.net">Dylan Verheul</a>
+ * @license MIT | GPL | Apache 2.0, see LICENSE.txt
+ * @see https://github.com/dyve/jquery-autocomplete
+ */
+.acResults {
+    padding: 0px;
+    border: 1px solid WindowFrame;
+    background-color: Window;
+    overflow: hidden;
+}
+
+.acResults ul {
+    margin: 0px;
+    padding: 0px;
+    list-style-position: outside;
+    list-style: none;
+}
+
+.acResults ul li {
+    margin: 0px;
+    padding: 2px 5px;
+    cursor: pointer;
+    display: block;
+    font: menu;
+    font-size: 12px;
+    overflow: hidden;
+}
+
+.acLoading {
+    background : url('indicator.gif') right center no-repeat;
+}
+
+.acSelect {
+    background-color: Highlight;
+    color: HighlightText;
+}
\ No newline at end of file
diff --git a/src/main/resources/res/ui/jquery.autocomplete.min.js b/src/main/resources/res/ui/jquery.autocomplete.min.js
new file mode 100644
index 0000000..4bb8d58
--- /dev/null
+++ b/src/main/resources/res/ui/jquery.autocomplete.min.js
@@ -0,0 +1,9 @@
+/**
+ * @fileOverview jquery-autocomplete, the jQuery Autocompleter
+ * @author <a href="mailto:dylan@dyve.net">Dylan Verheul</a>
+ * @version 2.4.4
+ * @requires jQuery 1.6+
+ * @license MIT | GPL | Apache 2.0, see LICENSE.txt
+ * @see https://github.com/dyve/jquery-autocomplete
+ */
+(function($){"use strict";$.fn.autocomplete=function(options){var url;if(arguments.length>1){url=options;options=arguments[1];options.url=url}else if(typeof options==="string"){url=options;options={url:url}}var opts=$.extend({},$.fn.autocomplete.defaults,options);return this.each(function(){var $this=$(this);$this.data("autocompleter",new $.Autocompleter($this,$.meta?$.extend({},opts,$this.data()):opts))})};$.fn.autocomplete.defaults={inputClass:"acInput",loadingClass:"acLoading",resultsClass:"acResults",selectClass:"acSelect",queryParamName:"q",extraParams:{},remoteDataType:false,lineSeparator:"\n",cellSeparator:"|",minChars:2,maxItemsToShow:10,delay:400,useCache:true,maxCacheLength:10,matchSubset:true,matchCase:false,matchInside:true,mustMatch:false,selectFirst:false,selectOnly:false,showResult:null,preventDefaultReturn:1,preventDefaultTab:0,autoFill:false,filterResults:true,filter:true,sortResults:true,sortFunction:null,onItemSelect:null,onNoMatch:null,onFinish:null,matchStringConverter:null,beforeUseConverter:null,autoWidth:"min-width",useDelimiter:false,delimiterChar:",",delimiterKeyCode:188,processData:null,onError:null,enabled:true};var sanitizeResult=function(result){var value,data;var type=typeof result;if(type==="string"){value=result;data={}}else if($.isArray(result)){value=result[0];data=result.slice(1)}else if(type==="object"){value=result.value;data=result.data}value=String(value);if(typeof data!=="object"){data={}}return{value:value,data:data}};var sanitizeInteger=function(value,stdValue,options){var num=parseInt(value,10);options=options||{};if(isNaN(num)||options.min&&num<options.min){num=stdValue}return num};var makeUrlParam=function(name,value){return[name,encodeURIComponent(value)].join("=")};var makeUrl=function(url,params){var urlAppend=[];$.each(params,function(index,value){urlAppend.push(makeUrlParam(index,value))});if(urlAppend.length){url+=url.indexOf("?")===-1?"?":"&";url+=urlAppend.join("&")}return url};var sortValueAlpha=function(a,b,matchCase){a=String(a.value);b=String(b.value);if(!matchCase){a=a.toLowerCase();b=b.toLowerCase()}if(a>b){return 1}if(a<b){return-1}return 0};var plainTextParser=function(text,lineSeparator,cellSeparator){var results=[];var i,j,data,line,value,lines;lines=String(text).replace("\r\n","\n").split(lineSeparator);for(i=0;i<lines.length;i++){line=lines[i].split(cellSeparator);data=[];for(j=0;j<line.length;j++){data.push(decodeURIComponent(line[j]))}value=data.shift();results.push({value:value,data:data})}return results};$.Autocompleter=function($elem,options){if(!$elem||!($elem instanceof $)||$elem.length!==1||$elem.get(0).tagName.toUpperCase()!=="INPUT"){throw new Error("Invalid parameter for jquery.Autocompleter, jQuery object with one element with INPUT tag expected.")}var self=this;this.options=options;this.cacheData_={};this.cacheLength_=0;this.selectClass_="jquery-autocomplete-selected-item";this.keyTimeout_=null;this.finishTimeout_=null;this.lastKeyPressed_=null;this.lastProcessedValue_=null;this.lastSelectedValue_=null;this.active_=false;this.finishOnBlur_=true;this.options.minChars=sanitizeInteger(this.options.minChars,$.fn.autocomplete.defaults.minChars,{min:0});this.options.maxItemsToShow=sanitizeInteger(this.options.maxItemsToShow,$.fn.autocomplete.defaults.maxItemsToShow,{min:0});this.options.maxCacheLength=sanitizeInteger(this.options.maxCacheLength,$.fn.autocomplete.defaults.maxCacheLength,{min:1});this.options.delay=sanitizeInteger(this.options.delay,$.fn.autocomplete.defaults.delay,{min:0});if(this.options.preventDefaultReturn!=2){this.options.preventDefaultReturn=this.options.preventDefaultReturn?1:0}if(this.options.preventDefaultTab!=2){this.options.preventDefaultTab=this.options.preventDefaultTab?1:0}this.dom={};this.dom.$elem=$elem;this.dom.$elem.attr("autocomplete","off").addClass(this.options.inputClass);this.dom.$results=$("<div></div>").hide().addClass(this.options.resultsClass).css({position:"absolute"});$("body").append(this.dom.$results);$elem.keydown(function(e){self.lastKeyPressed_=e.keyCode;switch(self.lastKeyPressed_){case self.options.delimiterKeyCode:if(self.options.useDelimiter&&self.active_){self.selectCurrent()}break;case 35:case 36:case 16:case 17:case 18:case 37:case 39:break;case 38:e.preventDefault();if(self.active_){self.focusPrev()}else{self.activate()}return false;case 40:e.preventDefault();if(self.active_){self.focusNext()}else{self.activate()}return false;case 9:if(self.active_){self.selectCurrent();if(self.options.preventDefaultTab){e.preventDefault();return false}}if(self.options.preventDefaultTab===2){e.preventDefault();return false}break;case 13:if(self.active_){self.selectCurrent();if(self.options.preventDefaultReturn){e.preventDefault();return false}}if(self.options.preventDefaultReturn===2){e.preventDefault();return false}break;case 27:if(self.active_){e.preventDefault();self.deactivate(true);return false}break;default:self.activate()}});$elem.on("paste",function(){self.activate()});var onBlurFunction=function(){self.deactivate(true)};$elem.blur(function(){if(self.finishOnBlur_){self.finishTimeout_=setTimeout(onBlurFunction,200)}});$elem.parents("form").on("submit",onBlurFunction)};$.Autocompleter.prototype.position=function(){var offset=this.dom.$elem.offset();var height=this.dom.$results.outerHeight();var totalHeight=$(window).outerHeight();var inputBottom=offset.top+this.dom.$elem.outerHeight();var bottomIfDown=inputBottom+height;var position={top:inputBottom,left:offset.left};if(bottomIfDown>totalHeight){var topIfUp=offset.top-height;if(topIfUp>=0){position.top=topIfUp}}this.dom.$results.css(position)};$.Autocompleter.prototype.cacheRead=function(filter){var filterLength,searchLength,search,maxPos,pos;if(this.options.useCache){filter=String(filter);filterLength=filter.length;if(this.options.matchSubset){searchLength=1}else{searchLength=filterLength}while(searchLength<=filterLength){if(this.options.matchInside){maxPos=filterLength-searchLength}else{maxPos=0}pos=0;while(pos<=maxPos){search=filter.substr(0,searchLength);if(this.cacheData_[search]!==undefined){return this.cacheData_[search]}pos++}searchLength++}}return false};$.Autocompleter.prototype.cacheWrite=function(filter,data){if(this.options.useCache){if(this.cacheLength_>=this.options.maxCacheLength){this.cacheFlush()}filter=String(filter);if(this.cacheData_[filter]!==undefined){this.cacheLength_++}this.cacheData_[filter]=data;return this.cacheData_[filter]}return false};$.Autocompleter.prototype.cacheFlush=function(){this.cacheData_={};this.cacheLength_=0};$.Autocompleter.prototype.callHook=function(hook,data){var f=this.options[hook];if(f&&$.isFunction(f)){return f(data,this)}return false};$.Autocompleter.prototype.activate=function(){if(!this.options.enabled)return;var self=this;if(this.keyTimeout_){clearTimeout(this.keyTimeout_)}this.keyTimeout_=setTimeout(function(){self.activateNow()},this.options.delay)};$.Autocompleter.prototype.activateNow=function(){var value=this.beforeUseConverter(this.dom.$elem.val());if(value!==this.lastProcessedValue_&&value!==this.lastSelectedValue_){this.fetchData(value)}};$.Autocompleter.prototype.fetchData=function(value){var self=this;var processResults=function(results,filter){if(self.options.processData){results=self.options.processData(results)}self.showResults(self.filterResults(results,filter),filter)};this.lastProcessedValue_=value;if(value.length<this.options.minChars){processResults([],value)}else if(this.options.data){processResults(this.options.data,value)}else{this.fetchRemoteData(value,function(remoteData){processResults(remoteData,value)})}};$.Autocompleter.prototype.fetchRemoteData=function(filter,callback){var data=this.cacheRead(filter);if(data){callback(data)}else{var self=this;var dataType=self.options.remoteDataType==="json"?"json":"text";var ajaxCallback=function(data){var parsed=false;if(data!==false){parsed=self.parseRemoteData(data);self.cacheWrite(filter,parsed)}self.dom.$elem.removeClass(self.options.loadingClass);callback(parsed)};this.dom.$elem.addClass(this.options.loadingClass);$.ajax({url:this.makeUrl(filter),success:ajaxCallback,error:function(jqXHR,textStatus,errorThrown){if($.isFunction(self.options.onError)){self.options.onError(jqXHR,textStatus,errorThrown)}else{ajaxCallback(false)}},dataType:dataType})}};$.Autocompleter.prototype.setExtraParam=function(name,value){var index=$.trim(String(name));if(index){if(!this.options.extraParams){this.options.extraParams={}}if(this.options.extraParams[index]!==value){this.options.extraParams[index]=value;this.cacheFlush()}}};$.Autocompleter.prototype.makeUrl=function(param){var self=this;var url=this.options.url;var params=$.extend({},this.options.extraParams);if(this.options.queryParamName===false){url+=encodeURIComponent(param)}else{params[this.options.queryParamName]=param}return makeUrl(url,params)};$.Autocompleter.prototype.parseRemoteData=function(remoteData){var remoteDataType;var data=remoteData;if(this.options.remoteDataType==="json"){remoteDataType=typeof remoteData;switch(remoteDataType){case"object":data=remoteData;break;case"string":data=$.parseJSON(remoteData);break;default:throw new Error("Unexpected remote data type: "+remoteDataType)}return data}return plainTextParser(data,this.options.lineSeparator,this.options.cellSeparator)};$.Autocompleter.prototype.defaultFilter=function(result,filter){if(!result.value){return false}if(this.options.filterResults){var pattern=this.matchStringConverter(filter);var testValue=this.matchStringConverter(result.value);if(!this.options.matchCase){pattern=pattern.toLowerCase();testValue=testValue.toLowerCase()}var patternIndex=testValue.indexOf(pattern);if(this.options.matchInside){return patternIndex>-1}else{return patternIndex===0}}return true};$.Autocompleter.prototype.filterResult=function(result,filter){if(this.options.filter===false){return true}if($.isFunction(this.options.filter)){return this.options.filter(result,filter)}return this.defaultFilter(result,filter)};$.Autocompleter.prototype.filterResults=function(results,filter){var filtered=[];var i,result;for(i=0;i<results.length;i++){result=sanitizeResult(results[i]);if(this.filterResult(result,filter)){filtered.push(result)}}if(this.options.sortResults){filtered=this.sortResults(filtered,filter)}if(this.options.maxItemsToShow>0&&this.options.maxItemsToShow<filtered.length){filtered.length=this.options.maxItemsToShow}return filtered};$.Autocompleter.prototype.sortResults=function(results,filter){var self=this;var sortFunction=this.options.sortFunction;if(!$.isFunction(sortFunction)){sortFunction=function(a,b,f){return sortValueAlpha(a,b,self.options.matchCase)}}results.sort(function(a,b){return sortFunction(a,b,filter,self.options)});return results};$.Autocompleter.prototype.matchStringConverter=function(s,a,b){var converter=this.options.matchStringConverter;if($.isFunction(converter)){s=converter(s,a,b)}return s};$.Autocompleter.prototype.beforeUseConverter=function(s){s=this.getValue(s);var converter=this.options.beforeUseConverter;if($.isFunction(converter)){s=converter(s)}return s};$.Autocompleter.prototype.enableFinishOnBlur=function(){this.finishOnBlur_=true};$.Autocompleter.prototype.disableFinishOnBlur=function(){this.finishOnBlur_=false};$.Autocompleter.prototype.createItemFromResult=function(result){var self=this;var $li=$("<li/>");$li.text(this.showResult(result.value,result.data));$li.data({value:result.value,data:result.data}).click(function(){self.selectItem($li)}).mousedown(self.disableFinishOnBlur).mouseup(self.enableFinishOnBlur);return $li};$.Autocompleter.prototype.getItems=function(){return $(">ul>li",this.dom.$results)};$.Autocompleter.prototype.showResults=function(results,filter){var numResults=results.length;var self=this;var $ul=$("<ul></ul>");var i,result,$li,autoWidth,first=false,$first=false;if(numResults){for(i=0;i<numResults;i++){result=results[i];$li=this.createItemFromResult(result);$ul.append($li);if(first===false){first=String(result.value);$first=$li;$li.addClass(this.options.firstItemClass)}if(i===numResults-1){$li.addClass(this.options.lastItemClass)}}this.dom.$results.html($ul).show();this.position();if(this.options.autoWidth){autoWidth=this.dom.$elem.outerWidth()-this.dom.$results.outerWidth()+this.dom.$results.width();this.dom.$results.css(this.options.autoWidth,autoWidth)}this.getItems().hover(function(){self.focusItem(this)},function(){});if(this.autoFill(first,filter)||this.options.selectFirst||this.options.selectOnly&&numResults===1){this.focusItem($first)}this.active_=true}else{this.hideResults();this.active_=false}};$.Autocompleter.prototype.showResult=function(value,data){if($.isFunction(this.options.showResult)){return this.options.showResult(value,data)}else{return value}};$.Autocompleter.prototype.autoFill=function(value,filter){var lcValue,lcFilter,valueLength,filterLength;if(this.options.autoFill&&this.lastKeyPressed_!==8){lcValue=String(value).toLowerCase();lcFilter=String(filter).toLowerCase();valueLength=value.length;filterLength=filter.length;if(lcValue.substr(0,filterLength)===lcFilter){var d=this.getDelimiterOffsets();var pad=d.start?" ":"";this.setValue(pad+value);var start=filterLength+d.start+pad.length;var end=valueLength+d.start+pad.length;this.selectRange(start,end);return true}}return false};$.Autocompleter.prototype.focusNext=function(){this.focusMove(+1)};$.Autocompleter.prototype.focusPrev=function(){this.focusMove(-1)};$.Autocompleter.prototype.focusMove=function(modifier){var $items=this.getItems();modifier=sanitizeInteger(modifier,0);if(modifier){for(var i=0;i<$items.length;i++){if($($items[i]).hasClass(this.selectClass_)){this.focusItem(i+modifier);return}}}this.focusItem(0)};$.Autocompleter.prototype.focusItem=function(item){var $item,$items=this.getItems();if($items.length){$items.removeClass(this.selectClass_).removeClass(this.options.selectClass);if(typeof item==="number"){if(item<0){item=0}else if(item>=$items.length){item=$items.length-1}$item=$($items[item])}else{$item=$(item)}if($item){$item.addClass(this.selectClass_).addClass(this.options.selectClass)}}};$.Autocompleter.prototype.selectCurrent=function(){var $item=$("li."+this.selectClass_,this.dom.$results);if($item.length===1){this.selectItem($item)}else{this.deactivate(false)}};$.Autocompleter.prototype.selectItem=function($li){var value=$li.data("value");var data=$li.data("data");var displayValue=this.displayValue(value,data);var processedDisplayValue=this.beforeUseConverter(displayValue);this.lastProcessedValue_=processedDisplayValue;this.lastSelectedValue_=processedDisplayValue;var d=this.getDelimiterOffsets();var delimiter=this.options.delimiterChar;var elem=this.dom.$elem;var extraCaretPos=0;if(this.options.useDelimiter){if(elem.val().substring(d.start-1,d.start)==delimiter&&delimiter!=" "){displayValue=" "+displayValue}if(elem.val().substring(d.end,d.end+1)!=delimiter&&this.lastKeyPressed_!=this.options.delimiterKeyCode){displayValue=displayValue+delimiter}else{extraCaretPos=1}}this.setValue(displayValue);this.setCaret(d.start+displayValue.length+extraCaretPos);this.callHook("onItemSelect",{value:value,data:data});this.deactivate(true);elem.focus()};$.Autocompleter.prototype.displayValue=function(value,data){if($.isFunction(this.options.displayValue)){return this.options.displayValue(value,data)}return value};$.Autocompleter.prototype.hideResults=function(){this.dom.$results.hide()};$.Autocompleter.prototype.deactivate=function(finish){if(this.finishTimeout_){clearTimeout(this.finishTimeout_)}if(this.keyTimeout_){clearTimeout(this.keyTimeout_)}if(finish){if(this.lastProcessedValue_!==this.lastSelectedValue_){if(this.options.mustMatch){this.setValue("")}this.callHook("onNoMatch")}if(this.active_){this.callHook("onFinish")}this.lastKeyPressed_=null;this.lastProcessedValue_=null;this.lastSelectedValue_=null;this.active_=false}this.hideResults()};$.Autocompleter.prototype.selectRange=function(start,end){var input=this.dom.$elem.get(0);if(input.setSelectionRange){input.focus();input.setSelectionRange(start,end)}else if(input.createTextRange){var range=input.createTextRange();range.collapse(true);range.moveEnd("character",end);range.moveStart("character",start);range.select()}};$.Autocompleter.prototype.setCaret=function(pos){this.selectRange(pos,pos)};$.Autocompleter.prototype.getCaret=function(){var $elem=this.dom.$elem;var elem=$elem[0];var val,selection,range,start,end,stored_range;if(elem.createTextRange){selection=document.selection;if(elem.tagName.toLowerCase()!="textarea"){val=$elem.val();range=selection.createRange().duplicate();range.moveEnd("character",val.length);if(range.text===""){start=val.length}else{start=val.lastIndexOf(range.text)}range=selection.createRange().duplicate();range.moveStart("character",-val.length);end=range.text.length}else{range=selection.createRange();stored_range=range.duplicate();stored_range.moveToElementText(elem);stored_range.setEndPoint("EndToEnd",range);start=stored_range.text.length-range.text.length;end=start+range.text.length}}else{start=$elem[0].selectionStart;end=$elem[0].selectionEnd}return{start:start,end:end}};$.Autocompleter.prototype.setValue=function(value){if(this.options.useDelimiter){var val=this.dom.$elem.val();var d=this.getDelimiterOffsets();var preVal=val.substring(0,d.start);var postVal=val.substring(d.end);value=preVal+value+postVal}this.dom.$elem.val(value)};$.Autocompleter.prototype.getValue=function(value){if(this.options.useDelimiter){var d=this.getDelimiterOffsets();return value.substring(d.start,d.end).trim()}else{return value}};$.Autocompleter.prototype.getDelimiterOffsets=function(){var val=this.dom.$elem.val();if(this.options.useDelimiter){var preCaretVal=val.substring(0,this.getCaret().start);var start=preCaretVal.lastIndexOf(this.options.delimiterChar)+1;var postCaretVal=val.substring(this.getCaret().start);var end=postCaretVal.indexOf(this.options.delimiterChar);if(end==-1)end=val.length;end+=this.getCaret().start}else{start=0;end=val.length}return{start:start,end:end}}})(jQuery);
\ No newline at end of file
diff --git a/src/main/resources/res/ui/slinglog.js b/src/main/resources/res/ui/slinglog.js
new file mode 100644
index 0000000..47bcae6
--- /dev/null
+++ b/src/main/resources/res/ui/slinglog.js
@@ -0,0 +1,133 @@
+/**
+ * Removes the editor (toggles all displayfields/editables).
+ */
+function removeEditor(row) {
+    $(row).find(".loggers").toggle();
+	$(row).find(".logLevels").toggle();
+	$(row).find(".logFile").toggle();
+	$(row).find(".configureLink").toggle();
+	$(row).find(".editElement").remove();
+	$(row).removeClass("currentEditor");
+}
+
+/**
+ * Turns the loglevel element into an selectfield (current loglevel is selected).
+ */
+function addLogLevelSelect(row) {
+    var logLevelElement = $(row).find(".logLevels");
+    // get the current loglevel
+	var currentLogLevel = logLevelElement.attr("data-currentloglevel");
+	if(!currentLogLevel) {
+	    // convenience default for new loggers
+	    currentLogLevel = "INFO";
+	}
+	// get all available loglevels (present in the "newlogger" element)
+	var allLogLevels = $("#allLogLevels").attr("data-loglevels").split(",");
+	var select = $('<select class="editElement" name="loglevel"></select>');
+	$.each(allLogLevels, function(index, logLevel) {
+		select.append('<option'+(logLevel == currentLogLevel ? ' selected="selected"' : '')+'>'+logLevel+'</option>');
+    });
+	logLevelElement.after(select);
+	logLevelElement.toggle();
+}
+
+/**
+ * Adds a new editable logger for the given loggerelement (with controls for adding/removing).
+ * @param loggersElement logger element
+ * @param loggerName name of the logger
+ */
+function addLogger(loggersElement, loggerName) {
+    var addButton = $('<input type="submit" name="add" class="ui-state-default ui-corner-all" value="+" style="width:5%;" />');
+    addButton.bind("click", function() {
+    	addLogger($(this).parent(), "");
+    	return false;
+    });
+	var removeButton = $('<input type="submit" class="ui-state-default ui-corner-all" name="remove" value="-" style="width:5%;" />');
+	removeButton.bind("click", function() {
+		$(this).parent().remove();
+		return false;
+	});
+	var loggerField = $('<input type="text" name="logger" class="loggerField ui-state-default ui-corner-all inputText" value="'+loggerName+'" autocomplete="off" style="width:89%;" />');
+	// add the autocomplete with the array of all loggers
+	loggerField.autocomplete({
+        data: loggers
+    });
+	var logger = $('<div class="editElement"></div>').append(loggerField, addButton, removeButton);
+	loggersElement.after(logger);
+}
+
+/**
+ * Turns the logger elements into inputfields (with controls).
+ */
+function addLoggers(row) {
+    var loggersElement = $(row).find(".loggers");
+	var loggers = loggersElement.find(".logger");
+	if(loggers.length == 0) {
+	    addLogger(loggersElement, "");	
+	}
+	$.each(loggers, function(index, logger) {
+	      addLogger(loggersElement, $(logger).html());		  
+	});
+	loggersElement.toggle();
+}
+
+/**
+ * Turns the logfile element into an inputfield.
+ */
+function addLogFile(row) {
+    var logFileElement = $(row).find(".logFile");
+    var logFile = "";
+    if(logFileElement.length > 0) {
+        logFile = $(logFileElement).html();
+    }
+    if (logFile.length == 0) {
+    	// no logfile -> new logger -> take default
+    	logFile = $("#defaultLogfile").attr("data-defaultlogfile");
+    }
+    logFileElement.after('<input style="width:100%" class="editElement ui-state-default ui-corner-all inputText" type="text" name="logfile" value="'+logFile+'" />');
+    logFileElement.toggle();
+}
+
+/**
+ * Activates the logger configurator (called by clicking the configure link).
+ * Turns all display fields in the logger row containing the configure link into edit fields.
+ * @param button configure link
+ */
+function configureLogger(button) {
+	var configureLink = $(button.currentTarget);
+	var row = configureLink.parent().parent();
+	var rowId = $(row).attr("id");
+	// remove the current editor, since we have only one form only one editor can be active the same time
+	removeEditor($(".currentEditor"));
+	// add class as marker (id is already used for pid)
+	row.addClass("currentEditor");
+	// add the editables
+    addLogLevelSelect(row);
+	addLoggers(row);
+    addLogFile(row);
+    // add controls
+    var hiddenField = $('<input class="editElement" type="hidden" name="pid" value="'+(rowId != 'newlogger' ? rowId : '')+'" />');
+    var saveButton = $('<input class="editElement" type="submit" name="save" value="Save" />');
+    var cancelButton=$('<input class="editElement" type="submit" value="Cancel" />');
+	cancelButton.bind("click", function() {
+	    var row = $(this).parent().parent();
+	    removeEditor(row);
+	    return false;
+	});
+    var deleteButton = $('<input class="editElement" type="submit" name="delete" value="Remove Logger" />');
+    configureLink.after(saveButton, cancelButton, hiddenField);
+    if (rowId !== "newlogger") {
+    	// add a delete buttons for existing loggers
+    	cancelButton.after(deleteButton);
+    }
+    configureLink.toggle();
+	// prevent click on link
+    return false;
+}
+
+/**
+ * Initializes the log panel.
+ */
+function initializeSlingLogPanel() {
+	$("#loggerConfig").find(".configureLink").bind("click", configureLogger);
+}
diff --git a/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java b/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java
index 4e2cd0c..f4b3f65 100644
--- a/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java
+++ b/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java
@@ -28,9 +28,7 @@
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.spi.ClassPackagingData;
 import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.classic.spi.StackTraceElementProxy;
 import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.AppenderBase;
 import org.junit.After;
@@ -46,9 +44,7 @@
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.slf4j.LoggerFactory;
 
-import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
@@ -123,26 +119,6 @@
         assertEquals(2, ta.events.size());
     }
 
-    @Test
-    public void testPackagingData() throws Exception {
-        TestAppender ta = registerAppender("foo.bar.packaging");
-        delay();
-
-        Logger foo = (Logger)LoggerFactory.getLogger("foo.bar.packaging");
-        foo.warn("This is a test", new Exception());
-
-        // One event should be logged.
-        assertEquals(1, ta.events.size());
-        ILoggingEvent e = ta.events.get(0);
-        StackTraceElementProxy[] stProxies = e.getThrowableProxy().getStackTraceElementProxyArray();
-
-        ClassPackagingData cpd1 = stProxies[0].getClassPackagingData();
-
-        //For pax exam the bundle is created with name starting with PAXEXAM-PROBE
-        //As codeLocation is OSGi env is bundle symbolic name we check for that
-        assertThat(cpd1.getCodeLocation(), is(bundleContext.getBundle().getSymbolicName()));
-    }
-
     @After
     public void unregisterAppender(){
         sr.unregister();
diff --git a/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java b/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java
index 4024517..39dd48b 100644
--- a/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java
+++ b/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java
@@ -25,6 +25,7 @@
 
 import javax.inject.Inject;
 
+import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import org.junit.Test;
@@ -77,6 +78,8 @@
 
     public static final String FACTORY_PID_CONFIGS = PID + ".factory.config";
 
+    public static final String LOG_PACKAGING_DATA = "org.apache.sling.commons.log.packagingDataEnabled";
+
     @Inject
     private ConfigurationAdmin ca;
 
@@ -138,6 +141,20 @@
     }
 
     @Test
+    public void testPackagingDataConfig() throws Exception {
+        // Set log level to debug for Root logger
+        Configuration config = ca.getConfiguration(PID, null);
+        Dictionary<String, Object> p = new Hashtable<String, Object>();
+        p.put(LOG_PACKAGING_DATA, Boolean.FALSE);
+        p.put(LOG_LEVEL, "INFO");
+        config.update(p);
+
+        delay();
+
+        assertFalse(((LoggerContext)LoggerFactory.getILoggerFactory()).isPackagingDataEnabled());
+    }
+
+    @Test
     public void testExternalConfig() throws Exception {
         Configuration config = ca.getConfiguration(PID, null);
         Dictionary<String, Object> p = new Hashtable<String, Object>();
diff --git a/src/test/java/org/apache/sling/commons/log/logback/integration/ITWebConsoleRemote.java b/src/test/java/org/apache/sling/commons/log/logback/integration/ITWebConsoleRemote.java
index 831441d..25e76b5 100644
--- a/src/test/java/org/apache/sling/commons/log/logback/integration/ITWebConsoleRemote.java
+++ b/src/test/java/org/apache/sling/commons/log/logback/integration/ITWebConsoleRemote.java
@@ -25,7 +25,6 @@
 import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
 import com.gargoylesoftware.htmlunit.WebClient;
 import com.gargoylesoftware.htmlunit.html.HtmlPage;
-
 import org.apache.commons.io.FilenameUtils;
 import org.apache.sling.commons.log.logback.integration.remote.WebConsoleTestActivator;
 import org.junit.AfterClass;
@@ -74,6 +73,7 @@
             mavenBundle("commons-io", "commons-io").versionAsInProject(),
             wrappedBundle(mavenBundle("commons-fileupload", "commons-fileupload").versionAsInProject()),
             wrappedBundle(mavenBundle("org.json", "json").versionAsInProject()),
+            configAdmin(),
             frameworkProperty("org.apache.sling.commons.log.configurationFile").value(
                 FilenameUtils.concat(new File(".").getAbsolutePath(), "src/test/resources/test-webconsole-remote.xml")),
             createWebConsoleTestBundle()
diff --git a/src/test/java/org/apache/sling/commons/log/logback/integration/remote/WebConsoleTestActivator.java b/src/test/java/org/apache/sling/commons/log/logback/integration/remote/WebConsoleTestActivator.java
index a185212..c6eb08b 100644
--- a/src/test/java/org/apache/sling/commons/log/logback/integration/remote/WebConsoleTestActivator.java
+++ b/src/test/java/org/apache/sling/commons/log/logback/integration/remote/WebConsoleTestActivator.java
@@ -18,6 +18,12 @@
  */
 package org.apache.sling.commons.log.logback.integration.remote;
 
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.spi.ILoggingEvent;
@@ -33,12 +39,6 @@
 import org.slf4j.Marker;
 import org.xml.sax.InputSource;
 
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-
 /**
  * Test bundle activator which registers all type of extension point supported by bundle
  * Used by ITWebConsoleRemote to assert output of the WebConsole Plugin
@@ -61,8 +61,8 @@
         Dictionary<String, Object> props = new Hashtable<String, Object>();
         String prefix = "WebConsoleTest";
         String[] loggers = {
-                prefix + ".foo.bar:DEBUG",
-                prefix + ".foo.baz:INFO",
+                prefix + ".foo.bar",
+                prefix + ".foo.baz",
         };
 
         props.put("loggers", loggers);
diff --git a/src/test/resources/test-jul-config.xml b/src/test/resources/test-jul-config.xml
index bceeac2..9e3a3f0 100755
--- a/src/test/resources/test-jul-config.xml
+++ b/src/test/resources/test-jul-config.xml
@@ -18,7 +18,9 @@
   -->
 
 <configuration>
-  <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
+  <newRule pattern="*/configuration/osgi"
+           actionClass="org.apache.sling.commons.log.logback.OsgiAction"/>
+  <osgi/>
 
   <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>