directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From erodrig...@apache.org
Subject svn commit: r209428 [1/2] - in /directory/sandbox/trunk/osgi-spec/trunk/configuration/src: ./ main/ main/java/ main/java/org/ main/java/org/apache/ main/java/org/apache/configuration/ main/java/org/apache/configuration/store/
Date Wed, 06 Jul 2005 08:02:10 GMT
Author: erodriguez
Date: Wed Jul  6 01:02:09 2005
New Revision: 209428

URL: http://svn.apache.org/viewcvs?rev=209428&view=rev
Log:
OSGi Configuration Admin service implementation.

Added:
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Activator.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminFactory.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminImpl.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDictionary.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDispatcher.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationImpl.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStore.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStoreFactory.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Logger.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/PluginManager.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Update.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/UpdateQueue.java
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/store/
    directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/store/SimpleConfigurationStore.java

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Activator.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Activator.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Activator.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Activator.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,81 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.io.File;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.apache.configuration.store.SimpleConfigurationStore;
+
+/**
+ * Configuration Admin bundle activator.
+ */
+public class Activator implements BundleActivator
+{
+    private static final String STORE_DIR_PROP    = "org.apache.configuration.store";
+    private static final String DEFAULT_STORE_DIR = "configuration";
+    public static final Logger LOG = new Logger();
+    
+    private ServiceRegistration serviceRegistration;
+    
+    static BundleContext bc;
+    
+    public void start( BundleContext bc ) throws BundleException
+    {
+        Activator.bc = bc;
+        
+        if ( bc == null )
+        {
+            throw new BundleException( "Null BundleContext in Activator." );
+        }
+        
+        ConfigurationStore store = new SimpleConfigurationStore( getStoreDir() );
+        serviceRegistration = bc.registerService( ConfigurationAdmin.class.getName(), new ConfigurationAdminFactory( store ), null );
+    }
+    
+    public void stop( BundleContext bc ) throws BundleException
+    {
+        if ( serviceRegistration != null )
+        {
+            serviceRegistration.unregister();
+            serviceRegistration = null;
+        }
+    }
+    
+    private File getStoreDir()
+    {
+        String storeDirName = System.getProperty( STORE_DIR_PROP );
+        File storeDir = null;
+        
+        if ( storeDirName == null || "".equals( storeDirName ) )
+        {
+            storeDir = bc.getDataFile( DEFAULT_STORE_DIR );
+        }
+        else
+        {
+            storeDir = new File( storeDirName );
+        }
+        
+        return storeDir;
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminFactory.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminFactory.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminFactory.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminFactory.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,680 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
+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.ServiceEvent;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationPlugin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * ConfigurationAdmin implementation
+ */
+class ConfigurationAdminFactory implements ServiceFactory, ServiceListener, BundleListener
+{
+    private Hashtable               locationToPids = new Hashtable();
+    private Hashtable               existingBundleLocations = new Hashtable();
+    private ConfigurationStore      store;
+    private PluginManager           pluginManager;
+    private ConfigurationDispatcher configurationDispatcher;
+    
+    // Constants
+    private static final String FILTER = "(|(objectClass=" + ManagedServiceFactory.class.getName() + ")"
+    									 + "(objectClass=" + ManagedService.class.getName() + ")"
+    									 + "(objectClass=" + ConfigurationPlugin.class.getName() + "))";
+    
+    static AdminPermission ADMIN_PERMISSION = new AdminPermission();
+    static String DYNAMIC_BUNDLE_LOCATION   = "dynamic.service.bundleLocation";
+    static String ANY_LOCATION              = "*";
+    
+    
+    public ConfigurationAdminFactory( ConfigurationStore store )
+    {
+        this.store = store;
+        
+        pluginManager = new PluginManager();
+
+        configurationDispatcher = new ConfigurationDispatcher( pluginManager );
+
+        lookForExistingBundleLocations();
+        
+        try
+        {
+            Activator.bc.addServiceListener( this, FILTER );
+            Activator.bc.addBundleListener( this );
+        }
+        catch (InvalidSyntaxException ignored)
+        {
+            ignored.printStackTrace();
+        }
+
+        lookForAlreadyRegisteredServices();
+    }
+    
+    
+    private void lookForAlreadyRegisteredServices()
+    {
+        notifyRegisteredServices( ConfigurationPlugin.class );
+        notifyRegisteredServices( ManagedServiceFactory.class );
+        notifyRegisteredServices( ManagedService.class );
+    }
+
+    private void notifyRegisteredServices( Class clazz )
+    {
+        try
+        {
+            ServiceReference[] srs = Activator.bc.getServiceReferences( clazz.getName(), null );
+            
+            for ( int ii = 0; srs != null && ii < srs.length; ++ii )
+            {
+                serviceChanged(srs[ii], ServiceEvent.REGISTERED, clazz.getName());
+            }
+        }
+        catch (InvalidSyntaxException ignored)
+        {
+        }
+    }
+
+    private void lookForExistingBundleLocations()
+    {
+        Bundle[] bs = Activator.bc.getBundles();
+        
+        for ( int ii = 0; bs != null && ii < bs.length; ++ii )
+        {
+            existingBundleLocations.put( bs[ii].getLocation(), bs[ii].getLocation() );
+        }
+    }
+
+    private boolean isNonExistingBundleLocation( String bundleLocation )
+    {
+        return bundleLocation != null && existingBundleLocations.get( bundleLocation ) == null;
+    }
+
+    private ConfigurationDictionary bindLocationIfNecessary( ServiceReference[] srs, ConfigurationDictionary d )
+            throws IOException
+    {
+        if ( srs == null || srs.length == 0 || d == null )
+        {
+            return d;
+        }
+        
+        String configLocation = (String) d.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+
+        if ( isNonExistingBundleLocation( configLocation ) )
+        {
+            Boolean dynamicLocation = (Boolean) d.get( DYNAMIC_BUNDLE_LOCATION );
+            
+            if ( dynamicLocation != null && dynamicLocation.booleanValue() )
+            {
+                configLocation = null;
+            }
+        }
+
+        if ( configLocation == null )
+        {
+            String fpid = (String) d.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+            String pid = (String) d.get( Constants.SERVICE_PID );
+            String serviceLocation = srs[0].getBundle().getLocation();
+
+            ConfigurationDictionary copy = d.createCopy();
+            copy.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, serviceLocation );
+            copy.put( DYNAMIC_BUNDLE_LOCATION, Boolean.TRUE );
+
+            store.store( pid, fpid, copy );
+            return copy;
+        }
+        
+        return d;
+    }
+
+    private void findAndUnbindConfigurationsDynamicallyBoundTo( String bundleLocation )
+    {
+        String filter = "(&(" + ConfigurationAdmin.SERVICE_BUNDLELOCATION + "=" + bundleLocation + ")"
+                + "(" + DYNAMIC_BUNDLE_LOCATION + "=" + Boolean.TRUE + "))";
+        try
+        {
+            Configuration[] configurations = listConfigurations( filter );
+            for ( int ii = 0; configurations != null && ii < configurations.length; ++ii )
+            {
+                configurations[ii].setBundleLocation( null );
+            }
+        }
+        catch (Exception e)
+        {
+            Activator.LOG.error( "Error while unbinding configurations bound to " + bundleLocation, e );
+        }
+    }
+
+    private ServiceReference[] filterOnMatchingLocations( ServiceReference[] srs, String configLocation )
+    {
+        List results = new ArrayList();
+        
+        for ( int ii = 0; ii < srs.length; ++ii )
+        {
+            String serviceLocation = srs[ii].getBundle().getLocation();
+            if ( locationsMatch( serviceLocation, configLocation ) )
+            {
+                results.add( srs[ii] );
+            }
+            else
+            {
+                Activator.LOG.error( "The bundle " + serviceLocation
+                                + " has registered a ManagedService(Factory) for a pid bound to "
+                                + configLocation );
+            }
+        }
+        
+        return (ServiceReference[])results.toArray( new ServiceReference[ results.size() ] );
+    }
+
+    private boolean locationsMatch( String serviceLocation, String configLocation )
+    {
+        if ( configLocation == null )
+        {
+            return false;
+        }
+        
+        if ( configLocation.equals( ANY_LOCATION ) || configLocation.equals( serviceLocation ) )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+
+    private void addToLocationToPidsAndCheck( ServiceReference sr )
+    {
+        if ( sr == null )
+        {
+            return;
+        }
+        
+        String bundleLocation = sr.getBundle().getLocation();
+        
+        String pid = (String) sr.getProperty( Constants.SERVICE_PID );
+        
+        if ( pid == null )
+        {
+            return;
+        }
+        
+        Hashtable pidsForLocation = (Hashtable) locationToPids.get( bundleLocation );
+        
+        if ( pidsForLocation == null )
+        {
+            pidsForLocation = new Hashtable();
+            locationToPids.put( bundleLocation, pidsForLocation );
+        }
+        
+        if ( pidsForLocation.contains( pid ) )
+        {
+            Activator.LOG.error( "Multiple ManagedServices registered from bundle "
+                            + bundleLocation + " for " + pid );
+        }
+        
+        pidsForLocation.put( sr, pid );
+    }
+
+    private void removeFromLocationToPids( ServiceReference sr )
+    {
+        if ( sr == null )
+        {
+            return;
+        }
+        
+        String bundleLocation = sr.getBundle().getLocation();
+        Hashtable pidsForLocation = (Hashtable) locationToPids.get( bundleLocation );
+        
+        if ( pidsForLocation == null )
+        {
+            return;
+        }
+        
+        pidsForLocation.remove( sr );
+        
+        if ( pidsForLocation.isEmpty() )
+        {
+            locationToPids.remove( bundleLocation );
+        }
+    }
+
+    private void updateTargetServicesMatching( ConfigurationDictionary cd )
+            throws IOException
+    {
+        String servicePid = (String) cd.get( Constants.SERVICE_PID );
+        
+        if ( servicePid == null )
+        {
+            return;
+        }
+        
+        String factoryPid = (String) cd.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+        String bundleLocation = (String) cd.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        
+        if ( factoryPid == null )
+        {
+            updateManagedServicesMatching( servicePid, bundleLocation );
+        }
+        else
+        {
+            updateManagedServiceFactoriesMatching( servicePid, factoryPid, bundleLocation );
+        }
+    }
+
+    private void updateManagedServiceFactoriesMatching( String servicePid,
+            String factoryPid, String bundleLocation ) throws IOException
+    {
+        ServiceReference[] srs = getTargetServiceReferences( ManagedServiceFactory.class, factoryPid );
+        ConfigurationDictionary cd = store.load( servicePid );
+        
+        if ( cd == null )
+        {
+            updateManagedServiceFactories( srs, servicePid, factoryPid, bundleLocation );
+        }
+        else
+        {
+            updateManagedServiceFactories( srs, servicePid, factoryPid, cd );
+        }
+    }
+
+    private void updateManagedServiceFactories( ServiceReference[] srs,
+            String servicePid, String factoryPid, ConfigurationDictionary cd )
+            throws IOException
+    {
+        ConfigurationDictionary bound = bindLocationIfNecessary( srs, cd );
+        String boundLocation = (String) bound.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        ServiceReference[] filtered = filterOnMatchingLocations( srs, boundLocation );
+        
+        for ( int ii = 0; ii < filtered.length; ++ii )
+        {
+            configurationDispatcher.dispatchUpdateFor( filtered[ii], servicePid, factoryPid, bound );
+        }
+    }
+    
+    private void updateManagedServiceFactories( ServiceReference[] srs,
+            String servicePid, String factoryPid, String boundLocation )
+    {
+        ServiceReference[] filtered = filterOnMatchingLocations( srs, boundLocation );
+        
+        for ( int ii = 0; ii < filtered.length; ++ii )
+        {
+            configurationDispatcher.dispatchUpdateFor( filtered[ii], servicePid, factoryPid, null );
+        }
+    }
+    
+    private void updateManagedServiceFactory( ServiceReference reference )
+            throws IOException
+    {
+        String factoryPid = (String) reference.getProperty( Constants.SERVICE_PID );
+        
+        ConfigurationDictionary[] cds = store.loadAll( factoryPid );
+        
+        if ( cds != null && cds.length > 0 )
+        {
+            ServiceReference[] srs = new ServiceReference[] { reference };
+            
+            for ( int ii = 0; ii < cds.length; ++ii )
+            {
+                String servicePid = (String) cds[ii].get( Constants.SERVICE_PID );
+                updateManagedServiceFactories( srs, servicePid, factoryPid, cds[ii] );
+            }
+        }
+    }
+    
+    private void updateManagedServicesMatching( String servicePid, String bundleLocation )
+    		throws IOException
+    {
+        ServiceReference[] srs = getTargetServiceReferences( ManagedService.class, servicePid );
+        ConfigurationDictionary cd = store.load( servicePid );
+        
+        if ( cd == null )
+        {
+            updateManagedServices( srs, servicePid, bundleLocation, null );
+        }
+        else
+        {
+            ConfigurationDictionary bound = bindLocationIfNecessary( srs, cd );
+            String boundLocation = (String) bound.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+            
+            updateManagedServices( srs, servicePid, boundLocation, bound );
+        }
+    }
+    
+    private void updateManagedServices( ServiceReference[] srs, String servicePid,
+            String boundLocation, ConfigurationDictionary bound )
+    {
+        ServiceReference[] filtered = filterOnMatchingLocations( srs, boundLocation );
+        
+        for ( int ii = 0; ii < filtered.length; ++ii )
+        {
+            configurationDispatcher.dispatchUpdateFor( filtered[ii], servicePid, null, bound );
+        }
+    }
+    
+    private void updateManagedService( ServiceReference sr ) throws IOException
+    {
+        final String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
+        ServiceReference[] srs = new ServiceReference[] { sr };
+        ConfigurationDictionary cd = store.load( servicePid );
+        
+        if ( cd == null )
+        {
+            for ( int ii = 0; ii < srs.length; ++ii )
+            {
+                configurationDispatcher.dispatchUpdateFor( srs[ii], servicePid, null, null );
+            }
+        }
+        else
+        {
+            cd = bindLocationIfNecessary( srs, cd );
+            String boundLocation = (String) cd.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+            srs = filterOnMatchingLocations( srs, boundLocation );
+            
+            for ( int ii = 0; ii < srs.length; ++ii )
+            {
+                configurationDispatcher.dispatchUpdateFor( srs[ii], servicePid, null, cd );
+            }
+        }
+    }
+
+    private ServiceReference[] getTargetServiceReferences( Class clazz, String pid )
+    {
+        String filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
+        
+        try
+        {
+            ServiceReference[] srs = Activator.bc.getServiceReferences( clazz.getName(), filter );
+            return srs == null ? new ServiceReference[0] : srs;
+        }
+        catch (InvalidSyntaxException e)
+        {
+            Activator.LOG.error( "Invalid syntax in ldap filter " + filter, e );
+            return new ServiceReference[0];
+        }
+    }
+
+    void delete( final ConfigurationImpl config ) throws IOException
+    {
+        try
+        {
+            AccessController.doPrivileged( new PrivilegedExceptionAction()
+            {
+                public Object run() throws IOException
+                {
+                    ConfigurationDictionary cd = store.delete( config.getPid() );
+                    
+                    if ( cd != null )
+                    {
+                        updateTargetServicesMatching( cd );
+                    }
+                    
+                    return null;
+                }
+            });
+        }
+        catch (PrivilegedActionException e)
+        {
+            throw (IOException) e.getException();
+        }
+    }
+
+    void update( final ConfigurationImpl config ) throws IOException
+    {
+        try
+        {
+            AccessController.doPrivileged( new PrivilegedExceptionAction()
+            {
+                public Object run() throws IOException
+                {
+                    store.store( config.getPid(), config.getFactoryPid(), config.getConfigurationDictionary() );
+                    updateTargetServicesMatching( config.getConfigurationDictionary() );
+                    return null;
+                }
+            });
+        }
+        catch (PrivilegedActionException e)
+        {
+            throw (IOException) e.getException();
+        }
+    }
+
+    String generatePid( final String factoryPid ) throws IOException
+    {
+        try
+        {
+            return (String) AccessController.doPrivileged(
+                    new PrivilegedExceptionAction()
+                    {
+                        public Object run() throws IOException
+                        {
+                            return store.generatePid( factoryPid );
+                        }
+                    });
+        }
+        catch (PrivilegedActionException e)
+        {
+            throw (IOException) e.getException();
+        }
+    }
+
+    ConfigurationDictionary load( final String pid ) throws IOException
+    {
+        try
+        {
+            return (ConfigurationDictionary) AccessController.doPrivileged(
+                    new PrivilegedExceptionAction()
+                    {
+                        public Object run() throws IOException
+                        {
+                            return store.load( pid );
+                        }
+                    });
+        }
+        catch (PrivilegedActionException e)
+        {
+            throw (IOException) e.getException();
+        }
+    }
+
+    Configuration[] listConfigurations( String filterString )
+            throws IOException, InvalidSyntaxException
+    {
+        Enumeration configurationPids = store.listPids();
+        
+        List results = new ArrayList();
+        
+        while ( configurationPids.hasMoreElements() )
+        {
+            String pid = (String) configurationPids.nextElement();
+            ConfigurationDictionary config = store.load( pid );
+            
+            if ( config == null )
+            {
+                continue;
+            }
+            
+            if ( filterString == null )
+            {
+                results.add( new ConfigurationImpl( this, config ) );
+            }
+            else
+            {
+                Filter filter = Activator.bc.createFilter( filterString );
+                
+                if ( filter.match( config ) )
+                {
+                    results.add( new ConfigurationImpl(this, config) );
+                }
+            }
+        }
+        
+        return (Configuration[])results.toArray( new Configuration[ results.size() ] );
+    }
+    
+    public Object getService( Bundle bundle, ServiceRegistration registration )
+    {
+        return new ConfigurationAdminImpl( this, bundle );
+    }
+    
+    public void ungetService( Bundle bundle, ServiceRegistration registration, Object service )
+    {
+        // For now we do nothing here
+    }
+    
+    public void bundleChanged( BundleEvent event )
+    {
+        if ( event.getType() == BundleEvent.UNINSTALLED )
+        {
+            String uninstalledBundleLocation = event.getBundle().getLocation();
+            existingBundleLocations.remove( uninstalledBundleLocation );
+            findAndUnbindConfigurationsDynamicallyBoundTo( uninstalledBundleLocation );
+        }
+        else if ( event.getType() == BundleEvent.INSTALLED )
+        {
+            String installedBundleLocation = event.getBundle().getLocation();
+            existingBundleLocations.put( installedBundleLocation, installedBundleLocation );
+        }
+    }
+
+    public void serviceChanged( ServiceEvent event )
+    {
+        ServiceReference sr = event.getServiceReference();
+        int eventType = event.getType();
+        String[] objectClasses = (String[]) sr.getProperty( "objectClass" );
+        
+        for ( int ii = 0; ii < objectClasses.length; ++ii )
+        {
+            serviceChanged( sr, eventType, objectClasses[ii] );
+        }
+    }
+
+    private void serviceChanged( ServiceReference sr, int eventType, String objectClass )
+    {
+        if ( ManagedServiceFactory.class.getName().equals( objectClass ) )
+        {
+            managedServiceFactoryChanged( sr, eventType );
+        }
+        else if ( ManagedService.class.getName().equals( objectClass ) )
+        {
+            managedServiceChanged( sr, eventType );
+        }
+        else if ( ConfigurationPlugin.class.getName().equals( objectClass ) )
+        {
+            pluginManager.configurationPluginChanged( sr, eventType );
+        }
+    }
+
+    private void managedServiceFactoryChanged( ServiceReference sr, int eventType )
+    {
+        String factoryPid = (String) sr.getProperty( Constants.SERVICE_PID );
+        
+        switch ( eventType )
+        {
+            case ServiceEvent.REGISTERED:
+                configurationDispatcher.addQueueFor( sr );
+                
+                if ( factoryPid == null )
+                {
+                    String bundleLocation = sr.getBundle().getLocation();
+                    Activator.LOG.error( "ManagedServiceFactory without valid service.pid registered by "
+                                    + bundleLocation );
+                    return;
+                }
+                
+                addToLocationToPidsAndCheck( sr );
+                
+                try
+                {
+                    updateManagedServiceFactory( sr );
+                }
+                catch (IOException e)
+                {
+                    Activator.LOG.error( "Error while notifying services.", e );
+                }
+                
+                break;
+            case ServiceEvent.MODIFIED:
+                break;
+            case ServiceEvent.UNREGISTERING:
+                removeFromLocationToPids( sr );
+                configurationDispatcher.removeQueueFor( sr );
+                break;
+        }
+    }
+
+    private void managedServiceChanged( ServiceReference sr, int eventType )
+    {
+        final String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
+        
+        switch ( eventType )
+        {
+            case ServiceEvent.REGISTERED:
+                configurationDispatcher.addQueueFor( sr );
+            
+                if ( servicePid == null )
+                {
+                    String bundleLocation = sr.getBundle().getLocation();
+                    Activator.LOG.error( "ManagedService without valid service.pid registered by "
+                                    + bundleLocation );
+                    return;
+                }
+                
+                addToLocationToPidsAndCheck( sr );
+                
+                try
+                {
+                    updateManagedService( sr );
+                }
+                catch (IOException e)
+                {
+                    Activator.LOG.error( "Error while notifying services.", e );
+                }
+                
+                break;
+            case ServiceEvent.MODIFIED:
+                break;
+            case ServiceEvent.UNREGISTERING:
+                removeFromLocationToPids( sr );
+                configurationDispatcher.removeQueueFor( sr );
+                break;
+        }
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminImpl.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminImpl.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminImpl.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationAdminImpl.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,162 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * The main purpose of the ConfigurationAdmin interface is to store bundle
+ * configuration data persistently.  This information is represented in
+ * Configuration objects.  The actual configuration data is a Dictionary of
+ * properties inside a Configuration object.
+ */
+class ConfigurationAdminImpl implements ConfigurationAdmin
+{
+    private final ConfigurationAdminFactory factory;
+    private Bundle callingBundle;
+    private String callingBundleLocation;
+
+    ConfigurationAdminImpl( ConfigurationAdminFactory factory, Bundle callingBundle )
+    {
+        this.callingBundle         = callingBundle;
+        this.factory               = factory;
+        this.callingBundleLocation = callingBundle.getLocation();
+    }
+
+    public Configuration createFactoryConfiguration( String factoryPid )
+            throws IOException
+    {
+        return createFactoryConfiguration( factoryPid, callingBundleLocation );
+    }
+
+    public Configuration createFactoryConfiguration( String factoryPid, String location )
+            throws IOException
+    {
+        ConfigurationImpl config = new ConfigurationImpl( factory, location, factoryPid,
+                this.factory.generatePid( factoryPid ) );
+        
+        config.update();
+        
+        return config;
+    }
+
+    public Configuration getConfiguration( String pid ) throws IOException
+    {
+        ConfigurationDictionary d;
+        
+        try
+        {
+            d = factory.load( pid );
+        }
+        catch (IOException e)
+        {
+            d = null;
+        }
+        
+        if ( d == null )
+        {
+            return new ConfigurationImpl( factory, callingBundleLocation, null, pid );
+        }
+        
+        String bundleLocation = (String) d.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        
+        if ( bundleLocation != null
+                && !bundleLocation.equals( callingBundleLocation )
+                && !callingBundle.hasPermission( ConfigurationAdminFactory.ADMIN_PERMISSION ) )
+        {
+            throw new SecurityException( "Not owner of the requested configuration, owned by "
+                                + bundleLocation + " caller is " + callingBundleLocation );
+        }
+        
+        String factoryPid = (String) d.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+        
+        return new ConfigurationImpl( factory, bundleLocation, factoryPid, pid, d );
+    }
+
+    public Configuration getConfiguration( String pid, String location )
+            throws IOException
+    {
+        ConfigurationDictionary dictionary;
+        
+        try
+        {
+            dictionary = this.factory.load( pid );
+        }
+        catch (IOException e)
+        {
+            dictionary = null;
+        }
+        
+        if ( dictionary == null )
+        {
+            ConfigurationImpl c = new ConfigurationImpl( factory, location, null, pid );
+            
+            if ( location != null )
+            {
+                c.setBundleLocation( location );
+            }
+            
+            return c;
+        }
+        
+        String bundleLocation = (String) dictionary.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        String factoryPid = (String) dictionary.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+        
+        return new ConfigurationImpl( factory, bundleLocation, factoryPid, pid, dictionary );
+    }
+
+    public Configuration[] listConfigurations( final String filterString )
+            throws IOException, InvalidSyntaxException
+    {
+        Configuration[] configurations = null;
+        
+        try
+        {
+            configurations = (Configuration[]) AccessController.doPrivileged( new PrivilegedExceptionAction()
+                    {
+                        public Object run() throws IOException,
+                                InvalidSyntaxException
+                        {
+                            return factory.listConfigurations( filterString );
+                        }
+                    } );
+        }
+        catch (PrivilegedActionException e)
+        {
+            configurations = null;
+            
+            if ( e.getException().getClass() == InvalidSyntaxException.class )
+            {
+                throw (InvalidSyntaxException) e.getException();
+            }
+            
+            throw (IOException) e.getException();
+        }
+        
+        return configurations;
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDictionary.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDictionary.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDictionary.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDictionary.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,489 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.lang.reflect.Array;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Vector;
+
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * This class implements the datatype restrictions, and case insensitive lookup,
+ * required of configuration dictionaries in the Configuration Admin.
+ */
+public final class ConfigurationDictionary extends Dictionary
+{
+    /**
+     * Allowed object types.
+     */
+    private final static Map allowedObjectTypes = new HashMap();
+    
+    static
+    {
+        allowedObjectTypes.put( Integer.class, Integer.class );
+        allowedObjectTypes.put( Short.class, Short.class );
+        allowedObjectTypes.put( Long.class, Long.class );
+        allowedObjectTypes.put( String.class, String.class );
+        allowedObjectTypes.put( Float.class, Float.class );
+        allowedObjectTypes.put( Double.class, Double.class );
+        allowedObjectTypes.put( Byte.class, Byte.class );
+        allowedObjectTypes.put( Character.class, Character.class );
+        allowedObjectTypes.put( Boolean.class, Boolean.class );
+    }
+
+    /**
+     * Allowed primitive types in arrays.
+     */
+    private final static Map allowedPrimitiveTypes = new HashMap();
+    
+    static
+    {
+        allowedPrimitiveTypes.put( Integer.TYPE, Integer.TYPE );
+        allowedPrimitiveTypes.put( Short.TYPE, Short.TYPE );
+        allowedPrimitiveTypes.put( Long.TYPE, Long.TYPE );
+        allowedPrimitiveTypes.put( Float.TYPE, Float.TYPE );
+        allowedPrimitiveTypes.put( Double.TYPE, Double.TYPE );
+        allowedPrimitiveTypes.put( Byte.TYPE, Byte.TYPE );
+        allowedPrimitiveTypes.put( Character.TYPE, Character.TYPE );
+        allowedPrimitiveTypes.put( Boolean.TYPE, Boolean.TYPE );
+    }
+
+    private final static Hashtable classToPrimitiveType = new Hashtable();
+    
+    static
+    {
+        classToPrimitiveType.put( Integer.class, Integer.TYPE );
+        classToPrimitiveType.put( Short.class, Short.TYPE );
+        classToPrimitiveType.put( Long.class, Long.TYPE );
+        classToPrimitiveType.put( Float.class, Float.TYPE );
+        classToPrimitiveType.put( Double.class, Double.TYPE );
+        classToPrimitiveType.put( Byte.class, Byte.TYPE );
+        classToPrimitiveType.put( Character.class, Character.TYPE );
+        classToPrimitiveType.put( Boolean.class, Boolean.TYPE );
+    }
+
+    /**
+     * Mapping of keys in lowercase to the case they had when added to the
+     * dictionary.
+     */
+    final Hashtable lowercaseToOriginalCase;
+
+    /**
+     * A dictionary holding the key-value pairs of the configuration with
+     * the keys in the original case they were entered in.
+     */
+    final Hashtable originalCase;
+
+    public ConfigurationDictionary()
+    {
+        this( new Hashtable() );
+    }
+
+    /**
+     * Construct a ConfigurationDictionary given an ordinary Dictionary.
+     * 
+     * @param dictionary The original dictionary.
+     */
+    public ConfigurationDictionary( Hashtable dictionary )
+    {
+        this.lowercaseToOriginalCase = new Hashtable();
+        this.originalCase = dictionary;
+        updateLowercaseToOriginalCase();
+    }
+
+    private ConfigurationDictionary( ConfigurationDictionary original )
+    {
+        this.originalCase = copyDictionary( original.originalCase );
+        this.lowercaseToOriginalCase = (Hashtable) original.lowercaseToOriginalCase.clone();
+    }
+
+    public Enumeration elements()
+    {
+        return originalCase.elements();
+    }
+
+    public Object get( Object key )
+    {
+        Object val = originalCase.get( key );
+
+        if ( val != null )
+        {
+            return val;
+        }
+
+        String lowercaseKey = ( (String) key ).toLowerCase();
+        String originalCaseKey = (String) lowercaseToOriginalCase.get( lowercaseKey );
+        
+        if ( originalCaseKey != null )
+        {
+            key = originalCaseKey;
+        }
+
+        val = originalCase.get( key );
+
+        return val;
+    }
+
+    public boolean isEmpty()
+    {
+        return originalCase.isEmpty();
+    }
+
+    public Enumeration keys()
+    {
+        return originalCase.keys();
+    }
+
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer( getClass().getName() + " [ " );
+        
+        for ( Enumeration e = keys(); e.hasMoreElements(); )
+        {
+            Object key = e.nextElement();
+            Object val = get( key );
+
+            sb.append( key + "=" + val );
+            if ( e.hasMoreElements() )
+            {
+                sb.append( ", " );
+            }
+        }
+        
+        sb.append( " ]" );
+        
+        return sb.toString();
+    }
+
+    public Object put( Object key, Object value )
+    {
+        String lowercaseKey = ( (String) key ).toLowerCase();
+        String originalCaseKey = (String) lowercaseToOriginalCase.get( lowercaseKey );
+        
+        if (originalCaseKey != null)
+        {
+            key = originalCaseKey;
+        }
+        
+        Object o = originalCase.put( key, value );
+        
+        if ( originalCaseKey == null )
+        {
+            updateLowercaseToOriginalCase( (String) key );
+        }
+        
+        return o;
+    }
+
+    public Object remove(Object key)
+    {
+        String lowercaseKey = ( (String) key ).toLowerCase();
+        
+        if ( !lowercaseToOriginalCase.containsKey( lowercaseKey ) )
+        {
+            return null;
+        }
+
+        String originalCaseKey = (String) lowercaseToOriginalCase.remove( lowercaseKey );
+        
+        return originalCase.remove( originalCaseKey );
+    }
+
+    public int size()
+    {
+        return originalCase.size();
+    }
+
+    Hashtable getOriginal()
+    {
+        return originalCase;
+    }
+
+    ConfigurationDictionary createCopy()
+    {
+        return new ConfigurationDictionary( this );
+    }
+
+    ConfigurationDictionary createCopyAndRemoveLocation()
+    {
+        ConfigurationDictionary cd = createCopy();
+        cd.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        cd.remove( ConfigurationAdminFactory.DYNAMIC_BUNDLE_LOCATION );
+        
+        return cd;
+    }
+    
+    private void updateLowercaseToOriginalCase()
+    {
+        Enumeration keys = originalCase.keys();
+        
+        while ( keys.hasMoreElements() )
+        {
+            String originalKey = (String) keys.nextElement();
+            updateLowercaseToOriginalCase( originalKey );
+        }
+    }
+
+    private void updateLowercaseToOriginalCase( String originalKey )
+    {
+        if ( originalKey == null )
+        {
+            return;
+        }
+        
+        String lowercaseKey = originalKey.toLowerCase();
+        
+        if ( !lowercaseToOriginalCase.containsKey( lowercaseKey ) )
+        {
+            lowercaseToOriginalCase.put( lowercaseKey, originalKey );
+        }
+    }
+
+    static public ConfigurationDictionary createDeepCopy( Dictionary in )
+    {
+        Hashtable h = copyDictionary( in );
+        return new ConfigurationDictionary( h );
+    }
+
+    static public Hashtable copyDictionary( Dictionary in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+
+        Hashtable out = new Hashtable();
+        Enumeration keys = in.keys();
+        
+        while ( keys.hasMoreElements() )
+        {
+            Object key     = keys.nextElement();
+            Object origVal = in.get( key );
+            Object val     = copyValue( origVal );
+
+            String s = (String) key;
+            String lower = s.toLowerCase();
+            
+            if ( !s.equals( lower ) )
+            {
+                Object lowerVal = in.get( lower );
+                
+                if ( null != lowerVal )
+                {
+                    key = lower;
+                }
+            }
+            out.put( key, val );
+        }
+        return out;
+    }
+
+    static private Object copyValue( Object in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+        
+        if ( in.getClass().isArray() )
+        {
+            return copyArray( in );
+        }
+        else if ( in instanceof Vector )
+        {
+            return copyVector( (Vector) in );
+        }
+        else
+        {
+            return in;
+        }
+    }
+
+    static private Vector copyVector( Vector in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+        
+        Vector out = new Vector();
+        Enumeration elements = in.elements();
+        
+        while ( elements.hasMoreElements() )
+        {
+            out.addElement( copyValue( elements.nextElement() ) );
+        }
+        
+        return out;
+    }
+
+    static private Object copyArray( Object in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+        
+        int length = Array.getLength( in );
+        
+        Object out = Array.newInstance( in.getClass().getComponentType(), length );
+        
+        for ( int ii = 0; ii < length; ++ii )
+        {
+            Array.set( out, ii, copyValue( Array.get( in, ii ) ) );
+        }
+        
+        return out;
+    }
+
+    static void validateDictionary( Dictionary dictionary )
+            throws IllegalArgumentException
+    {
+        if ( dictionary == null )
+        {
+            return;
+        }
+
+        Enumeration keys = dictionary.keys();
+        
+        while ( keys.hasMoreElements() )
+        {
+            Object key = keys.nextElement();
+            
+            if ( key.getClass() != String.class )
+            {
+                throw new IllegalArgumentException( "The key " + key
+                        + " is not of type java.lang.String." );
+            }
+            
+            try
+            {
+                validateValue( dictionary.get( key ) );
+            }
+            catch (IllegalArgumentException e)
+            {
+                throw new IllegalArgumentException( "The value for key " + key
+                        + " is not of correct type: " + e.getMessage() );
+            }
+        }
+    }
+
+    static private void validateValue( Object value )
+            throws IllegalArgumentException
+    {
+        if ( value == null )
+        {
+            return;
+        }
+
+        Class valueClass = value.getClass();
+        
+        if ( valueClass.isArray() )
+        {
+            validateArray( value );
+        }
+        else if ( valueClass == Vector.class )
+        {
+            validateVector( (Vector) value );
+        }
+        else
+        {
+            if ( !allowedObjectTypes.containsKey( valueClass ) )
+            {
+                throw new IllegalArgumentException( valueClass.toString()
+                        + " is not an allowed type." );
+            }
+        }
+    }
+
+    static private void validateArray( Object array )
+    {
+        Class componentType = array.getClass().getComponentType();
+        
+        int length = Array.getLength( array );
+        
+        if ( componentType.isArray() || componentType == Vector.class )
+        {
+            for ( int ii = 0; ii < length; ++ii )
+            {
+                Object o = Array.get( array, ii );
+                
+                if ( o != null )
+                {
+                    Class objectClass = o.getClass();
+                    
+                    if ( objectClass != componentType )
+                    {
+                        throw new IllegalArgumentException(
+                                "Objects with different type in array. " + "Found "
+                                + objectClass.toString() + " " + "Expected "
+                                + componentType.toString() );
+                    }
+                    validateValue( o );
+                }
+            }
+        }
+        else
+        {
+            if ( !allowedPrimitiveTypes.containsKey( componentType )
+                    && !allowedObjectTypes.containsKey( componentType ) )
+            {
+                throw new IllegalArgumentException( "Illegal component type for arrays: "
+                                + componentType.toString() );
+            }
+            
+            for ( int ii = 0; ii < length; ++ii )
+            {
+                Object o = Array.get( array, ii );
+                
+                if ( o != null )
+                {
+                    Class objectClass = o.getClass();
+                    
+                    if ( componentType.isPrimitive() )
+                    {
+                        objectClass = (Class) classToPrimitiveType.get( objectClass );
+                    }
+                    
+                    if ( objectClass != componentType )
+                    {
+                        throw new IllegalArgumentException(
+                                "Objects with different type in array. " + "Found "
+                                + objectClass.toString() + " " + "Expected "
+                                + componentType.toString() );
+                    }
+                }
+            }
+        }
+    }
+
+    static private void validateVector( Vector vector )
+    {
+        for ( int ii = 0; ii < vector.size(); ++ii )
+        {
+            Object element = vector.elementAt( ii );
+            validateValue( element );
+        }
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDispatcher.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDispatcher.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDispatcher.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationDispatcher.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,131 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.util.Hashtable;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * This class is responsible for dispatching configurations to
+ * ManagedService(Factories).  It is also responsible for calling
+ * <code>ConfigurationPlugins</code>.
+ */
+final class ConfigurationDispatcher
+{
+    /**
+     * The PluginManager to use.
+     */
+    private PluginManager pm;
+
+    /**
+     * One queue per target service.
+     */
+    private Hashtable serviceReferenceToTargetService = new Hashtable();
+
+    private Hashtable targetServiceToQueue = new Hashtable();
+
+    /**
+     * Construct a ConfigurationDispatcher given a ConfigurationServicesTracker.
+     * 
+     * @param tracker The ConfigurationServicesTracker to use.
+     */
+    ConfigurationDispatcher( PluginManager pm )
+    {
+        this.pm = pm;
+    }
+
+    public UpdateQueue getQueueFor( ServiceReference sr )
+    {
+        synchronized ( targetServiceToQueue )
+        {
+            Object targetService = serviceReferenceToTargetService.get( sr );
+            
+            if ( targetService == null )
+            {
+                return null;
+            }
+            
+            return (UpdateQueue) targetServiceToQueue.get( targetService );
+        }
+    }
+
+    public void addQueueFor( ServiceReference sr )
+    {
+        synchronized ( targetServiceToQueue )
+        {
+            Object targetService = serviceReferenceToTargetService.get( sr );
+            
+            if ( targetService == null )
+            {
+                targetService = Activator.bc.getService( sr );
+                
+                if ( targetService == null )
+                {
+                    Activator.LOG.error( "Failed getting target service to build new queue for." );
+                    return;
+                }
+                serviceReferenceToTargetService.put( sr, targetService );
+            }
+            
+            if ( !targetServiceToQueue.containsKey( targetService ) )
+            {
+                targetServiceToQueue.put( targetService, new UpdateQueue( pm ) );
+            }
+        }
+    }
+
+    public void removeQueueFor( ServiceReference sr )
+    {
+        synchronized ( targetServiceToQueue )
+        {
+            Object targetService = serviceReferenceToTargetService.remove( sr );
+            
+            if ( targetService == null )
+            {
+                Activator.LOG.error( "Missing target service for a ServiceReference in removeQueueFor(ServiceReference)" );
+            }
+            else if ( !serviceReferenceToTargetService.contains( targetService ) )
+            {
+                UpdateQueue uq = (UpdateQueue) targetServiceToQueue.remove( targetService );
+                
+                if ( uq == null )
+                {
+                    Activator.LOG.error( "Missing UpdateQueue for a ServiceReference in removeQueueFor(ServiceReference)" );
+                }
+            }
+        }
+    }
+
+    public void dispatchUpdateFor( ServiceReference sr, String pid,
+            String factoryPid, ConfigurationDictionary cd )
+    {
+        UpdateQueue uq = getQueueFor( sr );
+        
+        if ( uq == null )
+        {
+            Activator.LOG.error( "Missing UpdateQueue for " + factoryPid );
+            return;
+        }
+        
+        Update u = new Update( sr, pid, factoryPid, cd );
+
+        uq.enqueue( u );
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationImpl.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationImpl.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationImpl.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationImpl.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,220 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * The configuration information for a ManagedService
+ * or ManagedServiceFactory object.
+ */
+class ConfigurationImpl implements Configuration
+{
+    private final ConfigurationAdminFactory factory;
+    private final String factoryPid;
+    private final String servicePid;
+    
+    private String bundleLocation;
+    private boolean deleted = false;
+    
+    private ConfigurationDictionary properties;
+    
+    ConfigurationImpl( ConfigurationAdminFactory factory, String bundleLocation, String factoryPid, String servicePid )
+    {
+        this( factory, bundleLocation, factoryPid, servicePid, null );
+    }
+
+    ConfigurationImpl( ConfigurationAdminFactory factory, String bundleLocation, String factoryPid,
+            String servicePid, ConfigurationDictionary properties )
+    {
+        this.bundleLocation = bundleLocation;
+        this.factory        = factory;
+        this.factoryPid     = factoryPid;
+        this.servicePid     = servicePid;
+        this.properties     = properties;
+        
+        if ( this.properties == null )
+        {
+            this.properties = new ConfigurationDictionary();
+        }
+    }
+
+    ConfigurationImpl( ConfigurationAdminFactory factory, ConfigurationDictionary properties )
+    {
+        this.bundleLocation = (String) properties.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        this.factoryPid     = (String) properties.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+        this.servicePid     = (String) properties.get( Constants.SERVICE_PID);
+        
+        this.factory        = factory;
+        this.properties     = properties;
+    }
+
+    public void delete() throws IOException
+    {
+        throwIfDeleted();
+        factory.delete( this );
+        deleted = true;
+    }
+
+    public String getBundleLocation()
+    {
+        throwIfDeleted();
+        return bundleLocation;
+    }
+
+    public String getFactoryPid()
+    {
+        throwIfDeleted();
+        return factoryPid;
+    }
+
+    public String getPid()
+    {
+        throwIfDeleted();
+        return servicePid;
+    }
+
+    public Dictionary getProperties()
+    {
+        throwIfDeleted();
+        
+        if ( properties == null )
+        {
+            return null;
+        }
+        
+        return properties.createCopyAndRemoveLocation();
+    }
+    
+    public ConfigurationDictionary getConfigurationDictionary()
+    {
+        return properties;
+    }
+
+    public void setBundleLocation( String bundleLocation )
+    {
+        throwIfDeleted();
+        
+        this.bundleLocation = bundleLocation;
+        
+        ConfigurationDictionary old = properties;
+        
+        if ( properties == null )
+        {
+            properties = new ConfigurationDictionary();
+        }
+        else
+        {
+            properties = properties.createCopy();
+        }
+        
+        properties.remove( ConfigurationAdminFactory.DYNAMIC_BUNDLE_LOCATION );
+        
+        if ( bundleLocation == null )
+        {
+            properties.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        }
+        else
+        {
+            properties.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, bundleLocation );
+        }
+        
+        try
+        {
+            update();
+        }
+        catch (IOException e)
+        {
+            properties = old;
+        }
+    }
+    
+    public void update( Dictionary properties ) throws IOException
+    {
+        throwIfDeleted();
+        
+        ConfigurationDictionary.validateDictionary( properties );
+
+        ConfigurationDictionary old = this.properties;
+
+        if ( properties == null )
+        {
+            properties = new ConfigurationDictionary();
+        }
+        else
+        {
+            properties = ConfigurationDictionary.createDeepCopy( properties );
+        }
+
+        try
+        {
+            update();
+        }
+        catch (IOException e)
+        {
+            properties = old;
+            throw e;
+        }
+        catch (Exception e)
+        {
+            Activator.LOG.error( "Error while updating properties.", e );
+            properties = old;
+        }
+    }
+    
+    public void update() throws IOException
+    {
+        throwIfDeleted();
+        ensureAutoPropertiesAreWritten();
+        factory.update( this );
+    }
+    
+    void ensureAutoPropertiesAreWritten()
+    {
+        if ( properties == null )
+        {
+            return;
+        }
+        
+        this.properties.put( Constants.SERVICE_PID, getPid() );
+        
+        if ( getFactoryPid() != null )
+        {
+            this.properties.put( ConfigurationAdmin.SERVICE_FACTORYPID, getFactoryPid() );
+        }
+        
+        if ( getBundleLocation() != null )
+        {
+            this.properties.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, getBundleLocation() );
+        }
+    }
+
+    private void throwIfDeleted()
+    {
+        if ( deleted )
+        {
+            throw new IllegalStateException( "Configuration for " + servicePid + " has been deleted." );
+        }
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStore.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStore.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStore.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStore.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,47 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+
+public interface ConfigurationStore
+{
+    public abstract Enumeration listPids();
+
+    public abstract ConfigurationDictionary load( String pid )
+    		throws IOException;
+
+    public abstract ConfigurationDictionary[] loadAll( String factoryPid )
+            throws IOException;
+
+    public abstract void store( String pid, String factoryPid, Dictionary configuration )
+    		throws IOException;
+
+    public abstract ConfigurationDictionary delete( String pid )
+            throws IOException;
+
+    public abstract void deleteAll( String factoryPid )
+    		throws IOException;
+
+    public abstract String generatePid( String factoryPid )
+    		throws IOException;
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStoreFactory.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStoreFactory.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStoreFactory.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/ConfigurationStoreFactory.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,50 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+/**
+ * Factory class for the <code>ConfigurationStore</code> package.
+ * Use this instead of instantiating classes directly.
+ */
+public class ConfigurationStoreFactory
+{
+    /**
+     * Process administrators should specify the concrete
+     * implementation class to use by setting the
+     * <code>contacts.impl.SimpleContactFinder</code> property,
+     * and specify the class loader to use by setting
+     * the context class loader.
+     */
+    public ConfigurationStore getDefaultFinder()
+    {
+        try
+        {
+            String className = System.getProperty( "contacts.FinderClass",
+                    "contacts.impl.SimpleContactFinder" );
+            Class clazz = Class.forName( className, true, Thread.currentThread().getContextClassLoader() );
+            
+            return (ConfigurationStore) clazz.newInstance();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            throw new Error( "Default Finder not available" );
+        }
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Logger.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Logger.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Logger.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Logger.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,104 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Logger is a utility class for logging to the OSGi LogService.
+ */
+public class Logger
+{
+    private ServiceTracker   tracker;
+    private ServiceReference reference;
+
+    void start( BundleContext context )
+    {
+        if ( tracker == null )
+        {
+            tracker = new ServiceTracker( context, LogService.class.getName(), null );
+            tracker.open();
+        }
+    }
+
+    void stop()
+    {
+        tracker.close();
+        tracker = null;
+    }
+
+    void setServiceReference( ServiceReference sr )
+    {
+        this.reference = sr;
+    }
+
+    void error( String message )
+    {
+        log( LogService.LOG_ERROR, message, null );
+    }
+
+    void error( String message, Throwable exception )
+    {
+        log( LogService.LOG_ERROR, message, exception );
+    }
+
+    void warning( String message )
+    {
+        log( LogService.LOG_WARNING, message, null );
+    }
+
+    void warning( String message, Throwable exception )
+    {
+        log( LogService.LOG_WARNING, message, exception );
+    }
+
+    void info( String message )
+    {
+        log( LogService.LOG_INFO, message, null );
+    }
+
+    void info( String message, Throwable exception )
+    {
+        log( LogService.LOG_INFO, message, exception );
+    }
+
+    public void log( int level, String message, Throwable exception )
+    {
+        Object[] services = null;
+        if ( tracker != null )
+        {
+            services = tracker.getServices();
+        }
+        
+        if ( services != null )
+        {
+            for ( int ii = 0; ii < services.length; ++ii )
+            {
+                Object service = services[ii];
+                if ( service instanceof LogService )
+                {
+                    ( (LogService) service ).log( reference, level, message, exception );
+                }
+            }
+        }
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/PluginManager.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/PluginManager.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/PluginManager.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/PluginManager.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,295 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationPlugin;
+
+/**
+ * This class is responsible for managing ConfigurationPlugins.
+ */
+final class PluginManager
+{
+    private final static String CM_RANKING = "service.cmRanking";
+    private final static String CM_TARGET  = ConfigurationPlugin.CM_TARGET;
+
+    /**
+     * Sorted Vector of ServiceReferences to ConfigurationPlugins.
+     */
+    Vector preModificationPlugins = new Vector();
+
+    /**
+     * Sorted Vector of ServiceReferences to ConfigurationPlugins.
+     */
+    Vector modifyingPlugins = new Vector();
+
+    /**
+     * Sorted Vector of ServiceReferences to ConfigurationPlugins.
+     */
+    Vector postModificationPlugins = new Vector();
+
+    /**
+     * Hashtable mapping a ServiceReference to its ranking (Integer).
+     */
+    Hashtable rankings = new Hashtable();
+    
+    /**
+     * Handle ConfigurationPlugin ServiceEvents.
+     * 
+     * @param serviceReference ServiceReference of the plugin the event concerns
+     * @param eventType Type of the event that caused the change
+     */
+    public synchronized void configurationPluginChanged(
+            ServiceReference serviceReference, int eventType )
+    {
+        Object rankingProperty = serviceReference.getProperty( CM_RANKING );
+        
+        if ( rankingProperty == null )
+        {
+            rankingProperty = new Integer(0);
+        }
+        else if ( rankingProperty.getClass() != Integer.class )
+        {
+            rankingProperty = new Integer(0);
+        }
+
+        Long serviceId = (Long) serviceReference.getProperty( Constants.SERVICE_ID );
+        
+        if ( serviceId == null )
+        {
+            Activator.LOG.error( "Missing service id for a ConfigurationPlugin" );
+            return;
+        }
+
+        int ranking = ( (Integer)rankingProperty ).intValue();
+
+        switch ( eventType )
+        {
+            case ServiceEvent.REGISTERED:
+                rankings.put( serviceId, rankingProperty );
+                insertPluginReference( serviceReference, ranking );
+                break;
+            case ServiceEvent.MODIFIED:
+                int oldRanking = ( (Integer)rankings.get( serviceId ) ).intValue();
+            
+                if ( ranking == oldRanking )
+                {
+                    return;
+                }
+                
+                removePluginReference( serviceId, oldRanking );
+                rankings.put( serviceId, rankingProperty );
+                insertPluginReference( serviceReference, ranking );
+                break;
+            case ServiceEvent.UNREGISTERING:
+                rankings.remove( serviceId );
+                removePluginReference( serviceId, ranking );
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Insert a ServiceReference to a ConfigurationPlugin in the correct
+     * Vector based on its ranking.
+     * 
+     * @param serviceReference The ServiceReference.
+     * @param ranking The ranking the ServiceReference.
+     */
+    private void insertPluginReference( ServiceReference serviceReference, int ranking )
+    {
+        if ( ranking < 0 )
+        {
+            insertPluginReference( serviceReference, ranking, preModificationPlugins );
+        }
+        else if ( 0 <= ranking && ranking <= 1000 )
+        {
+            insertPluginReference( serviceReference, ranking, modifyingPlugins );
+        }
+        else if ( ranking > 1000 )
+        {
+            insertPluginReference( serviceReference, ranking, postModificationPlugins );
+        }
+    }
+
+    /**
+     * Insert a ServiceReference in a Vector sorted on cm.ranking property.
+     * 
+     * @param serviceReference The ServiceReference.
+     * @param pluginsVector The vector.
+     */
+    private void insertPluginReference( ServiceReference serviceReference,
+            int ranking, Vector pluginsVector )
+    {
+        int ii;
+        
+        for ( ii = 0; ii < pluginsVector.size(); ++ii )
+        {
+            ServiceReference nextReference = (ServiceReference) pluginsVector.elementAt(ii);
+            Long serviceId = (Long) nextReference.getProperty( Constants.SERVICE_ID );
+            Integer rankingOfNextReference = (Integer) rankings.get( serviceId );
+            
+            if ( ranking < rankingOfNextReference.intValue() )
+            {
+                break;
+            }
+        }
+        
+        pluginsVector.insertElementAt( serviceReference, ii );
+    }
+
+    /**
+     * Remove a ServiceReference to a ConfigurationPlugin given a service.id
+     * and a ranking.
+     * 
+     * @param serviceId The service.id of the ConfigurationPlugin.
+     * @param ranking The ranking of the ConfigurationPlugin.
+     */
+    private void removePluginReference( Object serviceId, int ranking )
+    {
+        if ( ranking < 0 )
+        {
+            removePluginReference( serviceId, preModificationPlugins );
+        }
+        else if ( 0 <= ranking && ranking <= 1000 )
+        {
+            removePluginReference( serviceId, modifyingPlugins );
+        }
+        else if ( ranking > 1000 )
+        {
+            removePluginReference( serviceId, postModificationPlugins );
+        }
+    }
+
+    private void removePluginReference( Object serviceId, Vector pluginsVector )
+    {
+        for ( int ii = 0; ii < pluginsVector.size(); ++ii )
+        {
+            ServiceReference serviceReference = (ServiceReference) pluginsVector.elementAt(ii);
+            
+            Long currentId = (Long) serviceReference.getProperty( Constants.SERVICE_ID );
+            
+            if ( currentId.equals( serviceId ) )
+            {
+                pluginsVector.removeElementAt( ii );
+                return;
+            }
+        }
+    }
+
+    /**
+     * Call all applicable ConfigurationPlugins given a pid and a dictionary.
+     * 
+     * @param pid The pid of the target ManagedService(Factory).
+     * @param dictionary The configuration dictionary to be modified.
+     * @return The description of what the method returns.
+     */
+    public synchronized ConfigurationDictionary callPluginsAndCreateACopy(
+            ServiceReference targetServiceReference,
+            ConfigurationDictionary dictionary )
+    {
+        if ( targetServiceReference == null )
+        {
+            return dictionary;
+        }
+        
+        if ( dictionary == null )
+        {
+            return null;
+        }
+        
+        callPlugins( targetServiceReference, dictionary, preModificationPlugins, false );
+
+        dictionary = callPlugins( targetServiceReference, dictionary, modifyingPlugins, true );
+
+        callPlugins( targetServiceReference, dictionary, postModificationPlugins, false );
+
+        if ( dictionary != null )
+        {
+            dictionary = dictionary.createCopyAndRemoveLocation();
+        }
+        
+        return dictionary;
+    }
+
+    /**
+     * Call all plugins contained in a Vector and optionally allow
+     * modifications.
+     * 
+     * @param targetServiceReference Reference to the target ManagedService(Factory).
+     * @param dictionary The configuration dictionary to process.
+     * @param plugins Vector of references to ConfigurationPlugins.
+     * @param allowModification Should modifications to the configuration dictionary be
+     *            allowed.
+     * @return The modified configuration dictionary.
+     */
+    private ConfigurationDictionary callPlugins( ServiceReference targetServiceReference,
+            ConfigurationDictionary dictionary, Vector plugins, boolean allowModification )
+    {
+        String pid = (String) targetServiceReference.getProperty( Constants.SERVICE_PID );
+        ConfigurationDictionary currentDictionary = dictionary;
+        Enumeration e = plugins.elements();
+        
+        while ( e.hasMoreElements() )
+        {
+            ServiceReference pluginReference = (ServiceReference) e.nextElement();
+
+            // Only call the plugin if no cm.target is specified or if it
+            // matches the pid of the target service
+            String cmTarget = (String) pluginReference.getProperty( CM_TARGET );
+            
+            if ( cmTarget == null || cmTarget.equals( pid ) )
+            {
+                ConfigurationPlugin plugin = (ConfigurationPlugin) Activator.bc.getService( pluginReference );
+                
+                if ( plugin == null )
+                {
+                    continue;
+                }
+                
+                ConfigurationDictionary dictionaryCopy = currentDictionary.createCopyAndRemoveLocation();
+                
+                try
+                {
+                    plugin.modifyConfiguration( targetServiceReference, dictionaryCopy );
+                    
+                    ConfigurationDictionary.validateDictionary( dictionary );
+                    
+                    if ( allowModification )
+                    {
+                        currentDictionary = dictionaryCopy;
+                    }
+                }
+                catch (Exception exception)
+                {
+                    Activator.LOG.error( "Exception thrown by plugin: " + exception.getMessage() );
+                }
+            }
+        }
+        
+        return currentDictionary;
+    }
+}
+

Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Update.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Update.java?rev=209428&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Update.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/Update.java Wed Jul  6 01:02:09 2005
@@ -0,0 +1,111 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed 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.configuration;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+final class Update
+{
+    final ServiceReference sr;
+    final String pid;
+    final String factoryPid;
+    final ConfigurationDictionary configuration;
+    ConfigurationDictionary processedConfiguration = null;
+
+    public Update( ServiceReference sr, String pid, String factoryPid,
+            ConfigurationDictionary configuration )
+    {
+        this.sr            = sr;
+        this.pid           = pid;
+        this.factoryPid    = factoryPid;
+        this.configuration = configuration;
+    }
+
+    public void doUpdate( PluginManager pm ) throws ConfigurationException
+    {
+        if ( sr == null )
+        {
+            return;
+        }
+        
+        Object targetService = getTargetService();
+        
+        if ( targetService == null )
+        {
+            return;
+        }
+        
+        processedConfiguration = pm.callPluginsAndCreateACopy( sr, configuration );
+        
+        if ( factoryPid == null )
+        {
+            update( (ManagedService) targetService );
+        }
+        else
+        {
+            update( (ManagedServiceFactory) targetService );
+        }
+    }
+
+    private void update( ManagedService targetService )
+            throws ConfigurationException
+    {
+        if ( targetService == null )
+        {
+            return;
+        }
+        
+        targetService.updated( processedConfiguration );
+    }
+
+    private void update( ManagedServiceFactory targetService )
+            throws ConfigurationException
+    {
+        if ( targetService == null )
+        {
+            return;
+        }
+        
+        if ( configuration == null )
+        {
+            targetService.deleted( pid );
+        }
+        else if ( processedConfiguration == null )
+        {
+            targetService.updated( pid, null );
+        }
+        else
+        {
+            targetService.updated( pid, configuration );
+        }
+    }
+
+    private Object getTargetService()
+    {
+        if ( sr == null )
+        {
+            return null;
+        }
+        
+        return Activator.bc.getService( sr );
+    }
+}
+



Mime
View raw message