This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.resourceresolver-1.0.4 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
commit df783940178485c4ea596e232b9ff2b0ee3249e7 Author: Carsten Ziegeler <cziege...@apache.org> AuthorDate: Thu Jan 31 16:56:17 2013 +0000 SLING-2719 : Deadlock in ResourceResolverFactoryActivator.checkFactoryPreconditions git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/resourceresolver@1441061 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/ResourceResolverFactoryActivator.java | 124 ++++++++++++++------- 1 file changed, 83 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java index 6d41bc3..aace6e4 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java @@ -75,6 +75,15 @@ import org.osgi.service.event.EventAdmin; @Reference(name = "ResourceDecorator", referenceInterface = ResourceDecorator.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC) }) public class ResourceResolverFactoryActivator { + private static final class FactoryRegistration { + + /** Registered resource resolver factory. */ + public volatile ResourceResolverFactoryImpl factory; + + /** Registration .*/ + public volatile ServiceRegistration factoryRegistration; + } + @Property(value = { "/apps", "/libs" }) public static final String PROP_PATH = "resource.resolver.searchpath"; @@ -86,7 +95,7 @@ public class ResourceResolverFactoryActivator { * Mangling means that any namespace prefix contained in the path is replaced as per the generic * substitution pattern <code>/([^:]+):/_$1_/</code> when calling the <code>map</code> method of * the resource resolver. Likewise the <code>resolve</code> methods will unmangle such namespace - * prefixes according to the substituation pattern <code>/_([^_]+)_/$1:/</code>. + * prefixes according to the substitution pattern <code>/_([^_]+)_/$1:/</code>. * <p> * This feature is provided since there may be systems out there in the wild which cannot cope * with URLs containing colons, even though they are perfectly valid characters in the path part @@ -105,7 +114,7 @@ public class ResourceResolverFactoryActivator { private static final String PROP_REQUIRED_PROVIDERS = "resource.resolver.required.providers"; /** - * The resolver.virtual property has no default configuration. But the sling + * The resolver.virtual property has no default configuration. But the Sling * maven plugin and the sling management console cannot handle empty * multivalue properties at the moment. So we just add a dummy direct * mapping. @@ -128,7 +137,7 @@ public class ResourceResolverFactoryActivator { /** all mappings */ private Mapping[] mappings; - /** The fake urls */ + /** The fake URLs */ private BidiMap virtualURLMap; /** <code>true</code>, if direct mappings from URI to handle are allowed */ @@ -150,19 +159,16 @@ public class ResourceResolverFactoryActivator { @Reference private EventAdmin eventAdmin; - /** Registered resource resolver factory. */ - private ResourceResolverFactoryImpl factory; - - /** Registration .*/ - private ServiceRegistration factoryRegistration; - /** ComponentContext */ - private ComponentContext componentContext; + private volatile ComponentContext componentContext; private int defaultVanityPathRedirectStatus; private final FactoryPreconditions preconds = new FactoryPreconditions(); + /** Factory registration. */ + private volatile FactoryRegistration factoryRegistration; + /** * Get the resource decorator tracker. */ @@ -272,7 +278,8 @@ public class ResourceResolverFactoryActivator { // the root of the resolver mappings mapRoot = PropertiesUtil.toString(properties.get(PROP_MAP_LOCATION), MapEntries.DEFAULT_MAP_ROOT); - defaultVanityPathRedirectStatus = PropertiesUtil.toInteger(properties.get(PROP_DEFAULT_VANITY_PATH_REDIRECT_STATUS), MapEntries.DEFAULT_DEFAULT_VANITY_PATH_REDIRECT_STATUS); + defaultVanityPathRedirectStatus = PropertiesUtil.toInteger(properties.get(PROP_DEFAULT_VANITY_PATH_REDIRECT_STATUS), + MapEntries.DEFAULT_DEFAULT_VANITY_PATH_REDIRECT_STATUS); final BundleContext bc = componentContext.getBundleContext(); @@ -283,7 +290,7 @@ public class ResourceResolverFactoryActivator { } /** - * Deativates this component (called by SCR to take out of service) + * Deactivates this component (called by SCR to take out of service) */ @Deactivate protected void deactivate() { @@ -292,47 +299,82 @@ public class ResourceResolverFactoryActivator { this.rootProviderEntry.setEventAdmin(null); this.resourceDecoratorTracker.close(); + this.unregisterFactory(); + } + + /** + * Unregister the factory (if registered) + */ + private void unregisterFactory() { + FactoryRegistration local = null; synchronized ( this ) { - this.unregisterFactory(); + if ( this.factoryRegistration != null ) { + local = this.factoryRegistration; + this.factoryRegistration = null; + } } + this.unregisterFactory(local); } - private void unregisterFactory() { - if ( this.factoryRegistration != null ) { - final ServiceRegistration local = this.factoryRegistration; - this.factoryRegistration = null; - local.unregister(); + /** + * Unregister the provided factory + */ + private void unregisterFactory(final FactoryRegistration local) { + if ( local != null ) { + if ( local.factoryRegistration != null ) { + local.factoryRegistration.unregister(); + } + if ( local.factory != null ) { + local.factory.deactivate(); + } + } + } + + /** + * Try to register the factory. + */ + private void registerFactory(final ComponentContext localContext) { + FactoryRegistration local = null; + synchronized ( this ) { + if ( this.factoryRegistration == null ) { + this.factoryRegistration = new FactoryRegistration(); + local = this.factoryRegistration; + } } - if ( this.factory != null ) { - final ResourceResolverFactoryImpl local = this.factory; - this.factory = null; - local.deactivate(); + if ( local != null ) { + // activate and register factory + local.factory = new ResourceResolverFactoryImpl(this); + local.factory.activate(localContext.getBundleContext()); + final Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(Constants.SERVICE_VENDOR, localContext.getProperties().get(Constants.SERVICE_VENDOR)); + serviceProps.put(Constants.SERVICE_DESCRIPTION, localContext.getProperties().get(Constants.SERVICE_DESCRIPTION)); + + local.factoryRegistration = localContext.getBundleContext().registerService(ResourceResolverFactory.class.getName(), + local.factory, serviceProps); + // check if an unregister happened in between + boolean doUnregister = false; + synchronized ( this ) { + if ( this.factoryRegistration != local ) { + doUnregister = true; + } + } + if ( doUnregister ) { + this.unregisterFactory(local); + } } } + /** + * Check the preconditions and if it changed, either register factory or unregister + */ private void checkFactoryPreconditions() { - if ( this.componentContext != null ) { + final ComponentContext localContext = this.componentContext; + if ( localContext != null ) { final boolean result = this.preconds.checkPreconditions(); if ( result ) { - synchronized ( this ) { - if ( factory == null ) { - // register factory - this.factory = new ResourceResolverFactoryImpl(this); - this.factory.activate(this.componentContext.getBundleContext()); - final Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); - serviceProps.put(Constants.SERVICE_VENDOR, this.componentContext.getProperties().get(Constants.SERVICE_VENDOR)); - serviceProps.put(Constants.SERVICE_DESCRIPTION, this.componentContext.getProperties().get(Constants.SERVICE_DESCRIPTION)); - - this.factoryRegistration = this.componentContext.getBundleContext().registerService(ResourceResolverFactory.class.getName(), - factory, serviceProps); - } - } + this.registerFactory(localContext); } else { - synchronized ( this ) { - if ( factory != null ) { - this.unregisterFactory(); - } - } + this.unregisterFactory(); } } } -- To stop receiving notification emails like this one, please contact "commits@sling.apache.org" <commits@sling.apache.org>.