/* 
 * 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.cm.impl;


import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.felix.cm.PersistenceManager;
import org.apache.felix.cm.file.FilePersistenceManager;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ConfigurationListener;
import org.osgi.service.cm.ConfigurationPlugin;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;


/**
 * The <code>ConfigurationManager</code> is the central class in this
 * implementation of the Configuration Admin Service Specification. As such it
 * has the following tasks:
 * <ul>
 * <li>It is a <code>BundleActivator</code> which is called when the bundle
 * is started and stopped.
 * <li>It is a <code>BundleListener</code> which gets informed when the
 * states of bundles change. Mostly this is needed to unbind any bound
 * configuration in case a bundle is uninstalled.
 * <li>It is a <code>ServiceListener</code> which gets informed when
 * <code>ManagedService</code> and <code>ManagedServiceFactory</code>
 * services are registered and unregistered. This is used to provide
 * configuration to these services. As a service listener it also listens for
 * {@link PersistenceManager} instances being registered to support different
 * configuration persistence layers.
 * <li>A {@link ConfigurationAdminFactory} instance is registered as the
 * <code>ConfigurationAdmin</code> service.
 * <li>A {@link FilePersistenceManager} instance is registered as a default
 * {@link PersistenceManager}.
 * <li>Last but not least this instance manages all tasks laid out in the
 * specification such as maintaining configuration, taking care of configuration
 * events, etc.
 * </ul>
 * <p>
 * The default {@link FilePersistenceManager} is configured with a configuration
 * location taken from the <code>felix.cm.dir</code> framework property. If
 * this property is not set the <code>config</code> directory in the current
 * working directory as specified in the <code>user.dir</code> system property
 * is used.
 * 
 * @author fmeschbe
 */
public class ConfigurationManager implements BundleActivator, BundleListener
{

    /**
     * The name of the bundle context property defining the location for the
     * configuration files (value is "felix.cm.dir").
     * 
     * @see #FilePersistenceManager(BundleContext)
     */
    public static final String CM_CONFIG_DIR = "felix.cm.dir";

    // random number generator to create configuration PIDs for factory
    // configurations
    private static SecureRandom numberGenerator;

    // comparator used to keep the ordered persistence manager map
    private static final Comparator cmRankComp = new RankingComparator( true, ConfigurationPlugin.CM_RANKING );

    // the BundleContext of the Configuration Admin Service bundle
    private BundleContext bundleContext;

    // the service reference to the ConfigurationAdmin service
    private ServiceReference configurationAdminReference;

    // the ServiceTracker to emit log services (see log(int, String, Throwable))
    private ServiceTracker logTracker;

    // the ConfigurationEvent listeners
    private ServiceTracker configurationListenerTracker;

    // service tracker for managed services
    private ServiceTracker managedServiceTracker;

    // service tracker for managed service factories
    private ServiceTracker managedServiceFactoryTracker;

    // PersistenceManager services
    private ServiceTracker persistenceManagerTracker;

    // the thread used to schedule tasks required to run asynchronously
    private UpdateThread updateThread;

    /**
     * The actual list of {@link PersistenceManager persistence managers} to use
     * when looking for configuration data. This list is built from the
     * {@link #persistenceManagerMap}, which is ordered according to the
     * {@link RankingComparator}.
     */
    private PersistenceManager[] persistenceManagers;

    // the persistenceManagerTracker.getTrackingCount when the
    // persistenceManagers were last got
    private int pmtCount;

    // the cache of Factory instances mapped by their factory PID
    private Map factories;

    // the cache of Configuration instances mapped by their PID
    private Map configurations;


