You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ie...@apache.org on 2013/02/27 09:36:44 UTC

svn commit: r1450675 [1/3] - in /sling/whiteboard/ieb/log: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/commons/ src/main/java/org/apache/sling/commons/log/...

Author: ieb
Date: Wed Feb 27 08:36:42 2013
New Revision: 1450675

URL: http://svn.apache.org/r1450675
Log:
Added a copy of the commons log bundle to my whiteboard to share possible monitor impl

Added:
    sling/whiteboard/ieb/log/
    sling/whiteboard/ieb/log/README.txt   (with props)
    sling/whiteboard/ieb/log/pom.xml   (with props)
    sling/whiteboard/ieb/log/src/
    sling/whiteboard/ieb/log/src/main/
    sling/whiteboard/ieb/log/src/main/java/
    sling/whiteboard/ieb/log/src/main/java/org/
    sling/whiteboard/ieb/log/src/main/java/org/apache/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/Activator.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/LogManager.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationException.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationServiceFactory.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/GlobalConfigurator.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogConfigurator.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactory.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LoggerManagedServiceFactory.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/FileRotator.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriter.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/ScheduledFileRotator.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SizeLimitedFileRotator.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingConfigurationPrinter.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLogPanel.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLogger.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerConfig.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerLevel.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerWriter.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/slf4j/
    sling/whiteboard/ieb/log/src/main/java/org/slf4j/impl/
    sling/whiteboard/ieb/log/src/main/java/org/slf4j/impl/StaticLoggerBinder.java   (with props)
    sling/whiteboard/ieb/log/src/main/java/org/slf4j/impl/StaticMarkerBinder.java   (with props)
    sling/whiteboard/ieb/log/src/main/resources/
    sling/whiteboard/ieb/log/src/main/resources/OSGI-INF/
    sling/whiteboard/ieb/log/src/main/resources/OSGI-INF/metatype/
    sling/whiteboard/ieb/log/src/main/resources/OSGI-INF/metatype/metatype.properties   (with props)
    sling/whiteboard/ieb/log/src/main/resources/OSGI-INF/metatype/metatype.xml   (with props)
    sling/whiteboard/ieb/log/src/test/
    sling/whiteboard/ieb/log/src/test/java/
    sling/whiteboard/ieb/log/src/test/java/org/
    sling/whiteboard/ieb/log/src/test/java/org/apache/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/ActivatorTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/config/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/config/AbstractSlingConfigTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/config/GlobalConfigurationTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactoryTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/AbstractSlingLogTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriterTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/SizeLimitedFileRotatorTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/SlingConfigurationPrinterTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/SlingLogPanelTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/SlingLogWriterTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerLevelTest.java   (with props)
    sling/whiteboard/ieb/log/src/test/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerTest.java   (with props)

Added: sling/whiteboard/ieb/log/README.txt
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/README.txt?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/README.txt (added)
+++ sling/whiteboard/ieb/log/README.txt Wed Feb 27 08:36:42 2013
@@ -0,0 +1,69 @@
+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.

Propchange: sling/whiteboard/ieb/log/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/ieb/log/README.txt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/whiteboard/ieb/log/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/pom.xml?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/pom.xml (added)
+++ sling/whiteboard/ieb/log/pom.xml Wed Feb 27 08:36:42 2013
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>15</version>
+        <relativePath>../../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.commons.log</artifactId>
+    <version>3.0.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling SLF4J Implementation</name>
+    <description>
+        This bundle implements the SLF4J API with support for dynamic
+        configuration through OSGi Configuration Admin Service.
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/commons/log</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/log</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log</url>
+    </scm>
+    
+    <properties>
+      <slf4j.version>1.6.4</slf4j.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.3.6</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>
+                            org.apache.sling.commons.log.internal.Activator
+                        </Bundle-Activator>
+                        <Bundle-DocURL>
+                            http://sling.apache.org/site/logging.html
+                        </Bundle-DocURL>
+                        <Export-Package>
+                            org.slf4j.impl;version=${slf4j.version}
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.sling.commons.log.*,
+                        </Private-Package>
+                        <Import-Package>
+                            !org.slf4j.impl,
+                            org.osgi.framework;version=1.3,
+                            org.slf4j;provide:=true,
+                            org.slf4j.spi;provide:=true,
+                            *
+                        </Import-Package>
+                        <DynamicImport-Package>
+                            org.osgi.service.cm;version=1.2,
+                            javax.servlet;javax.servlet.http;version=2.3
+                        </DynamicImport-Package>
+                        <Embed-Dependency>
+                            jul-to-slf4j;inline="org/slf4j/bridge/SLF4JBridgeHandler.class"
+                        </Embed-Dependency>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <!-- No javadocs at all -->
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </reporting>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jul-to-slf4j</artifactId>
+            <version>${slf4j.version}</version>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- OSGi Libraries not included here -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        
+        <!-- servlet API for the web console plugin -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.3</version>
+        </dependency>
+
+        <!--  OSGi Command Line Shell support -->        
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.gogo.runtime</artifactId>
+            <version>0.6.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <!-- testing -->
+        <!--  using mockito because its a bit more relaxed and makes it easier to maintain
+              the test cases if dependencies change -->
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.8.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+</project>

