You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2006/10/25 15:26:33 UTC

svn commit: r467635 - in /incubator/felix/trunk: ./ log/ log/src/ log/src/main/ log/src/main/java/ log/src/main/java/org/ log/src/main/java/org/apache/ log/src/main/java/org/apache/felix/ log/src/main/java/org/apache/felix/log/ log/src/main/java/org/ap...

Author: rickhall
Date: Wed Oct 25 06:26:32 2006
New Revision: 467635

URL: http://svn.apache.org/viewvc?view=rev&rev=467635
Log:
Initial commit of the Log service implementation from Dale Peakall.

Added:
    incubator/felix/trunk/log/   (with props)
    incubator/felix/trunk/log/pom.xml   (with props)
    incubator/felix/trunk/log/src/
    incubator/felix/trunk/log/src/main/
    incubator/felix/trunk/log/src/main/java/
    incubator/felix/trunk/log/src/main/java/org/
    incubator/felix/trunk/log/src/main/java/org/apache/
    incubator/felix/trunk/log/src/main/java/org/apache/felix/
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Activator.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Log.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogEntryImpl.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogException.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogListenerThread.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNode.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNodeEnumeration.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceFactory.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceImpl.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceFactory.java   (with props)
    incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceImpl.java   (with props)
Modified:
    incubator/felix/trunk/pom.xml

Propchange: incubator/felix/trunk/log/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Oct 25 06:26:32 2006
@@ -0,0 +1,17 @@
+classes
+target
+*.log
+*.ipr
+*.iws
+*.iml
+lib
+bundle
+dist
+.project
+.classpath
+bin
+build
+.settings
+.wtpmodules
+.deployables
+

