FELIX-1488 Only persist static configuration bindings and keep dynamic
bindings in-memory only (also fixes FELIX-1484)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@804740 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
index 0ad02e8..b126eef 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
@@ -1,4 +1,4 @@
-/*
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -84,7 +84,7 @@
{
configurationAdmin.checkPermission();
checkDeleted();
- delegatee.setBundleLocation( bundleLocation );
+ delegatee.setBundleLocation( bundleLocation, true );
}
@@ -117,7 +117,7 @@
public Dictionary getProperties()
{
checkDeleted();
-
+
// return a deep copy since the spec says, that modification of
// any value should not modify the internal, stored value
return delegatee.getProperties( true );
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
index 61c07c7..a1a6102 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
@@ -95,7 +95,8 @@
if ( config.getBundleLocation() == null )
{
- config.setBundleLocation( this.getBundle().getLocation() );
+ // statically bind the configuration
+ config.setBundleLocation( this.getBundle().getLocation(), true );
}
else if ( !config.getBundleLocation().equals( this.getBundle().getLocation() ) )
{
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
index 395ebe3..d67b549 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
@@ -92,6 +92,12 @@
private volatile String bundleLocation;
/**
+ * Flag indicating whether this configuration object is statically or
+ * dynamically bound.
+ */
+ private volatile boolean staticallyBound;
+
+ /**
* The <code>ServiceReference</code> of the serviceReference which first asked for
* this configuration. This field is <code>null</code> if the configuration
* has not been handed to a serviceReference by way of the <code>ManagedService.update(Dictionary)</code>
@@ -140,6 +146,7 @@
this.pid = ( String ) properties.remove( Constants.SERVICE_PID );
this.factoryPID = ( String ) properties.remove( ConfigurationAdmin.SERVICE_FACTORYPID );
this.bundleLocation = ( String ) properties.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ this.staticallyBound = bundleLocation != null;
// set the properties internally
configureFromPersistence( properties );
@@ -165,6 +172,7 @@
this.pid = pid;
this.factoryPID = factoryPid;
this.bundleLocation = bundleLocation;
+ this.staticallyBound = bundleLocation != null;
this.properties = null;
// this is a new configuration object, store immediately unless
@@ -172,7 +180,7 @@
// case the configuration is only stored when first updated
if (factoryPid == null) {
Dictionary props = new Hashtable();
- setAutoProperties( props, true );
+ setAutoProperties( props, staticallyBound );
props.put( CONFIGURATION_NEW, Boolean.TRUE );
persistenceManager.store( pid, props );
}
@@ -281,20 +289,30 @@
/* (non-Javadoc)
* @see org.osgi.service.cm.Configuration#setBundleLocation(java.lang.String)
*/
- public void setBundleLocation( String bundleLocation )
+ public void setBundleLocation( String bundleLocation, boolean staticBinding )
{
if ( !isDeleted() )
{
- this.bundleLocation = bundleLocation;
+ if ( staticBinding )
+ {
+ // set binding and mark static and store everything
+ this.bundleLocation = bundleLocation;
+ this.staticallyBound = staticBinding;
- // 104.15.2.8 The bundle location will be set persistently
- try
- {
- store();
+ // 104.15.2.8 The bundle location will be set persistently
+ try
+ {
+ store();
+ }
+ catch ( IOException ioe )
+ {
+ configurationManager.log( LogService.LOG_ERROR, "Persisting new bundle location failed", ioe );
+ }
}
- catch ( IOException ioe )
+ else if ( !staticallyBound )
{
- configurationManager.log( LogService.LOG_ERROR, "Persisting new bundle location failed", ioe );
+ // dynamic binding, no need to store
+ this.bundleLocation = bundleLocation;
}
}
}
@@ -339,7 +357,7 @@
{
CaseInsensitiveDictionary newProperties = new CaseInsensitiveDictionary( properties );
- setAutoProperties( newProperties, true );
+ setAutoProperties( newProperties, staticallyBound );
localPersistenceManager.store( pid, newProperties );
@@ -422,10 +440,11 @@
{
props = new Hashtable();
- // add automatic properties including the bundle location (if set)
- setAutoProperties( props, true );
+ // add automatic properties including the bundle location (if
+ // statically bound)
+ setAutoProperties( props, staticallyBound );
}
- else if ( getBundleLocation() != null )
+ else if ( getBundleLocation() != null && staticallyBound )
{
props.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, getBundleLocation() );
}
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
index 1bd31ff..98120b0 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
@@ -135,7 +135,7 @@
private int pmtCount;
// the cache of Factory instances mapped by their factory PID
- private Map factories;
+ private final Map factories = new HashMap();
// the cache of Configuration instances mapped by their PID
// have this always set to prevent NPE on bundle shutdown
@@ -173,7 +173,6 @@
// set up some fields
this.bundleContext = bundleContext;
- this.factories = new HashMap();
// configurationlistener support
configurationListenerTracker = new ServiceTracker( bundleContext, ConfigurationListener.class.getName(), null );
@@ -275,12 +274,18 @@
logTracker.close();
}
- // just ensure the configuration cache is cleared, not cleaning
+ // just ensure the configuration cache is empty
synchronized ( configurations )
{
configurations.clear();
}
+ // just ensure the factory cache is empty
+ synchronized ( factories )
+ {
+ factories.clear();
+ }
+
this.bundleContext = null;
}
@@ -296,11 +301,12 @@
}
- Iterator getCachedConfigurations()
+ ConfigurationImpl[] getCachedConfigurations()
{
synchronized ( configurations )
{
- return configurations.values().iterator();
+ return ( ConfigurationImpl[] ) configurations.values().toArray(
+ new ConfigurationImpl[configurations.size()] );
}
}
@@ -330,6 +336,34 @@
}
+ Factory getCachedFactory( String factoryPid )
+ {
+ synchronized ( factories )
+ {
+ return ( Factory ) factories.get( factoryPid );
+ }
+ }
+
+
+ Factory[] getCachedFactories()
+ {
+ synchronized ( factories )
+ {
+ return ( Factory[] ) factories.values().toArray( new Factory[factories.size()] );
+ }
+ }
+
+
+ void cacheFactory( Factory factory )
+ {
+ synchronized ( factories )
+ {
+ factories.put( factory.getFactoryPid(), factory );
+ }
+ }
+
+
+
// ---------- ConfigurationAdminImpl support -------------------------------
/*
@@ -502,57 +536,32 @@
{
if ( event.getType() == BundleEvent.UNINSTALLED && handleBundleEvents )
{
- String location = event.getBundle().getLocation();
+ final String location = event.getBundle().getLocation();
- try
+ // we only reset dynamic bindings, which are only present in
+ // cached configurations, hence only consider cached configs here
+ final ConfigurationImpl[] configs = getCachedConfigurations();
+ for ( int i = 0; i < configs.length; i++ )
{
- PersistenceManager[] pmList = getPersistenceManagers();
- for ( int i = 0; i < pmList.length; i++ )
+ final ConfigurationImpl cfg = configs[i];
+ if ( location.equals( cfg.getBundleLocation() ) )
{
- Enumeration configs = pmList[i].getDictionaries();
- while ( configs.hasMoreElements() )
- {
- Dictionary config = ( Dictionary ) configs.nextElement();
-
- String pid = ( String ) config.get( Constants.SERVICE_PID );
- if ( pid != null )
- {
- ConfigurationImpl cfg = getCachedConfiguration( pid );
- if ( cfg == null )
- {
- cfg = new ConfigurationImpl( this, pmList[i], config );
- }
-
- if ( location.equals( cfg.getBundleLocation() ) )
- {
- cfg.setBundleLocation( null );
- }
- }
- else
- {
-
- Factory factory = Factory.getFactory( pmList[i], config );
- if ( factory != null )
- {
- Factory cachedFactory = getCachedFactory( factory.getFactoryPid() );
- if ( cachedFactory != null )
- {
- factory = cachedFactory;
- }
-
- if ( location.equals( factory.getBundleLocation() ) )
- {
- factory.setBundleLocation( null );
- }
- }
- }
- }
+ // reset dynamic binding
+ cfg.setBundleLocation( null, false );
}
-
}
- catch ( Exception e )
+
+ // we only reset dynamic bindings, which are only present in
+ // cached factories, hence only consider cached factories here
+ final Factory[] factories = getCachedFactories();
+ for ( int i = 0; i < factories.length; i++ )
{
- log( LogService.LOG_WARNING, "Problem unbinding configurations for bundle " + location, e );
+ final Factory factory = factories[i];
+ if ( location.equals( factory.getBundleLocation() ) )
+ {
+ // reset dynamic binding
+ factory.setBundleLocation( null, false );
+ }
}
}
}
@@ -619,11 +628,10 @@
if ( pid != null )
{
ManagedServiceUpdate update = new ManagedServiceUpdate( pid, sr, service );
- updateThread.schedule( update );
+ updateThread.schedule( update );
+ }
}
- }
-
private void configure( ServiceReference sr, ManagedServiceFactory service )
{
@@ -631,11 +639,10 @@
if ( pid != null )
{
ManagedServiceFactoryUpdate update = new ManagedServiceFactoryUpdate( pid, sr, service );
- updateThread.schedule( update );
+ updateThread.schedule( update );
+ }
}
- }
-
/**
* Factory method to create a new configuration object. The configuration
@@ -647,13 +654,13 @@
* <code>null</code>.
* @param factoryPid
* The factory PID of the new configuration. Not
- * <code>null</code> if the new configuration object belongs to
- * a factory. The configuration object will not be persisted if
+ * <code>null</code> if the new configuration object belongs to a
+ * factory. The configuration object will not be persisted if
* this parameter is not <code>null</code>.
* @param bundleLocation
* The bundle location of the bundle to which the configuration
- * belongs or <code>null</code> if the configuration is not
- * bound yet.
+ * belongs or <code>null</code> if the configuration is not bound
+ * yet.
* @return The new configuration object
* @throws IOException
* May be thrown if an error occurrs persisting the new
@@ -665,24 +672,6 @@
}
- Factory getCachedFactory( String factoryPid )
- {
- synchronized ( factories )
- {
- return ( Factory ) factories.get( factoryPid );
- }
- }
-
-
- void cacheFactory( Factory factory )
- {
- synchronized ( factories )
- {
- factories.put( factory.getFactoryPid(), factory );
- }
- }
-
-
Factory getFactory( String factoryPid ) throws IOException
{
Factory factory = getCachedFactory( factoryPid );
@@ -938,7 +927,8 @@
String bundleLocation = serviceBundle.getLocation();
if ( cfg.getBundleLocation() == null )
{
- cfg.setBundleLocation( bundleLocation );
+ // dynamically bind to the location of the service if unbound
+ cfg.setBundleLocation( bundleLocation, false );
}
else if ( !bundleLocation.equals( cfg.getBundleLocation() ) )
{
@@ -1048,7 +1038,7 @@
if ( factory.getBundleLocation() == null )
{
// bind to the location of the service if unbound
- factory.setBundleLocation( bundleLocation );
+ factory.setBundleLocation( bundleLocation, false );
}
else if ( !bundleLocation.equals( factory.getBundleLocation() ) )
{
@@ -1114,8 +1104,8 @@
// check bundle location of configuration
if ( cfg.getBundleLocation() == null )
{
- // bind to the location of the service if unbound
- cfg.setBundleLocation( bundleLocation );
+ // dynamically bind to the location of the service if unbound
+ cfg.setBundleLocation( bundleLocation, false );
}
else if ( !bundleLocation.equals( cfg.getBundleLocation() ) )
{
@@ -1221,9 +1211,8 @@
String bundleLocation = sr.getBundle().getLocation();
if ( config.getBundleLocation() == null )
{
- // bind to the location of the service if
- // unbound
- config.setBundleLocation( bundleLocation );
+ // dynamically bind to the location of the service if unbound
+ config.setBundleLocation( bundleLocation, false );
}
else if ( !bundleLocation.equals( config.getBundleLocation() ) )
{
@@ -1269,9 +1258,8 @@
String bundleLocation = sr.getBundle().getLocation();
if ( config.getBundleLocation() == null )
{
- // bind to the location of the service if
- // unbound
- config.setBundleLocation( bundleLocation );
+ // dynamically bind to the location of the service if unbound
+ config.setBundleLocation( bundleLocation, false );
}
else if ( !bundleLocation.equals( config.getBundleLocation() ) )
{
@@ -1493,12 +1481,12 @@
if ( pid != null )
{
ConfigurationImpl cfg = cm.getCachedConfiguration( pid );
- if ( cfg != null && reference.equals( cfg.getServiceReference() ) )
- {
- cfg.setServiceReference( null );
- cfg.setDelivered( false );
+ if ( cfg != null && reference.equals( cfg.getServiceReference() ) )
+ {
+ cfg.setServiceReference( null );
+ cfg.setDelivered( false );
+ }
}
- }
super.removedService( reference, service );
}
@@ -1556,6 +1544,7 @@
return serviceObject;
}
+
public void removedService( ServiceReference reference, Object service )
{
// check whether we can take back the configuration objects
@@ -1563,19 +1552,19 @@
if ( factoryPid != null )
{
Factory factory = cm.getCachedFactory( factoryPid );
- if ( factory != null )
- {
- for ( Iterator pi = factory.getPIDs().iterator(); pi.hasNext(); )
+ if ( factory != null )
{
- String pid = ( String ) pi.next();
- ConfigurationImpl cfg = cm.getCachedConfiguration( pid );
- if ( cfg != null )
+ for ( Iterator pi = factory.getPIDs().iterator(); pi.hasNext(); )
{
- cfg.setDelivered( false );
+ String pid = ( String ) pi.next();
+ ConfigurationImpl cfg = cm.getCachedConfiguration( pid );
+ if ( cfg != null )
+ {
+ cfg.setDelivered( false );
+ }
}
}
}
- }
super.removedService( reference, service );
}
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/Factory.java b/configadmin/src/main/java/org/apache/felix/cm/impl/Factory.java
index 958ce9f..366090d 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/Factory.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/Factory.java
@@ -49,6 +49,9 @@
// the bundle location to which factory PID mapping is bound
private String bundleLocation;
+ // whether the factory is statically bound to a bundle or not
+ private boolean staticallyBound;
+
// the set of configuration PIDs belonging to this factory
private Set pids;
@@ -89,7 +92,9 @@
{
this.persistenceManager = persistenceManager;
this.factoryPid = factoryPid;
- pids = new HashSet();
+ this.pids = new HashSet();
+ this.bundleLocation = null;
+ this.staticallyBound = false;
}
@@ -98,7 +103,8 @@
this( persistenceManager, factoryPid );
// set bundle location
- bundleLocation = ( String ) props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ this.bundleLocation = ( String ) props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+ this.staticallyBound = this.bundleLocation != null;
// set pids
String[] pidList = ( String[] ) props.get( FACTORY_PID_LIST );
@@ -130,12 +136,20 @@
}
- void setBundleLocation( String bundleLocation )
+ void setBundleLocation( String bundleLocation, boolean staticBinding )
{
- this.bundleLocation = bundleLocation;
+ if ( staticBinding )
+ {
+ this.bundleLocation = bundleLocation;
+ this.staticallyBound = true;
- // 104.15.2.8 The bundle location will be set persistently
- storeSilently();
+ // 104.15.2.8 The bundle location will be set persistently
+ storeSilently();
+ }
+ else if ( !this.staticallyBound )
+ {
+ this.bundleLocation = bundleLocation;
+ }
}
@@ -161,7 +175,7 @@
{
Hashtable props = new Hashtable();
- if ( bundleLocation != null )
+ if ( bundleLocation != null && staticallyBound )
{
props.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, this.getBundleLocation() );
}