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

[sling-org-apache-sling-commons-logservice] annotated tag org.apache.sling.commons.logservice-1.0.0 created (now a060355)

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a change to annotated tag org.apache.sling.commons.logservice-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-logservice.git.


      at a060355  (tag)
 tagging 13ca43b6aa6bbb93dc71abeff093b3b2fc77a28e (commit)
      by Carsten Ziegeler
      on Tue Jan 31 14:04:01 2012 +0000

- Log -----------------------------------------------------------------
org.apache.sling.commons.logservice-1.0.0
-----------------------------------------------------------------------

This annotated tag includes the following new commits:

     new 3852c89  SLING-2224 Create new LogService bundle
     new 035cdda  SLING-2235 Use size limited, access ordered cache for bundle loggers and remove entries for uninstalled bundles
     new fb9e692  [maven-release-plugin] prepare release org.apache.sling.commons.logservice-1.0.0
     new 13ca43b  [maven-release-plugin]  copy for tag org.apache.sling.commons.logservice-1.0.0

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@sling.apache.org" <co...@sling.apache.org>'].

[sling-org-apache-sling-commons-logservice] 02/04: SLING-2235 Use size limited, access ordered cache for bundle loggers and remove entries for uninstalled bundles

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.logservice-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-logservice.git

commit 035cdda8857f738aa75a729d09ebe4d670da4a89
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Sun Oct 2 14:55:26 2011 +0000

    SLING-2235 Use size limited, access ordered cache for bundle loggers and remove entries for uninstalled bundles
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice@1178194 13f79535-47bb-0310-9956-ffa450edef68
---
 .../commons/logservice/internal/LogSupport.java    | 34 +++++++++++++++++++---
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java b/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
index 8a78926..d40d6e0 100644
--- a/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
@@ -18,7 +18,7 @@ package org.apache.sling.commons.logservice.internal;
 
 import java.util.Collections;
 import java.util.Enumeration;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -67,7 +67,15 @@ public class LogSupport implements BundleListener, ServiceListener,
 
     // The loggers by bundle id used for logging messages originated from
     // specific bundles
-    private Map<Long, Logger> loggers = new HashMap<Long, Logger>();
+    @SuppressWarnings("serial")
+    private Map<Long, Logger> loggers = new LinkedHashMap<Long, Logger>(16,
+        0.75f, true) {
+        private static final int MAX_SIZE = 50;
+
+        protected boolean removeEldestEntry(Map.Entry<Long, Logger> eldest) {
+            return size() > MAX_SIZE;
+        }
+    };
 
     // the worker thread actually sending LogEvents to LogListeners
     private LogEntryDispatcher logEntryDispatcher;
@@ -233,6 +241,8 @@ public class LogSupport implements BundleListener, ServiceListener,
                 message = "BundleEvent UPDATED";
                 break;
             case BundleEvent.UNINSTALLED:
+                // remove any cached logger for the uninstalled bundle
+                ungetLogger(event.getBundle());
                 message = "BundleEvent UNINSTALLED";
                 break;
             case BundleEvent.RESOLVED:
@@ -366,7 +376,10 @@ public class LogSupport implements BundleListener, ServiceListener,
      */
     private Logger getLogger(Bundle bundle) {
         Long bundleId = new Long((bundle == null) ? 0 : bundle.getBundleId());
-        Logger log = loggers.get(bundleId);
+        Logger log;
+        synchronized (loggers) {
+            log = loggers.get(bundleId);
+        }
         if (log == null) {
 
             String name;
@@ -392,12 +405,25 @@ public class LogSupport implements BundleListener, ServiceListener,
             }
 
             log = LoggerFactory.getLogger(name);
-            loggers.put(bundleId, log);
+            synchronized (loggers) {
+                loggers.put(bundleId, log);
+            }
         }
         return log;
     }
 
     /**
+     * Removes the cached logger for the given bundle, for example if the
+     * bundle is uninstalled and thus there will be no more logs from this
+     * bundle.
+     */
+    private void ungetLogger(Bundle bundle) {
+        synchronized (loggers) {
+            loggers.remove(bundle.getBundleId());
+        }
+    }
+
+    /**
      * Actually logs the given log entry to the logger for the bundle recorded
      * in the log entry.
      */

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-commons-logservice] 01/04: SLING-2224 Create new LogService bundle

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.logservice-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-logservice.git