Propchange: sling/whiteboard/ieb/log/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/ieb/log/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/Activator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/Activator.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/Activator.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/Activator.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,83 @@
+/*
+ * 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.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
+/**
+ * The <code>Activator</code> class is the <code>BundleActivator</code> for
+ * the log service bundle. This activator sets up logging in NLog4J and
+ * registers the <code>LogService</code> and <code>LogReaderService</code>.
+ * When the bundle is stopped, the NLog4J subsystem is simply shutdown.
+ */
+public class Activator implements BundleActivator {
+
+    private static final String JUL_SUPPORT = "org.apache.sling.commons.log.julenabled";
+
+    private LogManager logManager;
+
+    /**
+     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+     */
+    public void start(final BundleContext context) throws Exception {
+        logManager = new LogManager(context);
+
+        if (Boolean.parseBoolean(context.getProperty(JUL_SUPPORT))) {
+
+            // 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();
+        }
+    }
+
+    /**
+     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     */
+    public void stop(final BundleContext context) throws Exception {
+        SLF4JBridgeHandler.uninstall();
+
+        if (logManager != null) {
+            logManager.shutdown();
+            logManager = null;
+        }
+    }
+
+    /**
+     * 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.
+     */
+    public static class DummyLogManagerConfiguration {
+    }
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/Activator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/LogManager.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/LogManager.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/LogManager.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/LogManager.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,224 @@
+/*
+ * 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.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.commons.log.internal.config.ConfigurationServiceFactory;
+import org.apache.sling.commons.log.internal.slf4j.LogConfigManager;
+import org.apache.sling.commons.log.internal.slf4j.SlingConfigurationPrinter;
+import org.apache.sling.commons.log.internal.slf4j.SlingLogPanel;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>LogManager</code> manages the loggers used by the LogService and
+ * the rest of the system.
+ */
+public class LogManager {
+
+    public static final String LOG_LEVEL = "org.apache.sling.commons.log.level";
+
+    public static final String LOG_FILE = "org.apache.sling.commons.log.file";
+
+    public static final String LOG_FILE_NUMBER = "org.apache.sling.commons.log.file.number";
+
+    public static final String LOG_FILE_SIZE = "org.apache.sling.commons.log.file.size";
+
+    public static final String LOG_PATTERN = "org.apache.sling.commons.log.pattern";
+
+    public static final String LOG_PATTERN_DEFAULT = "{0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3} {5}";
+
+    public static final String LOG_LOGGERS = "org.apache.sling.commons.log.names";
+
+    public static final String LOG_LEVEL_DEFAULT = "INFO";
+
+    public static final int LOG_FILE_NUMBER_DEFAULT = 5;
+
+    public static final String LOG_FILE_SIZE_DEFAULT = "'.'yyyy-MM-dd";
+
+    public static final String PID = "org.apache.sling.commons.log.LogManager";
+
+    public static final String FACTORY_PID_WRITERS = PID + ".factory.writer";
+
+    public static final String FACTORY_PID_CONFIGS = PID + ".factory.config";
+
+    private final LogConfigManager logConfigManager;
+
+    /**
+     * default log category - set during init()
+     */
+    private Logger log;
+
+    private ServiceRegistration loggingConfigurable;
+
+    private ServiceRegistration writerConfigurer;
+
+    private ServiceRegistration configConfigurer;
+
+    private ServiceRegistration panelRegistration;
+
+    LogManager(final BundleContext context) {
+
+        // set the root folder for relative log file names
+        logConfigManager = LogConfigManager.getInstance();
+        logConfigManager.setRoot(context.getProperty("sling.home"));
+        logConfigManager.setDefaultConfiguration(getBundleConfiguration(context));
+
+        // get our own logger
+        log = LoggerFactory.getLogger(LogManager.class);
+        log.info("LogManager: Logging set up from context");
+
+        // prepare registration properties (will be reused)
+        Dictionary<String, String> props = new Hashtable<String, String>();
+        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+
+        // register for official (global) configuration now
+        props.put(Constants.SERVICE_PID, PID);
+        props.put(Constants.SERVICE_DESCRIPTION,
+            "LogManager Configuration Admin support");
+        loggingConfigurable = context.registerService(
+            "org.osgi.service.cm.ManagedService",
+            new ConfigurationServiceFactory(logConfigManager,
+                "org.apache.sling.commons.log.internal.config.GlobalConfigurator"),
+            props);
+
+        // register for log writer configuration
+        ConfigurationServiceFactory msf = new ConfigurationServiceFactory(
+            logConfigManager,
+            "org.apache.sling.commons.log.internal.config.LogWriterManagedServiceFactory");
+        props.put(Constants.SERVICE_PID, FACTORY_PID_WRITERS);
+        props.put(Constants.SERVICE_DESCRIPTION, "LogWriter configurator");
+        writerConfigurer = context.registerService(
+            "org.osgi.service.cm.ManagedServiceFactory", msf, props);
+
+        // register for log configuration
+        msf = new ConfigurationServiceFactory(
+            logConfigManager,
+            "org.apache.sling.commons.log.internal.config.LoggerManagedServiceFactory");
+        props.put(Constants.SERVICE_PID, FACTORY_PID_CONFIGS);
+        props.put(Constants.SERVICE_DESCRIPTION, "Logger configurator");
+        configConfigurer = context.registerService(
+            "org.osgi.service.cm.ManagedServiceFactory", msf, props);
+
+        // setup the web console plugin panel. This may fail loading
+        // the panel class if the Servlet API is not wired
+        try {
+            registerPanel(context);
+        } catch (Throwable ignore) {
+        }
+
+        // setup the web console configuration printer.
+        SlingConfigurationPrinter.registerPrinter(context);
+    }
+
+    void shutdown() {
+
+        // tear down the web console plugin panel (if created at all). This
+        // may fail loading the panel class if the Servlet API is not wired
+         unregisterPanel();
+
+        // tear down the web console configuration printer (if created at all).
+        SlingConfigurationPrinter.unregisterPrinter();
+
+        if (loggingConfigurable != null) {
+            loggingConfigurable.unregister();
+            loggingConfigurable = null;
+        }
+
+        if (writerConfigurer != null) {
+            writerConfigurer.unregister();
+            writerConfigurer = null;
+        }
+
+        if (configConfigurer != null) {
+            configConfigurer.unregister();
+            configConfigurer = null;
+        }
+
+        // shutdown the log manager
+        logConfigManager.close();
+    }
+
+    // ---------- ManagedService interface -------------------------------------
+
+    private Dictionary<String, String> getBundleConfiguration(
+            BundleContext bundleContext) {
+        Dictionary<String, String> config = new Hashtable<String, String>();
+
+        final String[] props = { LOG_LEVEL, LOG_LEVEL, LOG_FILE,
+            LOG_FILE_NUMBER, LOG_FILE_SIZE, LOG_PATTERN };
+        for (String prop : props) {
+            String value = bundleContext.getProperty(prop);
+            if (value != null) {
+                config.put(prop, value);
+            }
+        }
+
+        // ensure sensible default values for required configuration field(s)
+        if (config.get(LOG_LEVEL) == null) {
+            config.put(LOG_LEVEL, LOG_LEVEL_DEFAULT);
+        }
+
+        return config;
+    }
+
+    //---------- Logging Web Console Plugin
+
+    private void registerPanel(BundleContext ctx) {
+        if (panelRegistration == null) {
+            Dictionary<String, Object> props = new Hashtable<String, Object>();
+            props.put("felix.webconsole.label", "slinglog");
+            props.put("felix.webconsole.title", "Sling Log Support");
+
+            // SLING-1068 Prevent ClassCastException in Sling Engine 2.0.2-incubator
+            props.put("sling.core.servletName", "Sling Log Support Console Servlet");
+
+            panelRegistration = ctx.registerService("javax.servlet.Servlet", new ServiceFactory() {
+
+                private Object instance;
+
+                public Object getService(Bundle bundle, ServiceRegistration registration) {
+                    synchronized (this) {
+                        if (this.instance == null) {
+                            this.instance = new SlingLogPanel(LogManager.this.logConfigManager);
+                        }
+                        return instance;
+                    }
+                }
+
+                public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+                    // nothing to do for cleanup, just drop reference
+                }
+            }, props);
+        }
+    }
+
+    private void unregisterPanel() {
+        if (panelRegistration != null) {
+            panelRegistration.unregister();
+            panelRegistration = null;
+        }
+    }
+
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/LogManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationException.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationException.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationException.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationException.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,47 @@
+/*
+ * 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.internal.config;
+
+public class ConfigurationException extends Exception {
+
+    private static final long serialVersionUID = -9213226340780391070L;
+
+    private final String property;
+
+    private final String reason;
+
+    public ConfigurationException(final String property, final String reason) {
+        this(property, reason, null);
+    }
+
+    public ConfigurationException(final String property, final String reason,
+            final Throwable cause) {
+        super("", cause);
+        this.property = property;
+        this.reason = reason;
+    }
+
+    public String getProperty() {
+        return property;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationServiceFactory.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationServiceFactory.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationServiceFactory.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationServiceFactory.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,73 @@
+/*
+ * 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.internal.config;
+
+import org.apache.sling.commons.log.internal.slf4j.LogConfigManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+public class ConfigurationServiceFactory implements ServiceFactory {
+
+    private final LogConfigManager logConfigManager;
+
+    private final String serviceClass;
+
+    private int useCount;
+
+    private Object service;
+
+    public ConfigurationServiceFactory(final LogConfigManager logConfigManager,
+            final String serviceClass) {
+        this.logConfigManager = logConfigManager;
+        this.serviceClass = serviceClass;
+    }
+
+    public Object getService(Bundle bundle, ServiceRegistration registration) {
+        if (service == null) {
+            useCount = 1;
+            service = createInstance();
+        } else {
+            useCount++;
+        }
+        return service;
+    }
+
+    public void ungetService(Bundle bundle, ServiceRegistration registration,
+            Object service) {
+        useCount--;
+        if (useCount <= 0) {
+            this.service = null;
+        }
+    }
+
+    private Object createInstance() {
+        try {
+            Class<?> type = getClass().getClassLoader().loadClass(serviceClass);
+            Object instance = type.newInstance();
+            if (instance instanceof LogConfigurator) {
+                ((LogConfigurator) instance).setLogConfigManager(logConfigManager);
+            }
+            return instance;
+        } catch (Throwable t) {
+            throw new RuntimeException("Failed to create " + serviceClass
+                + " instance", t);
+        }
+    }
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/ConfigurationServiceFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/GlobalConfigurator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/GlobalConfigurator.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/GlobalConfigurator.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/GlobalConfigurator.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,38 @@
+/*
+ * 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.internal.config;
+
+import java.util.Dictionary;
+
+import org.osgi.service.cm.ManagedService;
+
+class GlobalConfigurator extends LogConfigurator implements ManagedService {
+
+    @SuppressWarnings("unchecked")
+    public void updated(Dictionary properties)
+            throws org.osgi.service.cm.ConfigurationException { // unchecked
+        try {
+            getLogConfigManager().updateGlobalConfiguration(properties);
+        } catch (ConfigurationException ce) {
+            throw new org.osgi.service.cm.ConfigurationException(
+                ce.getProperty(), ce.getReason(), ce);
+        }
+    }
+
+}
\ No newline at end of file

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/GlobalConfigurator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogConfigurator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogConfigurator.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogConfigurator.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogConfigurator.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,35 @@
+/*
+ * 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.internal.config;
+
+import org.apache.sling.commons.log.internal.slf4j.LogConfigManager;
+
+public class LogConfigurator {
+
+    private LogConfigManager logConfigManager;
+
+    void setLogConfigManager(final LogConfigManager logConfigManager) {
+        this.logConfigManager = logConfigManager;
+    }
+
+    LogConfigManager getLogConfigManager() {
+        return logConfigManager;
+    }
+
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogConfigurator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactory.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactory.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactory.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactory.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,54 @@
+/*
+ * 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.internal.config;
+
+import java.util.Dictionary;
+
+import org.apache.sling.commons.log.internal.slf4j.LogConfigManager;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+class LogWriterManagedServiceFactory extends LogConfigurator implements
+        ManagedServiceFactory {
+
+    public String getName() {
+        return "LogWriter configurator";
+    }
+
+    @SuppressWarnings("unchecked")
+    public void updated(String pid, Dictionary configuration)
+            throws org.osgi.service.cm.ConfigurationException {
+        try {
+            getLogConfigManager().updateLogWriter(pid, configuration);
+        } catch (ConfigurationException ce) {
+            throw new org.osgi.service.cm.ConfigurationException(
+                ce.getProperty(), ce.getReason(), ce);
+        }
+
+    }
+
+    public void deleted(String pid) {
+        try {
+            getLogConfigManager().updateLogWriter(pid, null);
+        } catch (ConfigurationException ce) {
+            // not expected
+            LogConfigManager.internalFailure(
+                "Unexpected Configuration Problem", ce);
+        }
+    }
+}
\ No newline at end of file

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LogWriterManagedServiceFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LoggerManagedServiceFactory.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LoggerManagedServiceFactory.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LoggerManagedServiceFactory.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LoggerManagedServiceFactory.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,53 @@
+/*
+ * 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.internal.config;
+
+import java.util.Dictionary;
+
+import org.apache.sling.commons.log.internal.slf4j.LogConfigManager;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+class LoggerManagedServiceFactory extends LogConfigurator implements
+        ManagedServiceFactory {
+
+    public String getName() {
+        return "Logger configurator";
+    }
+
+    @SuppressWarnings("unchecked")
+    public void updated(String pid, Dictionary configuration)
+            throws org.osgi.service.cm.ConfigurationException {
+        try {
+            getLogConfigManager().updateLoggerConfiguration(pid, configuration);
+        } catch (ConfigurationException ce) {
+            throw new org.osgi.service.cm.ConfigurationException(
+                ce.getProperty(), ce.getReason(), ce);
+        }
+    }
+
+    public void deleted(String pid) {
+        try {
+            getLogConfigManager().updateLoggerConfiguration(pid, null);
+        } catch (ConfigurationException ce) {
+            // not expected
+            LogConfigManager.internalFailure(
+                "Unexpected Configuration Problem", ce);
+        }
+    }
+}
\ No newline at end of file

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/config/LoggerManagedServiceFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/FileRotator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/FileRotator.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/FileRotator.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/FileRotator.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,74 @@
+/*
+ * 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.internal.slf4j;
+
+import java.io.File;
+
+/**
+ * The <code>FileRotator</code> interface defines the API used to implement log
+ * file rotation based on various limits such as the file size (see
+ * {@link SizeLimitedFileRotator} or some fixed scheduling (see
+ * {@link ScheduledFileRotator}.
+ */
+interface FileRotator {
+
+    /**
+     * The defualt file rotator is unlimited and never rotates the log file.
+     * This may for example be used as the rotator for the console.
+     */
+    static final FileRotator DEFAULT = new FileRotator() {
+
+        // never reaching the limit
+        public boolean isRotationDue(File file) {
+            return false;
+        }
+
+        public void rotate(File file) {
+            // no rotation
+        }
+
+        public File[] getRotatedFiles(File file) {
+            return null; // no rotation
+        }
+
+        @Override
+        public String toString() {
+            return "NullRotator";
+        }
+    };
+
+    /**
+     * Returns <code>true</code> if the current log <code>file</code> should be
+     * rotated.
+     */
+    boolean isRotationDue(File file);
+
+    /**
+     * Since the {@link #isRotationDue(File)} indicated that rotation is due for
+     * the given <code>file</code>, this method should actually rotate the log
+     * file.
+     */
+    void rotate(File file);
+
+    /**
+     * Return an array of already rotated files.
+     * @return An array of files or null.
+     */
+    File[] getRotatedFiles(File file);
+}
\ No newline at end of file

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/FileRotator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,807 @@
+/*
+ * 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.internal.slf4j;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.sling.commons.log.internal.LogManager;
+import org.apache.sling.commons.log.internal.config.ConfigurationException;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.Logger;
+
+public class LogConfigManager implements ILoggerFactory {
+
+    public static final String ROOT = "";
+
+    // the singleton instance of this class
+    private static LogConfigManager instance = new LogConfigManager();
+
+    // map of log writers indexed by configuration PID
+    private final Map<String, SlingLoggerWriter> writerByPid;
+
+    // map of log writers indexed by (absolute) file name. This map does
+    // not contain writers writing to standard out
+    private final Map<String, SlingLoggerWriter> writerByFileName;
+
+    // map of log configurations by configuration PID
+    private final Map<String, SlingLoggerConfig> configByPid;
+
+    // map of log configurations by the categories they are configured with
+    private final Map<String, SlingLoggerConfig> configByCategory;
+
+    // map of all loggers supplied by getLogger(String) by their names. Each
+    // entry is in fact a SoftReference to the actual logger, such that the
+    // loggers may be cleaned up if no used any more.
+    // There is no ReferenceQueue handling currently for removed loggers
+    private final Map<String, SoftReference<SlingLogger>> loggersByCategory;
+
+    // the default logger configuration set up by the constructor and managed
+    // by the global logger configuration
+    private final SlingLoggerConfig defaultLoggerConfig;
+
+    // the default writer configuration set up by the constructor and managed
+    // by the global logger configuration
+    private final SlingLoggerWriter defaultWriter;
+
+    // the root folder to make relative writer paths absolute
+    private File rootDir;
+
+    // global default configuration (from BundleContext properties)
+    private Dictionary<String, String> defaultConfiguration;
+
+    /**
+     * Returns the single instance of this log configuration instance.
+     */
+    public static LogConfigManager getInstance() {
+        return instance;
+    }
+
+    /**
+     * 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
+     * logging output.
+     */
+    public static void internalFailure(String message, Throwable t) {
+        System.err.println(message);
+        if (t != null) {
+            t.printStackTrace(System.err);
+        }
+    }
+
+    /**
+     * Sets up this log configuration manager by creating the default writers
+     * and logger configuration
+     */
+    private LogConfigManager() {
+        writerByPid = new ConcurrentHashMap<String, SlingLoggerWriter>();
+        writerByFileName = new ConcurrentHashMap<String, SlingLoggerWriter>();
+        configByPid = new ConcurrentHashMap<String, SlingLoggerConfig>();
+        configByCategory = new ConcurrentHashMap<String, SlingLoggerConfig>();
+        loggersByCategory = new ConcurrentHashMap<String, SoftReference<SlingLogger>>();
+
+        // configure the default writer to write to stdout (for now)
+        // and register for PID only
+        defaultWriter = new SlingLoggerWriter(LogManager.PID);
+        try {
+            defaultWriter.configure(null, 0, "0");
+        } catch (IOException ioe) {
+            internalFailure("Cannot initialize default SlingLoggerWriter", ioe);
+        }
+        writerByPid.put(LogManager.PID, defaultWriter);
+
+        // set up the default configuration using the default logger
+        // writing at INFO level to start with
+        Set<String> defaultCategories = new HashSet<String>();
+        defaultCategories.add(ROOT);
+        defaultLoggerConfig = new SlingLoggerConfig(LogManager.PID,
+            LogManager.LOG_PATTERN_DEFAULT, defaultCategories,
+            SlingLoggerLevel.INFO, defaultWriter);
+        configByPid.put(LogManager.PID, defaultLoggerConfig);
+        configByCategory.put(ROOT, defaultLoggerConfig);
+    }
+
+    /**
+     * Sets the root (folder) to be used to make relative paths absolute.
+     */
+    public void setRoot(String root) {
+        rootDir = new File((root == null) ? "" : root).getAbsoluteFile();
+    }
+
+    /**
+     * Sets and applies the default configuration used by the
+     * {@link #updateGlobalConfiguration(Dictionary)} method if no configuration
+     * is supplied.
+     */
+    public void setDefaultConfiguration(
+            Dictionary<String, String> defaultConfiguration) {
+        this.defaultConfiguration = defaultConfiguration;
+        try {
+            updateGlobalConfiguration(defaultConfiguration);
+        } catch (ConfigurationException ce) {
+            internalFailure(ce.getMessage(), ce);
+        }
+    }
+
+    /**
+     * Shuts this configuration manager down by dropping all references to
+     * existing configurations, dropping all stored loggers and closing all log
+     * writers.
+     * <p>
+     * After this methods is called, this instance should not be used again.
+     */
+    public void close() {
+        writerByPid.clear();
+        writerByFileName.clear();
+        configByPid.clear();
+        configByCategory.clear();
+
+        // remove references to the loggers
+        for (SoftReference<SlingLogger> logger : loggersByCategory.values()) {
+            logger.clear();
+        }
+        loggersByCategory.clear();
+
+        // shutdown the default writer
+        try {
+            defaultWriter.close();
+        } catch (IOException ignore) {
+            // don't care for this
+        }
+    }
+
+    // ---------- ILoggerFactory
+
+    /**
+     * Returns the name logger. If no logger for the name already exists, it is
+     * created and configured on the fly and returned. If a logger of the same
+     * name already exists, that logger is returned.
+     */
+    public Logger getLogger(String name) {
+        SoftReference<SlingLogger> logger = loggersByCategory.get(name);
+        SlingLogger slingLogger = (logger != null) ? logger.get() : null;
+
+        // no logger at all or reference has been collected, create a new one
+        if (slingLogger == null) {
+            slingLogger = new SlingLogger(name);
+            slingLogger.setLoggerConfig(getLoggerConfig(name));
+            loggersByCategory.put(name, new SoftReference<SlingLogger>(
+                slingLogger));
+        }
+
+        return slingLogger;
+    }
+
+    // ---------- SlingLogPanel support
+
+    /**
+     * Return configured {@link SlingLoggerConfig} instances as an iterator.
+     */
+    Iterator<SlingLoggerConfig> getSlingLoggerConfigs() {
+        return configByPid.values().iterator();
+    }
+
+    /**
+     * Return configured and implicit {@link SlingLoggerWriter} instances as
+     * an iterator.
+     */
+    Iterator<SlingLoggerWriter> getSlingLoggerWriters() {
+        return internalGetSlingLoggerWriters().iterator();
+    }
+
+    /**
+     * Returns the number of logger configurations active in the system
+     */
+    int getNumSlingLoggerConfigs() {
+        return configByPid.size();
+    }
+
+    /**
+     * Returns the number of logger writers active in the system
+     */
+    int getNumSlingLogWriters() {
+        return internalGetSlingLoggerWriters().size();
+    }
+
+    /**
+     * Returns the number of currently user logger categories
+     */
+    int getNumLoggers() {
+        return loggersByCategory.size();
+    }
+
+    /**
+     * Internal method returns the collection of explicitly configured and
+     * implicitly defined logger writers.
+     */
+    private Collection<SlingLoggerWriter> internalGetSlingLoggerWriters() {
+        // configured writers
+        Collection<SlingLoggerWriter> writers = new HashSet<SlingLoggerWriter>(
+            writerByPid.values());
+
+        // add implicit writers
+        for (SlingLoggerWriter slw : writerByFileName.values()) {
+            if (slw.getConfigurationPID() == null) {
+                writers.add(slw);
+            }
+        }
+
+        return writers;
+    }
+
+    // ---------- Configuration support
+
+    public void updateGlobalConfiguration(
+            Dictionary<String, String> configuration)
+            throws ConfigurationException {
+        // fallback to start default settings when the config is deleted
+        if (configuration == null) {
+            configuration = defaultConfiguration;
+        }
+
+        // set the logger name to a special value to indicate the global
+        // (ROOT) logger setting (SLING-529)
+        configuration.put(LogManager.LOG_LOGGERS, LogConfigManager.ROOT);
+
+        // update the default log writer and logger configuration
+        updateLogWriter(LogManager.PID, configuration);
+        updateLoggerConfiguration(LogManager.PID, configuration);
+    }
+
+    /**
+     * Updates or removes the log writer configuration identified by the
+     * <code>pid</code>. In case of log writer removal, any logger
+     * configuration referring to the removed log writer is modified to now log
+     * to the default log writer.
+     * <p>
+     * The configuration object is expected to contain the following properties:
+     * <dl>
+     * <dt>{@link LogManager#LOG_FILE}</dt>
+     * <dd>The relative of absolute path/name of the file to log to. If this
+     * property is missing or an empty string, the writer writes to standard
+     * output</dd>
+     * <dt>{@link LogManager#LOG_FILE_SIZE}</dt>
+     * <dd>The maximum size of the log file to write before rotating the log
+     * file. This property must be a number of be convertible to a number. The
+     * actual value may also be suffixed by a size indicator <code>k</code>,
+     * <code>kb</code>, <code>m</code>, <code>mb</code>, <code>g</code>
+     * or <code>gb</code> representing the respective factors of kilo, mega
+     * and giga.If this property is missing or cannot be converted to a number,
+     * the default value {@link LogManager#LOG_FILE_SIZE_DEFAULT} is assumed. If
+     * the writer writes standard output this property is ignored.</dd>
+     * <dt>{@link LogManager#LOG_FILE_NUMBER}</dt>
+     * <dd>The maximum number of rotated log files to keep. This property must
+     * be a number of be convertible to a number. If this property is missing or
+     * cannot be converted to a number, the default value
+     * {@link LogManager#LOG_FILE_NUMBER_DEFAULT} is assumed. If the writer
+     * writes standard output this property is ignored.</dd>
+     * </dl>
+     *
+     * @param pid The identifier of the log writer to update or remove
+     * @param configuration New configuration setting for the log writer or
+     *            <code>null</code> to indicate to remove the log writer.
+     * @throws ConfigurationException If another log writer already exists for
+     *             the same file as configured for the given log writer or if
+     *             configuring the log writer fails.
+     */
+    public void updateLogWriter(String pid, Dictionary<?, ?> configuration)
+            throws ConfigurationException {
+
+        if (configuration != null) {
+            SlingLoggerWriter slw = writerByPid.get(pid);
+
+            // get the log file parameter and normalize empty string to null
+            String logFileName = (String) configuration.get(LogManager.LOG_FILE);
+            if (logFileName != null && logFileName.trim().length() == 0) {
+                logFileName = null;
+            }
+
+            // if we have a file name, make it absolute and correct for our
+            // environment and verify there is no other writer already existing
+            // for the same file
+            if (logFileName != null) {
+
+                // ensure absolute path
+                logFileName = getAbsoluteLogFile(logFileName);
+
+                // ensure unique configuration of the log writer
+                SlingLoggerWriter existingWriter = writerByFileName.get(logFileName);
+                if (existingWriter != null) {
+                    if (slw == null) {
+
+                        // this is an implicit writer being configured now
+                        slw = existingWriter;
+                        slw.setConfigurationPID(pid);
+                        writerByPid.put(pid, slw);
+
+                    } else if (!existingWriter.getConfigurationPID().equals(pid)) {
+
+                        // this file is already configured by another LOG_PID
+                        throw new ConfigurationException(LogManager.LOG_FILE,
+                            "LogFile " + logFileName
+                                + " already configured by configuration "
+                                + existingWriter.getConfigurationPID());
+                    }
+                }
+            }
+
+            // get number of files and ensure minimum and default
+            Object fileNumProp = configuration.get(LogManager.LOG_FILE_NUMBER);
+            int fileNum = -1;
+            if (fileNumProp instanceof Number) {
+                fileNum = ((Number) fileNumProp).intValue();
+            } else if (fileNumProp != null) {
+                try {
+                    fileNum = Integer.parseInt(fileNumProp.toString());
+                } catch (NumberFormatException nfe) {
+                    // don't care
+                }
+            }
+
+            // get the log file size
+            Object fileSizeProp = configuration.get(LogManager.LOG_FILE_SIZE);
+            String fileSize = null;
+            if (fileSizeProp != null) {
+                fileSize = fileSizeProp.toString();
+            }
+
+            if (configureLogWriter(slw, pid, logFileName, fileNum, fileSize) == null) {
+                throw new ConfigurationException(LogManager.LOG_FILE,
+                    "Cannot create writer for log file " + logFileName);
+            }
+
+        } else {
+
+            final SlingLoggerWriter logWriter = writerByPid.remove(pid);
+            if (logWriter != null) {
+
+                // make the writer implicit
+                logWriter.setConfigurationPID(null);
+
+                // close if unused, otherwise reconfigure to default values
+                closeIfUnused(logWriter, true);
+            }
+        }
+    }
+
+    /**
+     * Updates or removes the logger configuration indicated by the given
+     * <code>pid</code>. If the case of modified categories or removal of the
+     * logger configuration, existing loggers will be modified to reflect the
+     * correct logger configurations available.
+     * <p>
+     * The configuration object is expected to contain the following properties:
+     * <dl>
+     * <dt>{@link LogManager#LOG_PATTERN}</dt>
+     * <dd>The <code>MessageFormat</code> pattern to apply to format the log
+     * message before writing it to the log writer. If this property is missing
+     * or the empty string the default pattern
+     * {@link LogManager#LOG_PATTERN_DEFAULT} is used.</dd>
+     * <dt>{@link LogManager#LOG_LEVEL}</dt>
+     * <dd>The log level to use for log message limitation. The supported
+     * values are <code>trace</code>, <code>debug</code>,
+     * <code>info</code>, <code>warn</code> and <code>error</code>. Case
+     * does not matter. If this property is missing a
+     * <code>ConfigurationException</code> is thrown and this logger
+     * configuration is not used.</dd>
+     * <dt>{@link LogManager#LOG_LOGGERS}</dt>
+     * <dd>The logger names to which this configuration applies. As logger
+     * names form a hierarchy like Java packages, the listed names also apply to
+     * "child names" unless more specific configuration applies for such
+     * children. This property may be a single string, an array of strings or a
+     * collection of strings. Each string may itself be a comma-separated list of
+     * logger names. If this property is missing a
+     * <code>ConfigurationException</code> is thrown.</dd>
+     * <dt>{@link LogManager#LOG_FILE}</dt>
+     * <dd>The name of the log writer to use. This may be the name of a log
+     * file configured for any log writer or it may be the configuration PID of
+     * such a writer. If this property is missing or empty or does not refer to
+     * an existing log writer configuration, the default log writer is used.</dd>
+     *
+     * @param pid The name of the configuration to update or remove.
+     * @param configuration The configuration object.
+     * @throws ConfigurationException If the log level and logger names
+     *             properties are not configured for the given configuration.
+     */
+    public void updateLoggerConfiguration(String pid,
+            Dictionary<?, ?> configuration) throws ConfigurationException {
+
+        // assume we have to reconfigure the loggers
+        boolean reconfigureLoggers = true;
+
+        if (configuration != null) {
+
+            String pattern = (String) configuration.get(LogManager.LOG_PATTERN);
+            String level = (String) configuration.get(LogManager.LOG_LEVEL);
+            String file = (String) configuration.get(LogManager.LOG_FILE);
+            Set<String> categories = toCategoryList(configuration.get(LogManager.LOG_LOGGERS));
+
+            // verify categories
+            if (categories == null) {
+                throw new ConfigurationException(LogManager.LOG_LOGGERS,
+                    "Missing categories in configuration " + pid);
+            }
+
+            // verify no other configuration has any of the categories
+            for (String cat : categories) {
+                SlingLoggerConfig cfg = configByCategory.get(cat);
+                if (cfg != null && !pid.equals(cfg.getConfigPid())) {
+                    throw new ConfigurationException(LogManager.LOG_LOGGERS,
+                        "Category " + cat
+                            + " already defined by configuration " + pid);
+                }
+            }
+
+            // verify writer
+            SlingLoggerWriter writer;
+            if (file != null && file.length() > 0) {
+                writer = writerByPid.get(file);
+                if (writer == null) {
+                    writer = writerByFileName.get(file);
+                    if (writer == null) {
+                        file = getAbsoluteLogFile(file);
+                        writer = writerByFileName.get(file);
+                        if (writer == null) {
+                            writer = configureLogWriter(null, null, file, -1, null);
+                        }
+                    }
+                }
+            } else {
+                writer = defaultWriter;
+            }
+
+            // verify log level
+            if (level == null) {
+                throw new ConfigurationException(LogManager.LOG_LEVEL,
+                    "Value required");
+            }
+            SlingLoggerLevel logLevel = SlingLoggerLevel.fromString(level);
+            if (logLevel == null) {
+                throw new ConfigurationException(LogManager.LOG_LEVEL,
+                    "Unsupported value: " + level);
+            }
+
+            // verify pattern
+            if (pattern == null || pattern.length() == 0) {
+                pattern = LogManager.LOG_PATTERN_DEFAULT;
+            }
+
+            // create or modify existing configuration object
+            SlingLoggerConfig config = configByPid.get(pid);
+            if (config == null) {
+
+                // create and store new configuration
+                config = new SlingLoggerConfig(pid, pattern, categories,
+                    logLevel, writer);
+                configByPid.put(pid, config);
+
+            } else {
+
+                // remove category to configuration mappings
+                final Set<String> oldCategories = config.getCategories();
+
+                // check whether the log writer is to be changed
+                final SlingLoggerWriter oldWriter = config.getLogWriter();
+
+                // reconfigure the configuration
+                config.configure(pattern, categories, logLevel, writer);
+
+                if (categories.equals(oldCategories)) {
+
+                    // no need to change category registrations, clear them
+                    // also no need to reconfigure the loggers
+                    categories.clear();
+                    reconfigureLoggers = false;
+
+                } else {
+
+                    // remove the old categories if different from the new ones
+                    configByCategory.keySet().removeAll(oldCategories);
+
+                }
+
+                // close the old log writer if replaced and not used any more
+                if (oldWriter != writer) {
+                    closeIfUnused(oldWriter, false);
+                }
+            }
+
+            // relink categories
+            for (String cat : categories) {
+                configByCategory.put(cat, config);
+            }
+
+        } else {
+
+            // configuration deleted if null
+
+            // remove configuration from pid list
+            SlingLoggerConfig config = configByPid.remove(pid);
+
+            if (config != null) {
+                // remove all configured categories
+                configByCategory.keySet().removeAll(config.getCategories());
+
+                // close the writer if unused (and unconfigured)
+                closeIfUnused(config.getLogWriter(), false);
+            }
+
+        }
+
+        // reconfigure existing loggers
+        if (reconfigureLoggers) {
+            reconfigureLoggers();
+        }
+    }
+
+    // ---------- Internal helpers ---------------------------------------------
+
+    /**
+     * Returns the <code>logFileName</code> argument converted into an
+     * absolute path name. If <code>logFileName</code> is already absolute it
+     * is returned unmodified. Otherwise it is made absolute by resolving it
+     * relative to the root directory set on this instance by the
+     * {@link #setRoot(String)} method.
+     *
+     * @throws NullPointerException if <code>logFileName</code> is
+     *             <code>null</code>.
+     */
+    private String getAbsoluteLogFile(String logFileName) {
+        // ensure proper separator in the path (esp. for systems, which do
+        // not use "slash" as a separator, e.g Windows)
+        logFileName = logFileName.replace('/', File.separatorChar);
+
+        // create a file instance and check whether this is absolute. If not
+        // create a new absolute file instance with the root dir and get
+        // the absolute path name from that
+        File logFile = new File(logFileName);
+        if (!logFile.isAbsolute()) {
+            logFile = new File(rootDir, logFileName);
+            logFileName = logFile.getAbsolutePath();
+        }
+
+        // return the correct log file name
+        return logFileName;
+    }
+
+    /**
+     * Reconfigures all loggers such that each logger is supplied with the
+     * {@link SlingLoggerConfig} most appropriate to its name. If a registered
+     * logger is not used any more, it is removed from the list.
+     */
+    private void reconfigureLoggers() {
+        // assign correct logger configs to all existing/known loggers
+        for (Iterator<SoftReference<SlingLogger>> si = loggersByCategory.values().iterator(); si.hasNext();) {
+            SlingLogger logger = si.next().get();
+            if (logger != null) {
+                logger.setLoggerConfig(getLoggerConfig(logger.getName()));
+            } else {
+                // if the logger has been GC-ed, remove the entry from the map
+                si.remove();
+            }
+        }
+    }
+
+    /**
+     * Returns a {@link SlingLoggerConfig} instance applicable to the given
+     * <code>logger</code> name. This is the instance applicable to a longest
+     * match log. If no such instance exists, the default logger configuration
+     * is returned.
+     */
+    private SlingLoggerConfig getLoggerConfig(String logger) {
+        for (;;) {
+            SlingLoggerConfig config = configByCategory.get(logger);
+            if (config != null) {
+                return config;
+            }
+
+            if (logger.length() == 0) {
+                break;
+            }
+
+            int dot = logger.lastIndexOf('.');
+            if (dot < 0) {
+                logger = ROOT;
+            } else {
+                logger = logger.substring(0, dot);
+            }
+        }
+
+        return defaultLoggerConfig;
+    }
+
+    /**
+     * Decomposes the <code>loggers</code> configuration object into a set of
+     * logger names. The <code>loggers</code> object may be a single string,
+     * an array of strings or a collection of strings. Each string may in turn be a
+     * comma-separated list of strings. Each entry makes up an entry in the
+     * resulting set.
+     *
+     * @param loggers The configuration object to be decomposed. If this is
+     *            <code>null</code>, <code>null</code> is returned
+     *            immediately
+     * @return The set of logger names provided by the <code>loggers</code>
+     *         object or <code>null</code> if the <code>loggers</code>
+     *         object itself is <code>null</code>.
+     */
+    private Set<String> toCategoryList(Object loggers) {
+
+        // quick exit if there is no configuration
+        if (loggers == null) {
+            return null;
+        }
+
+        // prepare set of names (used already in case loggers == ROOT)
+        Set<String> loggerNames = new HashSet<String>();
+
+        // in case of the special setting ROOT, return a set of just the
+        // root logger name (SLING-529)
+        if (loggers == ROOT) {
+            loggerNames.add(ROOT);
+            return loggerNames;
+        }
+
+        // convert the loggers object to an array
+        Object[] loggersArray;
+        if (loggers.getClass().isArray()) {
+            loggersArray = (Object[]) loggers;
+        } else if (loggers instanceof Collection<?>) {
+            loggersArray = ((Collection<?>) loggers).toArray();
+        } else {
+            loggersArray = new Object[] { loggers };
+        }
+
+        // conver the array of potentially comma-separated logger names
+        // into the set of logger names
+        for (Object loggerObject : loggersArray) {
+            if (loggerObject != null) {
+                String[] splitLoggers = loggerObject.toString().split(",");
+                for (String logger : splitLoggers) {
+                    logger = logger.trim();
+                    if (logger.length() > 0) {
+                        loggerNames.add(logger);
+                    }
+                }
+            }
+        }
+
+        // return those names
+        return loggerNames;
+    }
+
+    /**
+     * Configures and returns a {@link SlingLoggerWriter}. If the
+     * <code>pid</code> is not <code>null</code> the writer is also added to the
+     * by pid map. If the <code>fileName</code> is not <code>null</code> the
+     * writer is also added to the file name map.
+     *
+     * @param writer The {@link SlingLoggerWriter} to configure. If this is
+     *            <code>null</code> a new instance is created.
+     * @param pid The configuration PID to set on the <code>writer</code>. This
+     *            may be <code>null</code> to indicate that the logger writer is
+     *            not configured by any configuration.
+     * @param fileName The name of the file to log to.
+     * @param fileNum The number of log files to keep (if rotating by size) or
+     *            -1 to assume the default (
+     *            {@link java.util.logging.LogManager#LOG_FILE_NUMBER_DEFAULT}).
+     * @param threshold The log rotation threashold (size or data/time format
+     *            pattern or <code>null</code> to assume the default (
+     *            {@link java.util.logging.LogManager#LOG_FILE_SIZE_DEFAULT}).
+     * @return The {@link SlingLoggerWriter} or <code>null</code> if an error
+     *         occurrs configuring the writer.
+     */
+    private SlingLoggerWriter configureLogWriter(SlingLoggerWriter writer,
+            String pid, String fileName, int fileNum, String threshold) {
+
+        // create the writer instance if it is new
+        if (writer == null) {
+            writer = new SlingLoggerWriter(pid);
+        } else {
+            writer.setConfigurationPID(pid);
+        }
+
+        if (fileNum < 0) {
+            fileNum = LogManager.LOG_FILE_NUMBER_DEFAULT;
+        }
+
+        if (threshold == null || threshold.length() == 0) {
+            threshold = LogManager.LOG_FILE_SIZE_DEFAULT;
+        }
+
+        try {
+            writer.configure(fileName, fileNum, threshold);
+        } catch (IOException ioe) {
+            internalFailure("Cannot create log file " + fileName, ioe);
+            internalFailure("Logging to the console", null);
+            return null;
+        }
+
+        // add to maps
+        if (pid != null) {
+            writerByPid.put(pid, writer);
+        }
+        if (fileName != null) {
+            writerByFileName.put(fileName, writer);
+        }
+
+        // everything set and done
+        return writer;
+    }
+
+    /**
+     * Closes or resets the given <code>logWriter</code> if it is not referred
+     * to by any logger config or writer configuration.
+     *
+     * @param logWriter The {@link SlingLoggerWriter} to close or (optionally)
+     *            reconfigure.
+     * @param reset Whether the log writer should be reset to default values if
+     *            it is still referred to by any logger configuration.
+     */
+    private void closeIfUnused(SlingLoggerWriter logWriter, boolean reset) {
+
+        // The log writer is based on configuration, don't touch
+        if (logWriter.getConfigurationPID() != null) {
+            return;
+        }
+
+        // "Implicit" writer : check for references
+        for (SlingLoggerConfig config : configByPid.values()) {
+            if (config.getLogWriter() == logWriter) {
+
+                // optionally reconfigure to default values
+                if (reset) {
+                    try {
+                        logWriter.configure(logWriter.getPath(),
+                            LogManager.LOG_FILE_NUMBER_DEFAULT,
+                            LogManager.LOG_FILE_SIZE_DEFAULT);
+                    } catch (IOException ioe) {
+                        internalFailure(
+                            "Cannot reset the log writer to default configuration",
+                            ioe);
+                    }
+                }
+
+                // done here...
+                return;
+            }
+        }
+        // invariant: writer is not used and not configured any more
+
+        // remove from the writer file name map
+        String path = logWriter.getPath();
+        if (path != null) {
+            writerByFileName.remove(path);
+        }
+
+        // close it to clean up
+        try {
+            logWriter.close();
+        } catch (IOException ioe) {
+            // don't care
+        }
+    }
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriter.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriter.java?rev=1450675&view=auto
==============================================================================
--- sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriter.java (added)
+++ sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriter.java Wed Feb 27 08:36:42 2013
@@ -0,0 +1,87 @@
+/*
+ * 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.internal.slf4j;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+public class PrivilegedWriter extends FilterWriter {
+
+    PrivilegedWriter(Writer delegatee) {
+        super(delegatee);
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                public Void run() throws IOException {
+                    PrivilegedWriter.super.close();
+                    return null;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            rethrow(e.getCause());
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+        try {
+            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                public Void run() throws IOException {
+                    PrivilegedWriter.super.flush();
+                    return null;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            rethrow(e.getCause());
+        }
+    }
+
+    @Override
+    public void write(final char[] cbuf, final int off, final int len) throws IOException {
+        try {
+            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                public Void run() throws IOException {
+                    PrivilegedWriter.super.write(cbuf, off, len);
+                    return null;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            rethrow(e.getCause());
+        }
+    }
+
+    private void rethrow(Throwable cause) throws IOException {
+        if (cause instanceof IOException) {
+            throw (IOException) cause;
+        } else if (cause instanceof RuntimeException) {
+            throw (RuntimeException) cause;
+        } else if (cause instanceof Error) {
+            throw (Error) cause;
+        } else {
+            throw (IOException) new IOException(cause.getMessage()).initCause(cause);
+        }
+    }
+}

Propchange: sling/whiteboard/ieb/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/PrivilegedWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native