You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2005/09/21 12:16:02 UTC
svn commit: r290673 - in
/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration:
./ impl/
Author: erodriguez
Date: Wed Sep 21 03:15:53 2005
New Revision: 290673
URL: http://svn.apache.org/viewcvs?rev=290673&view=rev
Log:
Refactoring in the OSGi Config Admin service:
o introduction of event queue for asynchronous update dispatching per the OSGi spec
o more formal producer-consumer
Added:
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java (with props)
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateConsumer.java (with props)
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateEvent.java (with props)
Modified:
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationAdminFactory.java
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/PluginManager.java
directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/metadata.xml
Modified: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationAdminFactory.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationAdminFactory.java?rev=290673&r1=290672&r2=290673&view=diff
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationAdminFactory.java (original)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationAdminFactory.java Wed Sep 21 03:15:53 2005
@@ -17,29 +17,21 @@
package org.apache.configuration.impl;
-import java.io.IOException;
-import java.util.ArrayList;
import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import javax.naming.spi.InitialContextFactory;
import org.apache.configuration.ConfigurationListener;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
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;
import org.slf4j.Logger;
@@ -50,26 +42,22 @@
/**
* ConfigurationAdmin implementation
*/
-public class ConfigurationAdminFactory implements ServiceFactory, ServiceListener, BundleListener, Lifecycle
+public class ConfigurationAdminFactory implements ServiceFactory, Lifecycle
{
/** the log for this class */
private static final Logger log = LoggerFactory.getLogger( ConfigurationAdminFactory.class );
- private static final String ANY_LOCATION = "*";
- private static final String FILTER = "(|(objectClass=" + ManagedServiceFactory.class.getName() + ")"
- + "(objectClass=" + ManagedService.class.getName() + ")" + "(objectClass="
- + ConfigurationPlugin.class.getName() + "))";
-
public static final String DYNAMIC_BUNDLE_LOCATION = "dynamic.service.bundleLocation";
- private Hashtable locationToPids = new Hashtable();
- private Hashtable existingBundleLocations = new Hashtable();
- private JndiConfigurationStore store;
+ private BlockingQueue<UpdateEvent> queue = new LinkedBlockingQueue<UpdateEvent>();
private PluginManager pluginManager;
- private ConfigurationDispatcher configurationDispatcher;
+ private UpdateConsumer updateConsumer;
+ private Thread updateThread;
+
private InitialContextFactory factory;
+ private JndiConfigurationStore store;
- public static BundleContext bc;
+ public BundleContext bc;
public ConfigurationAdminFactory( ServiceBinderContext sbc )
{
@@ -86,23 +74,12 @@
store = new JndiConfigurationStore( factory );
setConfigurationListener();
- pluginManager = new PluginManager();
-
- configurationDispatcher = new ConfigurationDispatcher( pluginManager );
-
- lookForExistingBundleLocations();
-
- try
- {
- bc.addServiceListener( this, FILTER );
- bc.addBundleListener( this );
- }
- catch ( InvalidSyntaxException ise )
- {
- log.error( ise.getMessage(), ise );
- }
+ pluginManager = new PluginManager( bc );
- lookForAlreadyRegisteredServices();
+ updateConsumer = new UpdateConsumer( bc, store, pluginManager, queue );
+ updateThread = new Thread( updateConsumer, "Update Consumer" );
+ updateThread.setDaemon( true );
+ updateThread.start();
}
/**
@@ -111,273 +88,98 @@
*/
public void deactivate()
{
+ updateThread.interrupt();
store.deactivate();
}
- public String getName()
- {
- return "Apache Configuration Admin Service Factory";
- }
-
public void setInitialContextFactory( InitialContextFactory factory )
{
this.factory = factory;
- log.debug( getName() + " has bound to " + factory );
+ log.debug( "Binding to " + factory );
}
public void unsetInitialContextFactory( InitialContextFactory factory )
{
this.factory = null;
- log.debug( getName() + " has unbound from " + factory );
- }
-
- public Object getService( Bundle bundle, ServiceRegistration registration )
- {
- log.debug( getName() + " has received a ServiceFactory.getService() call" );
- return new ConfigurationAdminImpl( store, bundle );
- }
-
- public void ungetService( Bundle bundle, ServiceRegistration registration, Object service )
- {
- log.debug( getName() + " has received a ServiceFactory.ungetService() call" );
- // For now we do nothing here
+ log.debug( "Unbinding from " + factory );
}
- public void bundleChanged( BundleEvent event )
+ public void setManagedServiceFactory( ServiceReference sr, ManagedServiceFactory factory )
{
- 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 );
- }
- }
+ String location = sr.getBundle().getLocation();
+ String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
- public void serviceChanged( ServiceEvent event )
- {
- ServiceReference sr = event.getServiceReference();
- int eventType = event.getType();
- String[] objectClasses = (String[]) sr.getProperty( "objectClass" );
+ log.debug( "Binding to factory " + factory + " (" + servicePid + ") from " + location );
- for ( int ii = 0; ii < objectClasses.length; ++ii )
+ if ( servicePid == null )
{
- serviceChanged( sr, eventType, objectClasses[ ii ] );
+ log.error( "ManagedServiceFactory without valid service.pid registered by " + location );
+ return;
}
- }
- private void setConfigurationListener()
- {
- store.setConfigurationListener( new ConfigurationListener()
- {
- public void configurationChanged( Dictionary configuration )
- {
- try
- {
- updateTargetServicesMatching( new ConfigurationDictionary( configuration ) );
- }
- catch ( IOException ioe )
- {
- log.error( ioe.getMessage(), ioe );
- }
- }
- } );
+ dispatchUpdateEvent( sr, UpdateEvent.FACTORY_REGISTERING, servicePid );
}
- private void lookForAlreadyRegisteredServices()
+ public void unsetManagedServiceFactory( ServiceReference sr, ManagedServiceFactory factory )
{
- notifyRegisteredServices( ConfigurationPlugin.class.getName() );
- notifyRegisteredServices( ManagedServiceFactory.class.getName() );
- notifyRegisteredServices( ManagedService.class.getName() );
- }
-
- private void notifyRegisteredServices( String className )
- {
- try
- {
- ServiceReference[] srs = bc.getServiceReferences( className, null );
-
- for ( int ii = 0; srs != null && ii < srs.length; ++ii )
- {
- serviceChanged( srs[ ii ], ServiceEvent.REGISTERED, className );
- }
- }
- catch ( InvalidSyntaxException ignored )
- {
- }
- }
-
- private void lookForExistingBundleLocations()
- {
- Bundle[] bs = bc.getBundles();
+ String location = sr.getBundle().getLocation();
+ String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
- for ( int ii = 0; bs != null && ii < bs.length; ++ii )
- {
- existingBundleLocations.put( bs[ ii ].getLocation(), bs[ ii ].getLocation() );
- }
- }
+ log.debug( "Unbinding from factory " + factory + " (" + servicePid + ") from " + location );
- private boolean isNonExistingBundleLocation( String bundleLocation )
- {
- return bundleLocation != null && existingBundleLocations.get( bundleLocation ) == null;
+ dispatchUpdateEvent( sr, UpdateEvent.FACTORY_UNREGISTERING, servicePid );
}
- private ConfigurationDictionary bindLocationIfNecessary( ServiceReference[] srs, ConfigurationDictionary config )
- throws IOException
+ public void setManagedService( ServiceReference sr, ManagedService service )
{
- if ( srs == null || srs.length == 0 || config == null )
- {
- return config;
- }
-
- String configLocation = (String) config.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ String location = sr.getBundle().getLocation();
+ String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
- if ( isNonExistingBundleLocation( configLocation ) )
- {
- Boolean dynamicLocation = (Boolean) config.get( DYNAMIC_BUNDLE_LOCATION );
+ log.debug( "Binding to service " + service + " (" + servicePid + ") from " + location );
- if ( dynamicLocation != null && dynamicLocation.booleanValue() )
- {
- configLocation = null;
- }
- }
-
- if ( configLocation == null )
+ if ( servicePid == null )
{
- String factoryPid = (String) config.get( ConfigurationAdmin.SERVICE_FACTORYPID );
- String servicePid = (String) config.get( Constants.SERVICE_PID );
- String serviceLocation = srs[ 0 ].getBundle().getLocation();
-
- ConfigurationDictionary copy = config.createCopy();
- copy.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, serviceLocation );
- copy.put( DYNAMIC_BUNDLE_LOCATION, Boolean.TRUE );
-
- store.store( servicePid, factoryPid, copy );
- return copy;
+ log.error( "ManagedService without valid service.pid registered by " + location );
+ return;
}
- return config;
- }
-
- private void findAndUnbindConfigurationsDynamicallyBoundTo( String bundleLocation )
- {
- String filter = "(&(" + ConfigurationAdmin.SERVICE_BUNDLELOCATION + "=" + bundleLocation + ")" + "("
- + DYNAMIC_BUNDLE_LOCATION + "=" + Boolean.TRUE + "))";
- try
- {
- Configuration[] configurations = store.listConfigurations( filter );
- for ( int ii = 0; configurations != null && ii < configurations.length; ++ii )
- {
- configurations[ ii ].setBundleLocation( null );
- }
- }
- catch ( IOException ioe )
- {
- log.error( "Error loading configurations while unbinding configurations bound to " + bundleLocation, ioe );
- }
- catch ( InvalidSyntaxException ise )
- {
- log.error( "Error with filter while unbinding configurations bound to " + bundleLocation, ise );
- }
+ dispatchUpdateEvent( sr, UpdateEvent.SERVICE_REGISTERING, servicePid );
}
- private ServiceReference[] filterOnMatchingLocations( ServiceReference[] srs, String configLocation )
+ public void unsetManagedService( ServiceReference sr, ManagedService service )
{
- List results = new ArrayList();
+ String location = sr.getBundle().getLocation();
+ String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
- for ( int ii = 0; ii < srs.length; ++ii )
- {
- String serviceLocation = srs[ ii ].getBundle().getLocation();
- if ( locationsMatch( serviceLocation, configLocation ) )
- {
- results.add( srs[ ii ] );
- }
- else
- {
- log.error( "The bundle " + serviceLocation
- + " has registered a ManagedService(Factory) for a pid bound to " + configLocation );
- }
- }
+ log.debug( "Unbinding from service " + service + " (" + servicePid + ") from " + location );
- return (ServiceReference[]) results.toArray( new ServiceReference[ results.size() ] );
+ dispatchUpdateEvent( sr, UpdateEvent.SERVICE_UNREGISTERING, servicePid );
}
- private boolean locationsMatch( String serviceLocation, String configLocation )
+ public Object getService( Bundle bundle, ServiceRegistration registration )
{
- if ( configLocation == null )
- {
- return false;
- }
-
- if ( configLocation.equals( ANY_LOCATION ) || configLocation.equals( serviceLocation ) )
- {
- return true;
- }
-
- return false;
+ log.debug( "Received a ServiceFactory.getService() call" );
+ return new ConfigurationAdminImpl( store, bundle );
}
- private void addToLocationToPidsAndCheck( ServiceReference sr )
+ public void ungetService( Bundle bundle, ServiceRegistration registration, Object service )
{
- 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 ) )
- {
- log.error( "Multiple ManagedServices registered from bundle " + bundleLocation + " for " + pid );
- }
-
- pidsForLocation.put( sr, pid );
+ log.debug( "Received a ServiceFactory.ungetService() call" );
+ // For now we do nothing here
}
- private void removeFromLocationToPids( ServiceReference sr )
+ private void setConfigurationListener()
{
- 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() )
+ store.setConfigurationListener( new ConfigurationListener()
{
- locationToPids.remove( bundleLocation );
- }
+ public void configurationChanged( Dictionary configuration )
+ {
+ updateTargetServiceMatching( new ConfigurationDictionary( configuration ) );
+ }
+ } );
}
- private void updateTargetServicesMatching( ConfigurationDictionary cd ) throws IOException
+ private void updateTargetServiceMatching( ConfigurationDictionary cd )
{
String servicePid = (String) cd.get( Constants.SERVICE_PID );
@@ -387,236 +189,52 @@
}
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 );
+ ServiceReference sr = getTargetServiceReference( ManagedService.class, servicePid );
+ dispatchUpdateEvent( sr, UpdateEvent.SERVICE_UPDATING, servicePid );
}
else
{
- ConfigurationDictionary bound = bindLocationIfNecessary( srs, cd );
- String boundLocation = (String) bound.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
-
- updateManagedServices( srs, servicePid, boundLocation, bound );
+ ServiceReference sr = getTargetServiceReference( ManagedServiceFactory.class, factoryPid );
+ dispatchUpdateEvent( sr, UpdateEvent.FACTORY_UPDATING, servicePid );
}
}
- private void updateManagedServices( ServiceReference[] srs, String servicePid, String boundLocation,
- ConfigurationDictionary bound )
+ private ServiceReference getTargetServiceReference( Class clazz, String pid )
{
- 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 );
+ String filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
- if ( cd == null )
- {
- for ( int ii = 0; ii < srs.length; ++ii )
- {
- configurationDispatcher.dispatchUpdateFor( srs[ ii ], servicePid, null, null );
- }
- }
- else
+ try
{
- cd = bindLocationIfNecessary( srs, cd );
- String boundLocation = (String) cd.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
- srs = filterOnMatchingLocations( srs, boundLocation );
+ ServiceReference[] srs = bc.getServiceReferences( clazz.getName(), filter );
- for ( int ii = 0; ii < srs.length; ++ii )
+ if ( srs.length > 0 )
{
- configurationDispatcher.dispatchUpdateFor( srs[ ii ], servicePid, null, cd );
+ return srs[ 0 ];
}
- }
- }
-
- private ServiceReference[] getTargetServiceReferences( Class clazz, String pid )
- {
- String filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
- try
- {
- ServiceReference[] srs = bc.getServiceReferences( clazz.getName(), filter );
- return srs == null ? new ServiceReference[ 0 ] : srs;
+ return null;
}
catch ( InvalidSyntaxException e )
{
- log.error( "Invalid syntax in ldap filter " + filter, e );
- return new ServiceReference[ 0 ];
+ log.error( "Invalid syntax in LDAP filter " + filter, e );
+ return null;
}
}
- private void serviceChanged( ServiceReference sr, int eventType, String objectClass )
+ private void dispatchUpdateEvent( ServiceReference sr, int type, String servicePid )
{
- 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 );
- }
- }
+ UpdateEvent update = new UpdateEvent( sr, type, servicePid );
- private void managedServiceFactoryChanged( ServiceReference sr, int eventType )
- {
- String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
-
- switch ( eventType )
+ try
{
- case ServiceEvent.REGISTERED:
- configurationDispatcher.addQueueFor( sr );
-
- if ( servicePid == null )
- {
- String bundleLocation = sr.getBundle().getLocation();
- log.error( "ManagedServiceFactory without valid service.pid registered by " + bundleLocation );
- return;
- }
-
- addToLocationToPidsAndCheck( sr );
-
- try
- {
- updateManagedServiceFactory( sr );
- }
- catch ( IOException e )
- {
- log.error( "Error while notifying services.", e );
- }
-
- break;
- case ServiceEvent.MODIFIED:
- break;
- case ServiceEvent.UNREGISTERING:
- removeFromLocationToPids( sr );
- configurationDispatcher.removeQueueFor( sr );
- break;
+ queue.put( update );
}
- }
-
- private void managedServiceChanged( ServiceReference sr, int eventType )
- {
- final String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
-
- switch ( eventType )
+ catch ( InterruptedException ie )
{
- case ServiceEvent.REGISTERED:
- configurationDispatcher.addQueueFor( sr );
-
- if ( servicePid == null )
- {
- String bundleLocation = sr.getBundle().getLocation();
- log.error( "ManagedService without valid service.pid registered by " + bundleLocation );
- return;
- }
-
- addToLocationToPidsAndCheck( sr );
-
- try
- {
- updateManagedService( sr );
- }
- catch ( IOException e )
- {
- log.error( "Error while notifying services.", e );
- }
-
- break;
- case ServiceEvent.MODIFIED:
- break;
- case ServiceEvent.UNREGISTERING:
- removeFromLocationToPids( sr );
- configurationDispatcher.removeQueueFor( sr );
- break;
+ log.error( ie.getMessage(), ie );
}
}
}
Modified: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java?rev=290673&r1=290672&r2=290673&view=diff
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java (original)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java Wed Sep 21 03:15:53 2005
@@ -114,7 +114,7 @@
return properties.createCopyAndRemoveLocation();
}
- public ConfigurationDictionary getConfigurationDictionary()
+ private ConfigurationDictionary getConfigurationDictionary()
{
return properties;
}
Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java?rev=290673&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java Wed Sep 21 03:15:53 2005
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2003, KNOPFLERFISH project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * - Neither the name of the KNOPFLERFISH project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.configuration.impl;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * LDAP filter functions.
+ *
+ * @author Tommy Bohlin
+ * @author Jan Stein
+ * @version $Revision: 1.1.1.1 $
+ */
+class LDAPQuery {
+ private static final char WILDCARD=65535;
+ private static final String WILDCARD_STRING= new String(new char [] { WILDCARD });
+
+ private static final String NULL ="Null query";
+ private static final String GARBAGE ="Trailing garbage";
+ private static final String MALFORMED="Malformed query";
+ private static final String EMPTY ="Empty list";
+ private static final String SUBEXPR ="No subexpression";
+ private static final String OPERATOR ="Undefined operator";
+ private static final String TRUNCATED="Truncated expression";
+ private static final String EQUALITY ="Only equality supported";
+
+ private static final int EQ = 0;
+ private static final int LE = 1;
+ private static final int GE = 2;
+ private static final int APPROX = 3;
+
+ private static final Class[] classArg=new Class[] { String.class };
+ private static final Class[] objectArg=new Class[] { Object.class };
+
+ private static Class classBigDecimal;
+ private static Constructor consBigDecimal;
+ private static Method compBigDecimal;
+
+ static {
+ try {
+ classBigDecimal = Class.forName("java.math.BigDecimal");
+ consBigDecimal = classBigDecimal.getConstructor(new Class [] { String.class });
+ compBigDecimal = classBigDecimal.getMethod("compareTo", new Class [] { classBigDecimal });
+ } catch (Exception ignore) {
+ classBigDecimal = null;
+ }
+ }
+
+ boolean val;
+ String tail;
+ Dictionary prop;
+
+ public static void check(String q) throws InvalidSyntaxException {
+ query(q, null);
+ }
+
+ public static boolean query(String q, Dictionary p)
+ throws InvalidSyntaxException {
+ LDAPQuery lq=new LDAPQuery(q,p);
+ lq.doQuery();
+ if(lq.tail.length()>0) lq.error(GARBAGE);
+ return lq.val;
+ }
+
+ LDAPQuery(String q, Dictionary p) throws InvalidSyntaxException {
+ if(q==null || q.length()==0) error(NULL);
+ tail=q;
+ prop=p;
+ }
+
+ void doQuery() throws InvalidSyntaxException {
+ if(tail.length()<3 || !prefix("(")) error(MALFORMED);
+
+ switch(tail.charAt(0)) {
+ case '&': doAnd(); break;
+ case '|': doOr(); break;
+ case '!': doNot(); break;
+ default: doSimple(); break;
+ }
+
+ if(!prefix(")")) error(MALFORMED);
+ }
+
+ private void doAnd() throws InvalidSyntaxException {
+ tail=tail.substring(1);
+ boolean val1=true;
+ if(!tail.startsWith("(")) error(EMPTY);
+ do {
+ doQuery();
+ if(!val) val1=false;
+ } while(tail.startsWith("("));
+ val=val1;
+ }
+
+ private void doOr() throws InvalidSyntaxException {
+ tail=tail.substring(1);
+ boolean val1=false;
+ if(!tail.startsWith("(")) error(EMPTY);
+ do {
+ doQuery();
+ if(val) val1=true;
+ } while(tail.startsWith("("));
+ val=val1;
+ }
+
+ private void doNot() throws InvalidSyntaxException {
+ tail=tail.substring(1);
+ if(!tail.startsWith("(")) error(SUBEXPR);
+ doQuery();
+ val=!val;
+ }
+
+ private void doSimple() throws InvalidSyntaxException {
+ int op=0;
+ Object attr=getAttr();
+
+ if(prefix("=" )) op=EQ;
+ else if(prefix("<=")) op=LE;
+ else if(prefix(">=")) op=GE;
+ else if(prefix("~=")) op=APPROX;
+ else error(OPERATOR);
+
+ val=compare(attr,op,getValue());
+ }
+
+ private boolean prefix(String pre) {
+ if(!tail.startsWith(pre)) return false;
+ tail=tail.substring(pre.length());
+ return true;
+ }
+
+ private Object getAttr() {
+ int len=tail.length();
+ int ix=0;
+ label:for(;ix<len;ix++) {
+ switch(tail.charAt(ix)) {
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '=':
+ case '~':
+ case '*':
+ case '\\':
+ break label;
+ }
+ }
+ String attr=tail.substring(0,ix);
+ tail=tail.substring(ix);
+ return prop != null ? prop.get(attr) : null;
+ }
+
+ private String getValue() {
+ StringBuffer sb=new StringBuffer();
+ int len=tail.length();
+ int ix=0;
+ label:for(;ix<len;ix++) {
+ char c=tail.charAt(ix);
+ switch(c) {
+ case '(':
+ case ')':
+ break label;
+ case '*':
+ sb.append(WILDCARD);
+ break;
+ case '\\':
+ if(ix==len-1) break label;
+ sb.append(tail.charAt(++ix));
+ break;
+ default:
+ sb.append(c);
+ break;
+ }
+ }
+ tail=tail.substring(ix);
+ return sb.toString();
+ }
+
+ private void error(String m) throws InvalidSyntaxException {
+ throw new InvalidSyntaxException(m,tail);
+ }
+
+ private boolean compare(Object obj, int op, String s) {
+ if(obj==null) return false;
+ if(op==EQ && s.equals(WILDCARD_STRING)) return true;
+ try {
+ if(obj instanceof String) {
+ return compareString((String)obj,op,s);
+ } else if(obj instanceof Character) {
+ return compareString(obj.toString(),op,s);
+ } else if(obj instanceof Boolean) {
+ if (op==LE || op==GE)
+ return false;
+ return ((Boolean)obj).equals(new Boolean(s));
+ } else if (obj instanceof Number) {
+ if (obj instanceof Byte) {
+ switch(op) {
+ case LE:
+ return ((Byte)obj).byteValue() <= Byte.parseByte(s);
+ case GE:
+ return ((Byte)obj).byteValue() >= Byte.parseByte(s);
+ default: /*APPROX and EQ*/
+ return (new Byte(s)).equals(obj);
+ }
+ } else if (obj instanceof Integer) {
+ switch(op) {
+ case LE:
+ return ((Integer)obj).intValue() <= Integer.parseInt(s);
+ case GE:
+ return ((Integer)obj).intValue() >= Integer.parseInt(s);
+ default: /*APPROX and EQ*/
+ return (new Integer(s)).equals(obj);
+ }
+ } else if (obj instanceof Short) {
+ switch(op) {
+ case LE:
+ return ((Short)obj).shortValue() <= Short.parseShort(s);
+ case GE:
+ return ((Short)obj).shortValue() >= Short.parseShort(s);
+ default: /*APPROX and EQ*/
+ return (new Short(s)).equals(obj);
+ }
+ } else if (obj instanceof Long) {
+ switch(op) {
+ case LE:
+ return ((Long)obj).longValue() <= Long.parseLong(s);
+ case GE:
+ return ((Long)obj).longValue() >= Long.parseLong(s);
+ default: /*APPROX and EQ*/
+ return (new Long(s)).equals(obj);
+ }
+ } else if (obj instanceof Float) {
+ switch(op) {
+ case LE:
+ return ((Float)obj).floatValue() <= (new Float(s)).floatValue();
+ case GE:
+ return ((Float)obj).floatValue() >= (new Float(s)).floatValue();
+ default: /*APPROX and EQ*/
+ return (new Float(s)).equals(obj);
+ }
+ } else if (obj instanceof Double) {
+ switch(op) {
+ case LE:
+ return ((Double)obj).doubleValue() <= (new Double(s)).doubleValue();
+ case GE:
+ return ((Double)obj).doubleValue() >= (new Double(s)).doubleValue();
+ default: /*APPROX and EQ*/
+ return (new Double(s)).equals(obj);
+ }
+ } else if (obj instanceof BigInteger) {
+ int c = ((BigInteger)obj).compareTo(new BigInteger(s));
+ switch(op) {
+ case LE:
+ return c <= 0;
+ case GE:
+ return c >= 0;
+ default: /*APPROX and EQ*/
+ return c == 0;
+ }
+ } else if (classBigDecimal != null && classBigDecimal.isInstance(obj)) {
+ Object n = consBigDecimal.newInstance(new Object [] { s });
+ int c = ((Integer)compBigDecimal.invoke(obj, new Object [] { n })).intValue();
+ switch(op) {
+ case LE:
+ return c <= 0;
+ case GE:
+ return c >= 0;
+ default: /*APPROX and EQ*/
+ return c == 0;
+ }
+ }
+ } else if(obj instanceof Vector) {
+ for(Enumeration e=((Vector)obj).elements();e.hasMoreElements();)
+ if(compare(e.nextElement(),op,s)) return true;
+ } else if(obj.getClass().isArray()) {
+ int len=Array.getLength(obj);
+ for(int i=0;i<len;i++)
+ if(compare(Array.get(obj,i),op,s)) return true;
+ }
+ } catch(Exception e) { }
+ return false;
+ }
+
+ static boolean compareString(String s1, int op, String s2) {
+ switch(op) {
+ case LE:
+ return s1.compareTo(s2) <= 0;
+ case GE:
+ return s1.compareTo(s2) >= 0;
+ case EQ:
+ return patSubstr(s1,s2);
+ case APPROX:
+ return fixupString(s2).equals(fixupString(s1));
+ default:
+ return false;
+ }
+ }
+
+ static String fixupString(String s) {
+ StringBuffer sb=new StringBuffer();
+ int len=s.length();
+ boolean isStart=true;
+ boolean isWhite=false;
+ for(int i=0;i<len;i++) {
+ char c=s.charAt(i);
+ if(Character.isWhitespace(c)) {
+ isWhite=true;
+ } else {
+ if(!isStart && isWhite) sb.append(' ');
+ if(Character.isUpperCase(c)) c=Character.toLowerCase(c);
+ sb.append(c);
+ isStart=false;
+ isWhite=false;
+ }
+ }
+ return sb.toString();
+ }
+
+ static boolean patSubstr(String s, String pat) {
+ if(s==null) return false;
+ if(pat.length()==0) return s.length()==0;
+ if(pat.charAt(0)==WILDCARD) {
+ pat=pat.substring(1);
+ for(;;) {
+ if(patSubstr(s,pat)) return true;
+ if(s.length()==0) return false;
+ s=s.substring(1);
+ }
+ } else {
+ if(s.length()==0 || s.charAt(0)!=pat.charAt(0)) return false;
+ return patSubstr(s.substring(1),pat.substring(1));
+ }
+ }
+}
+
Propchange: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/LDAPQuery.java
------------------------------------------------------------------------------
svn:executable = *
Modified: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/PluginManager.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/PluginManager.java?rev=290673&r1=290672&r2=290673&view=diff
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/PluginManager.java (original)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/PluginManager.java Wed Sep 21 03:15:53 2005
@@ -17,12 +17,15 @@
package org.apache.configuration.impl;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationPlugin;
import org.slf4j.Logger;
@@ -31,85 +34,78 @@
/**
* This class is responsible for managing ConfigurationPlugins.
*/
-final class PluginManager
+final class PluginManager implements ServiceListener
{
/** the log for this class */
private static final Logger log = LoggerFactory.getLogger( PluginManager.class );
private final static String CM_RANKING = "service.cmRanking";
- private final static String CM_TARGET = ConfigurationPlugin.CM_TARGET;
- /**
- * Sorted Vector of ServiceReferences to ConfigurationPlugins.
- */
- private Vector preModificationPlugins = new Vector();
+ private static final String FILTER = "(objectClass=" + ConfigurationPlugin.class.getName() + ")";
+
+ private BundleContext bc;
/**
- * Sorted Vector of ServiceReferences to ConfigurationPlugins.
+ * Sorted Map of ranked ServiceReferences.
*/
- private Vector modifyingPlugins = new Vector();
+ private Map<RankingKey, ServiceReference> preModificationPlugins = new TreeMap<RankingKey, ServiceReference>();
/**
- * Sorted Vector of ServiceReferences to ConfigurationPlugins.
+ * Sorted Map of ranked ServiceReferences.
*/
- private Vector postModificationPlugins = new Vector();
+ private Map<RankingKey, ServiceReference> modifyingPlugins = new TreeMap<RankingKey, ServiceReference>();
/**
- * Hashtable mapping a ServiceReference to its ranking (Integer).
+ * Sorted Map of ranked ServiceReferences.
*/
- private Hashtable rankings = new Hashtable();
+ private Map<RankingKey, ServiceReference> postModificationPlugins = new TreeMap<RankingKey, ServiceReference>();
+
+ PluginManager( BundleContext bc )
+ {
+ this.bc = bc;
+
+ try
+ {
+ bc.addServiceListener( this, FILTER );
+ }
+ catch ( InvalidSyntaxException ise )
+ {
+ log.error( ise.getMessage(), ise );
+ }
+ }
/**
* Handle ConfigurationPlugin ServiceEvents.
*
- * @param serviceReference ServiceReference of the plugin the event concerns
- * @param eventType Type of the event that caused the change
+ * @param event The event that caused the change
*/
- public synchronized void configurationPluginChanged( ServiceReference serviceReference, int eventType )
+ public synchronized void serviceChanged( ServiceEvent event )
{
- Object rankingProperty = serviceReference.getProperty( CM_RANKING );
+ ServiceReference sr = event.getServiceReference();
+ int eventType = event.getType();
+ Object rankingProperty = sr.getProperty( CM_RANKING );
+
+ Integer ranking;
- if ( rankingProperty == null )
+ if ( rankingProperty == null || rankingProperty.getClass() != Integer.class )
{
- rankingProperty = new Integer( 0 );
+ ranking = new Integer( 0 );
}
else
- if ( rankingProperty.getClass() != Integer.class )
- {
- rankingProperty = new Integer( 0 );
- }
-
- Long serviceId = (Long) serviceReference.getProperty( Constants.SERVICE_ID );
-
- if ( serviceId == null )
{
- log.error( "Missing service id for a ConfigurationPlugin" );
- return;
+ ranking = (Integer) rankingProperty;
}
- int ranking = ( (Integer) rankingProperty ).intValue();
+ RankingKey key = new RankingKey( ranking, sr );
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 );
+ insertPluginReference( ranking, key, sr );
break;
case ServiceEvent.UNREGISTERING:
- rankings.remove( serviceId );
- removePluginReference( serviceId, ranking );
+ removePluginReference( key );
break;
default:
break;
@@ -123,88 +119,36 @@
* @param serviceReference The ServiceReference.
* @param ranking The ranking the ServiceReference.
*/
- private void insertPluginReference( ServiceReference serviceReference, int ranking )
+ private void insertPluginReference( int ranking, RankingKey key, ServiceReference serviceReference )
{
+ removePluginReference( key );
+
if ( ranking < 0 )
{
- insertPluginReference( serviceReference, ranking, preModificationPlugins );
+ preModificationPlugins.put( key, serviceReference );
}
else
if ( 0 <= ranking && ranking <= 1000 )
{
- insertPluginReference( serviceReference, ranking, modifyingPlugins );
+ modifyingPlugins.put( key, serviceReference );
}
else
if ( ranking > 1000 )
{
- insertPluginReference( serviceReference, ranking, postModificationPlugins );
+ postModificationPlugins.put( key, serviceReference );
}
}
/**
- * Insert a ServiceReference in a Vector sorted on cm.ranking property.
+ * Remove a plugin service reference given a ranking key.
*
- * @param serviceReference The ServiceReference.
- * @param pluginsVector The vector.
+ * @param key The key to the service reference of the ConfigurationPlugin.
*/
- private void insertPluginReference( ServiceReference serviceReference, int ranking, Vector pluginsVector )
+ private void removePluginReference( RankingKey key )
{
- 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;
- }
- }
+ preModificationPlugins.remove( key );
+ modifyingPlugins.remove( key );
+ postModificationPlugins.remove( key );
}
/**
@@ -228,9 +172,7 @@
}
callPlugins( targetServiceReference, dictionary, preModificationPlugins, false );
-
dictionary = callPlugins( targetServiceReference, dictionary, modifyingPlugins, true );
-
callPlugins( targetServiceReference, dictionary, postModificationPlugins, false );
if ( dictionary != null )
@@ -242,7 +184,7 @@
}
/**
- * Call all plugins contained in a Vector and optionally allow
+ * Call all plugins contained in collection of plugins and optionally allow
* modifications.
*
* @param targetServiceReference Reference to the target ManagedService(Factory).
@@ -253,23 +195,22 @@
* @return The modified configuration dictionary.
*/
private ConfigurationDictionary callPlugins( ServiceReference targetServiceReference,
- ConfigurationDictionary dictionary, Vector plugins, boolean allowModification )
+ ConfigurationDictionary dictionary, Map plugins, boolean allowModification )
{
String pid = (String) targetServiceReference.getProperty( Constants.SERVICE_PID );
ConfigurationDictionary currentDictionary = dictionary;
- Enumeration e = plugins.elements();
+ Iterator it = plugins.values().iterator();
- while ( e.hasMoreElements() )
+ while ( it.hasNext() )
{
- ServiceReference pluginReference = (ServiceReference) e.nextElement();
+ ServiceReference pluginReference = (ServiceReference) it.next();
- // 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 );
+ // Call the plugin if no cm.target is specified or if target matches
+ String cmTarget = (String) pluginReference.getProperty( ConfigurationPlugin.CM_TARGET );
if ( cmTarget == null || cmTarget.equals( pid ) )
{
- ConfigurationPlugin plugin = (ConfigurationPlugin) ConfigurationAdminFactory.bc.getService( pluginReference );
+ ConfigurationPlugin plugin = (ConfigurationPlugin) bc.getService( pluginReference );
if ( plugin == null )
{
@@ -297,5 +238,60 @@
}
return currentDictionary;
+ }
+
+ private class RankingKey implements Comparable
+ {
+ private Integer ranking;
+ private ServiceReference reference;
+
+ private RankingKey( Integer ranking, ServiceReference reference )
+ {
+ this.ranking = ranking;
+ this.reference = reference;
+ }
+
+ public int compareTo( Object o )
+ {
+ final int BEFORE = -1;
+ final int EQUAL = 0;
+ final int AFTER = 1;
+
+ if ( this == o )
+ {
+ return EQUAL;
+ }
+
+ final RankingKey that = (RankingKey) o;
+
+ if ( this.reference == that.reference )
+ {
+ return EQUAL;
+ }
+
+ if ( this.ranking < that.ranking )
+ {
+ return BEFORE;
+ }
+
+ if ( this.ranking > that.ranking )
+ {
+ return AFTER;
+ }
+
+ return EQUAL;
+ }
+
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+
+ final RankingKey that = (RankingKey) o;
+
+ return this.reference == that.reference;
+ }
}
}
Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateConsumer.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateConsumer.java?rev=290673&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateConsumer.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateConsumer.java Wed Sep 21 03:15:53 2005
@@ -0,0 +1,481 @@
+/*
+ * 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.impl;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UpdateConsumer implements Runnable, BundleListener
+{
+ /** the log for this class */
+ private static final Logger log = LoggerFactory.getLogger( ConfigurationAdminFactory.class );
+
+ public static final String DYNAMIC_BUNDLE_LOCATION = "dynamic.service.bundleLocation";
+
+ private static final String ANY_LOCATION = "*";
+ private Map<String, Set<String>> locationToPids = new HashMap<String, Set<String>>();
+ private Set<String> existingBundleLocations = new HashSet<String>();
+
+ private BundleContext bc;
+ private JndiConfigurationStore store;
+ private PluginManager pluginManager;
+ private BlockingQueue<UpdateEvent> queue;
+
+ public UpdateConsumer( BundleContext bc, JndiConfigurationStore store, PluginManager pluginManager,
+ BlockingQueue<UpdateEvent> queue )
+ {
+ this.bc = bc;
+ this.store = store;
+ this.pluginManager = pluginManager;
+ this.queue = queue;
+
+ lookForExistingBundleLocations();
+ }
+
+ 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.add( installedBundleLocation );
+ }
+ }
+
+ public void run()
+ {
+ UpdateEvent update;
+
+ while ( true )
+ {
+ try
+ {
+ update = queue.take();
+ log.debug( "Dequeued update " + update.toString() );
+ handleEvent( update );
+ }
+ catch ( InterruptedException ie )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( ie.getMessage(), ie );
+ }
+ else
+ {
+ log.info( ie.getMessage() );
+ }
+ }
+ }
+ }
+
+ private void handleEvent( UpdateEvent update )
+ {
+ ServiceReference sr = (ServiceReference) update.getSource();
+
+ if ( sr == null )
+ {
+ return;
+ }
+
+ String servicePid = update.getServicePid();
+
+ try
+ {
+ switch ( update.getType() )
+ {
+ case UpdateEvent.SERVICE_REGISTERING:
+ addLocationToPidsAndCheck( sr );
+ configureManagedService( sr );
+ break;
+ case UpdateEvent.FACTORY_REGISTERING:
+ addLocationToPidsAndCheck( sr );
+ configureManagedServiceFactory( sr );
+ break;
+ case UpdateEvent.SERVICE_UPDATING:
+ updateManagedServiceMatching( sr );
+ break;
+ case UpdateEvent.FACTORY_UPDATING:
+ updateManagedServiceFactoryMatching( sr, servicePid );
+ break;
+ case UpdateEvent.SERVICE_UNREGISTERING:
+ removeFromLocationToPids( sr );
+ break;
+ case UpdateEvent.FACTORY_UNREGISTERING:
+ removeFromLocationToPids( sr );
+ break;
+ default:
+ break;
+ }
+ }
+ catch ( IOException ioe )
+ {
+ log.debug( ioe.getMessage(), ioe );
+ }
+ }
+
+ private void update( ServiceReference sr, String pid, String factoryPid, ConfigurationDictionary cd )
+ {
+ Object targetService = getTargetService( sr );
+
+ if ( targetService == null )
+ {
+ return;
+ }
+
+ ConfigurationDictionary processedConfiguration = pluginManager.callPluginsAndCreateACopy( sr, cd );
+
+ try
+ {
+ if ( factoryPid != null )
+ {
+ update( (ManagedServiceFactory) targetService, pid, cd, processedConfiguration );
+ }
+ else
+ {
+ update( (ManagedService) targetService, processedConfiguration );
+ }
+ }
+ catch ( ConfigurationException ce )
+ {
+ log.error( ce.getMessage(), ce );
+ }
+ }
+
+ private void update( ManagedServiceFactory targetService, String pid, ConfigurationDictionary configuration,
+ ConfigurationDictionary processedConfiguration ) 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 void update( ManagedService targetService, ConfigurationDictionary processedConfiguration )
+ throws ConfigurationException
+ {
+ if ( targetService == null )
+ {
+ return;
+ }
+
+ targetService.updated( processedConfiguration );
+ }
+
+ private Object getTargetService( ServiceReference sr )
+ {
+ if ( sr == null )
+ {
+ return null;
+ }
+
+ return bc.getService( sr );
+ }
+
+ // SERVICE_REGISTERING
+ private void configureManagedService( ServiceReference sr ) throws IOException
+ {
+ final String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
+ ConfigurationDictionary cd = store.load( servicePid );
+
+ if ( cd == null )
+ {
+ update( sr, servicePid, null, null );
+ }
+ else
+ {
+ cd = bindLocationIfNecessary( sr, cd );
+ String boundLocation = (String) cd.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ sr = filterOnMatchingLocations( sr, boundLocation );
+
+ update( sr, servicePid, null, cd );
+ }
+ }
+
+ // FACTORY_REGISTERING
+ private void configureManagedServiceFactory( ServiceReference sr ) throws IOException
+ {
+ String factoryPid = (String) sr.getProperty( Constants.SERVICE_PID );
+
+ ConfigurationDictionary[] cds = store.loadAll( factoryPid );
+
+ if ( cds != null && cds.length > 0 )
+ {
+ for ( int ii = 0; ii < cds.length; ++ii )
+ {
+ String servicePid = (String) cds[ ii ].get( Constants.SERVICE_PID );
+ configureManagedServiceFactory( sr, servicePid, factoryPid, cds[ ii ] );
+ }
+ }
+ }
+
+ // FACTORY_REGISTERING
+ private void configureManagedServiceFactory( ServiceReference sr, String servicePid, String factoryPid,
+ ConfigurationDictionary cd ) throws IOException
+ {
+ ConfigurationDictionary bound = bindLocationIfNecessary( sr, cd );
+ String boundLocation = (String) bound.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ ServiceReference filtered = filterOnMatchingLocations( sr, boundLocation );
+
+ update( filtered, servicePid, factoryPid, bound );
+ }
+
+ // SERVICE_UPDATING
+ private void updateManagedServiceMatching( ServiceReference sr ) throws IOException
+ {
+ final String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
+ final String bundleLocation = (String) sr.getProperty( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+
+ ConfigurationDictionary cd = store.load( servicePid );
+
+ if ( cd == null )
+ {
+ updateManagedService( sr, servicePid, bundleLocation, null );
+ }
+ else
+ {
+ ConfigurationDictionary bound = bindLocationIfNecessary( sr, cd );
+ String boundLocation = (String) bound.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+
+ updateManagedService( sr, servicePid, boundLocation, bound );
+ }
+ }
+
+ // SERVICE_UPDATING
+ private void updateManagedService( ServiceReference sr, String servicePid, String boundLocation,
+ ConfigurationDictionary bound )
+ {
+ ServiceReference filtered = filterOnMatchingLocations( sr, boundLocation );
+
+ update( filtered, servicePid, null, bound );
+ }
+
+ // FACTORY_UPDATING
+ private void updateManagedServiceFactoryMatching( ServiceReference sr, String servicePid ) throws IOException
+ {
+ final String bundleLocation = (String) sr.getProperty( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+
+ ConfigurationDictionary cd = store.load( servicePid );
+ String factoryPid = (String) cd.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+
+ if ( cd == null )
+ {
+ ServiceReference filtered = filterOnMatchingLocations( sr, bundleLocation );
+ update( filtered, servicePid, factoryPid, null );
+ }
+ else
+ {
+ ConfigurationDictionary bound = bindLocationIfNecessary( sr, cd );
+ String boundLocation = (String) bound.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ ServiceReference filtered = filterOnMatchingLocations( sr, boundLocation );
+ update( filtered, servicePid, factoryPid, bound );
+ }
+ }
+
+ private void lookForExistingBundleLocations()
+ {
+ Bundle[] bs = bc.getBundles();
+
+ for ( int ii = 0; bs != null && ii < bs.length; ++ii )
+ {
+ existingBundleLocations.add( bs[ ii ].getLocation() );
+ }
+ }
+
+ private ConfigurationDictionary bindLocationIfNecessary( ServiceReference sr, ConfigurationDictionary config )
+ throws IOException
+ {
+ if ( sr == null || config == null )
+ {
+ return config;
+ }
+
+ String configLocation = (String) config.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+
+ if ( configLocation != null && !existingBundleLocations.contains( configLocation ) )
+ {
+ Boolean dynamicLocation = (Boolean) config.get( DYNAMIC_BUNDLE_LOCATION );
+
+ if ( dynamicLocation != null && dynamicLocation.booleanValue() )
+ {
+ configLocation = null;
+ }
+ }
+
+ if ( configLocation == null )
+ {
+ String factoryPid = (String) config.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+ String servicePid = (String) config.get( Constants.SERVICE_PID );
+ String serviceLocation = sr.getBundle().getLocation();
+
+ ConfigurationDictionary copy = config.createCopy();
+ copy.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, serviceLocation );
+ copy.put( DYNAMIC_BUNDLE_LOCATION, Boolean.TRUE );
+
+ store.store( servicePid, factoryPid, copy );
+ return copy;
+ }
+
+ return config;
+ }
+
+ private void findAndUnbindConfigurationsDynamicallyBoundTo( String bundleLocation )
+ {
+ String filter = "(&(" + ConfigurationAdmin.SERVICE_BUNDLELOCATION + "=" + bundleLocation + ")" + "("
+ + DYNAMIC_BUNDLE_LOCATION + "=" + Boolean.TRUE + "))";
+ try
+ {
+ Configuration[] configurations = store.listConfigurations( filter );
+ for ( int ii = 0; configurations != null && ii < configurations.length; ++ii )
+ {
+ configurations[ ii ].setBundleLocation( null );
+ }
+ }
+ catch ( IOException ioe )
+ {
+ log.error( "Error loading configurations while unbinding configurations bound to " + bundleLocation, ioe );
+ }
+ catch ( InvalidSyntaxException ise )
+ {
+ log.error( "Error with filter while unbinding configurations bound to " + bundleLocation, ise );
+ }
+ }
+
+ private ServiceReference filterOnMatchingLocations( ServiceReference sr, String configLocation )
+ {
+ String serviceLocation = sr.getBundle().getLocation();
+
+ if ( locationsMatch( serviceLocation, configLocation ) )
+ {
+ return sr;
+ }
+
+ log.error( "The bundle " + serviceLocation + " has registered a ManagedService(Factory) for a pid bound to "
+ + configLocation );
+
+ return null;
+ }
+
+ 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 addLocationToPidsAndCheck( ServiceReference sr )
+ {
+ if ( sr == null )
+ {
+ return;
+ }
+
+ String bundleLocation = sr.getBundle().getLocation();
+
+ String pid = (String) sr.getProperty( Constants.SERVICE_PID );
+
+ if ( pid == null )
+ {
+ return;
+ }
+
+ Set<String> pidsForLocation = locationToPids.get( bundleLocation );
+
+ if ( pidsForLocation == null )
+ {
+ pidsForLocation = new HashSet<String>();
+ locationToPids.put( bundleLocation, pidsForLocation );
+ }
+
+ if ( pidsForLocation.contains( pid ) )
+ {
+ log.error( "Multiple ManagedServices registered from bundle " + bundleLocation + " for " + pid );
+ }
+
+ pidsForLocation.add( pid );
+ }
+
+ private void removeFromLocationToPids( ServiceReference sr )
+ {
+ if ( sr == null )
+ {
+ return;
+ }
+
+ String bundleLocation = sr.getBundle().getLocation();
+ Set<String> pidsForLocation = locationToPids.get( bundleLocation );
+
+ if ( pidsForLocation == null )
+ {
+ return;
+ }
+
+ pidsForLocation.remove( bundleLocation );
+
+ if ( pidsForLocation.isEmpty() )
+ {
+ locationToPids.remove( bundleLocation );
+ }
+ }
+}
Propchange: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateConsumer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateEvent.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateEvent.java?rev=290673&view=auto
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateEvent.java (added)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateEvent.java Wed Sep 21 03:15:53 2005
@@ -0,0 +1,91 @@
+/*
+ * 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.impl;
+
+import java.util.EventObject;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+final class UpdateEvent extends EventObject
+{
+ public static final int SERVICE_REGISTERING = 1;
+ public static final int FACTORY_REGISTERING = 2;
+ public static final int SERVICE_UNREGISTERING = 3;
+ public static final int FACTORY_UNREGISTERING = 4;
+ public static final int SERVICE_UPDATING = 5;
+ public static final int FACTORY_UPDATING = 6;
+
+ private int type;
+ private String servicePid;
+
+ public UpdateEvent( ServiceReference sr, int type, String servicePid )
+ {
+ super( sr );
+
+ this.type = type;
+ this.servicePid = servicePid;
+ }
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public String getServicePid()
+ {
+ return servicePid;
+ }
+
+ public String toString()
+ {
+ ServiceReference sr = (ServiceReference) getSource();
+ String servicePid = (String) sr.getProperty( Constants.SERVICE_PID );
+
+ StringBuffer sb = new StringBuffer();
+
+ switch ( type )
+ {
+ case SERVICE_REGISTERING:
+ sb.append( "SERVICE_REGISTERING" );
+ break;
+ case FACTORY_REGISTERING:
+ sb.append( "FACTORY_REGISTERING" );
+ break;
+ case SERVICE_UNREGISTERING:
+ sb.append( "SERVICE_UNREGISTERING" );
+ break;
+ case FACTORY_UNREGISTERING:
+ sb.append( "FACTORY_UNREGISTERING" );
+ break;
+ case SERVICE_UPDATING:
+ sb.append( "SERVICE_UPDATING" );
+ break;
+ case FACTORY_UPDATING:
+ sb.append( "FACTORY_UPDATING" );
+ break;
+ default:
+ sb.append( "NULL EVENT" );
+ break;
+ }
+
+ sb.append( " with servicePid " + servicePid );
+
+ return sb.toString();
+ }
+}
Propchange: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/impl/UpdateEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/metadata.xml
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/metadata.xml?rev=290673&r1=290672&r2=290673&view=diff
==============================================================================
--- directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/metadata.xml (original)
+++ directory/sandbox/trunk/osgi-spec/trunk/configuration/src/main/java/org/apache/configuration/metadata.xml Wed Sep 21 03:15:53 2005
@@ -11,5 +11,21 @@
bind-method="setInitialContextFactory"
unbind-method="unsetInitialContextFactory"
/>
+ <requires
+ service="org.osgi.service.cm.ManagedServiceFactory"
+ filter=""
+ cardinality="0..n"
+ policy="dynamic"
+ bind-method="setManagedServiceFactory"
+ unbind-method="unsetManagedServiceFactory"
+ />
+ <requires
+ service="org.osgi.service.cm.ManagedService"
+ filter=""
+ cardinality="0..n"
+ policy="dynamic"
+ bind-method="setManagedService"
+ unbind-method="unsetManagedService"
+ />
</component>
</bundle>