commit 3852c89a413b87b702aa66fcb8f50070a81c3c38
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Sun Oct 2 13:32:34 2011 +0000

    SLING-2224 Create new LogService bundle
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice@1178187 13f79535-47bb-0310-9956-ffa450edef68
---
 README.txt                                         |  66 +++
 pom.xml                                            | 115 ++++
 .../commons/logservice/internal/Activator.java     |  77 +++
 .../commons/logservice/internal/LogEntryImpl.java  |  71 +++
 .../internal/LogReaderServiceFactory.java          |  83 +++
 .../logservice/internal/LogServiceFactory.java     |  97 ++++
 .../commons/logservice/internal/LogSupport.java    | 586 +++++++++++++++++++++
 7 files changed, 1095 insertions(+)

diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..45fc4a5
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,66 @@
+Apache Sling OSGi LogService Implementation
+
+
+=================================================
+Welcome to Sling - OSGi LogService Implementation
+=================================================
+
+The "logservice" project implements the OSGi LogService imple,entation ontop
+of the SLF4J logging API. This bundle should be installed as one of the first
+modules in the OSGi framework along with the SLF4J API and implementation and
+- provided the framework supports start levels - be set to start at start
+level 1. This ensures the Logging bundle is loaded as early as possible thus
+providing services to the framework and preparing logging.
+
+See the Apache Sling web site (http://sling.apache.org) for
+documentation and other information. You are welcome to join the
+Sling mailing lists (http://sling.apache.org/site/project-information.html)
+to discuss this component and to use the Sling issue tracker
+(http://issues.apache.org/jira/browse/SLING) to report issues or request
+new features.
+
+Apache Sling is a project of the Apache Software Foundation
+(http://www.apache.org).
+
+License (see also LICENSE)
+==========================
+
+Collective work: Copyright 2007 The Apache Software Foundation.
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Getting Started
+===============
+
+This component uses a Maven 2 (http://maven.apache.org/) build
+environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/)
+2.0.7 or later. We recommend to use the latest Maven version.
+
+If you have Maven 2 installed, you can compile and
+package the jar using the following command:
+
+    mvn package
+
+See the Maven 2 documentation for other build features.
+
+The latest source code for this component is available in the
+Subversion (http://subversion.tigris.org/) source repository of
+the Apache Software Foundation. If you have Subversion installed,
+you can checkout the latest source using the following command:
+
+    svn checkout http://svn.apache.org/repos/asf/sling/trunk/commons/log
+
+See the Subversion documentation for other source control features.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..de63690
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,115 @@
+<?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>12</version>
+        <relativePath>../../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.commons.logservice</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling OSGi LogService Implementation</name>
+    <description>
+        Implementation of the OSGi Compendium Log Service using SLF4J
+        as the actual logging backend.
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/bundles/commons/logservice</url>
+    </scm>
+    
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>
+                            org.apache.sling.commons.logservice.internal.Activator
+                        </Bundle-Activator>
+                        <Bundle-DocURL>
+                            http://sling.apache.org/site/logging.html
+                        </Bundle-DocURL>
+                        <Export-Package>
+                            org.osgi.service.log
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.sling.commons.logservice.*,
+                        </Private-Package>
+                        <Import-Package>
+                            org.osgi.service.log;version="[$(version;==;$(@)),$(version;=+;$(@)))",
+                            *
+                        </Import-Package>
+                    </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>1.5.0</version>
+            <scope>provided</scope>
+        </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.2.0</version>
+        </dependency>
+        
+        <!-- testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/Activator.java b/src/main/java/org/apache/sling/commons/logservice/internal/Activator.java
new file mode 100644
index 0000000..60766b5
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/Activator.java
@@ -0,0 +1,77 @@
+/*
+ * 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.logservice.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.log.LogReaderService;
+import org.osgi.service.log.LogService;
+
+/**
+ * The <code>Activator</code> class is the <code>BundleActivator</code> for the
+ * log service bundle. This activator registers the <code>LogService</code> and
+ * <code>LogReaderService</code>.
+ */
+public class Activator implements BundleActivator {
+
+    private static final String VENDOR = "The Apache Software Foundation";
+
+    private LogSupport logSupport;
+
+    /**
+     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+     */
+    public void start(final BundleContext context) throws Exception {
+        logSupport = new LogSupport();
+        context.addBundleListener(logSupport);
+        context.addFrameworkListener(logSupport);
+        context.addServiceListener(logSupport);
+
+        LogServiceFactory lsf = new LogServiceFactory(logSupport);
+        Dictionary<String, String> props = new Hashtable<String, String>();
+        props.put(Constants.SERVICE_PID, lsf.getClass().getName());
+        props.put(Constants.SERVICE_DESCRIPTION,
+            "Apache Sling LogService implementation");
+        props.put(Constants.SERVICE_VENDOR, VENDOR);
+        context.registerService(LogService.class.getName(), lsf, props);
+
+        LogReaderServiceFactory lrsf = new LogReaderServiceFactory(logSupport);
+        props = new Hashtable<String, String>();
+        props.put(Constants.SERVICE_PID, lrsf.getClass().getName());
+        props.put(Constants.SERVICE_DESCRIPTION,
+            "Apache Sling LogReaderService implementation");
+        props.put(Constants.SERVICE_VENDOR, VENDOR);
+        context.registerService(LogReaderService.class.getName(), lrsf, props);
+    }
+
+    /**
+     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     */
+    public void stop(final BundleContext context) throws Exception {
+        if (logSupport != null) {
+            context.removeBundleListener(logSupport);
+            context.removeFrameworkListener(logSupport);
+            context.removeServiceListener(logSupport);
+            logSupport.shutdown();
+            logSupport = null;
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/LogEntryImpl.java b/src/main/java/org/apache/sling/commons/logservice/internal/LogEntryImpl.java
new file mode 100644
index 0000000..a317293
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/LogEntryImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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.logservice.internal;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogEntry;
+
+public class LogEntryImpl implements LogEntry {
+
+    private final Bundle bundle;
+
+    private final ServiceReference serviceReference;
+
+    private final int level;
+
+    private final String message;
+
+    private final Throwable exception;
+
+    private final long time;
+
+    /* package */LogEntryImpl(Bundle bundle,
+            ServiceReference serviceReference, int level, String message,
+            Throwable exception) {
+        this.bundle = bundle;
+        this.serviceReference = serviceReference;
+        this.level = level;
+        this.message = message;
+        this.exception = exception;
+        this.time = System.currentTimeMillis();
+    }
+
+    public Bundle getBundle() {
+        return this.bundle;
+    }
+
+    public ServiceReference getServiceReference() {
+        return this.serviceReference;
+    }
+
+    public int getLevel() {
+        return this.level;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public Throwable getException() {
+        return this.exception;
+    }
+
+    public long getTime() {
+        return this.time;
+    }
+}
diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/LogReaderServiceFactory.java b/src/main/java/org/apache/sling/commons/logservice/internal/LogReaderServiceFactory.java
new file mode 100644
index 0000000..79791e4
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/LogReaderServiceFactory.java
@@ -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.logservice.internal;
+
+import java.util.Enumeration;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogListener;
+import org.osgi.service.log.LogReaderService;
+
+/**
+ * The <code>LogReaderServiceFactory</code> is the service factory for
+ * <code>LogReader</code> service instances supplied to bundles.
+ * <p>
+ * <blockquote> When a bundle which registers a LogListener object is stopped or
+ * otherwise releases the Log Reader Service, the Log Reader Service must remove
+ * all of the bundle's listeners.</blockquote>
+ */
+public class LogReaderServiceFactory implements ServiceFactory {
+
+    private LogSupport logSupport;
+
+    LogReaderServiceFactory(LogSupport logSupport) {
+        this.logSupport = logSupport;
+    }
+
+    // ---------- ServiceFactory interface ------------------------------------
+
+    public Object getService(Bundle bundle, ServiceRegistration registration) {
+        return new LogReaderServiceImpl(bundle);
+    }
+
+    public void ungetService(Bundle bundle, ServiceRegistration registration,
+            Object service) {
+        ((LogReaderServiceImpl) service).shutdown();
+    }
+
+    // --------- internal LogReaderService implementation ----------------------
+
+    private class LogReaderServiceImpl implements LogReaderService {
+
+        private Bundle bundle;
+
+        /* package */LogReaderServiceImpl(Bundle bundle) {
+            this.bundle = bundle;
+        }
+
+        /* package */void shutdown() {
+            LogReaderServiceFactory.this.logSupport.removeLogListeners(this.bundle);
+        }
+
+        public void addLogListener(LogListener listener) {
+            LogReaderServiceFactory.this.logSupport.addLogListener(this.bundle,
+                listener);
+        }
+
+        public void removeLogListener(LogListener listener) {
+            LogReaderServiceFactory.this.logSupport.removeLogListener(listener);
+        }
+
+        @SuppressWarnings("rawtypes")
+        public Enumeration getLog() {
+            return LogReaderServiceFactory.this.logSupport.getLog();
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/LogServiceFactory.java b/src/main/java/org/apache/sling/commons/logservice/internal/LogServiceFactory.java
new file mode 100644
index 0000000..e62faf8
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/LogServiceFactory.java
@@ -0,0 +1,97 @@
+/*
+ * 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.logservice.internal;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogService;
+
+/**
+ * The <code>LogServiceFactory</code> implements the OSGi Log Service
+ * specification and provides the functionality for the logging system. This
+ * service should be one of the first services loaded in the system.
+ */
+public class LogServiceFactory implements ServiceFactory {
+
+    private LogSupport logSupport;
+
+    /**
+     * Initializes the logging system with settings from some startup properties
+     * before the real configuration is read after ContentBus bootstrap.
+     * 
+     * @param properties The startup properties to initialize the logging system
+     *            with.
+     */
+    LogServiceFactory(LogSupport logSupport) {
+        this.logSupport = logSupport;
+
+    }
+
+    // ---------- ServiceFactory
+
+    public Object getService(Bundle bundle, ServiceRegistration registration) {
+        return new LogServiceImpl(bundle);
+    }
+
+    public void ungetService(Bundle bundle, ServiceRegistration registration,
+            Object service) {
+        // nothing to do currently
+    }
+
+    private class LogServiceImpl implements LogService {
+
+        private Bundle bundle;
+
+        /**
+         * Initializes the logging system with settings from some startup
+         * properties before the real configuration is read after ContentBus
+         * bootstrap.
+         * 
+         * @param properties The startup properties to initialize the logging
+         *            system with.
+         */
+        /* package */LogServiceImpl(Bundle bundle) {
+            this.bundle = bundle;
+        }
+
+        // ---------- LogService
+
+        public void log(int level, String message) {
+            this.log(null, level, message, null);
+        }
+
+        public void log(int level, String message, Throwable exception) {
+            this.log(null, level, message, exception);
+        }
+
+        public void log(ServiceReference sr, int level, String message) {
+            this.log(sr, level, message, null);
+        }
+
+        public void log(ServiceReference sr, int level, String message,
+                Throwable exception) {
+            // simply fire a log event
+            LogEntry entry = new LogEntryImpl(this.bundle, sr, level, message,
+                exception);
+            LogServiceFactory.this.logSupport.fireLogEvent(entry);
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java b/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
new file mode 100644
index 0000000..8a78926
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
@@ -0,0 +1,586 @@
+/*
+ * 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.logservice.internal;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentConstants;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
+import org.osgi.service.log.LogService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>LogReaderServiceFactory</code> TODO
+ */
+public class LogSupport implements BundleListener, ServiceListener,
+        FrameworkListener {
+
+    /**
+     * The service property name of the component name (value is
+     * "component.name"). Note: We use a private constant here to not create a
+     * unneded dependency on the org.osgi.service.component package.
+     */
+    private static final String COMPONENT_NAME = ComponentConstants.COMPONENT_NAME; // "component.name";
+
+    /**
+     * The empty enumeration currently returned on the {@link #getLog()} call
+     * because we do not currently record the log events.
+     */
+    private final Enumeration<?> EMPTY = Collections.enumeration(Collections.emptyList());
+
+    // The registered LogListeners
+    private LogListenerProxy[] listeners;
+
+    // The lock used to guard concurrent access to the listeners array
+    private final Object listenersLock = new Object();
+
+    // The loggers by bundle id used for logging messages originated from
+    // specific bundles
+    private Map<Long, Logger> loggers = new HashMap<Long, Logger>();
+
+    // the worker thread actually sending LogEvents to LogListeners
+    private LogEntryDispatcher logEntryDispatcher;
+
+    /* package */LogSupport() {
+        logEntryDispatcher = new LogEntryDispatcher(this);
+        logEntryDispatcher.start();
+    }
+
+    /* package */void shutdown() {
+
+        // terminate the dispatcher and wait for its termination here
+        logEntryDispatcher.terminate();
+        try {
+            logEntryDispatcher.join(1000L);
+        } catch (InterruptedException ie) {
+            // don't care
+        }
+
+        // drop all listeners
+        synchronized (listenersLock) {
+            listeners = null;
+        }
+    }
+
+    // ---------- LogReaderService interface -----------------------------------
+
+    /* package */void addLogListener(Bundle bundle, LogListener listener) {
+        synchronized (listenersLock) {
+            LogListenerProxy llp = new LogListenerProxy(bundle, listener);
+            if (listeners == null) {
+                listeners = new LogListenerProxy[] { llp };
+            } else if (getListener(listener) < 0) {
+                LogListenerProxy[] newListeners = new LogListenerProxy[listeners.length + 1];
+                System.arraycopy(listeners, 0, newListeners, 0,
+                    listeners.length);
+                newListeners[listeners.length] = llp;
+                listeners = newListeners;
+            }
+        }
+    }
+
+    /* package */void removeLogListener(LogListener listener) {
+        synchronized (listenersLock) {
+            // no listeners registered, nothing to do
+            if (listeners == null) {
+                return;
+            }
+
+            // listener is not registered, nothing to do
+            int idx = getListener(listener);
+            if (idx < 0) {
+                return;
+            }
+
+            LogListenerProxy[] newListeners = new LogListenerProxy[listeners.length - 1];
+            if (idx > 0) {
+                System.arraycopy(listeners, 0, newListeners, 0, idx);
+            }
+            if (idx < listeners.length) {
+                System.arraycopy(listeners, idx + 1, newListeners, 0,
+                    newListeners.length - idx);
+            }
+            listeners = newListeners;
+        }
+    }
+
+    /**
+     * Removes all registered LogListeners belonging to the given bundle. This
+     * is the task required by the specification from a Log Service
+     * implemenation:
+     * <p>
+     * <blockquote> When a bundle which registers a LogListener object is
+     * stopped or otherwise releases the Log Reader Service, the Log Reader
+     * Service must remove all of the bundle's listeners.</blockquote>
+     * <p>
+     *
+     * @param bundle The bundle whose listeners are to be removed.
+     */
+    /* package */void removeLogListeners(Bundle bundle) {
+        // grab an immediate copy of the array
+        LogListenerProxy[] current = getListeners();
+        if (current == null) {
+            return;
+        }
+
+        // check for listeners by bundle
+        for (int i = 0; i < current.length; i++) {
+            if (current[i].hasBundle(bundle)) {
+                removeLogListener(current[i]);
+            }
+        }
+    }
+
+    private int getListener(LogListener listener) {
+        if (listeners != null) {
+            for (int i = 0; i < listeners.length; i++) {
+                if (listeners[i].isSame(listener)) {
+                    return i;
+                }
+            }
+        }
+
+        // fall back to not found
+        return -1;
+    }
+
+    /**
+     * Returns the currently registered LogListeners
+     */
+    private LogListenerProxy[] getListeners() {
+        synchronized (listenersLock) {
+            return listeners;
+        }
+    }
+
+    /**
+     * Returns an empty enumeration for now because we do not implement log
+     * entry recording for the moment.
+     */
+    Enumeration<?> getLog() {
+        return EMPTY;
+    }
+
+    // ---------- Firing a log event -------------------------------------------
+
+    /**
+     * Logs the given log entry to the log file and enqueues for the dispatching
+     * to the registered LogListeners in a separate worker thread.
+     */
+    /* package */void fireLogEvent(LogEntry logEntry) {
+
+        // actually log it to SLF4J
+        logOut(logEntry);
+
+        // enqueue for asynchronous delivery
+        logEntryDispatcher.enqueLogEntry(logEntry);
+    }
+
+    // ---------- BundleListener -----------------------------------------------
+
+    /**
+     * Listens for Bundle events and logs the respective events according to the
+     * Log Service specification. In addition, all LogListener instances
+     * registered for stopped bundles are removed by this method.
+     */
+    public void bundleChanged(BundleEvent event) {
+        String message;
+        switch (event.getType()) {
+            case BundleEvent.INSTALLED:
+                message = "BundleEvent INSTALLED";
+                break;
+            case BundleEvent.STARTED:
+                message = "BundleEvent STARTED";
+                break;
+            case BundleEvent.STOPPED:
+                // this is special, as we have to fix the listener list for
+                // stopped bundles
+                removeLogListeners(event.getBundle());
+                message = "BundleEvent STOPPED";
+                break;
+            case BundleEvent.UPDATED:
+                message = "BundleEvent UPDATED";
+                break;
+            case BundleEvent.UNINSTALLED:
+                message = "BundleEvent UNINSTALLED";
+                break;
+            case BundleEvent.RESOLVED:
+                message = "BundleEvent RESOLVED";
+                break;
+            case BundleEvent.UNRESOLVED:
+                message = "BundleEvent UNRESOLVED";
+                break;
+            default:
+                message = "BundleEvent " + event.getType();
+        }
+
+        LogEntry entry = new LogEntryImpl(event.getBundle(), null,
+            LogService.LOG_INFO, message, null);
+        fireLogEvent(entry);
+    }
+
+    // ---------- ServiceListener ----------------------------------------------
+
+    /**
+     * Listens for Service events and logs the respective events according to
+     * the Log Service specification.
+     */
+    public void serviceChanged(ServiceEvent event) {
+        int level = LogService.LOG_INFO;
+        String message;
+        switch (event.getType()) {
+            case ServiceEvent.REGISTERED:
+                message = "ServiceEvent REGISTERED";
+                break;
+            case ServiceEvent.MODIFIED:
+                message = "ServiceEvent MODIFIED";
+                level = LogService.LOG_DEBUG;
+                break;
+            case ServiceEvent.UNREGISTERING:
+                message = "ServiceEvent UNREGISTERING";
+                break;
+            default:
+                message = "ServiceEvent " + event.getType();
+        }
+
+        String s = (event.getServiceReference().getBundle() == null)
+                ? null
+                : "Bundle " + event.getServiceReference().getBundle();
+        s = (s == null) ? message : s + " " + message;
+
+        LogEntry entry = new LogEntryImpl(
+            event.getServiceReference().getBundle(),
+            event.getServiceReference(), level, message, null);
+        fireLogEvent(entry);
+    }
+
+    // ---------- FrameworkListener --------------------------------------------
+
+    /**
+     * Listens for Framework events and logs the respective events according to
+     * the Log Service specification.
+     * <p>
+     * In the case of a Framework ERROR which is a ClassNotFoundException for an
+     * unresolved bundle, the message is logged at INFO level instead of ERROR
+     * level as prescribed by the spec. This is because such a situation should
+     * not really result in a Framework ERROR but the Apache Felix framework has
+     * no means of controlling this at the moment (framework 1.0.4 release).
+     */
+    public void frameworkEvent(FrameworkEvent event) {
+        int level = LogService.LOG_INFO;
+        String message;
+        Throwable exception = event.getThrowable();
+        switch (event.getType()) {
+            case FrameworkEvent.STARTED:
+                message = "FrameworkEvent STARTED";
+                break;
+            case FrameworkEvent.ERROR:
+                message = "FrameworkEvent ERROR";
+
+                // special precaution for Felix.loadBundleClass event overkill
+                // FIXME: actually, the error is ok, if the bundle failed to
+                // resolve
+                if (exception instanceof BundleException) {
+                    StackTraceElement[] ste = exception.getStackTrace();
+                    if (ste != null && ste.length > 0
+                        && "loadBundleClass".equals(ste[0].getMethodName())) {
+                        message += ": Class " + exception.getMessage()
+                            + " not found";
+                        if (event.getBundle() != null) {
+                            message += " in bundle "
+                                + event.getBundle().getSymbolicName() + " ("
+                                + event.getBundle().getBundleId() + ")";
+                        }
+                        level = LogService.LOG_INFO;
+                        exception = null; // don't care for a stack trace here
+                        break;
+                    }
+                }
+
+                level = LogService.LOG_ERROR;
+                break;
+            case FrameworkEvent.PACKAGES_REFRESHED:
+                message = "FrameworkEvent PACKAGES REFRESHED";
+                break;
+            case FrameworkEvent.STARTLEVEL_CHANGED:
+                message = "FrameworkEvent STARTLEVEL CHANGED";
+                break;
+            case FrameworkEvent.WARNING:
+                message = "FrameworkEvent WARNING";
+                break;
+            case FrameworkEvent.INFO:
+                message = "FrameworkEvent INFO";
+                break;
+            default:
+                message = "FrameworkEvent " + event.getType();
+        }
+
+        String s = (event.getBundle() == null) ? null : "Bundle "
+            + event.getBundle();
+        s = (s == null) ? message : s + " " + message;
+
+        LogEntry entry = new LogEntryImpl(event.getBundle(), null, level,
+            message, exception);
+        fireLogEvent(entry);
+    }
+
+    // ---------- Effective logging --------------------------------------------
+
+    /**
+     * Get a logger for messages orginating from the given bundle. If no bundle
+     * is specified, we use the system bundle logger.
+     *
+     * @param bundle The bundle for which a logger is to be returned.
+     * @return The Logger for the bundle.
+     */
+    private Logger getLogger(Bundle bundle) {
+        Long bundleId = new Long((bundle == null) ? 0 : bundle.getBundleId());
+        Logger log = loggers.get(bundleId);
+        if (log == null) {
+
+            String name;
+            if (bundle == null) {
+
+                // if we have no bundle, use the system bundle's name
+                name = Constants.SYSTEM_BUNDLE_SYMBOLICNAME;
+
+            } else {
+
+                // otherwise use the bundle symbolic name
+                name = bundle.getSymbolicName();
+
+                // if the bundle has no symbolic name, use the location
+                if (name == null) {
+                    name = bundle.getLocation();
+                }
+
+                // if the bundle also has no location, use the bundle Id
+                if (name == null) {
+                    name = String.valueOf(bundle.getBundleId());
+                }
+            }
+
+            log = LoggerFactory.getLogger(name);
+            loggers.put(bundleId, log);
+        }
+        return log;
+    }
+
+    /**
+     * Actually logs the given log entry to the logger for the bundle recorded
+     * in the log entry.
+     */
+    private void logOut(LogEntry logEntry) {
+        // /* package */ void logOut(Bundle bundle, ServiceReference sr, int
+        // level, String message, Throwable exception) {
+
+        // get the logger for the bundle
+        Logger log = getLogger(logEntry.getBundle());
+
+        StringBuffer msg = new StringBuffer();
+
+        ServiceReference sr = logEntry.getServiceReference();
+        if (sr != null) {
+            msg.append("Service [");
+            if (sr.getProperty(Constants.SERVICE_PID) != null) {
+                msg.append(sr.getProperty(Constants.SERVICE_PID)).append(',');
+            } else if (sr.getProperty(COMPONENT_NAME) != null) {
+                msg.append(sr.getProperty(COMPONENT_NAME)).append(',');
+            } else if (sr.getProperty(Constants.SERVICE_DESCRIPTION) != null) {
+                msg.append(sr.getProperty(Constants.SERVICE_DESCRIPTION)).append(
+                    ',');
+            }
+            msg.append(sr.getProperty(Constants.SERVICE_ID)).append("] ");
+        }
+
+        if (logEntry.getMessage() != null) {
+            msg.append(logEntry.getMessage());
+        }
+
+        Throwable exception = logEntry.getException();
+        if (exception != null) {
+            msg.append(" (").append(exception).append(')');
+        }
+
+        String message = msg.toString();
+        switch (logEntry.getLevel()) {
+            case LogService.LOG_DEBUG:
+                log.debug(message, exception);
+                break;
+            case LogService.LOG_INFO:
+                log.info(message, exception);
+                break;
+            case LogService.LOG_WARNING:
+                log.warn(message, exception);
+                break;
+            case LogService.LOG_ERROR:
+                log.error(message, exception);
+                break;
+            default:
+                if (logEntry.getLevel() > LogService.LOG_DEBUG) {
+                    log.trace(message, exception);
+                } else if (logEntry.getLevel() < LogService.LOG_ERROR) {
+                    log.error(message, exception);
+                }
+                break;
+        }
+    }
+
+    // ---------- internal class -----------------------------------------------
+
+    /**
+     * The <code>LogListenerProxy</code> class is a proxy to the actually
+     * registered <code>LogListener</code> which also records the bundle
+     * registering the listener. This allows for the removal of the log
+     * listeners registered by bundles which have not been removed before the
+     * bundle has been stopped.
+     */
+    private static class LogListenerProxy implements LogListener {
+
+        private final int runningBundle = Bundle.STARTING | Bundle.ACTIVE
+            | Bundle.STOPPING;
+
+        private final Bundle bundle;
+
+        private final LogListener delegatee;
+
+        public LogListenerProxy(Bundle bundle, LogListener delegatee) {
+            this.bundle = bundle;
+            this.delegatee = delegatee;
+        }
+
+        public void logged(LogEntry entry) {
+            if ((bundle.getState() & runningBundle) != 0) {
+                delegatee.logged(entry);
+            }
+        }
+
+        /* package */boolean isSame(LogListener listener) {
+            return listener == delegatee || listener == this;
+        }
+
+        /* package */boolean hasBundle(Bundle bundle) {
+            return this.bundle == bundle;
+        }
+    }
+
+    /**
+     * The <code>LogEntryDispatcher</code> implements the worker thread
+     * responsible for delivering log events to the log listeners.
+     */
+    private static class LogEntryDispatcher extends Thread {
+
+        // provides the actual log listeners on demand
+        private final LogSupport logSupport;
+
+        // the queue of log events to be dispatched
+        private final BlockingQueue<LogEntry> dispatchQueue;
+
+        // true as long as the thread is active
+        private boolean active;
+
+        LogEntryDispatcher(LogSupport logSupport) {
+            super("LogEntry Dispatcher");
+
+            this.logSupport = logSupport;
+            this.dispatchQueue = new LinkedBlockingQueue<LogEntry>();
+            this.active = true;
+        }
+
+        /**
+         * Add a log entry for dispatching.
+         */
+        void enqueLogEntry(LogEntry logEntry) {
+            dispatchQueue.offer(logEntry);
+        }
+
+        /**
+         * Get the next log entry for dispatching. This method blocks until an
+         * event is available or the thread is interrupted.
+         *
+         * @return The next event to dispatch
+         * @throws InterruptedException If the thread has been interrupted while
+         *             waiting for a log event to dispatch.
+         */
+        LogEntry dequeueLogEntry() throws InterruptedException {
+            return dispatchQueue.take();
+        }
+
+        /**
+         * Terminates this work thread by resetting the active flag and
+         * interrupting itself such that the {@link #dequeueLogEntry()} is
+         * aborted for the thread to terminate.
+         */
+        void terminate() {
+            active = false;
+            interrupt();
+        }
+
+        /**
+         * Runs the actual log event dispatching. This method continues to get
+         * log events from the {@link #dequeueLogEntry()} method until the
+         * active flag is reset.
+         */
+        @Override
+        public void run() {
+            while (active) {
+
+                LogEntry logEntry = null;
+                try {
+                    logEntry = dequeueLogEntry();
+                } catch (InterruptedException ie) {
+                    // don't care, this is expected
+                }
+
+                // dispatch the log entry
+                if (logEntry != null) {
+
+                    // grab an immediate copy of the array
+                    LogListener[] logListeners = logSupport.getListeners();
+
+                    // fire the events outside of the listenersLock
+                    if (logListeners != null) {
+                        for (LogListener logListener : logListeners) {
+                            try {
+                                logListener.logged(logEntry);
+                            } catch (Throwable t) {
+                                // should we really care ??
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-commons-logservice] 04/04: [maven-release-plugin] copy for tag org.apache.sling.commons.logservice-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.logservice-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-logservice.git

commit 13ca43b6aa6bbb93dc71abeff093b3b2fc77a28e
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Jan 31 14:04:01 2012 +0000

    [maven-release-plugin]  copy for tag org.apache.sling.commons.logservice-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.commons.logservice-1.0.0@1238553 13f79535-47bb-0310-9956-ffa450edef68

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-commons-logservice] 03/04: [maven-release-plugin] prepare release org.apache.sling.commons.logservice-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.logservice-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-logservice.git

commit fb9e692d6e4a5bc9279bcbd47801240bb1260feb
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Jan 31 14:03:51 2012 +0000

    [maven-release-plugin] prepare release org.apache.sling.commons.logservice-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice@1238552 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index de63690..b9fa37c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
     </parent>
 
     <artifactId>org.apache.sling.commons.logservice</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
+    <version>1.0.0</version>
     <packaging>bundle</packaging>
 
     <name>Apache Sling OSGi LogService Implementation</name>
@@ -38,9 +38,9 @@
     </description>
 
     <scm>
-        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice</connection>
-        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice</developerConnection>
-        <url>http://svn.apache.org/viewvc/sling/trunk/bundles/commons/logservice</url>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.commons.logservice-1.0.0</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.commons.logservice-1.0.0</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/tags/org.apache.sling.commons.logservice-1.0.0</url>
     </scm>
     
     <build>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.