Added: incubator/felix/trunk/log/pom.xml
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/pom.xml?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/pom.xml (added)
+++ incubator/felix/trunk/log/pom.xml Wed Oct 25 06:26:32 2006
@@ -0,0 +1,53 @@
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>osgi-bundle</packaging>
+  <name>Apache Felix Log Service</name>
+  <artifactId>org.apache.felix.log</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix.plugins</groupId>
+        <artifactId>maven-osgi-plugin</artifactId>
+        <version>${pom.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <osgiManifest>
+            <bundleName>LogService</bundleName>
+            <bundleVendor>Apache Software Foundation</bundleVendor>
+            <bundleDescription>
+              This bundle provides an implementation of the OSGi R4 Log service.
+            </bundleDescription>
+            <bundleActivator>
+              org.apache.felix.log.impl.Activator
+            </bundleActivator>
+            <importPackage>
+              org.osgi.framework, org.osgi.service.log; version=1.3
+            </importPackage>
+            <exportService>
+                 org.osgi.service.log.LogService, org.osgi.service.log.LogReaderService
+            </exportService>
+          </osgiManifest>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Propchange: incubator/felix/trunk/log/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Activator.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Activator.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Activator.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,132 @@
+/* 
+ * 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.felix.log.impl;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogReaderService;
+import org.osgi.service.log.LogService;
+
+/**
+ * The bundle activator for the OSGi log service (see section 101 of the service
+ * compendium).
+ * <p>
+ * The log service provides a general purpose message logger for the OSGi service
+ * platform.  It consists of two services, one for logging information and another
+ * for retrieving current or previously recorded log information.
+ * <p>
+ * The service knows about the following properties which are read at bundle
+ * startup:
+ * <dl>
+ *   <dt>org.apache.felix.log.maxSize</dt>
+ *   <dd>Determines the maximum size of the log used to maintain historic
+ *       log information.  A value of -1 means the log has no maximum size;
+ *       a value of 0 means that no historic log information will be maintained.
+ *       The default value is 100.</dd>
+ *
+ *   <dt>org.apache.felix.log.storeDebug</dt>
+ *   <dd>Determines whether or not debug messages will be stored as part of
+ *       the historic log information. The default value is false.</dd>
+ * </dl>
+ */
+public final class Activator implements BundleActivator {
+    /** The name of the property that defines the maximum size of the log. */
+    private static final String MAX_SIZE_PROPERTY = "org.apache.felix.log.maxSize";
+
+    /** The default value for the maximum size property. */
+    private static final int DEFAULT_MAX_SIZE = 100;
+
+    /** The name of the property that defines whether debug messages are stored. */
+    private static final String STORE_DEBUG_PROPERTY = "org.apache.felix.log.storeDebug";
+
+    /** The default value for the store debug property. */
+    private static final boolean DEFAULT_STORE_DEBUG = false;
+
+    /** The log. */
+    private Log m_log;
+
+    /**
+     * Returns the maximum size for the log.
+     * @param context the bundle context (used to look up a property)
+     * @return the maximum size for the log
+     */
+    private static int getMaxSize(final BundleContext context) {
+        int maxSize = DEFAULT_MAX_SIZE;
+
+        String maxSizePropValue = context.getProperty(MAX_SIZE_PROPERTY);
+        if (maxSizePropValue != null) {
+            try {
+                maxSize = Integer.parseInt(maxSizePropValue);
+            } catch (NumberFormatException e) {
+                // the property value is invalid - ignore
+            }
+        }
+
+        return maxSize;
+    }
+
+    /**
+     * Returns whether or not to store debug messages.
+     * @param context the bundle context (used to look up a property)
+     * @return whether or not to store debug messages
+     */
+    private static boolean getStoreDebug(final BundleContext context) {
+        boolean storeDebug = DEFAULT_STORE_DEBUG;
+
+        String storeDebugPropValue = context.getProperty(STORE_DEBUG_PROPERTY);
+        if (storeDebugPropValue != null) {
+            storeDebug = Boolean.valueOf(storeDebugPropValue).booleanValue();
+        }
+
+        return storeDebug;
+    }
+
+    /**
+     * Called by the OSGi framework when the bundle is started.
+     * Used to register the service implementations with the framework.
+     * @param context the bundle context
+     * @throws Exception if an error occurs
+     */
+    public void start(final BundleContext context) throws Exception {
+        // create the log instance
+        m_log = new Log(getMaxSize(context), getStoreDebug(context));
+
+        // register the listeners
+        context.addBundleListener(m_log);
+        context.addFrameworkListener(m_log);
+        context.addServiceListener(m_log);
+
+        // register the services with the framework
+        context.registerService(LogService.class.getName(),
+                new LogServiceFactory(m_log), null);
+
+        context.registerService(LogReaderService.class.getName(),
+                new LogReaderServiceFactory(m_log), null);
+    }
+
+    /**
+     * Called by the OSGi framework when the bundle is stopped.
+     * @param context the bundle context
+     * @throws Exception if an error occurs
+     */
+    public void stop(final BundleContext context) throws Exception {
+        // close the log
+        m_log.close();
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Activator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Log.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Log.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Log.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Log.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,265 @@
+/* 
+ * 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.felix.log.impl;
+
+import java.util.Enumeration;
+
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
+import org.osgi.service.log.LogService;
+
+/**
+ * Class used to represent the log.  This class is used by the implementations
+ * of both the {@link org.osgi.service.log.LogService} interface and the
+ * {@link org.osgi.service.log.LogReaderService} to access the log.
+ * @see org.osgi.service.log.LogService
+ * @see org.osgi.service.log.LogReaderService
+ */
+final class Log implements BundleListener, FrameworkListener, ServiceListener {
+    /** The first log entry. */
+    private LogNode m_head;
+
+    /** The last log entry. */
+    private LogNode m_tail;
+
+    /** The log size. */
+    private int m_size;
+
+    /** The log listener thread. */
+    private LogListenerThread listenerThread;
+
+    /** The maximum size for the log. */
+    private final int m_maxSize;
+
+    /** Whether or not to store debug messages. */
+    private final boolean m_storeDebug;
+
+    /**
+     * Create a new instance.
+     * @param maxSize the maximum size for the log
+     * @param storeDebug whether or not to store debug messages
+     */
+    Log(final int maxSize, final boolean storeDebug) {
+        this.m_maxSize = maxSize;
+        this.m_storeDebug = storeDebug;
+    }
+
+    /**
+     * Close the log.
+     */
+    void close() {
+        if (listenerThread != null) {
+            listenerThread.shutdown();
+            listenerThread = null;
+        }
+
+        m_head = null;
+        m_tail = null;
+        m_size = 0;
+    }
+
+    /**
+     * Adds the entry to the log.
+     * @param entry the entry to add to the log
+     */
+    synchronized void addEntry(final LogEntry entry) {
+        if (m_maxSize != 0) {
+            // add the entry to the historic log
+            if (m_storeDebug || entry.getLevel() != LogService.LOG_DEBUG) {
+                // create a new node for the entry
+                LogNode node = new LogNode(entry);
+
+                // add to the front of the linked list
+                node.setNextNode(m_head);
+                if (m_head != null) {
+                    m_head.setPreviousNode(node);
+                }
+
+                // and store the node
+                m_head = node;
+
+                // bump the size of the list
+                ++m_size;
+
+                // if no tail node - add the node to the tail
+                if (m_tail == null) {
+                    m_tail = node;
+                }
+            }
+
+            // ensure the historic log doesn't grow beyond a certain size
+            if (m_maxSize != -1) {
+                if (m_size > m_maxSize) {
+                    LogNode last = m_tail.getPreviousNode();
+                    last.setNextNode(null);
+                    m_tail = last;
+                    --m_size;
+                }
+            }
+        }
+
+        // notify any listeners
+        if (listenerThread != null) {
+            listenerThread.addEntry(entry);
+        }
+    }
+
+    /**
+     * Add a listener to the log.
+     * @param listener the log listener to subscribe
+     */
+    synchronized void addListener(final LogListener listener) {
+        if (listenerThread == null) {
+            // create a new listener thread if necessary:
+            // the listener thread only runs if there are any registered listeners
+            listenerThread = new LogListenerThread();
+            listenerThread.start();
+        }
+        listenerThread.addListener(listener);
+    }
+
+    /**
+     * Remove a listener from the log.
+     * @param listener the log listener to unsubscribe
+     */
+    synchronized void removeListener(final LogListener listener) {
+        if (listenerThread != null) {
+            listenerThread.removeListener(listener);
+
+            // shutdown the thread if there are no listeners
+            if (listenerThread.getListenerCount() == 0) {
+                listenerThread.shutdown();
+                listenerThread = null;
+            }
+        }
+    }
+
+    /**
+     * Returns an enumeration of all the entries in the log most recent first.
+     * @return an enumeration of all the entries in the log most recent first
+     */
+    synchronized Enumeration getEntries() {
+        return new LogNodeEnumeration(m_head, m_tail);
+    }
+
+    /** The messages returned for the framework events. */
+    private static final String[] FRAMEWORK_EVENT_MESSAGES = {
+        "FrameworkEvent STARTED",
+        "FrameworkEvent ERROR",
+        "FrameworkEvent PACKAGES REFRESHED",
+        "FrameworkEvent STARTLEVEL CHANGED",
+        "FrameworkEvent WARNING",
+        "FrameworkEvent INFO"
+    };
+
+    /**
+     * Called when a framework event occurs.
+     * @param event the event that occured
+     */
+    public void frameworkEvent(final FrameworkEvent event) {
+        int eventType = event.getType();
+        String message = null;
+
+        for (int i = 0; message == null && i < FRAMEWORK_EVENT_MESSAGES.length; ++i) {
+            if (eventType >> i == 1) {
+                message = FRAMEWORK_EVENT_MESSAGES[i];
+            }
+        }
+
+        LogEntry entry = new LogEntryImpl(event.getBundle(),
+                null,
+                (eventType == FrameworkEvent.ERROR) ? LogService.LOG_ERROR : LogService.LOG_INFO,
+                message,
+                event.getThrowable());
+
+        addEntry(entry);
+    }
+
+    /** The messages returned for the bundle events. */
+    private static final String[] BUNDLE_EVENT_MESSAGES = {
+        "BundleEvent INSTALLED",
+        "BundleEvent STARTED",
+        "BundleEvent STOPPED",
+        "BundleEvent UPDATED",
+        "BundleEvent UNINSTALLED",
+        "BundleEvent RESOLVED",
+        "BundleEvent UNRESOLVED"
+    };
+
+    /**
+     * Called when a bundle event occurs.
+     * @param event the event that occured
+     */
+    public void bundleChanged(final BundleEvent event) {
+        int eventType = event.getType();
+        String message = null;
+
+        for (int i = 0; message == null && i < BUNDLE_EVENT_MESSAGES.length; ++i) {
+            if (eventType >> i == 1) {
+                message = BUNDLE_EVENT_MESSAGES[i];
+            }
+        }
+
+        if (message != null) {
+            LogEntry entry = new LogEntryImpl(event.getBundle(),
+                    null,
+                    LogService.LOG_INFO,
+                    message,
+                    null);
+
+            addEntry(entry);
+        }
+    }
+
+    /** The messages returned for the service events. */
+    private static final String[] SERVICE_EVENT_MESSAGES = {
+        "ServiceEvent REGISTERED",
+        "ServiceEvent MODIFIED",
+        "ServiceEvent UNREGISTERING"
+    };
+
+    /**
+     * Called when a service event occurs.
+     * @param event the event that occured
+     */
+    public void serviceChanged(final ServiceEvent event) {
+        int eventType = event.getType();
+        String message = null;
+
+        for (int i = 0; message == null && i < SERVICE_EVENT_MESSAGES.length; ++i) {
+            if (eventType >> i == 1) {
+                message = SERVICE_EVENT_MESSAGES[i];
+            }
+        }
+
+        LogEntry entry = new LogEntryImpl(event.getServiceReference().getBundle(),
+                event.getServiceReference(),
+                (eventType == ServiceEvent.MODIFIED) ? LogService.LOG_DEBUG : LogService.LOG_INFO,
+                message,
+                null);
+
+        addEntry(entry);
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/Log.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogEntryImpl.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogEntryImpl.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogEntryImpl.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogEntryImpl.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,148 @@
+/* 
+ * 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.felix.log.impl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogEntry;
+
+/**
+ * Implementation of the OSGi {@link LogEntry} interface.  See section 101
+ * of the OSGi service compendium.
+ * <p>
+ * Provides methods to access the information contained in an individual Log
+ * Service log entry.
+ * <p>
+ * A LogEntry object may be acquired from the
+ * {@link org.osgi.service.log.LogReaderService#getLog()} method or by
+ * registering a {@link org.osgi.service.log.LogListener} object.
+ * @see org.osgi.service.log.LogReaderService#getLog()
+ * @see org.osgi.service.log.LogListener
+ */
+final class LogEntryImpl implements LogEntry {
+
+    /** The bundle that created the LogEntry object. */
+    private final Bundle m_bundle;
+
+    /** The exception associated with this LogEntry object. */
+    private final Throwable m_exception;
+
+    /** The severity level of this LogEntry object. */
+    private final int m_level;
+
+    /** The message associated with this LogEntry object. */
+    private final String m_message;
+
+    /** The service reference associated with this LogEntry object. */
+    private final ServiceReference m_serviceReference;
+
+    /** The system time in milliseconds when this LogEntry object was created. */
+    private final long m_time;
+
+    /**
+     * Create a new instance.
+     * @param bundle the bundle that created the LogEntry object
+     * @param sr the service reference to associate with this LogEntry object
+     * @param level the severity level for this LogEntry object
+     * @param message the message to associate with this LogEntry object
+     * @param exception the exception to associate with this LogEntry object
+     */
+    LogEntryImpl(final Bundle bundle,
+            final ServiceReference sr,
+            final int level,
+            final String message,
+            final Throwable exception) {
+        this.m_bundle = bundle;
+        this.m_exception = LogException.getException(exception);
+        this.m_level = level;
+        this.m_message = message;
+        this.m_serviceReference = sr;
+        this.m_time = System.currentTimeMillis();
+    }
+
+    /**
+     * Returns the bundle that created this LogEntry object.
+     * @return the bundle that created this LogEntry object;<code>null</code> if no
+     * bundle is associated with this LogEntry object
+     */
+    public Bundle getBundle() {
+        return m_bundle;
+    }
+
+    /**
+     * Returns the {@link ServiceReference} object for the service associated with
+     * this LogEntry object.
+     * @return the {@link ServiceReference} object for the service associated with
+     * this LogEntry object; <code>null</code> if no {@link ServiceReference} object
+     * was provided
+     */
+    public ServiceReference getServiceReference() {
+        return m_serviceReference;
+    }
+
+    /**
+     * Returns the severity level of this LogEntry object.
+     * <p>
+     * This is one of the severity levels defined by the
+     * {@link org.osgi.service.logLogService} interface.
+     * @return severity level of this LogEntry object.
+     * @see org.osgi.service.LogService#LOG_ERROR
+     * @see org.osgi.service.LogService#LOG_WARNING
+     * @see org.osgi.service.LogService#LOG_INFO
+     * @see org.osgi.service.LogService#LOG_DEBUG
+     */
+    public int getLevel() {
+        return m_level;
+    }
+
+    /**
+     * Returns the human readable message associated with this LogEntry object.
+     * @return a string containing the message associated with this LogEntry object
+     */
+    public String getMessage() {
+        return m_message;
+    }
+
+    /**
+     * Returns the exception object associated with this LogEntry object.
+     * <p>
+     * The returned exception may not be the original exception.  To avoid
+     * references to a bundle defined exception class, thus preventing an
+     * uninstalled bundle from being garbage collected, this LogService will
+     * return an exception object of an implementation defined
+     * {@link Throwable} sub-class.
+     * This exception will maintain as much information as possible from the
+     * original exception object such as the message and stack trace.
+     * @return throwable object of the exception associated with this LogEntry;
+     * <code>null</code> if no exception is associated with this LogEntry object
+     */
+    public Throwable getException() {
+        return m_exception;
+    }
+
+    /**
+     * Returns the value of {@link System#currentTimeMillis()} at the time this
+     * LogEntry object was created.
+     * @return the system time in milliseconds when this LogEntry object was created
+     * @see System#currentTimeMillis()
+     */
+    public long getTime() {
+        return m_time;
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogEntryImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogException.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogException.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogException.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogException.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,99 @@
+/* 
+ * 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.felix.log.impl;
+
+/**
+ * Implementation dependent exception class used to avoid references to any
+ * bundle defined exception class, which might prevent an uninstalled bundle
+ * from being garbage collected.  This exception maintains the class of the
+ * original exception (as part of the message), the message (appended to the
+ * class name) and the stack trace of both the exception thrown and any
+ * embedded exceptions.
+ */
+final class LogException extends Exception {
+    /** The class name of the original exception. */
+    private final String m_className;
+
+    /** The message from the original exception. */
+    private final String m_message;
+
+    /** The localized message from the original exception. */
+    private final String m_localizedMessage;
+
+    /**
+     * Create a new instance.
+     * @param exception the original exception.
+     */
+    private LogException(final Throwable exception) {
+        m_className = exception.getClass().getName();
+        m_message = exception.getMessage();
+        m_localizedMessage = exception.getLocalizedMessage();
+        setStackTrace(exception.getStackTrace());
+
+        Throwable cause = exception.getCause();
+        if (cause != null) {
+            cause = getException(cause);
+            initCause(cause);
+        }
+    }
+
+    /**
+     * Returns the message associated with the exception.  The message
+     * will be the class name of the original exception followed by the
+     * message of the original exception.
+     * @return the message associated with the exception
+     */
+    public String getMessage() {
+        return m_className + ": " + m_message;
+    }
+
+    /**
+     * Returns the localized message associated with the exception.  The
+     * localized message will be the class name of the original exception
+     * followed by the localized message of the original exception.
+     * @return the localized message associated with the exception
+     */
+    public String getLocalizedMessage() {
+        return m_className + ": " + m_localizedMessage;
+    }
+
+    /** The prefix that identifies classes from the "java" namespace. */
+    private static final String JAVA_PACKAGE_PREFIX = "java.";
+
+    /**
+     * Returns the exception to store in the {@link LogEntry}.
+     * @param exception the exception that was originally thrown.
+     * @return the exception to store in the {@link LogEntry}
+     */
+    static Throwable getException(final Throwable exception) {
+        Throwable result = null;
+
+        if (exception != null) {
+            String className = exception.getClass().getName();
+            if (exception.getCause() == null
+                    && className.startsWith(JAVA_PACKAGE_PREFIX)) {
+                result = exception;
+            } else {
+                result = new LogException(exception);
+            }
+        }
+
+        return result;
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogListenerThread.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogListenerThread.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogListenerThread.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogListenerThread.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,135 @@
+/* 
+ * 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.felix.log.impl;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
+
+/**
+ * This class is responsible for asynchronously delivering log messages to
+ * any {@link LogListener} subscribers.  A subscriber can be added using the
+ * {@link org.osgi.service.log.LogReaderService#addLogListener(LogListener)}
+ * method.
+ */
+final class LogListenerThread extends Thread {
+
+    /** Whether the thread is stopping or not. */
+    private boolean m_stopping = false;
+
+    /** The stack of entries waiting to be delivered to the log listeners. **/
+    private final Stack m_entriesToDeliver = new Stack();
+
+    /** The list of listeners. */
+    private final List m_listeners = new Vector();
+
+    /**
+     * Add an entry to the list of messages to deliver.
+     * @param entry the log entry to deliver
+     */
+    void addEntry(final LogEntry entry) {
+        synchronized (m_entriesToDeliver) {
+            m_entriesToDeliver.add(entry);
+            m_entriesToDeliver.notifyAll();
+        }
+    }
+
+    /**
+     * Add a listener to the list of listeners that are subscribed.
+     * @param listener the listener to add to the list of subscribed listeners
+     */
+    void addListener(final LogListener listener) {
+        synchronized (m_listeners) {
+            m_listeners.add(listener);
+        }
+    }
+
+    /**
+     * Remove a listener from the list of listeners that are subscribed.
+     * @param listener the listener to remove from the list of subscribed listeners
+     */
+    void removeListener(final LogListener listener) {
+        synchronized (m_listeners) {
+            m_listeners.remove(listener);
+        }
+    }
+
+    /**
+     * Returns the number of listeners that are currently registered.
+     * @return the number of listeners that are currently registered
+     */
+    int getListenerCount() {
+        return m_listeners.size();
+    }
+
+    /**
+     * Stop the thread.  This will happen asynchronously.
+     */
+    void shutdown() {
+        m_stopping = true;
+
+        synchronized (m_entriesToDeliver) {
+            m_entriesToDeliver.notifyAll();
+        }
+    }
+
+    /**
+     * The main method of the thread: waits for new messages to be receieved
+     * and then delivers them to any registered log listeners.
+     */
+    public void run() {
+        boolean stop = false;
+
+        for (; !stop;) {
+            synchronized (m_entriesToDeliver) {
+                if (!m_entriesToDeliver.isEmpty()) {
+                    LogEntry entry = (LogEntry) m_entriesToDeliver.pop();
+
+                    synchronized (m_listeners) {
+                        Iterator listenerIt = m_listeners.iterator();
+                        while (listenerIt.hasNext()) {
+                            try {
+                                LogListener listener = (LogListener) listenerIt.next();
+                                listener.logged(entry);
+                            } catch (Throwable t) {
+                                // catch and discard any exceptions thrown by the listener
+                            }
+                        }
+                    }
+                }
+
+                if (m_entriesToDeliver.isEmpty()) {
+                    try {
+                        m_entriesToDeliver.wait();
+                    } catch (InterruptedException e) {
+                        // do nothing
+                    }
+                }
+            }
+
+            if (m_stopping) {
+                stop = true;
+            }
+        }
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogListenerThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNode.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNode.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNode.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNode.java Wed Oct 25 06:26:32 2006
@@ -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.felix.log.impl;
+
+import org.osgi.service.log.LogEntry;
+
+/**
+ * The class used as a doubly linked list node in the log.
+ */
+final class LogNode {
+    /** The previous node. */
+    private LogNode m_previous;
+
+    /** The next node. */
+    private LogNode m_next;
+
+    /** The log entry. */
+    private final LogEntry m_entry;
+
+    /**
+     * Create a new instance.
+     * @param entry the log entry.
+     */
+    LogNode(final LogEntry entry) {
+        m_entry = entry;
+    }
+
+    /**
+     * Returns the associated entry.
+     * @return the associated entry
+     */
+    LogEntry getEntry() {
+        return m_entry;
+    }
+
+    /**
+     * Get the next node.
+     * @return the next node
+     */
+    LogNode getNextNode() {
+        return m_next;
+    }
+
+    /**
+     * Set the next node.
+     * @param next the next node
+     */
+    void setNextNode(final LogNode next) {
+        m_next = next;
+    }
+
+    /**
+     * Get the previous node.
+     * @return the previous node
+     */
+    LogNode getPreviousNode() {
+        return m_previous;
+    }
+
+    /**
+     * Set the previous node.
+     * @param previous the previous node
+     */
+    void setPreviousNode(final LogNode previous) {
+        m_previous = previous;
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNodeEnumeration.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNodeEnumeration.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNodeEnumeration.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNodeEnumeration.java Wed Oct 25 06:26:32 2006
@@ -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.felix.log.impl;
+
+import java.util.Enumeration;
+
+import org.osgi.service.log.LogEntry;
+
+/**
+ * Implementation of the {@link Enumeration} interface for a linked list of
+ * {@link LogNode} entries.
+ */
+final class LogNodeEnumeration implements Enumeration {
+    /** The next node. */
+    private LogNode m_next;
+
+    /** The last node. */
+    private final LogNode m_last;
+
+    /**
+     * Creates a new instance.
+     * @param start the first node to return
+     * @param end the last node to return
+     */
+    LogNodeEnumeration(final LogNode start, final LogNode end) {
+        m_next = start;
+        m_last = end;
+    }
+
+    /**
+     * Determines whether there are any more elements to return.
+     * @return <code>true</code> if there are more elements; <code>false</code> otherwise
+     */
+    public boolean hasMoreElements() {
+        return m_next != null;
+    }
+
+    /**
+     * Returns the current element and moves onto the next element.
+     * @return the current element
+     */
+    public Object nextElement() {
+        LogEntry result = null;
+
+        if (m_next == m_last) {
+            result = m_next.getEntry();
+            m_next = null;
+        } else if (m_next != null) {
+            result = m_next.getEntry();
+            m_next = m_next.getNextNode();
+        }
+
+        return result;
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogNodeEnumeration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceFactory.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceFactory.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceFactory.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceFactory.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,64 @@
+/* 
+ * 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.felix.log.impl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * {@link ServiceFactory} implementation for {@link LogReaderService}.  Associates
+ * an individual {@link LogReaderService} with a {@link Bundle}.
+ */
+final class LogReaderServiceFactory implements ServiceFactory {
+    /** The log to associate the service implementations with. */
+    private final Log m_log;
+
+    /**
+     * Create a new instance.
+     * @param log the log to associate the service implementations with.,
+     */
+    LogReaderServiceFactory(final Log log) {
+        m_log = log;
+    }
+
+    /**
+     * Get the service to use for the specified bundle.
+     * @param bundle the bundle requesting the service
+     * @param registration the service registration
+     * @return the log reader service implementation for the specified bundle
+     */
+    public Object getService(final Bundle bundle,
+            final ServiceRegistration registration) {
+        return new LogReaderServiceImpl(m_log);
+    }
+
+    /**
+     * Release the service previously obtained through
+     * {@link #getService(Bundle, ServiceRegistration)}.
+     * @param bundle the bundle that originally requested the service
+     * @param registration the service registration
+     * @param service the service to release
+     */
+    public void ungetService(final Bundle bundle,
+            final ServiceRegistration registration,
+            final Object service) {
+        ((LogReaderServiceImpl) service).removeAllLogListeners();
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceImpl.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceImpl.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceImpl.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,102 @@
+/* 
+ * 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.felix.log.impl;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.osgi.service.log.LogListener;
+import org.osgi.service.log.LogReaderService;
+
+/**
+ * Implementation of the OSGi {@link LogReaderService} interface.  See section 101
+ * of the OSGi service compendium.
+ * <p>
+ * The {@link LogReaderService} maintains a list of {@link org.osgi.service.log.LogEntry}
+ * objects called the <i>log</i>.  The {@link LogReaderService} is a service that bundle
+ * developers can use to retrieve information contained in this log, and receive
+ * notifications about {@link org.osgi.service.log.LogEntry} objects when they are created
+ * through the {@link org.osgi.service.log.LogService}.
+ */
+final class LogReaderServiceImpl implements LogReaderService {
+
+    /** The log implementation. */
+    private final Log m_log;
+
+    /** The listeners associated with this service. */
+    private final List m_listeners = new Vector();
+
+    /**
+     * Create a new instance.
+     * @param log the log implementation
+     */
+    LogReaderServiceImpl(final Log log) {
+        this.m_log = log;
+    }
+
+    /**
+     * This method is used to subscribe to the Log Reader Service in order to receive
+     * log messages as they occur.  Unlike the previously recorded log entries, all
+     * log messages must be sent to subscribers of the Log Reader Service as they are
+     * recorded.
+     * <p>
+     * A subscriber to the Log Reader Service must implement the {@link LogListener}
+     * interface.
+     * <p>
+     * After a subscription of the Log Reader Service has been started, the subscriber's
+     * {@link LogListener#logged(LogEntry)} method must be called with a {@link LogEntry}
+     * object for the message each time a message is logged.
+     * @param listener the listener object to subscribe
+     */
+    public synchronized void addLogListener(final LogListener listener) {
+        m_listeners.add(listener);
+        m_log.addListener(listener);
+    }
+
+    /**
+     * This method is used to unsubscribe from the Log Reader Service.
+     * @param listener the listener object to unsubscribe
+     */
+    public synchronized void removeLogListener(final LogListener listener) {
+        m_listeners.remove(listener);
+        m_log.removeListener(listener);
+    }
+
+    /**
+     * This method retrieves past log entries as an enumeration with the most recent
+     * entry first.
+     * @return an enumeration of the {@link LogEntry} objects that have been stored
+     */
+    public Enumeration getLog() {
+        return m_log.getEntries();
+    }
+
+    /**
+     * Remove all log listeners registered through this service.
+     */
+    synchronized void removeAllLogListeners() {
+        Iterator listenerIt = m_listeners.iterator();
+        while (listenerIt.hasNext()) {
+            LogListener listener = (LogListener) listenerIt.next();
+            m_log.removeListener(listener);
+        }
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogReaderServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceFactory.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceFactory.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceFactory.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceFactory.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,64 @@
+/* 
+ * 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.felix.log.impl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * {@link ServiceFactory} implementation for {@link LogService}.  Associates
+ * an individual {@link LogService} with a {@link Bundle}.
+ */
+final class LogServiceFactory implements ServiceFactory {
+    /** The log to associate the service implementations with. */
+    private final Log m_log;
+
+    /**
+     * Create a new instance.
+     * @param log the log to associate the service implementations with.,
+     */
+    LogServiceFactory(final Log log) {
+        m_log = log;
+    }
+
+    /**
+     * Get the service to use for the specified bundle.
+     * @param bundle the bundle requesting the service
+     * @param registration the service registration
+     * @return the log service implementation for the specified bundle
+     */
+    public Object getService(final Bundle bundle,
+            final ServiceRegistration registration) {
+        return new LogServiceImpl(m_log, bundle);
+    }
+
+    /**
+     * Release the service previously obtained through
+     * {@link #getService(Bundle, ServiceRegistration)}.
+     * @param bundle the bundle that originally requested the service
+     * @param registration the service registration
+     * @param service the service to release
+     */
+    public void ungetService(final Bundle bundle,
+            final ServiceRegistration registration,
+            final Object service) {
+        // do nothing
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceImpl.java?view=auto&rev=467635
==============================================================================
--- incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceImpl.java (added)
+++ incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceImpl.java Wed Oct 25 06:26:32 2006
@@ -0,0 +1,99 @@
+/* 
+ * 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.felix.log.impl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * Implementation of the OSGi {@link LogService}.
+ */
+final class LogServiceImpl implements LogService {
+
+    /** The log implementation. */
+    private final Log m_log;
+
+    /** The bundle associated with this implementation. */
+    private final Bundle m_bundle;
+
+    /**
+     * Create a new instance.
+     * @param log the log implementation
+     * @param bundle the bundle associated with this implementation
+     */
+    LogServiceImpl(final Log log, final Bundle bundle) {
+        this.m_log = log;
+        this.m_bundle = bundle;
+    }
+
+    /**
+     * Log the specified message at the specified level.
+     * @param level the level to log the message at
+     * @param message the message to log
+     */
+    public void log(final int level, final String message) {
+        log(null, level, message, null);
+    }
+
+    /**
+     * Log the specified message along with the specified exception at the
+     * specified level.
+     * @param level the level to log the message and exception at
+     * @param message the message to log
+     * @param exception the exception to log
+     */
+    public void log(final int level,
+            final String message,
+            final Throwable exception) {
+        log(null, level, message, exception);
+    }
+
+    /**
+     * Log the specified message along with the speicified service reference
+     * at the specified level.
+     * @param sr the service reference of the service that produced the message
+     * @param level the level to log the message at
+     * @param message the message to log
+     */
+    public void log(final ServiceReference sr,
+            final int level,
+            final String message) {
+        log(sr, level, message, null);
+    }
+
+    /**
+     * Log the specified message along with the specified exception and
+     * service reference at the specified level.
+     * @param sr the service reference of the service that produced the message
+     * @param level the level to log the message at
+     * @param message the message to log
+     * @param exception the exception to log
+     */
+    public void log(final ServiceReference sr,
+            final int level,
+            final String message,
+            final Throwable exception) {
+        m_log.addEntry(new LogEntryImpl((sr != null) ? sr.getBundle() : m_bundle,
+                sr,
+                level,
+                message,
+                exception));
+    }
+}

Propchange: incubator/felix/trunk/log/src/main/java/org/apache/felix/log/impl/LogServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/felix/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/pom.xml?view=diff&rev=467635&r1=467634&r2=467635
==============================================================================
--- incubator/felix/trunk/pom.xml (original)
+++ incubator/felix/trunk/pom.xml Wed Oct 25 06:26:32 2006
@@ -77,6 +77,7 @@
     <module>eventadmin.bridge.configuration</module>
     <module>eventadmin.bridge.useradmin</module>
     <module>eventadmin.bridge.wireadmin</module>
+    <module>log</module>
 
     <module>tools/mangen</module>