    public void start( BundleContext bundleContext )
    {
        // track the log service using a ServiceTracker
        logTracker = new ServiceTracker( bundleContext, LogService.class.getName(), null );
        logTracker.open();

        // set up some fields
        this.bundleContext = bundleContext;
        this.factories = new HashMap();
        this.configurations = new HashMap();

        // configurationlistener support
        configurationListenerTracker = new ServiceTracker( bundleContext, ConfigurationListener.class.getName(), null );
        configurationListenerTracker.open();

        // initialize the asynchonous updater thread
        this.updateThread = new UpdateThread( this );
        this.updateThread.start();

        // set up the location (might throw IllegalArgumentException)
        try
        {
            FilePersistenceManager fpm = new FilePersistenceManager( bundleContext, bundleContext
                .getProperty( CM_CONFIG_DIR ) );
            Hashtable props = new Hashtable();
            props.put( Constants.SERVICE_PID, fpm.getClass().getName() );
            props.put( Constants.SERVICE_DESCRIPTION, "Platform Filesystem Persistence Manager" );
            props.put( Constants.SERVICE_VENDOR, "Apache Software Foundation" );
            props.put( Constants.SERVICE_RANKING, new Integer( Integer.MIN_VALUE ) );
            bundleContext.registerService( PersistenceManager.class.getName(), fpm, props );
        }
        catch ( IllegalArgumentException iae )
        {
            log( LogService.LOG_ERROR, "Cannot create the FilePersistenceManager", iae );
        }

        // register as bundle and service listener
        bundleContext.addBundleListener( this );

        // get all persistence managers to begin with
        pmtCount = 1; // make sure to get the persistence managers at least
        // once
        persistenceManagerTracker = new ServiceTracker( bundleContext, PersistenceManager.class.getName(), null );
        persistenceManagerTracker.open();

        // create and register configuration admin - start after PM tracker ...
        ConfigurationAdminFactory caf = new ConfigurationAdminFactory( this );
        Hashtable props = new Hashtable();
        props.put( Constants.SERVICE_PID, "org.apache.felix.cm.ConfigurationAdmin" );
        props.put( Constants.SERVICE_DESCRIPTION, "Configuration Admin Service Specification 1.2 Implementation" );
        props.put( Constants.SERVICE_VENDOR, "Apache Software Foundation" );
        bundleContext.registerService( ConfigurationAdmin.class.getName(), caf, props );

        // start handling ManagedService[Factory] services
        managedServiceTracker = new ManagedServiceTracker();
        managedServiceFactoryTracker = new ManagedServiceFactoryTracker();
    }


    public void stop( BundleContext bundleContext )
    {
        // stop handling ManagedService[Factory] services
        managedServiceFactoryTracker.close();
        managedServiceTracker.close();

        // don't care for PersistenceManagers any more
        persistenceManagerTracker.close();

        // stop listening for events
        bundleContext.removeBundleListener( this );

        if ( configurationListenerTracker != null )
        {
            configurationListenerTracker.close();
        }

        if ( updateThread != null )
        {
            // terminate asynchrounous updates
            updateThread.terminate();

            // wait for all updates to terminate
            try
            {
                updateThread.join();
            }
            catch ( InterruptedException ie )
            {
                // don't really care
            }
        }

        if ( logTracker != null )
        {
            logTracker.close();
        }

        this.bundleContext = null;
        this.configurations = null;
    }


    // ---------- Configuration caching support --------------------------------

    ConfigurationImpl getCachedConfiguration( String pid )
    {
        synchronized ( configurations )
        {
            return ( ConfigurationImpl ) configurations.get( pid );
        }
    }


    Iterator getCachedConfigurations()
    {
        synchronized ( configurations )
        {
            return configurations.values().iterator();
        }
    }


    void cacheConfiguration( ConfigurationImpl configuration )
    {
        synchronized ( configurations )
        {
            configurations.put( configuration.getPid(), configuration );
        }
    }


    void removeConfiguration( ConfigurationImpl configuration )
    {
        synchronized ( configurations )
        {
            configurations.remove( configuration.getPid() );
        }
    }


    // ---------- ConfigurationAdminImpl support -------------------------------

    /*
     * (non-Javadoc)
     * 
     * @see org.osgi.service.cm.ConfigurationAdmin#createFactoryConfiguration(java.lang.String)
     */
    ConfigurationImpl createFactoryConfiguration( ConfigurationAdminImpl configurationAdmin, String factoryPid )
        throws IOException
    {
        Factory factory = getFactory( factoryPid );

        // check Persmission if factory is bound to another bundle
        if ( factory.getBundleLocation() != null
            && !factory.getBundleLocation().equals( configurationAdmin.getBundle().getLocation() ) )
        {
            configurationAdmin.checkPermission();
        }

        // create the configuration
        String pid = createPid( factoryPid );
        ConfigurationImpl config = createConfiguration( pid, factoryPid );
        config.setBundleLocation( configurationAdmin.getBundle().getLocation() );

        // add the configuration to the factory
        factory.addPID( pid );
        factory.store();

        return config;
    }


