summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java37
-rw-r--r--sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java65
-rw-r--r--sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java12
-rw-r--r--sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java2
-rw-r--r--sca-java-2.x/trunk/modules/domain-node/pom.xml9
-rw-r--r--sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java29
-rw-r--r--sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaElementImpl.java27
-rw-r--r--sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java9
-rw-r--r--sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java47
9 files changed, 200 insertions, 37 deletions
diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
index 5d084d9289..8d84e0352e 100644
--- a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
+++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.tuscany.sca.interfacedef.impl;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -44,8 +45,8 @@ import org.apache.tuscany.sca.interfacedef.DataType;
*/
public class DataTypeImpl<L> implements DataType<L> {
private String dataBinding;
- private Class<?> physical;
- private Type genericType;
+ private WeakReference<Class<?>> physical;
+ private WeakReference<Type> genericType;
private L logical;
private Map<Class<?>, Object> metaDataMap;
@@ -78,8 +79,8 @@ public class DataTypeImpl<L> implements DataType<L> {
public DataTypeImpl(String dataBinding, Class<?> physical, Type genericType, L logical) {
super();
this.dataBinding = dataBinding;
- this.physical = physical;
- this.genericType = genericType;
+ this.physical = new WeakReference<Class<?>>(physical);
+ this.genericType = new WeakReference<Type>(genericType);
this.logical = logical;
}
@@ -89,14 +90,14 @@ public class DataTypeImpl<L> implements DataType<L> {
* @return the physical type used by the runtime
*/
public Class<?> getPhysical() {
- return physical;
+ return physical.get();
}
/**
* @param physical the physical to set
*/
public void setPhysical(Class<?> physical) {
- this.physical = physical;
+ this.physical = new WeakReference<Class<?>>(physical);
}
/**
@@ -104,7 +105,7 @@ public class DataTypeImpl<L> implements DataType<L> {
* @return The java generic type
*/
public Type getGenericType() {
- return genericType;
+ return genericType.get();
}
/**
@@ -112,7 +113,7 @@ public class DataTypeImpl<L> implements DataType<L> {
* @param genericType
*/
public void setGenericType(Type genericType) {
- this.genericType = genericType;
+ this.genericType = new WeakReference<Type>(genericType);
}
/**
@@ -156,8 +157,8 @@ public class DataTypeImpl<L> implements DataType<L> {
StringBuilder b = new StringBuilder( 256 );
b.append( "DataType[" );
b.append( "dataBinding=" + ((dataBinding==null) ? "null" : dataBinding) );
- b.append( ", genericType=" + ((genericType==null) ? "null" : genericType) );
- b.append( ", physical=" + ((physical==null) ? "null" : physical) );
+ b.append( ", genericType=" + ((genericType==null || genericType.get() == null) ? "null" : genericType) );
+ b.append( ", physical=" + ((physical==null || physical.get() == null) ? "null" : physical) );
b.append( ", logical=" + ((logical==null) ? "null" : logical) );
b.append( ", metaData size=" + ((metaDataMap==null) ? "0" : metaDataMap.size()) );
b.append( "]" );
@@ -190,9 +191,9 @@ public class DataTypeImpl<L> implements DataType<L> {
final int prime = 31;
int result = 1;
result = prime * result + ((dataBinding == null) ? 0 : dataBinding.hashCode());
- result = prime * result + ((genericType == null) ? 0 : genericType.hashCode());
+ result = prime * result + ((genericType == null || genericType.get() == null) ? 0 : genericType.hashCode());
result = prime * result + ((logical == null) ? 0 : logical.hashCode());
- result = prime * result + ((physical == null) ? 0 : physical.hashCode());
+ result = prime * result + ((physical == null || physical.get() == null) ? 0 : physical.hashCode());
return result;
}
@@ -210,20 +211,20 @@ public class DataTypeImpl<L> implements DataType<L> {
return false;
} else if (!dataBinding.equals(other.dataBinding))
return false;
- if (genericType == null) {
- if (other.genericType != null)
+ if (genericType == null || genericType.get() == null) {
+ if (other.genericType != null && other.genericType.get() != null)
return false;
- } else if (!genericType.equals(other.genericType))
+ } else if (!genericType.get().equals(other.genericType.get()))
return false;
if (logical == null) {
if (other.logical != null)
return false;
} else if (!logical.equals(other.logical))
return false;
- if (physical == null) {
- if (other.physical != null)
+ if (physical == null || physical.get() == null) {
+ if (other.physical != null && other.physical.get() != null)
return false;
- } else if (!physical.equals(other.physical))
+ } else if (!physical.get().equals(other.physical.get()))
return false;
return true;
}
diff --git a/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java b/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
index 77b6b619ad..5ddf7d3604 100644
--- a/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
+++ b/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
@@ -59,6 +59,7 @@ import javax.xml.transform.Source;
import org.apache.tuscany.sca.common.java.collection.LRUCache;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.extensibility.ClassLoaderContext;
+import org.oasisopen.sca.ServiceRuntimeException;
/**
* @version $Rev$ $Date$
@@ -403,6 +404,12 @@ public class JAXBContextCache {
}
}
}
+ public void removeCtx(K key){
+ Map<K,List<V>> map = softMap.get();
+ if (map !=null && key !=null){
+ map.remove(key);
+ }
+ }
}
/**
@@ -566,5 +573,61 @@ public class JAXBContextCache {
}
}
-}
+ public void removeJAXBContextFromPools(JAXBContext ctx){
+ if (mpool != null && ctx != null){
+ mpool.removeCtx(ctx);
+ }
+ if (upool != null && ctx !=null){
+ upool.removeCtx(ctx);
+ }
+ }
+
+ /**
+ * Removes all the cached information relating to a contribution. The
+ * contribution is identified by the contribution classloader passed in
+ * as a parameter. This is used when a contribution is removed from
+ * the runtime.
+ *
+ * @param contributionClassloader
+ */
+ public void removeJAXBContextForContribution(ClassLoader contributionClassloader){
+ if (cache != null){
+ try {
+ synchronized(cache) {
+ Set<Object> objSet = cache.keySet();
+ List<Object> toRemove = new ArrayList<Object>();
+ Iterator<Object> i = objSet.iterator();
+ while(i.hasNext()) {
+ Object obj = i.next();
+ if (obj instanceof Set){
+ Set<Class> innerSet = (Set<Class>)obj;
+ Iterator<Class> j = innerSet.iterator();
+ loop:
+ while(j.hasNext()) {
+ Class cls = j.next();
+ ClassLoader cl = cls.getClassLoader();
+ while (cl != null){
+ if (cl == contributionClassloader){
+ toRemove.add(obj);
+ break loop;
+ }
+ // take account of generated classes
+ cl = cl.getParent();
+ }
+ }
+ }
+ }
+ for (Object obj : toRemove){
+ JAXBContext ctx = cache.get(obj);
+ removeJAXBContextFromPools(ctx);
+ cache.remove(obj);
+ }
+ }
+ } catch(Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+ }
+
+}
diff --git a/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java b/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
index 1837e43c36..44c172a07a 100644
--- a/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
+++ b/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
@@ -66,7 +66,7 @@ import org.apache.tuscany.sca.interfacedef.util.XMLType;
*
* @version $Rev$ $Date$
*/
-// FIXME: [rfeng] We probably should turn this into a pluggable system service
+
public final class JAXBContextHelper {
private final JAXBContextCache cache;
private final static SimpleTypeMapper SIMPLE_TYPE_MAPPER = new SimpleTypeMapperImpl();
@@ -587,4 +587,14 @@ public final class JAXBContextHelper {
return name.substring(0, decap).toLowerCase() + name.substring(decap);
}
+ public void removeJAXBContextForContribution(ClassLoader contributionClassloader){
+ cache.removeJAXBContextForContribution(contributionClassloader);
+ }
+
+ /**
+ * Just for testing that the cache is being removed on stop
+ */
+ public JAXBContextCache getJAXBContextCache(){
+ return cache;
+ }
}
diff --git a/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java b/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java
index 0725237936..ae9a869417 100644
--- a/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java
+++ b/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java
@@ -226,7 +226,7 @@ public class DeployerImpl implements Deployer {
// Add the (empty) matchingExports List and report a warning
import_.setModelResolver(new DefaultImportModelResolver(matchingExports));
- // push context here as the "stack" in this case is a list of nexted contributions
+ // push context here as the "stack" in this case is a list of nested contributions
// through which imports have been chased which may not make much sense to the
// user so just report the contribution in error
monitor.pushContext("Contribution: " + contribution.getURI());
diff --git a/sca-java-2.x/trunk/modules/domain-node/pom.xml b/sca-java-2.x/trunk/modules/domain-node/pom.xml
index 7f012c48a3..56092a1f9d 100644
--- a/sca-java-2.x/trunk/modules/domain-node/pom.xml
+++ b/sca-java-2.x/trunk/modules/domain-node/pom.xml
@@ -37,12 +37,19 @@
<artifactId>tuscany-node-impl</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
+
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-assembly-xml</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-databinding-jaxb</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-implementation-java-runtime</artifactId>
@@ -55,7 +62,7 @@
<artifactId>tuscany-data-api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>test</scope>
- </dependency>
+ </dependency>
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
diff --git a/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java b/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java
index e95dd9f699..9ee36c1e38 100644
--- a/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java
+++ b/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java
@@ -38,6 +38,7 @@ import javax.xml.stream.XMLStreamException;
import org.apache.tuscany.sca.Node;
import org.apache.tuscany.sca.TuscanyRuntime;
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Composite;
import org.apache.tuscany.sca.assembly.xml.Utils;
import org.apache.tuscany.sca.common.java.io.IOHelper;
@@ -51,8 +52,11 @@ import org.apache.tuscany.sca.contribution.resolver.ClassReference;
import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver;
import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper;
import org.apache.tuscany.sca.deployment.Deployer;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.ValidationException;
import org.apache.tuscany.sca.runtime.ActivationException;
@@ -73,6 +77,8 @@ public class NodeImpl implements Node {
private CompositeActivator compositeActivator;
private DomainRegistry domainRegistry;
private ExtensionPointRegistry extensionPointRegistry;
+ private UtilityExtensionPoint utilityExtensionPoint;
+ private FactoryExtensionPoint factoryExtensionPoint;
private TuscanyRuntime tuscanyRuntime;
private Map<String, Contribution> loadedContributions = new ConcurrentHashMap<String, Contribution>();
@@ -95,8 +101,11 @@ public class NodeImpl implements Node {
this.domainRegistry = domainRegistry;
this.extensionPointRegistry = extensionPointRegistry;
this.tuscanyRuntime = tuscanyRuntime;
-
- extensionPointRegistry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(ActiveNodes.class).getActiveNodes().add(this);
+
+ utilityExtensionPoint = extensionPointRegistry.getExtensionPoint(UtilityExtensionPoint.class);
+ factoryExtensionPoint = extensionPointRegistry.getExtensionPoint(FactoryExtensionPoint.class);
+
+ utilityExtensionPoint.getUtility(ActiveNodes.class).getActiveNodes().add(this);
domainRegistry.addContributionListener(new ContributionListener() {
public void contributionInstalled(String uri) {
@@ -226,6 +235,21 @@ public class NodeImpl implements Node {
}
public void uninstallContribution(String contributionURI) {
+ // give the runtime the chance to release only artifacts
+ // held by this contribution (and its classloader)
+ Contribution contribution = loadedContributions.get(contributionURI);
+ if (contribution != null) {
+ ClassLoader contributionClassloader = contribution.getClassLoader();
+
+ // These are very specific at the moment as there is no
+ // common lifecycle interface at this level
+ JAXBContextHelper jaxbContextHelper = utilityExtensionPoint.getUtility(JAXBContextHelper.class);
+ jaxbContextHelper.removeJAXBContextForContribution(contributionClassloader);
+
+ JavaInterfaceFactory javaInterfaceFactory = factoryExtensionPoint.getFactory(JavaInterfaceFactory.class);
+ javaInterfaceFactory.removeInterfacesForContribution(contributionClassloader);
+ }
+
domainRegistry.uninstallContribution(contributionURI);
// remove any stopped composite that used the contribution
@@ -236,6 +260,7 @@ public class NodeImpl implements Node {
i.remove();
}
}
+
if (logger.isLoggable(quietLogging? Level.FINE : Level.INFO)) logger.log(quietLogging? Level.FINE : Level.INFO, "uninstallContribution: " + contributionURI);
}
diff --git a/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaElementImpl.java b/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaElementImpl.java
index e748a5f6fa..44dec0376a 100644
--- a/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaElementImpl.java
+++ b/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaElementImpl.java
@@ -21,6 +21,7 @@ package org.apache.tuscany.sca.implementation.java;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
+import java.lang.ref.WeakReference;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -36,8 +37,8 @@ import java.lang.reflect.Type;
public class JavaElementImpl {
private AnnotatedElement anchor;
private ElementType elementType;
- private Class<?> type;
- private Type genericType;
+ private WeakReference<Class<?>> type;
+ private WeakReference<Type> genericType;
private int index = -1;
private String name;
private Class<? extends Annotation> classifer;
@@ -45,24 +46,24 @@ public class JavaElementImpl {
public JavaElementImpl(Class<?> cls) {
this.anchor = cls;
this.elementType = ElementType.TYPE;
- this.type = cls;
- this.genericType = cls;
+ this.type = new WeakReference<Class<?>>(cls);
+ this.genericType = new WeakReference<Type>(cls);
this.name = cls.getName();
}
public JavaElementImpl(Field field) {
this.anchor = field;
this.elementType = ElementType.FIELD;
- this.type = field.getType();
- this.genericType = field.getGenericType();
+ this.type = new WeakReference<Class<?>>(field.getType());
+ this.genericType = new WeakReference<Type>(field.getGenericType());
this.name = field.getName();
}
public JavaElementImpl(Constructor<?> constructor, int index) {
this.anchor = constructor;
this.elementType = ElementType.PARAMETER;
- this.type = constructor.getParameterTypes()[index];
- this.genericType = constructor.getGenericParameterTypes()[index];
+ this.type = new WeakReference<Class<?>>(constructor.getParameterTypes()[index]);
+ this.genericType = new WeakReference<Type>(constructor.getGenericParameterTypes()[index]);
this.index = index;
this.name = "";
}
@@ -70,8 +71,8 @@ public class JavaElementImpl {
public JavaElementImpl(Method method, int index) {
this.anchor = method;
this.elementType = ElementType.PARAMETER;
- this.type = method.getParameterTypes()[index];
- this.genericType = method.getGenericParameterTypes()[index];
+ this.type = new WeakReference<Class<?>>(method.getParameterTypes()[index]);
+ this.genericType = new WeakReference<Type>(method.getGenericParameterTypes()[index]);
this.index = index;
this.name = "";
}
@@ -86,7 +87,7 @@ public class JavaElementImpl {
*/
public JavaElementImpl(String name, Class<?> type, Class<? extends Annotation> classifer) {
super();
- this.type = type;
+ this.type = new WeakReference<Class<?>>(type);
this.name = name;
this.classifer = classifer;
}
@@ -109,7 +110,7 @@ public class JavaElementImpl {
* @return the genericType
*/
public Type getGenericType() {
- return genericType;
+ return genericType.get();
}
/**
@@ -123,7 +124,7 @@ public class JavaElementImpl {
* @return the type
*/
public Class<?> getType() {
- return type;
+ return type.get();
}
/**
diff --git a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java
index 55d694d7f8..c1357af9d6 100644
--- a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java
+++ b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java
@@ -96,4 +96,13 @@ public interface JavaInterfaceFactory {
* @return
*/
List<JavaInterfaceVisitor> getInterfaceVisitors();
+
+ /**
+ * Remove the interfaces that have been registered for
+ * the contribution identified by the contribution class
+ * loader provided
+ *
+ * @param contributionClassloader
+ */
+ void removeInterfacesForContribution(ClassLoader contributionClassloader);
}
diff --git a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
index 8229c7812d..21c21e075d 100644
--- a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
+++ b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
@@ -21,8 +21,10 @@ package org.apache.tuscany.sca.interfacedef.java.impl;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.WeakHashMap;
import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
@@ -31,6 +33,7 @@ import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor;
+import org.oasisopen.sca.ServiceRuntimeException;
/**
* A factory for the Java model.
@@ -112,4 +115,48 @@ public abstract class JavaInterfaceFactoryImpl implements JavaInterfaceFactory {
op.setName(method.getName());
return op;
}
+
+ /**
+ * Removes all the cached information relating to a contribution. The
+ * contribution is identified by the contribution classloader passed in
+ * as a parameter. This is used when a contribution is removed from
+ * the runtime.
+ *
+ * @param contributionClassloader
+ */
+ public void removeInterfacesForContribution(ClassLoader contributionClassloader){
+ removeInterfacesFromCache(contributionClassloader, normalCache);
+ removeInterfacesFromCache(contributionClassloader, forceRemotableCache);
+ }
+
+ private void removeInterfacesFromCache(ClassLoader contributionClassloader, Map<Class<?>, JavaInterface> cache){
+ try {
+ synchronized(cache) {
+ Set<Class<?>> clsSet = cache.keySet();
+ Iterator<Class<?>> i = clsSet.iterator();
+ while (i.hasNext()) {
+ Class<?> cls = i.next();
+ if (cls.getClassLoader() == contributionClassloader) {
+ i.remove();
+ }
+ }
+ }
+ } catch(Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ /**
+ * For testing so we can check that the cache is being cleared
+ */
+ public Map<Class<?>, JavaInterface> getNormalCache(){
+ return normalCache;
+ }
+
+ /**
+ * For testing so we can check that the cache is being cleared
+ */
+ public Map<Class<?>, JavaInterface> getForceRemotableCache(){
+ return forceRemotableCache;
+ }
}