You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ch...@apache.org on 2013/11/13 09:43:01 UTC

svn commit: r1541422 - in /sling/trunk/bundles/commons/log/src: main/java/org/apache/sling/commons/log/logback/ main/java/org/apache/sling/commons/log/logback/internal/ main/resources/ test/java/org/apache/sling/commons/log/logback/integration/ test/re...

Author: chetanm
Date: Wed Nov 13 08:43:00 2013
New Revision: 1541422

URL: http://svn.apache.org/r1541422
Log:
SLING-3242 - Allow referring to OSGi appenders from within Logback config

Adding a new action OsgiAppenderRefAction which allows referring to OSGi appenders
from within the config file. The logger -> appender mapping would be stored in
AppenderTracker and it would associate the appender to all such logger whenever
such a service is registered

Added:
    sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/OsgiAppenderRefAction.java   (with props)
    sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiAppenderRefInternalAction.java   (with props)
    sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml   (with props)
Modified:
    sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/AppenderTracker.java
    sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java
    sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiInternalAction.java
    sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java
    sling/trunk/bundles/commons/log/src/main/resources/logback-empty.xml
    sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java
    sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java
    sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/LogTestBase.java

Added: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/OsgiAppenderRefAction.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/OsgiAppenderRefAction.java?rev=1541422&view=auto
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/OsgiAppenderRefAction.java (added)
+++ sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/OsgiAppenderRefAction.java Wed Nov 13 08:43:00 2013
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import aQute.bnd.annotation.ProviderType;
+import org.apache.sling.commons.log.logback.internal.OsgiAppenderRefInternalAction;
+
+/**
+ * The action class needs to be referred in external files hence adding a marker
+ * class in public package which extends the internal class.
+ * <p>
+ * This class is for configuration reference only. Consumers are not intended to
+ * instantiate or extend from it.
+ */
+@ProviderType
+public final class OsgiAppenderRefAction extends OsgiAppenderRefInternalAction {
+}

