/*
 * 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.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.apache.felix.cm.PersistenceManager;
import org.apache.felix.cm.file.FilePersistenceManager;
import org.apache.felix.cm.impl.helper.BaseTracker;
import org.apache.felix.cm.impl.helper.ConfigurationMap;
import org.apache.felix.cm.impl.helper.ManagedServiceFactoryTracker;
import org.apache.felix.cm.impl.helper.ManagedServiceTracker;
import org.apache.felix.cm.impl.helper.TargetedPID;
import org.osgi.framework.Bundle;
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.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
import org.osgi.service.cm.ConfigurationPermission;
import org.osgi.service.cm.ConfigurationPlugin;
import org.osgi.service.cm.SynchronousConfigurationListener;
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.
 */
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 #start(BundleContext)
     */
    public static final String CM_CONFIG_DIR = "felix.cm.dir";

    /**
     * The name of the bundle context property defining the maximum log level
     * (value is "felix.cm.loglevel"). The log level setting is only used if
     * there is no OSGi LogService available. Otherwise this setting is ignored.
     * <p>
     * This value of this property is expected to be an integer number
     * corresponding to the log level values of the OSGi LogService. That is 1
     * for errors, 2 for warnings, 3 for informational messages and 4 for debug
     * messages. The default value is 2, such that only warnings and errors are
     * logged in the absence of a LogService.
     */
    public static final String CM_LOG_LEVEL = "felix.cm.loglevel";

    // The name of the LogService (not using the class, which might be missing)
    private static final String LOG_SERVICE_NAME = "org.osgi.service.log.LogService";

    private static final int CM_LOG_LEVEL_DEFAULT = 2;

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

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

    // the service registration of the default file persistence manager
    private volatile ServiceRegistration filepmRegistration;

    // the service registration of the configuration admin
    private volatile ServiceRegistration configurationAdminRegistration;

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

    // the ConfigurationEvent listeners
    private ServiceTracker configurationListenerTracker;

    // the synchronous ConfigurationEvent listeners
    private ServiceTracker syncConfigurationListenerTracker;

    // service tracker for managed services
    private ManagedServiceTracker managedServiceTracker;

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

    // PersistenceManager services
    private ServiceTracker persistenceManagerTracker;

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

    // the thread used to schedule events to be dispatched asynchronously
    private UpdateThread eventThread;

    /**
     * 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 final HashMap<String, Factory> factories = new HashMap<String, Factory>();

    // the cache of Configuration instances mapped by their PID
    // have this always set to prevent NPE on bundle shutdown
    private final HashMap<String, ConfigurationImpl> configurations = new HashMap<String, ConfigurationImpl>();

    /**
     * The map of dynamic configuration bindings. This maps the
     * PID of the dynamically bound configuration or factory to its bundle
     * location.
     * <p>
     * On bundle startup this map is loaded from persistence and validated
     * against the locations of installed bundles: Entries pointing to bundle
     * locations not currently installed are removed.
     * <p>
     * The map is written to persistence on each change.
     */
    private DynamicBindings dynamicBindings;

    // the maximum log level when no LogService is available
    private int logLevel = CM_LOG_LEVEL_DEFAULT;

    // flag indicating whether BundleChange events should be consumed (FELIX-979)
    private volatile boolean handleBundleEvents;

    // flag indicating whether the manager is considered alive
    private volatile boolean isActive;

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

        // assign the log level
        String logLevelProp = bundleContext.getProperty( CM_LOG_LEVEL );
        if ( logLevelProp == null )
        {
            logLevel = CM_LOG_LEVEL_DEFAULT;
        }
        else
        {
            try
            {
                logLevel = Integer.parseInt( logLevelProp );
            }
            catch ( NumberFormatException nfe )
            {
                logLevel = CM_LOG_LEVEL_DEFAULT;
            }
        }

        // set up some fields
        this.bundleContext = bundleContext;

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

        // initialize the asynchonous updater thread
        ThreadGroup tg = new ThreadGroup( "Configuration Admin Service" );
        tg.setDaemon( true );
        this.updateThread = new UpdateThread( this, tg, "CM Configuration Updater" );
        this.eventThread = new UpdateThread( this, tg, "CM Event Dispatcher" );

        // 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 ) );
            filepmRegistration = bundleContext.registerService( PersistenceManager.class.getName(), fpm, props );

            // setup dynamic configuration bindings
            dynamicBindings = new DynamicBindings( bundleContext, fpm );
        }
        catch ( IOException ioe )
        {
            log( LogService.LOG_ERROR, "Failure setting up dynamic configuration bindings", ioe );
        }
        catch ( IllegalArgumentException iae )
        {
            log( LogService.LOG_ERROR, "Cannot create the FilePersistenceManager", iae );
        }

        // register as bundle and service listener
        handleBundleEvents = true;
        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();

        // consider alive now (before clients use Configuration Admin
        // service registered in the next step)
        isActive = true;

        // 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" );
        configurationAdminRegistration = bundleContext.registerService( ConfigurationAdmin.class.getName(), caf, props );

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

        // start processing the event queues only after registering the service
        // see FELIX-2813 for details
        this.updateThread.start();
        this.eventThread.start();
    }


    public void stop( BundleContext bundleContext )
    {

        // stop handling bundle events immediately
        handleBundleEvents = false;

        // stop handling ManagedService[Factory] services
        managedServiceFactoryTracker.close();
        managedServiceTracker.close();

        // stop queue processing before unregistering the service
        // see FELIX-2813 for details
        if ( updateThread != null )
        {
            updateThread.terminate();
        }
        if ( eventThread != null )
        {
            eventThread.terminate();
        }

        // immediately unregister the Configuration Admin before cleaning up
        // clearing the field before actually unregistering the service
        // prevents IllegalStateException in getServiceReference() if
        // the field is not null but the service already unregistered
        final ServiceRegistration caReg = configurationAdminRegistration;
        configurationAdminRegistration = null;
        if ( caReg != null )
        {
            caReg.unregister();
        }

        // consider inactive after unregistering such that during
        // unregistration the manager is still alive and can react
        isActive = false;

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

        // shutdown the file persistence manager
        final ServiceRegistration filePmReg = filepmRegistration;
        filepmRegistration = null;
        if ( filePmReg != null )
        {
            filePmReg.unregister();
        }

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

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

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

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

        // just ensure the configuration cache is empty
        synchronized ( configurations )
        {
            configurations.clear();
        }

        // just ensure the factory cache is empty
        synchronized ( factories )
        {
            factories.clear();
        }

        this.bundleContext = null;
    }


    /**
     * Returns <code>true</code> if this manager is considered active.
     */
    boolean isActive()
    {
        return isActive;
    }

    public BundleContext getBundleContext()
    {
        return bundleContext;
    }

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

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


    ConfigurationImpl[] getCachedConfigurations()
    {
        synchronized ( configurations )
        {
            return configurations.values().toArray(
                new ConfigurationImpl[configurations.size()] );
        }
    }


    ConfigurationImpl cacheConfiguration( ConfigurationImpl configuration )
    {
        synchronized ( configurations )
        {
            final String pid = configuration.getPidString();
            final Object existing = configurations.get( pid );
            if ( existing != null )
            {
                return ( ConfigurationImpl ) existing;
            }

            configurations.put( pid, configuration );
            return configuration;
        }
    }


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


    Factory getCachedFactory( String factoryPid )
    {
        synchronized ( factories )
        {
            return factories.get( factoryPid );
        }
    }


    Factory[] getCachedFactories()
    {
        synchronized ( factories )
        {
            return factories.values().toArray( new Factory[factories.size()] );
        }
    }


    void cacheFactory( Factory factory )
    {
        synchronized ( factories )
        {
            factories.put( factory.getFactoryPidString(), factory );
        }
    }


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

    void setDynamicBundleLocation( final String pid, final String location )
    {
        if ( dynamicBindings != null )
        {
            try
            {
                dynamicBindings.putLocation( pid, location );
            }
            catch ( IOException ioe )
            {
                log( LogService.LOG_ERROR, "Failed storing dynamic configuration binding for {0} to {1}", new Object[]
                    { pid, location, ioe } );
            }
        }
    }


    String getDynamicBundleLocation( final String pid )
    {
        if ( dynamicBindings != null )
        {
            return dynamicBindings.getLocation( pid );
        }

        return null;
    }


    ConfigurationImpl createFactoryConfiguration( String factoryPid, String location ) throws IOException
    {
        return cacheConfiguration( createConfiguration( createPid( factoryPid ), factoryPid, location ) );
    }

    /**
     * Returns a targeted configuration for the given service PID and
     * the reference target service.
     * <p>
     * A configuration returned has already been checked for visibility
     * by the bundle registering the referenced service. Additionally,
     * the configuration is also dynamically bound if needed.
     *
     * @param rawPid The raw service PID to get targeted configuration for.
     * @param target The target <code>ServiceReference</code> to get
     *      configuration for.
     * @return The best matching targeted configuration or <code>null</code>
     *      if there is no configuration at all.
     * @throwss IOException if an error occurrs reading configurations
     *      from persistence.
     */
    ConfigurationImpl getTargetedConfiguration( final String rawPid, final ServiceReference target ) throws IOException
    {
        final Bundle serviceBundle = target.getBundle();
        if ( serviceBundle != null )
        {
            // list of targeted PIDs to check
            // (StringBuffer for pre-1.5 API compatibility)
            final StringBuffer targetedPid = new StringBuffer( rawPid );
            int i = 3;
            String[] names = new String[4];
            names[i--] = targetedPid.toString();
            targetedPid.append( '|' ).append( serviceBundle.getSymbolicName() );
            names[i--] = targetedPid.toString();
            targetedPid.append( '|' ).append( TargetedPID.getBundleVersion( serviceBundle ) );
            names[i--] = targetedPid.toString();
            targetedPid.append( '|' ).append( serviceBundle.getLocation() );
            names[i--] = targetedPid.toString();

            for ( String candidate : names )
            {
                ConfigurationImpl config = getConfiguration( candidate );
                if ( config != null && !config.isDeleted() )
                {
                    // check visibility to use and dynamically bind
                    if ( canReceive( serviceBundle, config.getBundleLocation() ) )
                    {
                        config.tryBindLocation( serviceBundle.getLocation() );
                        return config;
                    }

                    // CM 1.4 / 104.13.2.2 / 104.5.3
                    // act as if there is no configuration
                    log(
                        LogService.LOG_DEBUG,
                        "Cannot use configuration {0} for {1}: No visibility to configuration bound to {2}; calling with null",
                        new Object[]
                            { config.getPid(), toString( target ), config.getBundleLocation() } );
                }
            }
        }
        else
        {
            log( LogService.LOG_INFO,
                "Service for PID {0} seems to already have been unregistered, not updating with configuration",
                new Object[]
                    { rawPid } );
        }

        // service already unregistered, nothing to do really
        return null;
    }


    /**
     * Returns the {@link ConfigurationImpl} with the given PID if
     * available in the internal cache or from any persistence manager.
     * Otherwise <code>null</code> is returned.
     *
     * @param pid The PID for which to return the configuration
     * @return The configuration or <code>null</code> if non exists
     * @throws IOException If an error occurrs reading from a persistence
     *      manager.
     */
    ConfigurationImpl getConfiguration( String pid ) throws IOException
    {
        ConfigurationImpl config = getCachedConfiguration( pid );
        if ( config != null )
        {
            log( LogService.LOG_DEBUG, "Found cached configuration {0} bound to {1}", new Object[]
                { pid, config.getBundleLocation() } );

            config.ensureFactoryConfigPersisted();

            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 );
                log( LogService.LOG_DEBUG, "Found existing configuration {0} bound to {1}", new Object[]
                    { pid, config.getBundleLocation() } );
                return cacheConfiguration( config );
            }
        }

        // neither the cache nor any persistence manager has configuration
        return null;
    }


    /**
     * Creates a regular (non-factory) configuration for the given PID
     * setting the bundle location accordingly.
     * <p>
     * This method assumes the configuration to not exist yet and will
     * create it without further checking.
     *
     * @param pid The PID of the new configuration
     * @param bundleLocation The location to set on the new configuration.
     *      This may be <code>null</code> to not bind the configuration
     *      yet.
     * @return The new configuration persisted in the first persistence
     *      manager.
     * @throws IOException If an error occurrs writing the configuration
     *      to the persistence.
     */
    ConfigurationImpl createConfiguration( String pid, String bundleLocation ) throws IOException
    {
        // check for existing (cached or persistent) configuration
        ConfigurationImpl config = getConfiguration( pid );
        if ( config != null )
        {
            return config;
        }

        // else create new configuration also setting the bundle location
        // and cache the new configuration
        config = createConfiguration( pid, null, bundleLocation );
        return cacheConfiguration( config );
    }


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

        log( LogService.LOG_DEBUG, "Listing configurations matching {0}", new Object[]
            { filterString } );

        List configList = new ArrayList();

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

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

                // CM 1.4 / 104.13.2.3 Permission required
                if ( !configurationAdmin.hasPermission( this,
                    ( String ) config.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) ) )
                {
                    log(
                        LogService.LOG_DEBUG,
                        "Omitting configuration {0}: No permission for bundle {1} on configuration bound to {2}",
                        new Object[]
                            { pid, configurationAdmin.getBundle().getLocation(),
                                config.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) } );
                    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 );
                    }

                    // FELIX-611: Ignore configuration objects without props
                    if ( !cfg.isNew() )
                    {
                        log( LogService.LOG_DEBUG, "Adding configuration {0}", new Object[]
                            { pid } );
                        configList.add( cfg );
                    }
                    else
                    {
                        log( LogService.LOG_DEBUG, "Omitting configuration {0}: Is new", new Object[]
                            { pid } );
                    }
                } else {
                    log( LogService.LOG_DEBUG, "Omitting configuration {0}: Does not match filter", new Object[]
                        { pid } );
                }
            }
        }

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


    void deleted( ConfigurationImpl config )
    {
        // remove the configuration from the cache
        removeConfiguration( config );
        fireConfigurationEvent( ConfigurationEvent.CM_DELETED, config.getPidString(), config.getFactoryPidString() );
        updateThread.schedule( new DeleteConfiguration( config ) );
        log( LogService.LOG_DEBUG, "DeleteConfiguration({0}) scheduled", new Object[]
            { config.getPid() } );
    }


    void updated( ConfigurationImpl config, boolean fireEvent )
    {
        if ( fireEvent )
        {
            fireConfigurationEvent( ConfigurationEvent.CM_UPDATED, config.getPidString(), config.getFactoryPidString() );
        }
        updateThread.schedule( new UpdateConfiguration( config ) );
        log( LogService.LOG_DEBUG, "UpdateConfiguration({0}) scheduled", new Object[]
            { config.getPid() } );
    }


    void locationChanged( ConfigurationImpl config, String oldLocation )
    {
        fireConfigurationEvent( ConfigurationEvent.CM_LOCATION_CHANGED, config.getPidString(), config.getFactoryPidString() );
        if ( oldLocation != null && !config.isNew() )
        {
            updateThread.schedule( new LocationChanged( config, oldLocation ) );
            log( LogService.LOG_DEBUG, "LocationChanged({0}, {1}=>{2}) scheduled", new Object[]
                { config.getPid(), oldLocation, config.getBundleLocation() } );
        }
        else
        {
            log( LogService.LOG_DEBUG,
                "LocationChanged not scheduled for {0} (old location is null or configuration is new)", new Object[]
                    { config.getPid() } );
        }
    }


    void fireConfigurationEvent( int type, String pid, String factoryPid )
    {
        // prevent event senders
        FireConfigurationEvent asyncSender = new FireConfigurationEvent( this.configurationListenerTracker, type, pid,
            factoryPid );
        FireConfigurationEvent syncSender = new FireConfigurationEvent( this.syncConfigurationListenerTracker, type,
            pid, factoryPid );

        // send synchronous events
        if ( syncSender.hasConfigurationEventListeners() )
        {
            syncSender.run();
        }
        else
        {
            log( LogService.LOG_DEBUG, "No SynchronousConfigurationListeners to send {0} event to.", new Object[]
                { syncSender.getTypeName() } );
        }

        // schedule asynchronous events
        if ( asyncSender.hasConfigurationEventListeners() )
        {
            eventThread.schedule( asyncSender );
        }
        else
        {
            log( LogService.LOG_DEBUG, "No ConfigurationListeners to send {0} event to.", new Object[]
                { asyncSender.getTypeName() } );
        }
    }


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

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

            // we only reset dynamic bindings, which are only present in
            // cached configurations, hence only consider cached configs here
            final ConfigurationImpl[] configs = getCachedConfigurations();
            for ( int i = 0; i < configs.length; i++ )
            {
                final ConfigurationImpl cfg = configs[i];
                if ( location.equals( cfg.getDynamicBundleLocation() ) )
                {
                    cfg.setDynamicBundleLocation( null, true );
                }
            }
        }
    }


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

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

            List pmList = new ArrayList();
            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
                if ( refs.length > 1 )
                {
                    Arrays.sort( refs, RankingComparator.SRV_RANKING );
                }

                // create the service array from the sorted set of referenecs
                for ( int i = 0; i < refs.length; i++ )
                {
                    Object service = persistenceManagerTracker.getService( refs[i] );
                    if ( service != null )
                    {
                        pmList.add( new CachingPersistenceManagerProxy( ( PersistenceManager ) service ) );
                    }
                }

                pm = ( PersistenceManager[] ) pmList.toArray( new PersistenceManager[pmList.size()] );
            }

            pmtCount = pm.length;
            persistenceManagers = pm;
        }

        return persistenceManagers;
    }


    private ServiceReference getServiceReference()
    {
        ServiceRegistration reg = configurationAdminRegistration;
        if (reg != null) {
            return reg.getReference();
        }

        // probably called for firing an event during service registration
        // since we didn't get the service registration yet we use the
        // service registry to get our service reference
        BundleContext context = bundleContext;
        if ( context != null )
        {
            try
            {
                ServiceReference[] refs = context.getServiceReferences( ConfigurationAdmin.class.getName(), null );
                if ( refs != null )
                {
                    for ( int i = 0; i < refs.length; i++ )
                    {
                        if ( refs[i].getBundle().getBundleId() == context.getBundle().getBundleId() )
                        {
                            return refs[i];
                        }
                    }
                }
            }
            catch ( InvalidSyntaxException e )
            {
                // unexpected since there is no filter
            }
        }

        // service references
        return null;
    }


    /**
     * Configures the ManagedService and returns the service.pid
     * service property as a String[], which may be <code>null</code> if
     * the ManagedService does not have such a property.
     */
    /**
     * Configures the ManagedServiceFactory and returns the service.pid
     * service property as a String[], which may be <code>null</code> if
     * the ManagedServiceFactory does not have such a property.
     */
    /**
     * Schedules the configuration of the referenced service with
     * configuration for the given PID.
     *
     * @param pid The list of service PID of the configurations to be
     *      provided to the referenced service.
     * @param sr The <code>ServiceReference</code> to the service
     *      to be configured.
     * @param factory <code>true</code> If the service is considered to
     *      be a <code>ManagedServiceFactory</code>. Otherwise the service
     *      is considered to be a <code>ManagedService</code>.
     */
    public void configure( String[] pid, ServiceReference sr, final boolean factory, final ConfigurationMap<?> configs )
    {
        if ( this.isLogEnabled( LogService.LOG_DEBUG ) )
        {
            this.log( LogService.LOG_DEBUG, "configure(ManagedService {0})", new Object[]
                { toString( sr ) } );
        }

        Runnable r;
        if ( factory )
        {
            r = new ManagedServiceFactoryUpdate( pid, sr, configs );
        }
        else
        {
            r = new ManagedServiceUpdate( pid, sr, configs );
        }
        updateThread.schedule( r );
        log( LogService.LOG_DEBUG, "[{0}] scheduled", new Object[]
            { r } );
    }


    /**
     * Factory method to create a new configuration object. The configuration
     * object returned is not stored in configuration cache and only persisted
     * if the <code>factoryPid</code> parameter is <code>null</code>.
     *
     * @param pid
     *            The PID of the new configuration object. Must not be
     *            <code>null</code>.
     * @param factoryPid
     *            The factory PID of the new configuration. Not
     *            <code>null</code> if the new configuration object belongs to a
     *            factory. The configuration object will not be persisted if
     *            this parameter is not <code>null</code>.
     * @param bundleLocation
     *            The bundle location of the bundle to which the configuration
     *            belongs or <code>null</code> if the configuration is not bound
     *            yet.
     * @return The new configuration object
     * @throws IOException
     *             May be thrown if an error occurrs persisting the new
     *             configuration object.
     */
    ConfigurationImpl createConfiguration( String pid, String factoryPid, String bundleLocation ) throws IOException
    {
        log( LogService.LOG_DEBUG, "createConfiguration({0}, {1}, {2})", new Object[]
            { pid, factoryPid, bundleLocation } );
        return new ConfigurationImpl( this, getPersistenceManagers()[0], pid, factoryPid, bundleLocation );
    }


    /**
     * Returns a list of {@link Factory} instances according to the
     * Configuration Admin 1.5 specification for targeted PIDs (Section
     * 104.3.2)
     *
     * @param rawFactoryPid The raw factory PID without any targetting.
     * @param target The <code>ServiceReference</code> of the service to
     *      be supplied with targeted configuration.
     * @return A list of {@link Factory} instances as listed above. This
     *      list will always at least include an instance for the
     *      <code>rawFactoryPid</code>. Other instances are only included
     *      if existing.
     * @throws IOException If an error occurrs reading any of the
     *      {@link Factory} instances from persistence
     */
    List<Factory> getTargetedFactories( final String rawFactoryPid, final ServiceReference target ) throws IOException
    {
        LinkedList<Factory> factories = new LinkedList<Factory>();

        final Bundle serviceBundle = target.getBundle();
        if ( serviceBundle != null )
        {
            // for pre-1.5 API compatibility
            final StringBuffer targetedPid = new StringBuffer( rawFactoryPid );
            factories.add( getOrCreateFactory( targetedPid.toString() ) );

            targetedPid.append( '|' ).append( serviceBundle.getSymbolicName() );
            Factory f = getFactory( targetedPid.toString() );
            if ( f != null )
            {
                factories.add( 0, f );
            }

            targetedPid.append( '|' ).append( TargetedPID.getBundleVersion( serviceBundle ) );
            f = getFactory( targetedPid.toString() );
            if ( f != null )
            {
                factories.add( 0, f );
            }

            targetedPid.append( '|' ).append( serviceBundle.getLocation() );
            f = getFactory( targetedPid.toString() );
            if ( f != null )
            {
                factories.add( 0, f );
            }
        }

        return factories;
    }


    /**
     * Gets the factory with the exact identifier from the cached or from
     * the persistence managers. If no factory exists already one is
     * created and cached.
     *
     * @param factoryPid The PID of the {@link Factory} to return
     * @return The existing or newly created {@link Factory}
     * @throws IOException If an error occurrs reading the factory from
     *      a {@link PersistenceManager}
     */
    Factory getOrCreateFactory( String factoryPid ) throws IOException
    {
        Factory factory = getFactory( factoryPid );
        if ( factory != null )
        {
            return factory;
        }

        return createFactory( factoryPid );
    }


    /**
     * Gets the factory with the exact identifier from the cached or from
     * the persistence managers. If no factory exists <code>null</code>
     * is returned.
     *
     * @param factoryPid The PID of the {@link Factory} to return
     * @return The existing {@link Factory} or <code>null</code>
     * @throws IOException If an error occurrs reading the factory from
     *      a {@link PersistenceManager}
     */
    Factory getFactory( String factoryPid ) throws IOException
    {
        // check for cached factory
        Factory factory = getCachedFactory( factoryPid );
        if ( factory != null )
        {
            return factory;
        }

        // try to load factory from persistence
        PersistenceManager[] pmList = getPersistenceManagers();
        for ( int i = 0; i < pmList.length; i++ )
        {
            if ( Factory.exists( pmList[i], factoryPid ) )
            {
                factory = Factory.load( this, pmList[i], factoryPid );
                cacheFactory( factory );
                return factory;
            }
        }

        // no existing factory
        return null;
    }


    /**
     * Creates a new factory with the given <code>factoryPid</code>.
     */
    Factory createFactory( String factoryPid )
    {
        Factory factory = new Factory( this, getPersistenceManagers()[0], factoryPid );
        cacheFactory( factory );
        return factory;
    }


    /**
     * Calls the registered configuration plugins on the given configuration
     * properties from the given configuration object.
     * <p>
     * The plugins to be called are selected as <code>ConfigurationPlugin</code>
     * services registered with a <code>cm.target</code> property set to
     * <code>*</code> or the factory PID of the configuration (for factory
     * configurations) or the PID of the configuration (for non-factory
     * configurations).
     *
     * @param props The configuraiton properties run through the registered
     *          ConfigurationPlugin services. This must not be
     *          <code>null</code>.
     * @param sr The service reference of the managed service (factory) which
     *          is to be updated with configuration
     * @param configPid The PID of the configuration object whose properties
     *          are to be augmented
     * @param factoryPid the factory PID of the configuration object whose
     *          properties are to be augmented. This is non-<code>null</code>
     *          only for a factory configuration.
     */
    public void callPlugins( final Dictionary props, final ServiceReference sr, final String configPid,
        final String factoryPid )
    {
        ServiceReference[] plugins = null;
        try
        {
            final String targetPid = (factoryPid == null) ? configPid : factoryPid;
            String filter = "(|(!(cm.target=*))(cm.target=" + targetPid + "))";
            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;
        }

        // sort the plugins by their service.cmRanking
        if ( plugins.length > 1 )
        {
            Arrays.sort( plugins, RankingComparator.CM_RANKING );
        }

        // call the plugins in order
        for ( int i = 0; i < plugins.length; i++ )
        {
            ServiceReference pluginRef = plugins[i];
            ConfigurationPlugin plugin = ( ConfigurationPlugin ) bundleContext.getService( pluginRef );
            if ( plugin != null )
            {
                try
                {
                    plugin.modifyConfiguration( sr, props );
                }
                catch ( Throwable t )
                {
                    log( LogService.LOG_ERROR, "Unexpected problem calling configuration plugin {0}", new Object[]
                        { toString( pluginRef ), t } );
                }
                finally
                {
                    // ensure ungetting the plugin
                    bundleContext.ungetService( pluginRef );
                }
                ConfigurationImpl.setAutoProperties( props, configPid, factoryPid );
            }
        }
    }


    /**
     * Creates a PID for the given factoryPid
     *
     * @param factoryPid
     * @return
     */
    private static String createPid( String factoryPid )
    {
        Random ng = numberGenerator;
        if ( ng == null )
        {
            // FELIX-2771 Secure Random not available on Mika
            try
            {
                ng = new SecureRandom();
            }
            catch ( Throwable t )
            {
                // fall back to Random
                ng = new Random();
            }
        }

        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();
    }


    public boolean isLogEnabled( int level )
    {
        return level <= logLevel;
    }


    public void log( int level, String format, Object[] args )
    {
        if ( isLogEnabled( level ) )
        {
            Throwable throwable = null;
            String message = format;

            if ( args != null && args.length > 0 )
            {
                if ( args[args.length - 1] instanceof Throwable )
                {
                    throwable = ( Throwable ) args[args.length - 1];
                }
                message = MessageFormat.format( format, args );
            }

            log( level, message, throwable );
        }
    }


    public void log( int level, String message, Throwable t )
    {
        // log using the LogService if available
        Object log = logTracker.getService();
        if ( log != null )
        {
            ( ( LogService ) log ).log( getServiceReference(), level, message, t );
            return;
        }

        // Otherwise only log if more serious than the configured level
        if ( isLogEnabled( level ) )
        {
            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 );
            }
        }
    }


    public static String toString( ServiceReference ref )
    {
        String[] ocs = ( String[] ) ref.getProperty( "objectClass" );
        StringBuffer buf = new StringBuffer( "[" );
        for ( int i = 0; i < ocs.length; i++ )
        {
            buf.append( ocs[i] );
            if ( i < ocs.length - 1 )
                buf.append( ", " );
        }

        buf.append( ", id=" ).append( ref.getProperty( Constants.SERVICE_ID ) );

        Bundle provider = ref.getBundle();
        if ( provider != null )
        {
            buf.append( ", bundle=" ).append( provider.getBundleId() );
            buf.append( '/' ).append( provider.getLocation() );
        }
        else
        {
            buf.append( ", unregistered" );
        }

        buf.append( "]" );
        return buf.toString();
    }


    /**
     * Checks whether the bundle is allowed to receive the configuration
     * with the given location binding.
     * <p>
     * This method implements the logic defined CM 1.4 / 104.4.1:
     * <ul>
     * <li>If the location is <code>null</code> (the configuration is not
     * bound yet), assume the bundle is allowed</li>
     * <li>If the location is a single location (no leading "?"), require
     * the bundle's location to match</li>
     * <li>If the location is a multi-location (leading "?"), assume the
     * bundle is allowed if there is no security manager. If there is a
     * security manager, check whether the bundle has "target" permission
     * on this location.</li>
     * </ul>
     */
    boolean canReceive( final Bundle bundle, final String location )
    {
        if ( location == null )
        {
            log( LogService.LOG_DEBUG, "canReceive=true; bundle={0}; configuration=(unbound)", new Object[]
                { bundle.getLocation() } );
            return true;
        }
        else if ( location.startsWith( "?" ) )
        {
            // multi-location
            if ( System.getSecurityManager() != null )
            {
                final boolean hasPermission = bundle.hasPermission( new ConfigurationPermission( location,
                    ConfigurationPermission.TARGET ) );
                log( LogService.LOG_DEBUG, "canReceive={0}: bundle={1}; configuration={2} (SecurityManager check)",
                    new Object[]
                        { new Boolean( hasPermission ), bundle.getLocation(), location } );
                return hasPermission;
            }

            log( LogService.LOG_DEBUG, "canReceive=true; bundle={0}; configuration={1} (no SecurityManager)",
                new Object[]
                    { bundle.getLocation(), location } );
            return true;
        }
        else
        {
            // single location, must match
            final boolean hasPermission = location.equals( bundle.getLocation() );
            log( LogService.LOG_DEBUG, "canReceive={0}: bundle={1}; configuration={2}", new Object[]
                { new Boolean( hasPermission ), bundle.getLocation(), location } );
            return hasPermission;
        }
    }


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

    /**
     * The <code>ManagedServiceUpdate</code> updates a freshly registered
     * <code>ManagedService</code> with a specific configuration. If a
     * ManagedService is registered with multiple PIDs an instance of this
     * class is used for each registered PID.
     */
    private class ManagedServiceUpdate implements Runnable
    {
        private final String[] pids;

        private final ServiceReference sr;

        private final ConfigurationMap<?> configs;


        ManagedServiceUpdate( String[] pids, ServiceReference sr, ConfigurationMap<?> configs )
        {
            this.pids = pids;
            this.sr = sr;
            this.configs = configs;
        }


        public void run()
        {
            for ( String pid : this.pids )
            {
                try
                {
                    final ConfigurationImpl config = getTargetedConfiguration( pid, this.sr );
                    provide( pid, config );
                }
                catch ( IOException ioe )
                {
                    log( LogService.LOG_ERROR, "Error loading configuration for {0}", new Object[]
                        { pid, ioe } );
                }
                catch ( Exception e )
                {
                    log( LogService.LOG_ERROR, "Unexpected problem providing configuration {0} to service {1}",
                        new Object[]
                            { pid, ConfigurationManager.toString( this.sr ), e } );
                }
            }
        }


        private void provide(final String servicePid, final ConfigurationImpl config)
        {
            // check configuration
            final TargetedPID configPid;
            final Dictionary properties;
            final long revision;
            if ( config != null )
            {
                synchronized ( config )
                {
                    configPid = config.getPid();
                    properties = config.getProperties( true );
                    revision = config.getRevision();
                }
            }
            else
            {
                // 104.5.3 ManagedService.updated must be called with null
                // if no configuration is available
                configPid = new TargetedPID( servicePid );
                properties = null;
                revision = -1;
            }

            log( LogService.LOG_DEBUG, "Updating service {0} with configuration {1}@{2}", new Object[]
                { servicePid, configPid, new Long( revision ) } );

            managedServiceTracker.provideConfiguration( sr, configPid, null, properties, revision, this.configs );
        }

        public String toString()
        {
            return "ManagedService Update: pid=" + Arrays.asList( pids );
        }
    }

    /**
     * The <code>ManagedServiceFactoryUpdate</code> updates a freshly
     * registered <code>ManagedServiceFactory</code> with a specific
     * configuration. If a ManagedServiceFactory is registered with
     * multiple PIDs an instance of this class is used for each registered
     * PID.
     */
    private class ManagedServiceFactoryUpdate implements Runnable
    {
        private final String[] factoryPids;

        private final ServiceReference sr;

        private final ConfigurationMap<?> configs;


        ManagedServiceFactoryUpdate( String[] factoryPids, ServiceReference sr, final ConfigurationMap<?> configs )
        {
            this.factoryPids = factoryPids;
            this.sr = sr;
            this.configs = configs;
        }


        public void run()
        {
            for ( String factoryPid : this.factoryPids )
            {

                List<Factory> factories = null;
                try
                {
                    factories = getTargetedFactories( factoryPid, sr );
                    for ( Factory factory : factories )
                    {
                        for ( Iterator pi = factory.getPIDs().iterator(); pi.hasNext(); )
                        {
                            final String pid = ( String ) pi.next();
                            ConfigurationImpl cfg;
                            try
                            {
                                cfg = getConfiguration( pid );
                            }
                            catch ( IOException ioe )
                            {
                                log( LogService.LOG_ERROR, "Error loading configuration for {0}", new Object[]
                                    { pid, ioe } );
                                continue;
                            }

                            // sanity check on the configuration
                            if ( cfg == null )
                            {
                                log( LogService.LOG_ERROR,
                                    "Configuration {0} referred to by factory {1} does not exist", new Object[]
                                        { pid, factoryPid } );
                                factory.removePID( pid );
                                factory.storeSilently();
                                continue;
                            }
                            else if ( cfg.isNew() )
                            {
                                // Configuration has just been created but not yet updated
                                // we currently just ignore it and have the update mechanism
                                // provide the configuration to the ManagedServiceFactory
                                // As of FELIX-612 (not storing new factory configurations)
                                // this should not happen. We keep this for added stability
                                // but raise the logging level to error.
                                log( LogService.LOG_ERROR, "Ignoring new configuration pid={0}", new Object[]
                                    { pid } );
                                continue;
                            }

                            /*
                             * this code would catch targeted factory PIDs;
                             * since this is not expected any way, we can
                             * leave this out
                             */
                            /*
                            else if ( !factoryPid.equals( cfg.getFactoryPid() ) )
                            {
                                log( LogService.LOG_ERROR,
                                    "Configuration {0} referred to by factory {1} seems to belong to factory {2}",
                                    new Object[]
                                        { pid, factoryPid, cfg.getFactoryPid() } );
                                factory.removePID( pid );
                                factory.storeSilently();
                                continue;
                            }
                            */

                            provide( factoryPid, cfg );
                        }
                    }
                }
                catch ( IOException ioe )
                {
                    log( LogService.LOG_ERROR, "Cannot get factory mapping for factory PID {0}", new Object[]
                        { factoryPid, ioe } );
                }
            }
        }


        private void provide(final String factoryPid, final ConfigurationImpl config) {

            final Dictionary rawProperties;
            final long revision;
            synchronized ( config )
            {
                rawProperties = config.getProperties( true );
                revision = config.getRevision();
            }

            log( LogService.LOG_DEBUG, "Updating service {0} with configuration {1}/{2}@{3}", new Object[]
                { factoryPid, config.getFactoryPid(), config.getPid(), new Long( revision ) } );

            // CM 1.4 / 104.13.2.1
            final Bundle serviceBundle = this.sr.getBundle();
            if ( serviceBundle == null )
            {
                log(
                    LogService.LOG_INFO,
                    "ManagedServiceFactory for factory PID {0} seems to already have been unregistered, not updating with factory",
                    new Object[]
                        { factoryPid } );
                return;
            }

            if ( !canReceive( serviceBundle, config.getBundleLocation() ) )
            {
                log( LogService.LOG_ERROR,
                    "Cannot use configuration {0} for {1}: No visibility to configuration bound to {2}",
                    new Object[]
                        { config.getPid(), ConfigurationManager.toString( sr ), config.getBundleLocation() } );

                // no service, really, bail out
                return;
            }

            // 104.4.2 Dynamic Binding
            config.tryBindLocation( serviceBundle.getLocation() );

            // update the service with the configuration (if non-null)
            if ( rawProperties != null )
            {
                log( LogService.LOG_DEBUG, "{0}: Updating configuration pid={1}", new Object[]
                    { ConfigurationManager.toString( sr ), config.getPid() } );
                managedServiceFactoryTracker.provideConfiguration( sr, config.getPid(), config.getFactoryPid(),
                    rawProperties, revision, this.configs );
            }
        }


        public String toString()
        {
            return "ManagedServiceFactory Update: factoryPid=" + Arrays.asList( this.factoryPids );
        }
    }

    private abstract class ConfigurationProvider<T> implements Runnable
    {

        protected final ConfigurationImpl config;
        protected final long revision;
        protected final Dictionary<String, ?> properties;
        private BaseTracker<T> helper;


        protected ConfigurationProvider( final ConfigurationImpl config )
        {
            synchronized ( config )
            {
                this.config = config;
                this.revision = config.getRevision();
                this.properties = config.getProperties( true );
            }
        }


        protected TargetedPID getTargetedServicePid()
        {
            final TargetedPID factoryPid = this.config.getFactoryPid();
            if ( factoryPid != null )
            {
                return factoryPid;
            }
            return this.config.getPid();
        }


        protected BaseTracker<T> getHelper()
        {
            if ( this.helper == null )
            {
                this.helper = ( BaseTracker<T> ) ( ( this.config.getFactoryPid() == null ) ? ConfigurationManager.this.managedServiceTracker
                    : ConfigurationManager.this.managedServiceFactoryTracker );
            }
            return this.helper;
        }


        protected boolean provideReplacement( ServiceReference<T> sr )
        {
            if ( this.config.getFactoryPid() == null )
            {
                try
                {
                    final String configPidString = this.getHelper().getServicePid( sr, this.config.getPid() );
                    final ConfigurationImpl rc = getTargetedConfiguration( configPidString, sr );
                    if ( rc != null )
                    {
                        final TargetedPID configPid;
                        final Dictionary properties;
                        final long revision;
                        synchronized ( rc )
                        {
                            configPid = rc.getPid();
                            properties = rc.getProperties( true );
                            revision = rc.getRevision();
                        }

                        this.getHelper().provideConfiguration( sr, configPid, null, properties, -revision, null );

                        return true;
                    }
                }
                catch ( IOException ioe )
                {
                    log( LogService.LOG_ERROR, "Error loading configuration for {0}", new Object[]
                        { this.config.getPid(), ioe } );
                }
                catch ( Exception e )
                {
                    log( LogService.LOG_ERROR, "Unexpected problem providing configuration {0} to service {1}",
                        new Object[]
                            { this.config.getPid(), ConfigurationManager.toString( sr ), e } );
                }
            }

            // factory or no replacement available
            return false;
        }
    }

    /**
     * The <code>UpdateConfiguration</code> is used to update
     * <code>ManagedService[Factory]</code> services with the configuration
     * they are subscribed to. This may cause the configuration to be
     * supplied to multiple services.
     */
    private class UpdateConfiguration extends ConfigurationProvider
    {

        UpdateConfiguration( final ConfigurationImpl config )
        {
            super( config );
        }


        public void run()
        {
            log( LogService.LOG_DEBUG, "Updating configuration {0} to revision #{1}", new Object[]
                { config.getPid(), new Long( revision ) } );

            final List<ServiceReference<?>> srList = this.getHelper().getServices( getTargetedServicePid() );
            if ( !srList.isEmpty() )
            {
                // optionally bind dynamically to the first service
                config.tryBindLocation( srList.get( 0 ).getBundle().getLocation() );

                final String configBundleLocation = config.getBundleLocation();

                // provide configuration to all services from the
                // correct bundle
                for (ServiceReference<?> ref : srList)
                {
                    final Bundle refBundle = ref.getBundle();
                    if ( refBundle == null )
                    {
                        log( LogService.LOG_DEBUG,
                            "Service {0} seems to be unregistered concurrently (not providing configuration)",
                            new Object[]
                                { ConfigurationManager.toString( ref ) } );
                    }
                    else if ( canReceive( refBundle, configBundleLocation ) )
                    {
                        this.getHelper().provideConfiguration( ref, this.config.getPid(), this.config.getFactoryPid(),
                            this.properties, this.revision, null );
                    }
                    else
                    {
                        // CM 1.4 / 104.13.2.2
                        log( LogService.LOG_ERROR,
                            "Cannot use configuration {0} for {1}: No visibility to configuration bound to {2}",
                            new Object[]
                                { config.getPid(), ConfigurationManager.toString( ref ), configBundleLocation } );
                    }

                }
            }
            else if ( isLogEnabled( LogService.LOG_DEBUG ) )
            {
                log( LogService.LOG_DEBUG, "No ManagedService[Factory] registered for updates to configuration {0}",
                    new Object[]
                        { config.getPid() } );
            }
        }


        public String toString()
        {
            return "Update: pid=" + config.getPid();
        }
    }


    /**
     * The <code>DeleteConfiguration</code> class is used to inform
     * <code>ManagedService[Factory]</code> services of a configuration
     * being deleted.
     */
    private class DeleteConfiguration extends ConfigurationProvider
    {

        private final String configLocation;


        DeleteConfiguration( ConfigurationImpl config )
        {
            /*
             * NOTE: We keep the configuration because it might be cleared just
             * after calling this method. The pid and factoryPid fields are
             * final and cannot be reset.
             */
            super(config);
            this.configLocation = config.getBundleLocation();
        }


        public void run()
        {
            List<ServiceReference<?>> srList = this.getHelper().getServices( getTargetedServicePid() );
            if ( !srList.isEmpty() )
            {
                for (ServiceReference<?> sr : srList)
                {
                    final Bundle srBundle = sr.getBundle();
                    if ( srBundle == null )
                    {
                        log( LogService.LOG_DEBUG,
                            "Service {0} seems to be unregistered concurrently (not removing configuration)",
                            new Object[]
                                { ConfigurationManager.toString( sr ) } );
                    }
                    else if ( canReceive( srBundle, configLocation ) )
                    {
                        // revoke configuration unless a replacement
                        // configuration can be provided
                        if ( !this.provideReplacement( sr ) )
                        {
                            this.getHelper().removeConfiguration( sr, this.config.getPid(), this.config.getFactoryPid() );
                        }
                    }
                    else
                    {
                        // CM 1.4 / 104.13.2.2
                        log( LogService.LOG_ERROR,
                            "Cannot remove configuration {0} for {1}: No visibility to configuration bound to {2}",
                            new Object[]
                                { config.getPid(), ConfigurationManager.toString( sr ), configLocation } );
                    }
                }
            }

            final TargetedPID factoryPid = config.getFactoryPid();
            if ( factoryPid != null )
            {
                // remove the pid from the factory
                final String pid = config.getPidString();
                try
                {
                    Factory factory = getOrCreateFactory( factoryPid.toString() );
                    factory.removePID( pid );
                    factory.store();
                }
                catch ( IOException ioe )
                {
                    log( LogService.LOG_ERROR, "Failed removing {0} from the factory {1}", new Object[]
                        { pid, factoryPid, ioe } );
                }
            }
        }

        public String toString()
        {
            return "Delete: pid=" + config.getPid();
        }
    }

    private class LocationChanged extends ConfigurationProvider
    {
        private final String oldLocation;


        LocationChanged( ConfigurationImpl config, String oldLocation )
        {
            super( config );
            this.oldLocation = oldLocation;
        }


        public void run()
        {
            List<ServiceReference<?>> srList = this.getHelper().getServices( getTargetedServicePid() );
            if ( !srList.isEmpty() )
            {
                for (final ServiceReference<?> sr : srList)
                {
                    final Bundle srBundle = sr.getBundle();
                    if ( srBundle == null )
                    {
                        log( LogService.LOG_DEBUG,
                            "Service {0} seems to be unregistered concurrently (not processing)", new Object[]
                                { ConfigurationManager.toString( sr ) } );
                        continue;
                    }

                    final boolean wasVisible = canReceive( srBundle, oldLocation );
                    final boolean isVisible = canReceive( srBundle, config.getBundleLocation() );

                    // make sure the config is dynamically bound to the first
                    // service if the config has been unbound causing this update
                    if ( isVisible )
                    {
                        config.tryBindLocation( srBundle.getLocation() );
                    }

                    if ( wasVisible && !isVisible )
                    {
                        // revoke configuration unless a replacement
                        // configuration can be provided
                        if ( !this.provideReplacement( sr ) )
                        {
                            this.getHelper().removeConfiguration( sr, this.config.getPid(), this.config.getFactoryPid() );
                            log( LogService.LOG_DEBUG, "Configuration {0} revoked from {1} (no more visibility)",
                                new Object[]
                                    { config.getPid(), ConfigurationManager.toString( sr ) } );
                        }
                    }
                    else if ( !wasVisible && isVisible )
                    {
                        // call updated method
                        this.getHelper().provideConfiguration( sr, this.config.getPid(), this.config.getFactoryPid(),
                            this.properties, this.revision, null );
                        log( LogService.LOG_DEBUG, "Configuration {0} provided to {1} (new visibility)", new Object[]
                            { config.getPid(), ConfigurationManager.toString( sr ) } );
                    }
                    else
                    {
                        // same visibility as before
                        log( LogService.LOG_DEBUG, "Unmodified visibility to configuration {0} for {1}", new Object[]
                            { config.getPid(), ConfigurationManager.toString( sr ) } );
                    }
                }
            }
        }


        public String toString()
        {
            return "Location Changed (pid=" + config.getPid() + "): " + oldLocation + " ==> "
                + config.getBundleLocation();
        }
    }

    private class FireConfigurationEvent implements Runnable
    {
        private final int type;

        private final String pid;

        private final String factoryPid;

        private final ServiceReference[] listenerReferences;

        private final ConfigurationListener[] listeners;

        private final Bundle[] listenerProvider;

        private ConfigurationEvent event;

        private FireConfigurationEvent( final ServiceTracker listenerTracker, final int type, final String pid, final String factoryPid)
        {
            this.type = type;
            this.pid = pid;
            this.factoryPid = factoryPid;

            final ServiceReference[] srs = listenerTracker.getServiceReferences();
            if ( srs == null || srs.length == 0 )
            {
                this.listenerReferences = null;
                this.listeners = null;
                this.listenerProvider = null;
            }
            else
            {
                this.listenerReferences = srs;
                this.listeners = new ConfigurationListener[srs.length];
                this.listenerProvider = new Bundle[srs.length];
                for ( int i = 0; i < srs.length; i++ )
                {
                    this.listeners[i] = ( ConfigurationListener ) listenerTracker.getService( srs[i] );
                    this.listenerProvider[i] = srs[i].getBundle();
                }
            }
        }


        boolean hasConfigurationEventListeners()
        {
            return this.listenerReferences != null;
        }


        String getTypeName()
        {
            switch ( type )
            {
                case ConfigurationEvent.CM_DELETED:
                    return "CM_DELETED";
                case ConfigurationEvent.CM_UPDATED:
                    return "CM_UPDATED";
                case ConfigurationEvent.CM_LOCATION_CHANGED:
                    return "CM_LOCATION_CHANGED";
                default:
                    return "<UNKNOWN(" + type + ")>";
            }
        }


        public void run()
        {
            for ( int i = 0; i < listeners.length; i++ )
            {
                sendEvent( i );
            }
        }


        public String toString()
        {
            return "Fire ConfigurationEvent: pid=" + pid;
        }


        private ConfigurationEvent getConfigurationEvent()
        {
            if ( event == null )
            {
                this.event = new ConfigurationEvent( getServiceReference(), type, factoryPid, pid );
            }
            return event;
        }


        private void sendEvent( final int serviceIndex )
        {
            if ( listenerProvider[serviceIndex].getState() == Bundle.ACTIVE && this.listeners[serviceIndex] != null )
            {
                log( LogService.LOG_DEBUG, "Sending {0} event for {1} to {2}", new Object[]
                    { getTypeName(), pid, ConfigurationManager.toString( listenerReferences[serviceIndex] ) } );

                try
                {
                    listeners[serviceIndex].configurationEvent( getConfigurationEvent() );
                }
                catch ( Throwable t )
                {
                    log( LogService.LOG_ERROR, "Unexpected problem delivering configuration event to {0}", new Object[]
                        { ConfigurationManager.toString( listenerReferences[serviceIndex] ), t } );
                }
                finally
                {
                    this.listeners[serviceIndex] = null;
                }
            }
        }
    }
}