    /*
     * (non-Javadoc)
     * 
     * @see org.osgi.service.cm.ConfigurationAdmin#createFactoryConfiguration(java.lang.String,
     *      java.lang.String)
     */
    ConfigurationImpl createFactoryConfiguration( String factoryPid, String location ) throws IOException
    {
        // create the configuration
        String pid = createPid( factoryPid );
        ConfigurationImpl config = createConfiguration( pid, factoryPid );
        if ( location != null )
        {
            config.setBundleLocation( location );
        }

        // add the configuration to the factory
        Factory factory = getFactory( factoryPid );
        factory.addPID( pid );
        factory.store();

        return config;
    }


    ConfigurationImpl getConfiguration( String pid ) throws IOException
    {
        return getConfiguration( pid, true );
    }


    ConfigurationImpl getConfiguration( String pid, String bundleLocation ) throws IOException
    {
        ConfigurationImpl config = getConfiguration( pid, false );

        if ( config == null )
        {
            config = createConfiguration( pid, null );
            if ( bundleLocation != null )
            {
                config.setBundleLocation( bundleLocation );
            }
        }

        return config;
    }


    ConfigurationImpl[] listConfigurations( ConfigurationAdminImpl configurationAdmin, String filterString )
        throws IOException, InvalidSyntaxException
    {
        Filter filter = null;
        if ( filterString != null )
        {
            filter = bundleContext.createFilter( filterString );
        }

        boolean unprivileged = configurationAdmin != null && !configurationAdmin.hasPermission();
        String location = unprivileged ? configurationAdmin.getBundle().getLocation() : null;

        List configList = new ArrayList();

        PersistenceManager[] pmList = getPersistenceManagers();
        for ( int i = 0; i < pmList.length; i++ )
        {
            Enumeration configs = pmList[i].getDictionaries();
            while ( configs.hasMoreElements() )
            {
                Dictionary config = ( Dictionary ) configs.nextElement();

                // ignore non-Configuration dictionaries
                String pid = ( String ) config.get( Constants.SERVICE_PID );
                if ( pid == null )
                {
                    continue;
                }

                // ignore this config if not privileged and not bound to bundle
                if ( unprivileged )
                {
                    Object boundLocation = config.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
                    if ( !location.equals( boundLocation ) )
                    {
                        continue;
                    }
                }

                // check filter
                if ( filter == null || filter.match( config ) )
                {
                    // ensure the service.pid and returned a cached config if available
                    ConfigurationImpl cfg = getCachedConfiguration( pid );
                    if ( cfg == null )
                    {
                        cfg = new ConfigurationImpl( this, pmList[i], config );
                    }

                    configList.add( cfg );
                }
            }
        }

        return ( ConfigurationImpl[] ) configList.toArray( new ConfigurationImpl[configList
            .size()] );
    }


    void deleted( ConfigurationImpl config )
    {
        // remove the configuration from the cache
        removeConfiguration( config );
        updateThread.schedule( new DeleteConfiguration( config ) );
    }


    void updated( ConfigurationImpl config )
    {
        updateThread.schedule( new UpdateConfiguration( config ) );
    }


    void fireConfigurationEvent( int type, ConfigurationImpl config )
    {

        updateThread.schedule( new FireConfigurationEvent( type, config ) );
    }


    // ---------- BundleListener -----------------------------------------------

    public void bundleChanged( BundleEvent event )
    {
        if ( event.getType() == BundleEvent.UNINSTALLED )
        {
            String location = event.getBundle().getLocation();

            try
            {
                PersistenceManager[] pmList = getPersistenceManagers();
                for ( int i = 0; i < pmList.length; i++ )
                {
                    Enumeration configs = pmList[i].getDictionaries();
                    while ( configs.hasMoreElements() )
                    {
                        Dictionary config = ( Dictionary ) configs.nextElement();

                        String pid = ( String ) config.get( Constants.SERVICE_PID );
                        if ( pid != null )
                        {
                            ConfigurationImpl cfg = getCachedConfiguration( pid );
                            if ( cfg == null )
                            {
                                cfg = new ConfigurationImpl( this, pmList[i], config );
                            }

                            if ( location.equals( cfg.getBundleLocation() ) )
                            {
                                cfg.setBundleLocation( null );
                            }
                        }
                        else
                        {

                            Factory factory = Factory.getFactory( pmList[i], config );
                            if ( factory != null )
                            {
                                Factory cachedFactory = ( Factory ) factories.get( factory.getFactoryPid() );
                                if ( cachedFactory != null )
                                {
                                    factory = cachedFactory;
                                }

                                if ( location.equals( factory.getBundleLocation() ) )
                                {
                                    factory.setBundleLocation( null );
                                }
                            }
                        }
                    }
                }

            }
            catch ( Exception e )
            {
                log( LogService.LOG_WARNING, "Problem unbinding configurations for bundle " + location, e );
            }
        }
    }