Propchange: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/OsgiAppenderRefAction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/AppenderTracker.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/AppenderTracker.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/AppenderTracker.java (original)
+++ sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/AppenderTracker.java Wed Nov 13 08:43:00 2013
@@ -21,10 +21,17 @@ package org.apache.sling.commons.log.log
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
 import org.apache.sling.commons.log.logback.internal.util.Util;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -34,11 +41,6 @@ import org.osgi.framework.InvalidSyntaxE
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
 
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
-
 public class AppenderTracker extends ServiceTracker implements LogbackResetListener {
 
     private static final String PROP_LOGGER = "loggers";
@@ -47,6 +49,8 @@ public class AppenderTracker extends Ser
 
     private final Map<ServiceReference, AppenderInfo> appenders = new ConcurrentHashMap<ServiceReference, AppenderInfo>();
 
+    private final Map<String,Set<String>> appenderNameToLoggerMap = new ConcurrentHashMap<String, Set<String>>();
+
     public AppenderTracker(final BundleContext context, final LoggerContext loggerContext) throws InvalidSyntaxException {
         super(context, createFilter(), null);
         this.loggerContext = loggerContext;
@@ -94,7 +98,7 @@ public class AppenderTracker extends Ser
 
     private void detachAppender(final AppenderInfo ai) {
         if (ai != null) {
-            for (final String name : ai.loggers) {
+            for (final String name : ai.getLoggers()) {
                 final Logger logger = loggerContext.getLogger(name);
 
                 logger.detachAppender(ai.appender);
@@ -104,7 +108,7 @@ public class AppenderTracker extends Ser
 
     private void attachAppender(final AppenderInfo ai) {
         if (ai != null) {
-            for (final String name : ai.loggers) {
+            for (final String name : ai.getLoggers()) {
                 final Logger logger = loggerContext.getLogger(name);
 
                 logger.addAppender(ai.appender);
@@ -114,14 +118,21 @@ public class AppenderTracker extends Ser
 
     @Override
     public void onResetStart(final LoggerContext context) {
-        for (AppenderInfo ai : appenders.values()) {
-            attachAppender(ai);
-        }
+        attachAppenders();
     }
 
     @Override
     public void onResetComplete(final LoggerContext context) {
+        @SuppressWarnings("unchecked")
+        Map<String,Set<String>> appenderRefBag =
+                (Map<String, Set<String>>) context.getObject(OsgiAppenderRefInternalAction.OSGI_APPENDER_REF_BAG);
+        if(appenderRefBag == null){
+            appenderRefBag = Collections.emptyMap();
+        }
+        this.appenderNameToLoggerMap.clear();
+        this.appenderNameToLoggerMap.putAll(appenderRefBag);
 
+        attachAppenders();
     }
 
     @Override
@@ -130,18 +141,26 @@ public class AppenderTracker extends Ser
         appenders.clear();
     }
 
+    private void attachAppenders() {
+        for (AppenderInfo ai : appenders.values()) {
+            attachAppender(ai);
+        }
+    }
+
     private static Filter createFilter() throws InvalidSyntaxException {
         String filter = String.format("(&(objectClass=%s)(%s=*))", Appender.class.getName(), PROP_LOGGER);
         return FrameworkUtil.createFilter(filter);
     }
 
-    static class AppenderInfo {
-        final List<String> loggers;
+    class AppenderInfo {
+        private final List<String> loggers;
 
         final Appender<ILoggingEvent> appender;
 
         final String pid;
 
+        final String name;
+
         public AppenderInfo(final ServiceReference ref, Appender<ILoggingEvent> appender) {
             this.appender = appender;
             this.pid = ref.getProperty(Constants.SERVICE_ID).toString();
@@ -151,6 +170,22 @@ public class AppenderTracker extends Ser
             }
 
             this.loggers = loggers;
+            this.name = appender.getName();
         }
+
+        public Set<String> getLoggers(){
+            Set<String> result = new HashSet<String>(loggers);
+
+            if(name != null){
+                Set<String> loggersFromConfig = appenderNameToLoggerMap.get(name);
+                if(loggersFromConfig != null){
+                    result.addAll(loggersFromConfig);
+                }
+            }
+
+            return Collections.unmodifiableSet(result);
+        }
+
+
     }
 }

Modified: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java (original)
+++ sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/LogbackManager.java Wed Nov 13 08:43:00 2013
@@ -35,6 +35,7 @@ import ch.qos.logback.core.status.Status
 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.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -43,9 +44,7 @@ import org.osgi.framework.ServiceFactory
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.ServiceTracker;
-import org.slf4j.ILoggerFactory;
 import org.slf4j.LoggerFactory;
-import org.slf4j.impl.StaticLoggerBinder;
 
 public class LogbackManager extends LoggerContextAwareBase {
     private static final String PREFIX = "org.apache.sling.commons.log";
@@ -461,7 +460,8 @@ public class LogbackManager extends Logg
 
         final Map<String, Appender<ILoggingEvent>> appenders = new HashMap<String, Appender<ILoggingEvent>>();
 
-        final Map<Appender<ILoggingEvent>, AppenderTracker.AppenderInfo> dynamicAppenders = new HashMap<Appender<ILoggingEvent>, AppenderTracker.AppenderInfo>();
+        final Map<Appender<ILoggingEvent>, AppenderInfo> dynamicAppenders =
+                new HashMap<Appender<ILoggingEvent>, AppenderInfo>();
 
         final Map<ServiceReference,TurboFilter> turboFilters;
 

Added: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiAppenderRefInternalAction.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiAppenderRefInternalAction.java?rev=1541422&view=auto
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiAppenderRefInternalAction.java (added)
+++ sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiAppenderRefInternalAction.java Wed Nov 13 08:43:00 2013
@@ -0,0 +1,93 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.core.joran.action.Action;
+import ch.qos.logback.core.joran.action.ActionConst;
+import ch.qos.logback.core.joran.spi.ActionException;
+import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.util.OptionHelper;
+import org.xml.sax.Attributes;
+
+/**
+ * Joran action enabling referring to OSGi based appenders from within Logback config file. It is based on
+ * {@link ch.qos.logback.core.joran.action.AppenderRefAction}.
+ */
+public class OsgiAppenderRefInternalAction extends Action {
+    static String OSGI_APPENDER_REF_BAG = "OSGI_APPENDER_BAG";
+
+    boolean inError = false;
+
+    @Override
+    public void begin(InterpretationContext ec, String tagName, Attributes attributes) throws ActionException {
+        // Let us forget about previous errors (in this object)
+        inError = false;
+
+        Object o = ec.peekObject();
+
+        if (!(o instanceof Logger)) {
+            String errMsg = "Could not find an Logger at the top of execution stack. Near ["
+                    + tagName + "] line " + getLineNumber(ec);
+            inError = true;
+            addError(errMsg);
+            return;
+        }
+
+        Logger logger = (Logger) o;
+
+        String appenderName = ec.subst(attributes.getValue(ActionConst.REF_ATTRIBUTE));
+
+        if (OptionHelper.isEmpty(appenderName)) {
+            // print a meaningful error message and return
+            String errMsg = "Missing appender ref attribute in <appender-ref> tag.";
+            inError = true;
+            addError(errMsg);
+
+            return;
+        }
+
+        @SuppressWarnings("unchecked")
+        Map<String, Set<String>> appenderBag =
+                (Map<String, Set<String>>) ec.getObjectMap().get(OSGI_APPENDER_REF_BAG);
+
+        if(appenderBag == null){
+            appenderBag = new HashMap<String, Set<String>>();
+            ec.getObjectMap().put(OSGI_APPENDER_REF_BAG,appenderBag);
+        }
+
+        Set<String> loggers = appenderBag.get(appenderName);
+        if(loggers == null){
+            loggers = new HashSet<String>();
+            appenderBag.put(appenderName,loggers);
+        }
+
+        loggers.add(logger.getName());
+    }
+
+    @Override
+    public void end(InterpretationContext ic, String name) throws ActionException {
+
+    }
+}

Propchange: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiAppenderRefInternalAction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiInternalAction.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiInternalAction.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiInternalAction.java (original)
+++ sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/OsgiInternalAction.java Wed Nov 13 08:43:00 2013
@@ -22,12 +22,8 @@ package org.apache.sling.commons.log.log
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.joran.action.Action;
 import ch.qos.logback.core.joran.action.ActionConst;
 import ch.qos.logback.core.joran.event.EndEvent;
@@ -37,7 +33,6 @@ import ch.qos.logback.core.joran.event.S
 import ch.qos.logback.core.joran.spi.ActionException;
 import ch.qos.logback.core.joran.spi.InterpretationContext;
 import ch.qos.logback.core.joran.spi.JoranException;
-
 import org.apache.sling.commons.log.logback.internal.util.Util;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
@@ -52,15 +47,11 @@ import static org.apache.sling.commons.l
 public class OsgiInternalAction extends Action {
     private static final String INCLUDED_TAG = "included";
 
-    private Map<String, Appender<ILoggingEvent>> appenderBag;
 
     @SuppressWarnings("unchecked")
     @Override
     public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException {
-        ec.addInPlayListener(new ConfigCompleteListener());
-
-        //Extract the appender bag from InterpretationContext. It would be used later
-        appenderBag = (HashMap<String, Appender<ILoggingEvent>>) ec.getObjectMap().get(ActionConst.APPENDER_BAG);
+        ec.addInPlayListener(new ConfigCompleteListener(ec));
 
         populateSubstitutionProperties(ec);
 
@@ -146,17 +137,40 @@ public class OsgiInternalAction extends 
      */
     private class ConfigCompleteListener implements InPlayListener {
         private static final String CONFIG_TAG = "configuration";
+        private final String[] OBJECT_NAMES = {
+                ActionConst.APPENDER_BAG,
+                OsgiAppenderRefInternalAction.OSGI_APPENDER_REF_BAG,
+        };
+
+        private final InterpretationContext ic;
+
+        public ConfigCompleteListener(InterpretationContext ec) {
+            this.ic = ec;
+        }
+
         @Override
         public void inPlay(SaxEvent event) {
             if(event instanceof EndEvent
                     && event.qName.equalsIgnoreCase(CONFIG_TAG)){
                 //Export the appender bag to LoggerContext object
-                getContext().putObject(ActionConst.APPENDER_BAG,appenderBag);
+                transferObjectsToContext();
 
                 getLogbackManager().fireResetCompleteListeners();
 
                 //Clear the appender bag entry
-                getContext().putObject(ActionConst.APPENDER_BAG,null);
+                removeTransferredObjects();
+            }
+        }
+
+        private void transferObjectsToContext(){
+            for(String name : OBJECT_NAMES){
+                getContext().putObject(name,ic.getObjectMap().get(name));
+            }
+        }
+
+        private void removeTransferredObjects(){
+            for(String name : OBJECT_NAMES){
+                getContext().putObject(name,null);
             }
         }
     }

Modified: sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java (original)
+++ sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/logback/internal/SlingLogPanel.java Wed Nov 13 08:43:00 2013
@@ -43,7 +43,7 @@ import ch.qos.logback.core.FileAppender;
 import ch.qos.logback.core.helpers.Transform;
 import ch.qos.logback.core.status.Status;
 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.util.SlingRollingFileAppender;
 import org.apache.sling.commons.log.logback.internal.util.Util;
@@ -53,7 +53,6 @@ import org.osgi.framework.ServiceReferen
 import org.slf4j.LoggerFactory;
 import org.xml.sax.InputSource;
 
-import static org.apache.sling.commons.log.logback.internal.AppenderTracker.AppenderInfo;
 import static org.apache.sling.commons.log.logback.internal.ConfigSourceTracker.ConfigSourceInfo;
 
 /**

Modified: sling/trunk/bundles/commons/log/src/main/resources/logback-empty.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/resources/logback-empty.xml?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/main/resources/logback-empty.xml (original)
+++ sling/trunk/bundles/commons/log/src/main/resources/logback-empty.xml Wed Nov 13 08:43:00 2013
@@ -26,5 +26,7 @@
   <jmxConfigurator />
   <newRule pattern="*/configuration/osgi"
            actionClass="org.apache.sling.commons.log.logback.OsgiAction"/>
+  <newRule pattern="*/configuration/appender-ref-osgi"
+           actionClass="org.apache.sling.commons.log.logback.OsgiAppenderRefAction"/>
   <osgi/>
 </configuration>
\ No newline at end of file

Modified: sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java (original)
+++ sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java Wed Nov 13 08:43:00 2013
@@ -19,8 +19,6 @@
 
 package org.apache.sling.commons.log.logback.integration;
 
-import static org.junit.Assert.assertEquals;
-
 import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.Hashtable;
@@ -28,19 +26,28 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.AppenderBase;
+import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
 import org.slf4j.LoggerFactory;
 
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
-import ch.qos.logback.core.AppenderBase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.composite;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 
 @RunWith(PaxExam.class)
 @ExamReactorStrategy(PerClass.class)
@@ -49,44 +56,85 @@ public class ITAppenderServices extends 
     @Inject
     private BundleContext bundleContext;
 
+    @Inject
+    private ConfigurationAdmin ca;
+
+    private ServiceRegistration sr;
+
     static {
         // uncomment to enable debugging of this test class
         // paxRunnerVmOption = DEBUG_VM_OPTION;
 
     }
 
+    @Override
+    protected Option addExtraOptions() {
+        return composite(configAdmin(), mavenBundle("commons-io", "commons-io").versionAsInProject());
+    }
+
     @Test
     public void testAppenderService() throws Exception {
-        TestAppender ta = new TestAppender();
-        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        TestAppender ta = registerAppender("foo.bar", "foo.baz");
+        delay();
 
-        String[] loggers = {
-            "foo.bar", "foo.baz",
-        };
+        Logger bar = (Logger)LoggerFactory.getLogger("foo.bar");
+        bar.setLevel(Level.DEBUG);
+        Logger baz = (Logger)LoggerFactory.getLogger("foo.baz");
+        baz.setLevel(Level.INFO);
 
-        props.put("loggers", loggers);
-        ServiceRegistration sr = bundleContext.registerService(Appender.class.getName(), ta, props);
+        bar.debug("Test message");
+        baz.debug("Test message"); // Would not be logged
+
+        // One event should be logged.
+        assertEquals(1, ta.events.size());
+    }
+
+    @Test
+    public void testOsgiAppenderRef() throws Exception {
+        Configuration config = ca.getConfiguration(ITConfigAdminSupport.PID, null);
+        Dictionary<String, Object> p = new Hashtable<String, Object>();
+        p.put(ITConfigAdminSupport.LOG_LEVEL, "INFO");
+        p.put(ITConfigAdminSupport.LOGBACK_FILE,absolutePath("test-osg-appender-ref-config.xml"));
+        config.update(p);
 
         delay();
 
-        ch.qos.logback.classic.Logger bar = (ch.qos.logback.classic.Logger)LoggerFactory.getLogger("foo.bar");
+        Logger ref = (Logger)LoggerFactory.getLogger("foo.ref.osgi");
+        assertTrue(ref.isDebugEnabled());
+
+        TestAppender ta = registerAppender("foo.bar", "foo.baz");
+        delay();
+
+        Logger bar = (Logger)LoggerFactory.getLogger("foo.bar");
         bar.setLevel(Level.DEBUG);
-        ch.qos.logback.classic.Logger baz = (ch.qos.logback.classic.Logger)LoggerFactory.getLogger("foo.baz");
+        Logger baz = (Logger)LoggerFactory.getLogger("foo.baz");
         baz.setLevel(Level.INFO);
 
         bar.debug("Test message");
         baz.debug("Test message"); // Would not be logged
 
+        ref.debug("Test message ref");
+
         // One event should be logged.
-        assertEquals(1, ta.events.size());
+        assertEquals(2, ta.events.size());
+    }
 
-        // Now unregister the appender and check that log level state is also
-        // reverted
+    @After
+    public void unregisterAppender(){
         sr.unregister();
-        delay();
+    }
+
 
+    private TestAppender registerAppender(String... loggers){
+        TestAppender ta = new TestAppender();
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put("loggers", loggers);
+        sr = bundleContext.registerService(Appender.class.getName(), ta, props);
+        delay();
+        return ta;
     }
 
+
     private static class TestAppender extends AppenderBase<ILoggingEvent> {
         final List<ILoggingEvent> events = new ArrayList<ILoggingEvent>();
 
@@ -94,6 +142,11 @@ public class ITAppenderServices extends 
         protected void append(ILoggingEvent eventObject) {
             events.add(eventObject);
         }
+
+        @Override
+        public String getName() {
+            return "TestAppender";
+        }
     }
 
 }

Modified: sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java (original)
+++ sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigAdminSupport.java Wed Nov 13 08:43:00 2013
@@ -19,7 +19,6 @@
 
 package org.apache.sling.commons.log.logback.integration;
 
-import java.io.File;
 import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.Iterator;
@@ -28,8 +27,6 @@ import javax.inject.Inject;
 
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.sling.commons.log.logback.integration.LogTestBase;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
@@ -47,6 +44,7 @@ import static org.junit.Assert.assertTru
 import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 
+@SuppressWarnings("UnusedDeclaration")
 @RunWith(PaxExam.class)
 @ExamReactorStrategy(PerClass.class)
 public class ITConfigAdminSupport extends LogTestBase {
@@ -144,8 +142,7 @@ public class ITConfigAdminSupport extend
         Configuration config = ca.getConfiguration(PID, null);
         Dictionary<String, Object> p = new Hashtable<String, Object>();
         p.put(LOG_LEVEL, "DEBUG");
-        p.put(LOGBACK_FILE,
-            FilenameUtils.concat(new File(".").getAbsolutePath(), "src/test/resources/test1-external-config.xml"));
+        p.put(LOGBACK_FILE,absolutePath("test1-external-config.xml"));
         config.update(p);
 
         delay();

Modified: sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/LogTestBase.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/LogTestBase.java?rev=1541422&r1=1541421&r2=1541422&view=diff
==============================================================================
--- sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/LogTestBase.java (original)
+++ sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/LogTestBase.java Wed Nov 13 08:43:00 2013
@@ -79,7 +79,8 @@ public abstract class LogTestBase {
         final File bundleFile = new File(bundleFileName);
         if (!bundleFile.canRead()) {
             throw new IllegalArgumentException("Cannot read from bundle file " + bundleFileName + " specified in the "
-                + BUNDLE_JAR_SYS_PROP + " system property");
+                + BUNDLE_JAR_SYS_PROP + " system property. Try building the project first " +
+                    "with 'mvn clean install -Pide -DskipTests'");
         }
         return options(
             // the current project (the bundle under test)
@@ -135,6 +136,10 @@ public abstract class LogTestBase {
         return new DefaultCompositeOption();
     }
 
+    protected static String absolutePath(String configFileName){
+        return FilenameUtils.concat(new File(".").getAbsolutePath(), "src/test/resources/"+configFileName);
+    }
+
     protected static void delay() {
         try {
             TimeUnit.MILLISECONDS.sleep(300);

Added: sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml?rev=1541422&view=auto
==============================================================================
--- sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml (added)
+++ sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml Wed Nov 13 08:43:00 2013
@@ -0,0 +1,34 @@
+<!--
+  ~ 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.
+  -->
+
+<configuration>
+  <newRule pattern="*/configuration/osgi"
+           actionClass="org.apache.sling.commons.log.logback.OsgiAction"/>
+  <newRule pattern="*/configuration/appender-ref-osgi"
+           actionClass="org.apache.sling.commons.log.logback.OsgiAppenderRefAction"/>
+  <osgi/>
+
+  <logger name="foo.ref.osgi" level="DEBUG">
+    <appender-ref-osgi ref="TestAppender" />
+  </logger>
+
+  <root level="INFO">
+  </root>
+</configuration>
+       
\ No newline at end of file

Propchange: sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/log/src/test/resources/test-osg-appender-ref-config.xml
------------------------------------------------------------------------------
    svn:executable = *