SLING-2617 Make sure the dynamic class loader used as the parent to the repository class loader is acquired for the same bundle which acquired the ClassLoaderWriter
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1396651 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java b/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
index a86cd65..c7774d0 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
@@ -45,6 +45,9 @@
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,7 +61,7 @@
*/
@Component(metatype=true, label="%loader.name", description="%loader.description",
name="org.apache.sling.jcr.classloader.internal.DynamicClassLoaderProviderImpl")
-@Service(value=ClassLoaderWriter.class)
+@Service(value = ClassLoaderWriter.class, serviceFactory = true)
@Properties({
@org.apache.felix.scr.annotations.Property(name="service.vendor", value="The Apache Software Foundation"),
@org.apache.felix.scr.annotations.Property(name="service.description", value="Repository based classloader writer")
@@ -96,18 +99,30 @@
@Reference(policy=ReferencePolicy.DYNAMIC, cardinality=ReferenceCardinality.OPTIONAL_UNARY)
private MimeTypeService mimeTypeService;
- @Reference
- private DynamicClassLoaderManager dynamicClassLoaderManager;
+ @Reference(
+ referenceInterface = DynamicClassLoaderManager.class,
+ bind = "bindDynamicClassLoaderManager",
+ unbind = "unbindDynamicClassLoaderManager")
+ private ServiceReference dynamicClassLoaderManager;
+
+ /** The bundle asking for this service instance */
+ private Bundle callerBundle;
/** Cached repository class loader. */
private volatile RepositoryClassLoader repositoryClassLoader;
/**
+ * The dynamic class loader used as the parent of the repository
+ * class loader.
+ */
+ private volatile ClassLoader dynamicClassLoader;
+
+ /**
* Activate this component.
* @param props The configuration properties
*/
@Activate
- protected void activate(final Map<String, Object> properties) {
+ protected void activate(final ComponentContext componentContext, final Map<String, Object> properties) {
Object prop = properties.get(CLASS_PATH_PROP);
if ( prop instanceof String[] && ((String[])prop).length > 0 ) {
this.classPath = ((String[])prop)[0];
@@ -120,6 +135,8 @@
prop = properties.get(OWNER_PROP);
this.classLoaderOwner = (prop instanceof String)? (String) prop : OWNER_DEFAULT;
+
+ this.callerBundle = componentContext.getUsingBundle();
}
/**
@@ -127,10 +144,44 @@
*/
@Deactivate
protected void deactivate() {
- if ( this.repositoryClassLoader != null ) {
+ destroyRepositoryClassLoader();
+ }
+
+ /**
+ * Called to handle binding the DynamicClassLoaderManager service
+ * reference
+ */
+ @SuppressWarnings("unused")
+ private void bindDynamicClassLoaderManager(final ServiceReference ref) {
+ this.dynamicClassLoaderManager = ref;
+ }
+
+ /**
+ * Called to handle unbinding the DynamicClassLoaderManager service
+ * reference
+ */
+ @SuppressWarnings("unused")
+ private void unbindDynamicClassLoaderManager(final ServiceReference ref) {
+ if (this.dynamicClassLoaderManager == ref) {
+ this.dynamicClassLoaderManager = null;
+ }
+ }
+
+ /**
+ * Destroys the repository class loader if existing and ungets the
+ * DynamicClassLoaderManager service if a dynamic class loader is
+ * being used.
+ */
+ private void destroyRepositoryClassLoader() {
+ if (this.repositoryClassLoader != null) {
this.repositoryClassLoader.destroy();
this.repositoryClassLoader = null;
}
+
+ if (this.dynamicClassLoader != null) {
+ this.callerBundle.getBundleContext().ungetService(this.dynamicClassLoaderManager);
+ this.dynamicClassLoader = null;
+ }
}
/**
@@ -162,13 +213,20 @@
private synchronized ClassLoader getOrCreateClassLoader() {
if ( this.repositoryClassLoader == null || !this.repositoryClassLoader.isLive() ) {
- if ( this.repositoryClassLoader != null ) {
- this.repositoryClassLoader.destroy();
- }
+
+ // make sure to cleanup any existing class loader
+ this.destroyRepositoryClassLoader();
+
+ // get the dynamic class loader for the bundle using this
+ // class loader writer
+ DynamicClassLoaderManager dclm = (DynamicClassLoaderManager) this.callerBundle.getBundleContext().getService(
+ this.dynamicClassLoaderManager);
+ this.dynamicClassLoader = dclm.getDynamicClassLoader();
+
this.repositoryClassLoader = new RepositoryClassLoader(
this.classPath,
this,
- this.dynamicClassLoaderManager.getDynamicClassLoader());
+ this.dynamicClassLoader);
}
return this.repositoryClassLoader;
}