    // ---------- internal -----------------------------------------------------

    private PersistenceManager[] getPersistenceManagers()
    {
        int currentPmtCount = persistenceManagerTracker.getTrackingCount();
        if ( persistenceManagers == null || currentPmtCount > pmtCount )
        {

            PersistenceManager[] pm;

            ServiceReference[] refs = persistenceManagerTracker.getServiceReferences();
            if ( refs == null || refs.length == 0 )
            {
                pm = new PersistenceManager[0];
            }
            else
            {
                // sort the references according to the cmRanking property
                SortedSet pms = new TreeSet( new RankingComparator( false ) );
                for ( int i = 0; i < refs.length; i++ )
                {
                    pms.add( refs[i] );
                }

                // create the service array from the sorted set of referenecs
                pm = new PersistenceManager[pms.size()];
                int pmIndex = 0;
                for ( Iterator pi = pms.iterator(); pi.hasNext(); pmIndex++)
                {
                    ServiceReference ref = ( ServiceReference ) pi.next();
                    pm[pmIndex] = ( PersistenceManager ) persistenceManagerTracker.getService( ref );
                }
            }

            pmtCount = currentPmtCount;
            persistenceManagers = pm;
        }

        return persistenceManagers;
    }


    private void configure( ServiceReference sr, ManagedService service )
    {
        String pid = ( String ) sr.getProperty( Constants.SERVICE_PID );
        if ( pid != null )
        {
            ManagedServiceUpdate update = new ManagedServiceUpdate( pid, sr, service );
            updateThread.schedule( update );
        }

    }


    private void configure( ServiceReference sr, ManagedServiceFactory service )
    {
        String pid = ( String ) sr.getProperty( Constants.SERVICE_PID );
        if ( pid != null )
        {
            ManagedServiceFactoryUpdate update = new ManagedServiceFactoryUpdate( pid, sr, service );
            updateThread.schedule( update );
        }

    }


    ConfigurationImpl getConfiguration( String pid, boolean create ) throws IOException
    {
        ConfigurationImpl config = getCachedConfiguration( pid );
        if ( config != null )
        {
            return config;
        }

        PersistenceManager[] pmList = getPersistenceManagers();
        for ( int i = 0; i < pmList.length; i++ )
        {
            if ( pmList[i].exists( pid ) )
            {
                Dictionary props = pmList[i].load( pid );
                config = new ConfigurationImpl( this, pmList[i], props );
                cacheConfiguration( config );
                return config;
            }
        }

        // if getting here, there is no configuration yet, optionally create new
        return ( create ) ? createConfiguration( pid, null ) : null;
    }


    ConfigurationImpl createConfiguration( String pid, String factoryPid ) throws IOException
    {
        ConfigurationImpl config = new ConfigurationImpl( this, getPersistenceManagers()[0], pid, factoryPid );

        // immediately store the configuration, yet getProperties() must still
        // return null
        config.store();

        cacheConfiguration( config );

        return config;
    }


    Factory getFactory( String factoryPid ) throws IOException
    {
        Factory factory = ( Factory ) factories.get( factoryPid );
        if ( factory != null )
        {
            return factory;
        }

        PersistenceManager[] pmList = getPersistenceManagers();
        for ( int i = 0; i < pmList.length; i++ )
        {
            if ( Factory.exists( pmList[i], factoryPid ) )
            {
                factory = Factory.load( pmList[i], factoryPid );
                factories.put( factoryPid, factory );
                return factory;
            }
        }

        // if getting here, there is no configuration yet, optionally create new
        return createFactory( factoryPid );
    }


    Factory createFactory( String factoryPid )
    {
        Factory factory = new Factory( getPersistenceManagers()[0], factoryPid );
        factories.put( factoryPid, factory );
        return factory;
    }


