You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2010/08/06 18:46:17 UTC

svn commit: r983048 - in /felix/sandbox/cziegeler/dp-fileinstall: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/fileinstall/ src/main/java/org/apache/felix/f...

Author: cziegeler
Date: Fri Aug  6 16:46:16 2010
New Revision: 983048

URL: http://svn.apache.org/viewvc?rev=983048&view=rev
Log:
Initial version of deployment package support for FileInstall

Added:
    felix/sandbox/cziegeler/dp-fileinstall/
    felix/sandbox/cziegeler/dp-fileinstall/pom.xml   (with props)
    felix/sandbox/cziegeler/dp-fileinstall/src/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java   (with props)
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java   (with props)
    felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java   (with props)

Added: felix/sandbox/cziegeler/dp-fileinstall/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/dp-fileinstall/pom.xml?rev=983048&view=auto
==============================================================================
--- felix/sandbox/cziegeler/dp-fileinstall/pom.xml (added)
+++ felix/sandbox/cziegeler/dp-fileinstall/pom.xml Fri Aug  6 16:46:16 2010
@@ -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.
+-->
+<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">
+    <parent>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>felix-parent</artifactId>
+        <version>1.2.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>bundle</packaging>
+    <name>Apache Felix FileInstall DeploymentPackage</name>
+    <description>
+	    This bundle provides deployment package support for the FileInstall
+    </description>
+    <version>0.1.0-SNAPSHOT</version>
+    <artifactId>org.apache.felix.fileinstall.dp</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>4.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>4.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.fileinstall</artifactId>
+            <version>3.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>1.4.3</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>
+                            ${pom.artifactId} 
+	                    </Bundle-SymbolicName>
+  	                    <Bundle-Activator>
+                            org.apache.felix.fileinstall.dp.Activator
+                        </Bundle-Activator>
+                        <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
+                        <DynamicImport-Package>
+                            org.osgi.service.log
+                        </DynamicImport-Package>
+                        <Import-Package>
+                            !org.osgi.service.log,
+                            <!-- default -->
+                            *
+                        </Import-Package>
+                        <Private-Package>org.apache.felix.fileinstall.dp</Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

