Simplify component service objects handling
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1691603 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
index a1be501..31ff915 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
@@ -40,9 +40,7 @@
{
private final BundleContext bundleContext;
- private final Map<ServiceReference, ServiceObjects> serviceObjectsMap = new HashMap<ServiceReference, ServiceObjects>();
-
- private final Map<ServiceObjects, List<Object>> services = new HashMap<ServiceObjects, List<Object>>();
+ private final Map<ServiceReference<?>, ComponentServiceObjectsImpl> services = new HashMap<ServiceReference<?>, ComponentServiceObjectsImpl>();
private final ConcurrentMap<ServiceReference, Object> prototypeInstances = new ConcurrentHashMap<ServiceReference, Object>();
@@ -55,15 +53,11 @@
{
synchronized ( this )
{
- for(final Map.Entry<ServiceObjects, List<Object>> entry : services.entrySet())
+ for(final Map.Entry<ServiceReference<?>, ComponentServiceObjectsImpl> entry : services.entrySet())
{
- for(final Object service : entry.getValue())
- {
- entry.getKey().ungetService(service);
- }
+ entry.getValue().close();
}
services.clear();
- serviceObjectsMap.clear();
}
prototypeInstances.clear();
}
@@ -72,67 +66,33 @@
{
synchronized ( this )
{
- ServiceObjects<?> so = this.serviceObjectsMap.get(ref);
- if ( so == null )
+ ComponentServiceObjectsImpl cso = this.services.get(ref);
+ if ( cso == null )
{
- so = this.bundleContext.getServiceObjects(ref);
- if ( so != null )
+ final ServiceObjects serviceObjects = this.bundleContext.getServiceObjects(ref);
+ if ( serviceObjects != null )
{
- this.serviceObjectsMap.put(ref, so);
+ cso = new ComponentServiceObjectsImpl(serviceObjects);
+ this.services.put(ref, cso);
}
}
-
- if ( so != null )
- {
- List<Object> services = this.services.get(so);
- if ( services == null )
- {
- services = new ArrayList<Object>();
- this.services.put(so, services);
- }
- final ServiceObjects serviceObjects = so;
- final List<Object> serviceList = services;
-
- return new ComponentServiceObjects()
- {
-
- public Object getService()
- {
- final Object service = serviceObjects.getService();
- if ( service != null )
- {
- synchronized ( serviceList )
- {
- serviceList.add(service);
- }
- }
- return service;
- }
-
- public void ungetService(final Object service)
- {
- boolean remove;
- synchronized ( serviceList )
- {
- remove = serviceList.remove(service);
- }
- if ( remove ) {
- serviceObjects.ungetService(service);
- }
- }
-
- public ServiceReference<?> getServiceReference()
- {
- return ref;
- }
- };
- }
+ return cso;
}
- return null;
}
-
- public <T> T getPrototypeRefInstance(final ServiceReference<T> ref, ServiceObjects<T> serviceObjects)
+ public void closeServiceObjects(final ServiceReference<?> ref) {
+ ComponentServiceObjectsImpl cso;
+ synchronized ( this )
+ {
+ cso = this.services.remove(ref);
+ }
+ if ( cso != null )
+ {
+ cso.close();
+ }
+ }
+
+ public <T> T getPrototypeRefInstance(final ServiceReference<T> ref, ServiceObjects<T> serviceObjects)
{
T service = (T) prototypeInstances.get(ref);
if ( service == null )
@@ -148,5 +108,91 @@
}
return service;
}
-
+
+ private static final class ComponentServiceObjectsImpl implements ComponentServiceObjects
+ {
+ private final List<Object> instances = new ArrayList<Object>();
+
+ private volatile ServiceObjects serviceObjects;
+
+ public ComponentServiceObjectsImpl(final ServiceObjects so)
+ {
+ this.serviceObjects = so;
+ }
+
+ /**
+ * Close this instance and unget all services.
+ */
+ public void close()
+ {
+ final ServiceObjects so = this.serviceObjects;
+ this.serviceObjects = null;
+ if ( so != null )
+ {
+ synchronized ( this.instances )
+ {
+ for(final Object obj : instances)
+ {
+ try
+ {
+ so.ungetService(obj);
+ }
+ catch ( final IllegalStateException ise )
+ {
+ // ignore (this happens if the bundle is not valid anymore)
+ }
+ catch ( final IllegalArgumentException iae )
+ {
+ // ignore (this happens if the service has not been returned by the service objects)
+ }
+ }
+ this.instances.clear();
+ }
+ }
+ }
+
+ public Object getService()
+ {
+ final ServiceObjects so = this.serviceObjects;
+ Object service = null;
+ if ( so != null )
+ {
+ service = so.getService();
+ if ( service != null )
+ {
+ synchronized ( this.instances )
+ {
+ this.instances.add(service);
+ }
+ }
+ }
+ return service;
+ }
+
+ public void ungetService(final Object service)
+ {
+ final ServiceObjects so = this.serviceObjects;
+ if ( so != null )
+ {
+ boolean remove;
+ synchronized ( instances )
+ {
+ remove = instances.remove(service);
+ }
+ if ( remove ) {
+ so.ungetService(service);
+ }
+ }
+ }
+
+ public ServiceReference<?> getServiceReference()
+ {
+ final ServiceObjects so = this.serviceObjects;
+ if ( so != null )
+ {
+ return so.getServiceReference();
+ }
+ return null;
+ }
+ }
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
index 38f24b9..5a767a4 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
@@ -26,7 +26,6 @@
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -478,7 +477,7 @@
private boolean initField(final Object componentInstance,
final SimpleLogger logger )
{
- if ( valueType == ParamType.ignore )
+ if ( valueType == ParamType.ignore )
{
return true;
}
@@ -514,10 +513,10 @@
valueType = ParamType.ignore;
return true;
}
- if ( fieldType == ClassUtils.LIST_CLASS )
+ if ( fieldType == ClassUtils.LIST_CLASS )
{
this.setFieldValue(componentInstance, new CopyOnWriteArrayList<Object>());
- }
+ }
else
{
this.setFieldValue(componentInstance, new CopyOnWriteArraySet<Object>());
@@ -569,7 +568,7 @@
if ( !this.metadata.isMultiple() )
{
// unary references
-
+
// unbind needs only be done, if reference is dynamic and optional
if ( mType == METHOD_TYPE.UNBIND )
{
@@ -648,13 +647,13 @@
// updated needs only be done, if the value type is map or tuple
else if ( mType == METHOD_TYPE.UPDATED)
{
- if ( this.valueType == ParamType.map || this.valueType == ParamType.tuple )
+ if ( this.valueType == ParamType.map || this.valueType == ParamType.tuple )
{
if ( !this.metadata.isStatic() )
{
final Object obj = getValue(key, refPair);
final Object oldObj = this.boundValues.put(refPair, obj);
-
+
if ( metadata.isReplace() )
{
this.setFieldValue(componentInstance, getReplaceCollection());
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
index 693d89c..eea9808 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
@@ -19,7 +19,6 @@
package org.apache.felix.scr.impl.helper;
import org.apache.felix.scr.impl.metadata.DSVersion;
-import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
/**
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/UpdatedMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/UpdatedMethod.java
index 6bf0ff7..72ef123 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/UpdatedMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/UpdatedMethod.java
@@ -19,7 +19,6 @@
package org.apache.felix.scr.impl.helper;
import org.apache.felix.scr.impl.metadata.DSVersion;
-import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
/**
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 8f40b64..8500fe5 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -270,7 +270,7 @@
public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
{
- refPair.setDeleted( true );
+ refPair.markDeleted();
if ( !cardinalitySatisfied( getTracker().getServiceCount() ) )
{
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
@@ -358,7 +358,7 @@
public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
- refPair.setDeleted( true );
+ refPair.markDeleted();
boolean unbind = cardinalitySatisfied( getTracker().getServiceCount() );
if ( unbind )
{
@@ -479,7 +479,7 @@
public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
- refPair.setDeleted( true );
+ refPair.markDeleted();
tracked( trackingCount );
if ( isActive() )
{
@@ -587,7 +587,7 @@
public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
- refPair.setDeleted( true );
+ refPair.markDeleted();
tracked( trackingCount );
Collection<RefPair<S, T>> refs = this.refs.get();
if ( isActive() && refs != null )
@@ -764,7 +764,7 @@
public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
- refPair.setDeleted( true );
+ refPair.markDeleted();
boolean deactivate = false;
boolean untracked = true;
RefPair<S, T> oldRefPair = null;
@@ -966,15 +966,15 @@
this.refPair = null;
}
}
- m_componentManager.activateInternal( );
+ m_componentManager.activateInternal( );
}
- m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
+ m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
- refPair.setDeleted( true );
+ refPair.markDeleted();
this.trackingCount = trackingCount;
tracked( trackingCount );
boolean reactivate;
@@ -1747,6 +1747,7 @@
{
m_componentManager.setServiceProperties( methodResult );
}
+ componentContext.getComponentServiceObjectsHelper().closeServiceObjects(refPair.getRef());
}
else
{
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
index da2f1a9..f381aa3 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
@@ -51,11 +51,11 @@
}
public abstract boolean getServiceObject( ComponentContextImpl<S> key, BundleContext context, SimpleLogger logger );
-
+
public abstract T getServiceObject(ComponentContextImpl<S> key);
public abstract boolean setServiceObject( ComponentContextImpl<S> key, T serviceObject );
-
+
public abstract T unsetServiceObject(ComponentContextImpl<S> key);
public void setFailed( )
@@ -73,10 +73,8 @@
return deleted;
}
- public void setDeleted(boolean deleted)
+ public void markDeleted()
{
- this.deleted = deleted;
+ this.deleted = true;
}
-
-
}