    private Dictionary callPlugins( ServiceReference sr, ConfigurationImpl cfg )
    {
        Dictionary props = cfg.getProperties();

        ServiceReference[] plugins = null;
        try
        {
            String pid = ( String ) sr.getProperty( Constants.SERVICE_PID );
            String filter = "(|(!(cm.target=*))(cm.target=" + pid + "))";
            plugins = bundleContext.getServiceReferences( ConfigurationPlugin.class.getName(), filter );

        }
        catch ( InvalidSyntaxException ise )
        {
            // no filter, no exception ...
        }

        // abort early if there are no plugins
        if ( plugins == null || plugins.length == 0 )
        {
            return props;
        }

        // sort the plugins by their service.cmRanking
        SortedSet pluginSet = new TreeSet( cmRankComp );
        for ( int i = 0; plugins != null && i < plugins.length; i++ )
        {
            pluginSet.add( plugins[i] );
        }

        // call the plugins in order
        for ( Iterator pi = pluginSet.iterator(); pi.hasNext(); )
        {
            ServiceReference pluginRef = ( ServiceReference ) pi.next();
            ConfigurationPlugin plugin = ( ConfigurationPlugin ) bundleContext.getService( pluginRef );
            try
            {
                plugin.modifyConfiguration( sr, props );
            }
            catch ( Throwable t )
            {
                log( LogService.LOG_ERROR, "Unexpected problem calling" + " configuration plugin", t );
            }
            finally
            {
                // ensure ungetting the plugin
                bundleContext.ungetService( pluginRef );
            }
            cfg.setAutoProperties( props, false );
        }

        return props;
    }


    /**
     * Creates a PID for the given factoryPid
     * 
     * @param factoryPid
     * @return
     */
    private static String createPid( String factoryPid )
    {
        SecureRandom ng = numberGenerator;
        if ( ng == null )
        {
            numberGenerator = ng = new SecureRandom();
        }

        byte[] randomBytes = new byte[16];
        ng.nextBytes( randomBytes );
        randomBytes[6] &= 0x0f; /* clear version */
        randomBytes[6] |= 0x40; /* set to version 4 */
        randomBytes[8] &= 0x3f; /* clear variant */
        randomBytes[8] |= 0x80; /* set to IETF variant */

        StringBuffer buf = new StringBuffer( factoryPid.length() + 1 + 36 );

        // prefix the new pid with the factory pid
        buf.append( factoryPid ).append( "." );

        // serialize the UUID into the buffer
        for ( int i = 0; i < randomBytes.length; i++ )
        {

            if ( i == 4 || i == 6 || i == 8 || i == 10 )
            {
                buf.append( '-' );
            }

            int val = randomBytes[i] & 0xff;
            buf.append( Integer.toHexString( val >> 4 ) );
            buf.append( Integer.toHexString( val & 0xf ) );
        }

        return buf.toString();
    }


    void log( int level, String message, Throwable t )
    {
        LogService log = ( LogService ) logTracker.getService();
        if ( log != null )
        {
            log.log( configurationAdminReference, level, message, t );
            return;
        }

        String code;
        switch ( level )
        {
            case LogService.LOG_INFO:
                code = "*INFO *";
                break;

            case LogService.LOG_WARNING:
                code = "*WARN *";
                break;

            case LogService.LOG_ERROR:
                code = "*ERROR*";
                break;

            case LogService.LOG_DEBUG:
            default:
                code = "*DEBUG*";
        }

        System.err.println( code + " " + message );
        if ( t != null )
        {
            t.printStackTrace( System.err );
        }
    }

    // ---------- inner classes ------------------------------------------------

    private class ManagedServiceUpdate implements Runnable
    {
        private String pid;

        private ServiceReference sr;

        private ManagedService service;


        ManagedServiceUpdate( String pid, ServiceReference sr, ManagedService service )
        {
            this.pid = pid;
            this.sr = sr;
            this.service = service;
        }


        public void run()
        {
            ConfigurationImpl cfg;
            try
            {
                cfg = getConfiguration( pid, sr.getBundle().getLocation() );
            }
            catch ( IOException ioe )
            {
                log( LogService.LOG_ERROR, "Error loading configuration for " + pid, ioe );
                return;
            }

            // 104.3 Ignore duplicate PIDs from other bundles and report them to
            // the log
            // 104.4.1 No update call back for PID already bound to another
            // bundle location
            String bundleLocation = sr.getBundle().getLocation();
            if ( cfg.getBundleLocation() != null && !bundleLocation.equals( cfg.getBundleLocation() ) )
            {
                log( LogService.LOG_ERROR, "Cannot use configuration for " + pid + " requested by bundle "
                    + sr.getBundle().getLocation() + " but belongs to " + cfg.getBundleLocation(), null );
                return;
            }

            // 104.3 Report an error in the log if more than one service with
            // the same PID asks for the configuration
            if ( cfg.getServiceReference() != null && !sr.equals( cfg.getServiceReference() ) )
            {
                log( LogService.LOG_ERROR, "Configuration for " + pid + " has already been used for service "
                    + cfg.getServiceReference() + " and will now also be given to " + sr, null );
            }
            else
            {
                // assign the configuration to the service
                cfg.setServiceReference( sr );
            }

            // prepare the configuration for the service (call plugins)
            Dictionary dictionary = callPlugins( sr, cfg );

            // update the service with the configuration
            try
            {
                service.updated( dictionary );
            }
            catch ( ConfigurationException ce )
            {
                if ( ce.getProperty() != null )
                {
                    log( LogService.LOG_ERROR, sr + ": Updating configuration property " + ce.getProperty()
                        + " caused a problem: " + ce.getReason(), ce );
                }
                else
                {
                    log( LogService.LOG_ERROR, sr + ": Updating configuration caused a problem: " + ce.getReason(), ce );

                }
            }
            catch ( Throwable t )
            {
                log( LogService.LOG_ERROR, sr + ": Unexpected problem updating configuration", t );
            }

            // 104.5.3 CM_UPDATED is sent asynchronously to all
            // ConfigurationListeners
            fireConfigurationEvent( ConfigurationEvent.CM_UPDATED, cfg );
        }
    }

    private class ManagedServiceFactoryUpdate implements Runnable
    {
        private String factoryPid;

        private ServiceReference sr;

        private ManagedServiceFactory service;


        ManagedServiceFactoryUpdate( String factoryPid, ServiceReference sr, ManagedServiceFactory service )
        {
            this.factoryPid = factoryPid;
            this.sr = sr;
            this.service = service;
        }


        public void run()
        {
            Factory factory;
            try
            {
                factory = getFactory( factoryPid );
            }
            catch ( IOException ioe )
            {
                log( LogService.LOG_ERROR, "Cannot get factory mapping for factory PID " + factoryPid, ioe );
                return;
            }

            String bundleLocation = sr.getBundle().getLocation();
            if ( factory.getBundleLocation() == null )
            {
                // bind to the location of the service if unbound
                factory.setBundleLocation( bundleLocation );
            }
            else if ( !bundleLocation.equals( factory.getBundleLocation() ) )
            {
                // factory PID is bound to another bundle
                log( LogService.LOG_ERROR, "Cannot use Factory configuration for " + factoryPid
                    + " requested by bundle " + sr.getBundle().getLocation() + " but belongs to "
                    + factory.getBundleLocation(), null );
                return;
            }

            Set pids = factory.getPIDs();

            for ( Iterator pi = pids.iterator(); pi.hasNext(); )
            {
                String pid = ( String ) pi.next();
                ConfigurationImpl cfg;
                try
                {
                    cfg = getConfiguration( pid, false );
                }
                catch ( IOException ioe )
                {
                    log( LogService.LOG_ERROR, "Error loading configuration for " + pid, ioe );
                    continue;
                }

                // sanity check on the configuration
                if ( cfg == null )
                {
                    log( LogService.LOG_ERROR, "Configuration " + pid + " referred to by factory " + factoryPid
                        + " does not exist", null );
                    factory.removePID( pid );
                    factory.storeSilently();
                    continue;
                }
                else if ( !factoryPid.equals( cfg.getFactoryPid() ) )
                {
                    log( LogService.LOG_ERROR, "Configuration " + pid + " referred to by factory " + factoryPid
                        + " seems to belong to factory " + cfg.getFactoryPid(), null );
                    factory.removePID( pid );
                    factory.storeSilently();
                    continue;
                }

                // check bundle location of configuration
                if ( cfg.getBundleLocation() == null )
                {
                    // bind to the location of the service if unbound
                    cfg.setBundleLocation( bundleLocation );
                }
                else if ( !bundleLocation.equals( cfg.getBundleLocation() ) )
                {
                    // configuration is bound to another bundle
                    log( LogService.LOG_ERROR, "Configuration " + pid + " (factory " + factoryPid
                        + ") belongs to bundle " + cfg.getBundleLocation() + " but was requested for bundle "
                        + bundleLocation, null );
                    continue;
                }

                // prepare the configuration for the service (call plugins)
                Dictionary dictionary = callPlugins( sr, cfg );

                // update the service with the configuration
                try
                {
                    service.updated( pid, dictionary );
                }
                catch ( ConfigurationException ce )
                {
                    if ( ce.getProperty() != null )
                    {
                        log( LogService.LOG_ERROR, sr + ": Updating configuration property " + ce.getProperty()
                            + " caused a problem: " + ce.getReason(), ce );
                    }
                    else
                    {
                        log( LogService.LOG_ERROR, sr + ": Updating configuration caused a problem: " + ce.getReason(),
                            ce );

                    }
                }
                catch ( Throwable t )
                {
                    log( LogService.LOG_ERROR, sr + ": Unexpected problem updating configuration", t );
                }
            }
        }
    }