Propchange: felix/sandbox/cziegeler/dp-fileinstall/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/dp-fileinstall/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/sandbox/cziegeler/dp-fileinstall/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java?rev=983048&view=auto
==============================================================================
--- felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java (added)
+++ felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java Fri Aug  6 16:46:16 2010
@@ -0,0 +1,98 @@
+/*
+ * 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.fileinstall.dp;
+
+import java.util.Hashtable;
+
+import org.apache.felix.fileinstall.ArtifactInstaller;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+
+public class Activator implements ServiceListener, BundleActivator {
+
+    private static final String DEPLOYMENT_ADMIN = "org.osgi.service.deploymentadmin.DeploymentAdmin";
+
+    /** The bundle context. */
+    private BundleContext bundleContext;
+
+    /** The service reference to the deployment admin. */
+    private ServiceReference deploymentAdminReference;
+
+    /** The service registration for the install service. */
+    private ServiceRegistration serviceReg;
+
+    /**
+     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+     */
+    public void start(final BundleContext context) throws Exception {
+        this.bundleContext = context;
+        LogWrapper.setContext(this.bundleContext);
+        this.bundleContext.addServiceListener(this, "(" + Constants.OBJECTCLASS
+                + "=" + DEPLOYMENT_ADMIN + ")");
+
+        }
+        /**
+     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     */
+    public void stop(final BundleContext context) throws Exception {
+        this.bundleContext.removeServiceListener(this);
+        LogWrapper.setContext(null);
+        this.unregister();
+        this.bundleContext = null;
+    }
+
+    /**
+     * Wait for the deployment admin service.
+     * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+     */
+    public synchronized void serviceChanged(ServiceEvent event) {
+        if ( event.getType() == ServiceEvent.REGISTERED && this.deploymentAdminReference == null ) {
+            this.deploymentAdminReference = this.bundleContext.getServiceReference(DEPLOYMENT_ADMIN);
+            if ( this.deploymentAdminReference != null ) {
+                final DeploymentAdmin deploymentAdmin = (DeploymentAdmin) this.bundleContext.getService(this.deploymentAdminReference);
+                if ( deploymentAdmin == null ) {
+                    this.deploymentAdminReference = null;
+                } else {
+                    final Hashtable props = new Hashtable();
+                    props.put(Constants.SERVICE_DESCRIPTION, "Apache Felix Deployment Package Support for FileInstall");
+                    props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+                    this.serviceReg = this.bundleContext.registerService(new String[] {ArtifactInstaller.class.getName()},
+                        new DeploymentPackageInstaller(deploymentAdmin), props);
+                }
+            }
+        } else if ( event.getType() == ServiceEvent.UNREGISTERING && this.deploymentAdminReference != null ) {
+            this.unregister();
+        }
+    }
+
+    private void unregister() {
+        if ( this.deploymentAdminReference != null ) {
+            this.bundleContext.ungetService(this.deploymentAdminReference);
+            this.deploymentAdminReference = null;
+        }
+        if ( serviceReg != null ) {
+            serviceReg.unregister();
+            serviceReg = null;
+        }
+    }
+}

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/Activator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java?rev=983048&view=auto
==============================================================================
--- felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java (added)
+++ felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java Fri Aug  6 16:46:16 2010
@@ -0,0 +1,128 @@
+/*
+ * 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.fileinstall.dp;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.apache.felix.fileinstall.ArtifactInstaller;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+import org.osgi.service.deploymentadmin.DeploymentPackage;
+
+/**
+ * This is an extension for FileInstall.
+ * It listens for files ending with ".dp" and installs them through
+ * the deployment package admin.
+ *
+ */
+public class DeploymentPackageInstaller implements ArtifactInstaller {
+
+    /** The extension for deployment packages. */
+    private static final String EXTENSION = ".dp";
+
+    private static final String DEPLOYMENTPACKAGE_SYMBOLICMAME = "DeploymentPackage-SymbolicName";
+
+    private final DeploymentAdmin deploymentAdmin;
+
+    public DeploymentPackageInstaller(final DeploymentAdmin dpA) {
+        this.deploymentAdmin = dpA;
+    }
+
+    /**
+     * @see org.apache.felix.fileinstall.ArtifactListener#canHandle(java.io.File)
+     */
+    public boolean canHandle(final File artifact) {
+        return artifact.getName().endsWith(EXTENSION);
+    }
+
+
+    /**
+     * @see org.apache.felix.fileinstall.ArtifactInstaller#install(java.io.File)
+     */
+    public void install(final File artifact) throws Exception {
+        LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG, "Installing Deployment Package "
+                + " from " + artifact);
+        // install this as a deployment package
+        final InputStream ins = new FileInputStream(artifact);
+        try {
+            this.deploymentAdmin.installDeploymentPackage(ins);
+            LogWrapper.getLogger().log(LogWrapper.LOG_INFO, "Deployment Package "
+                    + " installed from " + artifact);
+        } finally {
+            try {
+                ins.close();
+            } catch (IOException ignore) {}
+        }
+    }
+
+    /**
+     * @see org.apache.felix.fileinstall.ArtifactInstaller#update(java.io.File)
+     */
+    public void update(final File artifact) throws Exception {
+        LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG, "Updating Deployment Package "
+                + " from " + artifact);
+        this.install(artifact);
+    }
+
+    /**
+     * Get the manifest from the artifact.
+     * @param artifact
+     * @return
+     * @throws IOException
+     */
+    private Manifest getManifest(final File artifact) throws IOException {
+        JarFile file = null;
+        try {
+            file = new JarFile(artifact);
+            return file.getManifest();
+        } finally {
+            if (file != null) {
+                try {
+                    file.close();
+                } catch (IOException ignore) {
+                }
+            }
+        }
+    }
+
+    /**
+     * @see org.apache.felix.fileinstall.ArtifactInstaller#uninstall(java.io.File)
+     */
+    public void uninstall(final File artifact) throws Exception {
+        LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG, "Uninstalling Deployment Package "
+                + " from " + artifact);
+        // get symbolic name
+        final Manifest manifest = this.getManifest(artifact);
+        final String symbolicName = manifest.getMainAttributes().getValue(DEPLOYMENTPACKAGE_SYMBOLICMAME);
+        if ( symbolicName != null ) {
+            final DeploymentPackage dp = this.deploymentAdmin.getDeploymentPackage(symbolicName);
+            if ( dp != null ) {
+                dp.uninstall();
+            } else {
+                LogWrapper.getLogger().log(LogWrapper.LOG_ERROR, "Unable to find deployment package with symbolic name "
+                        + symbolicName);
+            }
+        } else {
+            LogWrapper.getLogger().log(LogWrapper.LOG_ERROR, "Artifact from "
+                    + artifact + " has no deployment package symbolic name header");
+        }
+    }
+}

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/DeploymentPackageInstaller.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java?rev=983048&view=auto
==============================================================================
--- felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java (added)
+++ felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java Fri Aug  6 16:46:16 2010
@@ -0,0 +1,449 @@
+/*
+ * 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.fileinstall.dp;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * This class mimics the standard OSGi <tt>LogService</tt> interface. An
+ * instance of this class will be used by the EventAdmin for all logging. The
+ * implementation of this class sends log messages to standard output, if no
+ * <tt>LogService</tt> is present; it uses a log service if one is
+ * installed in the framework. To do that without creating a hard dependency on the
+ * package it uses fully qualified class names and registers a listener with the
+ * framework hence, it does not need access to the <tt>LogService</tt> class but will
+ * use it if the listener is informed about an available service. By using a
+ * DynamicImport-Package dependency we don't need the package but
+ * use it if present. Additionally, all log methods prefix the log message with
+ * <tt>EventAdmin: </tt>.
+ *
+ * @see org.osgi.service.log.LogService
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+**/
+// TODO: At the moment we log a message to all currently available LogServices.
+//       Maybe, we should only log to the one with the highest ranking instead?
+//       What is the best practice in this case?
+public class LogWrapper
+{
+    /**
+     * ERROR LEVEL
+     *
+     * @see org.osgi.service.log.LogService#LOG_ERROR
+     */
+    public static final int LOG_ERROR = 1;
+
+    /**
+     * WARNING LEVEL
+     *
+     * @see org.osgi.service.log.LogService#LOG_WARNING
+     */
+    public static final int LOG_WARNING = 2;
+
+    /**
+     * INFO LEVEL
+     *
+     * @see org.osgi.service.log.LogService#LOG_INFO
+     */
+    public static final int LOG_INFO = 3;
+
+    /**
+     * DEBUG LEVEL
+     *
+     * @see org.osgi.service.log.LogService#LOG_DEBUG
+     */
+    public static final int LOG_DEBUG = 4;
+
+    // A set containing the currently available LogServices. Furthermore used as lock
+    private final Set m_loggerRefs = new HashSet();
+
+    // Only null while not set and m_loggerRefs is empty hence, only needs to be
+    // checked in case m_loggerRefs is empty otherwise it will not be null.
+    private BundleContext m_context;
+
+    private ServiceListener m_logServiceListener;
+    /*
+     * A thread save variant of the double checked locking singleton.
+     */
+    private static class LogWrapperLoader
+    {
+        static final LogWrapper m_singleton = new LogWrapper();
+    }
+
+    /**
+     * Returns the singleton instance of this LogWrapper that can be used to send
+     * log messages to all currently available LogServices or to standard output,
+     * respectively.
+     *
+     * @return the singleton instance of this LogWrapper.
+     */
+    public static LogWrapper getLogger()
+    {
+        return LogWrapperLoader.m_singleton;
+    }
+
+    /**
+     * Set the <tt>BundleContext</tt> of the bundle. This method registers a service
+     * listener for LogServices with the framework that are subsequently used to
+     * log messages.
+     * <p>
+     * If the bundle context is <code>null</code>, the service listener is
+     * unregistered and all remaining references to LogServices dropped before
+     * internally clearing the bundle context field.
+     *
+     *  @param context The context of the bundle.
+     */
+    public static void setContext( final BundleContext context )
+    {
+        LogWrapper logWrapper = LogWrapperLoader.m_singleton;
+
+        // context is removed, unregister and drop references
+        if ( context == null )
+        {
+            if ( logWrapper.m_logServiceListener != null )
+            {
+                logWrapper.m_context.removeServiceListener( logWrapper.m_logServiceListener );
+                logWrapper.m_logServiceListener = null;
+            }
+            logWrapper.removeLoggerRefs();
+        }
+
+        // set field
+        logWrapper.setBundleContext( context );
+
+        // context is set, register and get existing services
+        if ( context != null )
+        {
+            try
+            {
+                ServiceListener listener = new ServiceListener()
+                {
+                    // Add a newly available LogService reference to the singleton.
+                    public void serviceChanged( final ServiceEvent event )
+                    {
+                        if ( ServiceEvent.REGISTERED == event.getType() )
+                        {
+                            LogWrapperLoader.m_singleton.addLoggerRef( event.getServiceReference() );
+                        }
+                        // unregistered services are handled in the next log operation.
+                    }
+
+                };
+                context.addServiceListener( listener, "(" + Constants.OBJECTCLASS + "=org.osgi.service.log.LogService)" );
+                logWrapper.m_logServiceListener = listener;
+
+                // Add all available LogService references to the singleton.
+                final ServiceReference[] refs = context.getServiceReferences( "org.osgi.service.log.LogService", null );
+
+                if ( null != refs )
+                {
+                    for ( int i = 0; i < refs.length; i++ )
+                    {
+                        logWrapper.addLoggerRef( refs[i] );
+                    }
+                }
+            }
+            catch ( InvalidSyntaxException e )
+            {
+                // this never happens
+            }
+        }
+    }
+
+
+    /*
+     * The private singleton constructor.
+     */
+    LogWrapper()
+    {
+        // Singleton
+    }
+
+    /*
+     * Removes all references to LogServices still kept
+     */
+    void removeLoggerRefs()
+    {
+        synchronized ( m_loggerRefs )
+        {
+            m_loggerRefs.clear();
+        }
+    }
+
+    /*
+     * Add a reference to a newly available LogService
+     */
+    void addLoggerRef( final ServiceReference ref )
+    {
+        synchronized (m_loggerRefs)
+        {
+            m_loggerRefs.add(ref);
+        }
+    }
+
+    /*
+     * Set the context of the bundle in the singleton implementation.
+     */
+    private void setBundleContext(final BundleContext context)
+    {
+        synchronized(m_loggerRefs)
+        {
+            m_context = context;
+        }
+    }
+
+    /**
+     * Log a message with the given log level. Note that this will prefix the message
+     * with <tt>EventAdmin: </tt>.
+     *
+     * @param level The log level with which to log the msg.
+     * @param msg The message to log.
+     */
+    public void log(final int level, final String msg)
+    {
+        // The method will remove any unregistered service reference as well.
+        synchronized(m_loggerRefs)
+        {
+            final String logMsg = "EventAdmin: " + msg;
+
+            if (!m_loggerRefs.isEmpty())
+            {
+                // There is at least one LogService available hence, we can use the
+                // class as well.
+                for (Iterator iter = m_loggerRefs.iterator(); iter.hasNext();)
+                {
+                    final ServiceReference next = (ServiceReference) iter.next();
+
+                    org.osgi.service.log.LogService logger =
+                        (org.osgi.service.log.LogService) m_context.getService(next);
+
+                    if (null != logger)
+                    {
+                        logger.log(level, logMsg);
+
+                        m_context.ungetService(next);
+                    }
+                    else
+                    {
+                        // The context returned null for the reference - it follows
+                        // that the service is unregistered and we can remove it
+                        iter.remove();
+                    }
+                }
+            }
+            else
+            {
+                _log(null, level, logMsg, null);
+            }
+        }
+    }
+
+    /**
+     * Log a message with the given log level and the associated exception. Note that
+     * this will prefix the message with <tt>EventAdmin: </tt>.
+     *
+     * @param level The log level with which to log the msg.
+     * @param msg The message to log.
+     * @param ex The exception associated with the message.
+     */
+    public void log(final int level, final String msg, final Throwable ex)
+    {
+        // The method will remove any unregistered service reference as well.
+        synchronized(m_loggerRefs)
+        {
+            final String logMsg = "EventAdmin: " + msg;
+
+            if (!m_loggerRefs.isEmpty())
+            {
+                // There is at least one LogService available hence, we can use the
+                // class as well.
+                for (Iterator iter = m_loggerRefs.iterator(); iter.hasNext();)
+                {
+                    final ServiceReference next = (ServiceReference) iter.next();
+
+                    org.osgi.service.log.LogService logger =
+                        (org.osgi.service.log.LogService) m_context.getService(next);
+
+                    if (null != logger)
+                    {
+                        logger.log(level, logMsg, ex);
+
+                        m_context.ungetService(next);
+                    }
+                    else
+                    {
+                        // The context returned null for the reference - it follows
+                        // that the service is unregistered and we can remove it
+                        iter.remove();
+                    }
+                }
+            }
+            else
+            {
+                _log(null, level, logMsg, ex);
+            }
+        }
+    }
+
+    /**
+     * Log a message with the given log level together with the associated service
+     * reference. Note that this will prefix the message with <tt>EventAdmin: </tt>.
+     *
+     * @param sr The reference of the service associated with this message.
+     * @param level The log level with which to log the msg.
+     * @param msg The message to log.
+     */
+    public void log(final ServiceReference sr, final int level, final String msg)
+    {
+        // The method will remove any unregistered service reference as well.
+        synchronized(m_loggerRefs)
+        {
+            final String logMsg = "EventAdmin: " + msg;
+
+            if (!m_loggerRefs.isEmpty())
+            {
+                // There is at least one LogService available hence, we can use the
+                // class as well.
+                for (Iterator iter = m_loggerRefs.iterator(); iter.hasNext();)
+                {
+                    final ServiceReference next = (ServiceReference) iter.next();
+
+                    org.osgi.service.log.LogService logger =
+                        (org.osgi.service.log.LogService) m_context.getService(next);
+
+                    if (null != logger)
+                    {
+                        logger.log(sr, level, logMsg);
+
+                        m_context.ungetService(next);
+                    }
+                    else
+                    {
+                        // The context returned null for the reference - it follows
+                        // that the service is unregistered and we can remove it
+                        iter.remove();
+                    }
+                }
+            }
+            else
+            {
+                _log(sr, level, logMsg, null);
+            }
+        }
+    }
+
+    /**
+     * Log a message with the given log level, the associated service reference and
+     * exception. Note that this will prefix the message with <tt>EventAdmin: </tt>.
+     *
+     * @param sr The reference of the service associated with this message.
+     * @param level The log level with which to log the msg.
+     * @param msg The message to log.
+     * @param ex The exception associated with the message.
+     */
+    public void log(final ServiceReference sr, final int level, final String msg,
+        final Throwable ex)
+    {
+        // The method will remove any unregistered service reference as well.
+        synchronized(m_loggerRefs)
+        {
+            final String logMsg = "EventAdmin: " + msg;
+
+            if (!m_loggerRefs.isEmpty())
+            {
+                // There is at least one LogService available hence, we can use the
+                // class as well.
+                for (Iterator iter = m_loggerRefs.iterator(); iter.hasNext();)
+                {
+                       final ServiceReference next = (ServiceReference) iter.next();
+
+                    org.osgi.service.log.LogService logger =
+                        (org.osgi.service.log.LogService) m_context.getService(next);
+
+                    if (null != logger)
+                    {
+                        logger.log(sr, level, logMsg, ex);
+
+                        m_context.ungetService(next);
+                    }
+                    else
+                    {
+                        // The context returned null for the reference - it follows
+                        // that the service is unregistered and we can remove it
+                        iter.remove();
+                    }
+                }
+            }
+            else
+            {
+                _log(sr, level, logMsg, ex);
+            }
+        }
+    }
+
+    /*
+     * Log the message to standard output. This appends the level to the message.
+     * null values are handled appropriate.
+     */
+    private void _log(final ServiceReference sr, final int level, final String msg,
+        Throwable ex)
+    {
+        String s = (sr == null) ? null : "SvcRef " + sr;
+        s = (s == null) ? msg : s + " " + msg;
+        s = (ex == null) ? s : s + " (" + ex + ")";
+
+        switch (level)
+        {
+            case LOG_DEBUG:
+                System.out.println("DEBUG: " + s);
+                break;
+            case LOG_ERROR:
+                System.out.println("ERROR: " + s);
+                if (ex != null)
+                {
+                    if ((ex instanceof BundleException)
+                        && (((BundleException) ex).getNestedException() != null))
+                    {
+                        ex = ((BundleException) ex).getNestedException();
+                    }
+
+                    ex.printStackTrace();
+                }
+                break;
+            case LOG_INFO:
+                System.out.println("INFO: " + s);
+                break;
+            case LOG_WARNING:
+                System.out.println("WARNING: " + s);
+                break;
+            default:
+                System.out.println("UNKNOWN[" + level + "]: " + s);
+        }
+    }
+}

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/sandbox/cziegeler/dp-fileinstall/src/main/java/org/apache/felix/fileinstall/dp/LogWrapper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain