FELIX-3740 Track MetaTypeProvider services in the MetaTypeServiceImpl
instead of in the MetaTypeInformationImpl objects.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1403000 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeInformationImpl.java b/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeInformationImpl.java
index 7b5e5b4..02b0314 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeInformationImpl.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeInformationImpl.java
@@ -57,8 +57,6 @@
private final Map metaTypeProviders;
- private final MetaTypeProviderTracker providerTacker;
-
private Set locales;
@@ -68,16 +66,11 @@
this.pids = new HashSet();
this.factoryPids = new HashSet();
this.metaTypeProviders = new HashMap();
-
- this.providerTacker = new MetaTypeProviderTracker( serviceBundleContext, this );
- this.providerTacker.open();
}
void dispose()
{
- this.providerTacker.close();
-
this.pids.clear();
this.factoryPids.clear();
this.locales = null;
diff --git a/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeProviderTracker.java b/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeProviderTracker.java
index c4417ba..196e2b4 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeProviderTracker.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeProviderTracker.java
@@ -30,28 +30,29 @@
public class MetaTypeProviderTracker extends ServiceTracker
{
- final MetaTypeInformationImpl mti;
+ final MetaTypeServiceImpl mti;
- public MetaTypeProviderTracker( BundleContext context, final MetaTypeInformationImpl mti )
+ public MetaTypeProviderTracker( BundleContext context, final String serviceType, final MetaTypeServiceImpl mti )
{
- super( context, MetaTypeProvider.class, null );
+ super( context, serviceType, null );
this.mti = mti;
}
public Object addingService( ServiceReference reference )
{
- // only care for services of our bundle
- if ( !this.mti.getBundle().equals( reference.getBundle() ) )
+ final Object service = this.context.getService( reference );
+ final RegistrationPropertyHolder rph;
+ if ( service instanceof MetaTypeProvider )
{
- return null;
+ rph = new RegistrationPropertyHolder( reference, ( MetaTypeProvider ) service );
+ rph.addMetaTypeProvider( this.mti );
}
-
- final MetaTypeProvider mtp = ( MetaTypeProvider ) this.context.getService( reference );
- final RegistrationPropertyHolder rph = new RegistrationPropertyHolder( reference, mtp );
-
- rph.addMetaTypeProvider( this.mti );
+ else
+ {
+ rph = null;
+ }
return rph;
}
@@ -59,22 +60,23 @@
public void modifiedService( ServiceReference reference, Object service )
{
- RegistrationPropertyHolder rph = ( RegistrationPropertyHolder ) service;
- rph.update( this.mti, reference );
+ ( ( RegistrationPropertyHolder ) service ).update( this.mti );
}
public void removedService( ServiceReference reference, Object service )
{
- RegistrationPropertyHolder rph = ( RegistrationPropertyHolder ) service;
- rph.removeMetaTypeProvider( this.mti );
+ ( ( RegistrationPropertyHolder ) service ).removeMetaTypeProvider( this.mti );
this.context.ungetService( reference );
}
- private static class RegistrationPropertyHolder
+
+ static class RegistrationPropertyHolder
{
private String[] pids;
private String[] factoryPids;
+
+ private final ServiceReference reference;
private final MetaTypeProvider provider;
@@ -83,6 +85,8 @@
this.pids = ServiceMetaTypeInformation.getStringPlus( reference, MetaTypeProvider.METATYPE_PID );
this.factoryPids = ServiceMetaTypeInformation.getStringPlus( reference,
MetaTypeProvider.METATYPE_FACTORY_PID );
+
+ this.reference = reference;
this.provider = provider;
}
@@ -93,38 +97,50 @@
}
- void addMetaTypeProvider( final MetaTypeInformationImpl mti )
+ String[] getPids()
+ {
+ return pids;
+ }
+
+
+ String[] getFactoryPids()
+ {
+ return factoryPids;
+ }
+
+
+ void addMetaTypeProvider( final MetaTypeServiceImpl mti )
{
if ( pids != null )
{
- mti.addSingletonMetaTypeProvider( pids, provider );
+ mti.addSingletonMetaTypeProvider( reference.getBundle(), pids, provider );
}
if ( factoryPids != null )
{
- mti.addFactoryMetaTypeProvider( factoryPids, provider );
+ mti.addFactoryMetaTypeProvider( reference.getBundle(), factoryPids, provider );
}
}
- void removeMetaTypeProvider( final MetaTypeInformationImpl mti )
+ void removeMetaTypeProvider( final MetaTypeServiceImpl mti )
{
if ( pids != null )
{
- mti.removeSingletonMetaTypeProvider( pids );
+ mti.removeSingletonMetaTypeProvider( reference.getBundle(), pids );
}
if ( factoryPids != null )
{
- mti.removeFactoryMetaTypeProvider( factoryPids );
+ mti.removeFactoryMetaTypeProvider( reference.getBundle(), factoryPids );
}
}
- void update( final MetaTypeInformationImpl mti, final ServiceReference reference )
+ void update( final MetaTypeServiceImpl mti )
{
- String[] pids = ServiceMetaTypeInformation.getStringPlus( reference, MetaTypeProvider.METATYPE_PID );
- String[] factoryPids = ServiceMetaTypeInformation.getStringPlus( reference,
+ String[] pids = ServiceMetaTypeInformation.getStringPlus( this.reference, MetaTypeProvider.METATYPE_PID );
+ String[] factoryPids = ServiceMetaTypeInformation.getStringPlus( this.reference,
MetaTypeProvider.METATYPE_FACTORY_PID );
if ( !Arrays.equals( pids, this.pids ) || !Arrays.equals( factoryPids, this.factoryPids ) )
diff --git a/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeServiceImpl.java b/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeServiceImpl.java
index b52e4eb..67de54c 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeServiceImpl.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/internal/MetaTypeServiceImpl.java
@@ -20,20 +20,24 @@
import java.io.IOException;
+import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.Enumeration;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.felix.metatype.MetaData;
import org.apache.felix.metatype.MetaDataReader;
+import org.apache.felix.metatype.internal.MetaTypeProviderTracker.RegistrationPropertyHolder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.log.LogService;
import org.osgi.service.metatype.MetaTypeInformation;
+import org.osgi.service.metatype.MetaTypeProvider;
import org.osgi.service.metatype.MetaTypeService;
@@ -52,6 +56,7 @@
private final Map bundleMetaTypeInformation;
+ private final MetaTypeProviderTracker providerTracker;
/**
* Creates an instance of this class.
@@ -62,26 +67,19 @@
MetaTypeServiceImpl( BundleContext bundleContext )
{
this.bundleContext = bundleContext;
- this.bundleMetaTypeInformation = new HashMap();
+ this.bundleMetaTypeInformation = new ConcurrentHashMap();
bundleContext.addBundleListener( this );
+
+ this.providerTracker = new MetaTypeProviderTracker( bundleContext, MetaTypeProvider.class.getName(), this );
+ this.providerTracker.open();
}
void dispose()
{
- MetaTypeInformationImpl[] mti;
- synchronized ( bundleMetaTypeInformation )
- {
- mti = ( MetaTypeInformationImpl[] ) this.bundleMetaTypeInformation.values().toArray(
- new MetaTypeInformationImpl[bundleMetaTypeInformation.values().size()] );
- this.bundleMetaTypeInformation.clear();
- }
-
- for ( int i = 0; i < mti.length; i++ )
- {
- mti[i].dispose();
- }
+ this.providerTracker.close();
+ this.bundleMetaTypeInformation.clear();
}
@@ -89,16 +87,15 @@
{
if ( event.getType() == BundleEvent.STOPPING )
{
- MetaTypeInformationImpl mti;
- synchronized ( this.bundleMetaTypeInformation )
+ SoftReference mtir = ( SoftReference ) this.bundleMetaTypeInformation.remove( new Long( event.getBundle()
+ .getBundleId() ) );
+ if ( mtir != null )
{
- mti = ( MetaTypeInformationImpl ) this.bundleMetaTypeInformation.remove( new Long( event.getBundle()
- .getBundleId() ) );
- }
-
- if ( mti != null )
- {
- mti.dispose();
+ MetaTypeInformationImpl mti = ( MetaTypeInformationImpl ) mtir.get();
+ if ( mti != null )
+ {
+ mti.dispose();
+ }
}
}
}
@@ -123,12 +120,7 @@
return null;
}
- MetaTypeInformation mti;
- synchronized ( this.bundleMetaTypeInformation )
- {
- mti = ( MetaTypeInformation ) this.bundleMetaTypeInformation.get( new Long( bundle.getBundleId() ) );
- }
-
+ MetaTypeInformationImpl mti = getMetaTypeInformationInternal( bundle );
if ( mti == null )
{
mti = fromDocuments( bundle );
@@ -138,17 +130,14 @@
}
MetaTypeInformationImpl impl = null;
- synchronized ( this.bundleMetaTypeInformation )
+ if ( bundle.getState() == Bundle.ACTIVE )
{
- if ( bundle.getState() == Bundle.ACTIVE )
- {
- this.bundleMetaTypeInformation.put( new Long( bundle.getBundleId() ), mti );
- }
- else
- {
- impl = ( MetaTypeInformationImpl ) mti;
- mti = null;
- }
+ putMetaTypeInformationInternal( bundle, mti );
+ }
+ else
+ {
+ impl = mti;
+ mti = null;
}
if ( impl != null )
@@ -161,7 +150,7 @@
}
- private MetaTypeInformation fromDocuments( Bundle bundle )
+ private MetaTypeInformationImpl fromDocuments( Bundle bundle )
{
MetaDataReader reader = new MetaDataReader();
@@ -191,4 +180,82 @@
}
return cmti;
}
+
+
+ protected void addSingletonMetaTypeProvider( final Bundle bundle, final String[] pids, MetaTypeProvider mtp )
+ {
+ MetaTypeInformationImpl mti = getMetaTypeInformationInternal( bundle );
+ if ( mti != null )
+ {
+ mti.addSingletonMetaTypeProvider( pids, mtp );
+ }
+ }
+
+
+ protected void addFactoryMetaTypeProvider( final Bundle bundle, final String[] factoryPids, MetaTypeProvider mtp )
+ {
+ MetaTypeInformationImpl mti = getMetaTypeInformationInternal( bundle );
+ if ( mti != null )
+ {
+ mti.addFactoryMetaTypeProvider( factoryPids, mtp );
+ }
+ }
+
+
+ protected boolean removeSingletonMetaTypeProvider( final Bundle bundle, final String[] pids )
+ {
+ MetaTypeInformationImpl mti = getMetaTypeInformationInternal( bundle );
+ if ( mti != null )
+ {
+ return mti.removeSingletonMetaTypeProvider( pids );
+ }
+ return false;
+ }
+
+
+ protected boolean removeFactoryMetaTypeProvider( final Bundle bundle, final String[] factoryPids )
+ {
+ MetaTypeInformationImpl mti = getMetaTypeInformationInternal( bundle );
+ if ( mti != null )
+ {
+ return mti.removeFactoryMetaTypeProvider( factoryPids );
+ }
+ return false;
+ }
+
+
+ private void putMetaTypeInformationInternal( final Bundle bundle, final MetaTypeInformationImpl mti )
+ {
+ final ServiceReference refs[] = this.providerTracker.getServiceReferences();
+ if ( refs != null )
+ {
+ for ( int i = 0; i < refs.length; i++ )
+ {
+ ServiceReference ref = refs[i];
+ if ( bundle.equals( ref.getBundle() ) )
+ {
+ final MetaTypeProviderTracker.RegistrationPropertyHolder holder = ( RegistrationPropertyHolder ) this.providerTracker
+ .getService( ref );
+ if ( holder.getPids() != null )
+ {
+ mti.addSingletonMetaTypeProvider( holder.getPids(), holder.getProvider() );
+ }
+ if ( holder.getFactoryPids() != null )
+ {
+ mti.addFactoryMetaTypeProvider( holder.getFactoryPids(), holder.getProvider() );
+ }
+ }
+ }
+ }
+
+ this.bundleMetaTypeInformation.put( new Long( bundle.getBundleId() ),
+ new SoftReference( mti ) );
+ }
+
+
+ private MetaTypeInformationImpl getMetaTypeInformationInternal( final Bundle bundle )
+ {
+ SoftReference mtir = ( SoftReference ) this.bundleMetaTypeInformation.get( new Long( bundle.getBundleId() ) );
+ return ( MetaTypeInformationImpl ) ( ( mtir == null ) ? null : mtir.get() );
+ }
}