    private class UpdateConfiguration implements Runnable
    {

        private ConfigurationImpl config;


        UpdateConfiguration( ConfigurationImpl config )
        {
            this.config = config;
        }


        public void run()
        {
            try
            {
                if ( config.getFactoryPid() == null )
                {
                    ServiceReference[] sr = bundleContext.getServiceReferences( ManagedService.class.getName(), "("
                        + Constants.SERVICE_PID + "=" + config.getPid() + ")" );
                    if ( sr != null && sr.length > 0 )
                    {
                        ManagedService srv = ( ManagedService ) bundleContext.getService( sr[0] );
                        try
                        {
                            // bind the configuration, fail if bound to another
                            // bundle !!
                            // check bundle location of configuration
                            String bundleLocation = sr[0].getBundle().getLocation();
                            if ( config.getBundleLocation() == null )
                            {
                                // bind to the location of the service if
                                // unbound
                                config.setBundleLocation( bundleLocation );
                            }
                            else if ( !bundleLocation.equals( config.getBundleLocation() ) )
                            {
                                // configuration is bound to another bundle
                                log( LogService.LOG_ERROR, "Configuration " + config.getPid() + " belongs to bundle "
                                    + config.getBundleLocation() + " but was requested for bundle " + bundleLocation,
                                    null );
                                return;
                            }

                            // prepare the configuration for the service (call plugins)
                            Dictionary dictionary = callPlugins( sr[0], config );

                            // update the ManagedService with the properties
                            srv.updated( dictionary );
                        }
                        finally
                        {
                            bundleContext.ungetService( sr[0] );
                        }
                    }
                }
                else
                {
                    ServiceReference[] sr = bundleContext.getServiceReferences( ManagedServiceFactory.class.getName(),
                        "(" + Constants.SERVICE_PID + "=" + config.getFactoryPid() + ")" );
                    if ( sr != null && sr.length > 0 )
                    {
                        ManagedServiceFactory srv = ( ManagedServiceFactory ) bundleContext.getService( sr[0] );
                        try
                        {
                            // bind the configuration, fail if bound to another
                            // bundle !!
                            // check bundle location of configuration
                            String bundleLocation = sr[0].getBundle().getLocation();
                            if ( config.getBundleLocation() == null )
                            {
                                // bind to the location of the service if
                                // unbound
                                config.setBundleLocation( bundleLocation );
                            }
                            else if ( !bundleLocation.equals( config.getBundleLocation() ) )
                            {
                                // configuration is bound to another bundle
                                log( LogService.LOG_ERROR, "Configuration " + config.getPid() + " (factory "
                                    + config.getFactoryPid() + ") belongs to bundle " + config.getBundleLocation()
                                    + " but was requested for bundle " + bundleLocation, null );
                                return;
                            }


                            // prepare the configuration for the service (call plugins)
                            Dictionary dictionary = callPlugins( sr[0], config );

                            // update the ManagedServiceFactory with the properties
                            srv.updated( config.getPid(), dictionary );
                        }
                        finally
                        {
                            bundleContext.ungetService( sr[0] );
                        }
                    }
                }
            }
            catch ( ConfigurationException ce )
            {
                if ( ce.getProperty() != null )
                {
                    log( LogService.LOG_ERROR, "Updating configuration property " + ce.getProperty()
                        + " caused a problem: " + ce.getReason(), ce );
                }
                else
                {
                    log( LogService.LOG_ERROR, "Updating configuration caused a problem: " + ce.getReason(), ce );

                }
            }
            catch ( Throwable t )
            {
                log( LogService.LOG_ERROR, "Unexpected problem updating configuration", t );
            }

            fireConfigurationEvent( ConfigurationEvent.CM_UPDATED, config );
        }
    }

    private class DeleteConfiguration implements Runnable
    {
        private ConfigurationImpl config;


        DeleteConfiguration( ConfigurationImpl config )
        {
            this.config = config;
        }


        public void run()
        {
            try
            {
                if ( config.getFactoryPid() == null )
                {
                    ServiceReference[] sr = bundleContext.getServiceReferences( ManagedService.class.getName(), "("
                        + Constants.SERVICE_PID + "=" + config.getPid() + ")" );
                    if ( sr != null && sr.length > 0 )
                    {
                        ManagedService srv = ( ManagedService ) bundleContext.getService( sr[0] );
                        try
                        {
                            srv.updated( null );
                        }
                        finally
                        {
                            bundleContext.ungetService( sr[0] );
                        }
                    }
                }
                else
                {
                    // remove the pid from the factory
                    Factory factory = getFactory( config.getFactoryPid() );
                    factory.removePID( config.getPid() );
                    factory.store();

                    ServiceReference[] sr = bundleContext.getServiceReferences( ManagedServiceFactory.class.getName(),
                        "(" + Constants.SERVICE_PID + "=" + config.getFactoryPid() + ")" );
                    if ( sr != null && sr.length > 0 )
                    {
                        ManagedServiceFactory srv = ( ManagedServiceFactory ) bundleContext.getService( sr[0] );
                        try
                        {
                            srv.deleted( config.getPid() );
                        }
                        finally
                        {
                            bundleContext.ungetService( sr[0] );
                        }
                    }
                }
            }
            catch ( ConfigurationException ce )
            {
                if ( ce.getProperty() != null )
                {
                    log( LogService.LOG_ERROR, "Updating configuration property " + ce.getProperty()
                        + " caused a problem: " + ce.getReason(), ce );
                }
                else
                {
                    log( LogService.LOG_ERROR, "Updating configuration caused a problem: " + ce.getReason(), ce );

                }
            }
            catch ( Throwable t )
            {
                log( LogService.LOG_ERROR, "Unexpected problem updating configuration", t );
            }

            fireConfigurationEvent( ConfigurationEvent.CM_DELETED, config );
        }
    }

    private class FireConfigurationEvent implements Runnable
    {
        private int type;

        private ConfigurationImpl config;


        FireConfigurationEvent( int type, ConfigurationImpl config )
        {
            this.type = type;
            this.config = config;
        }


        public void run()
        {
            // get the listeners
            ServiceReference[] srs = configurationListenerTracker.getServiceReferences();
            if ( srs == null || srs.length == 0 )
            {
                return;
            }

            ConfigurationEvent event = new ConfigurationEvent( configurationAdminReference, type, config
                .getFactoryPid(), config.getPid() );

            for ( int i = 0; i < srs.length; i++ )
            {
                ConfigurationListener cl = ( ConfigurationListener ) configurationListenerTracker.getService( srs[i] );
                try
                {
                    cl.configurationEvent( event );
                }
                catch ( Throwable t )
                {
                    log( LogService.LOG_ERROR, "Unexpected problem delivery configuration event to " + srs[i], t );
                }
            }
        }
    }

    private abstract class AbstractManagedServiceTracker extends ServiceTracker
    {
        AbstractManagedServiceTracker( String className )
        {
            super( bundleContext, className, null );
            open();
        }


        public void removedService( ServiceReference reference, Object service )
        {
            // check whether we can take back the configuration object
            String pid = ( String ) reference.getProperty( Constants.SERVICE_PID );
            if ( pid != null )
            {
                ConfigurationImpl cfg = getCachedConfiguration( pid );
                if ( cfg != null && reference.equals( cfg.getServiceReference() ) )
                {
                    cfg.setServiceReference( null );
                }
            }

            super.removedService( reference, service );
        }
    }

    private class ManagedServiceTracker extends AbstractManagedServiceTracker
    {
        ManagedServiceTracker()
        {
            super( ManagedService.class.getName() );
        }


        public Object addingService( ServiceReference reference )
        {
            ManagedService service = ( ManagedService ) super.addingService( reference );

            // configure the managed service
            if ( service != null )
            {
                configure( reference, service );
            }

            return service;
        }
    }

    private class ManagedServiceFactoryTracker extends AbstractManagedServiceTracker
    {
        ManagedServiceFactoryTracker()
        {
            super( ManagedServiceFactory.class.getName() );
        }


        public Object addingService( ServiceReference reference )
        {
            ManagedServiceFactory service = ( ManagedServiceFactory ) super.addingService( reference );

            // configure the managed service
            if ( service != null )
            {
                configure( reference, service );
            }

            return service;
        }
    }
}
