You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2012/12/17 13:48:40 UTC
svn commit: r1422911 - in /aries/trunk/blueprint/blueprint-core/src:
main/java/org/apache/aries/blueprint/container/
test/java/org/apache/aries/blueprint/
test/java/org/apache/aries/blueprint/container/
Author: gnodet
Date: Mon Dec 17 12:48:38 2012
New Revision: 1422911
URL: http://svn.apache.org/viewvc?rev=1422911&view=rev
Log:
[ARIES-986] Make sure the extender receives all stopping events, even if still in the initial tracking phase, avoid some processing in the container when it is stopping, stop containers when the proxy manager has been lost. Add additional checks before creating the container
Modified:
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java?rev=1422911&r1=1422910&r2=1422911&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java Mon Dec 17 12:48:38 2012
@@ -138,7 +138,7 @@ public class BlueprintContainerImpl
private Set<URI> namespaces;
private State state = State.Unknown;
private NamespaceHandlerSet handlerSet;
- private boolean destroyed;
+ private final AtomicBoolean destroyed = new AtomicBoolean(false);
private Parser parser;
private BlueprintRepository repository;
private ServiceRegistration registration;
@@ -151,15 +151,15 @@ public class BlueprintContainerImpl
private ScheduledFuture timeoutFuture;
private final AtomicBoolean scheduled = new AtomicBoolean();
private List<ServiceRecipe> services;
- private AccessControlContext accessControlContext;
+ private final AccessControlContext accessControlContext;
private final IdSpace tempRecipeIdSpace = new IdSpace();
- private ProxyManager proxyManager;
+ private final ProxyManager proxyManager;
- public BlueprintContainerImpl(BundleContext bundleContext, Bundle extenderBundle, BlueprintListener eventDispatcher,
+ public BlueprintContainerImpl(Bundle bundle, BundleContext bundleContext, Bundle extenderBundle, BlueprintListener eventDispatcher,
NamespaceHandlerRegistry handlers, ExecutorService executor, ScheduledExecutorService timer,
List<Object> pathList, ProxyManager proxyManager) {
+ this.bundle = bundle;
this.bundleContext = bundleContext;
- this.bundle = bundleContext != null ? bundleContext.getBundle() : null;
this.extenderBundle = extenderBundle;
this.eventDispatcher = eventDispatcher;
this.handlers = handlers;
@@ -171,6 +171,8 @@ public class BlueprintContainerImpl
this.processors = new ArrayList<Processor>();
if (System.getSecurityManager() != null) {
this.accessControlContext = BlueprintDomainCombiner.createAccessControlContext(bundleContext);
+ } else {
+ this.accessControlContext = null;
}
this.proxyManager = proxyManager;
}
@@ -233,6 +235,9 @@ public class BlueprintContainerImpl
public void reload() {
synchronized (scheduled) {
+ if (destroyed.get()) {
+ return;
+ }
tidyupComponents();
this.componentDefinitionRegistry.reset();
this.repository = null;
@@ -263,7 +268,7 @@ public class BlueprintContainerImpl
private void doRun() {
try {
for (;;) {
- if (destroyed) {
+ if (destroyed.get()) {
return;
}
if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) {
@@ -317,6 +322,9 @@ public class BlueprintContainerImpl
Runnable r = new Runnable() {
public void run() {
synchronized (scheduled) {
+ if (destroyed.get()) {
+ return;
+ }
Throwable t = new TimeoutException();
state = State.Failed;
String[] missingDependecies = getMissingDependencies();
@@ -607,6 +615,9 @@ public class BlueprintContainerImpl
}
public void notifySatisfaction(SatisfiableRecipe satisfiable) {
+ if (destroyed.get()) {
+ return;
+ }
LOGGER.debug("Notified satisfaction {} in bundle {}: {}",
new Object[] { satisfiable.getName(), bundle.getSymbolicName(), satisfiable.isSatisfied() });
if (state == State.Create || state == State.Created ) {
@@ -727,7 +738,7 @@ public class BlueprintContainerImpl
}
public Object getComponentInstance(String id) throws NoSuchComponentException {
- if (repository == null) {
+ if (repository == null || destroyed.get()) {
throw new NoSuchComponentException(id);
}
try {
@@ -827,38 +838,30 @@ public class BlueprintContainerImpl
}
public void destroy() {
-// synchronized (scheduled) {
- destroyed = true;
- eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYING, getBundle(), getExtenderBundle()));
- executors.shutdownNow();
-
- cancelFutureIfPresent();
- AriesFrameworkUtil.safeUnregisterService(registration);
-
- unregisterServices();
-
- if (handlerSet != null) {
- handlerSet.removeListener(this);
- handlerSet.destroy();
- }
-
- destroyComponents();
+ synchronized (scheduled) {
+ destroyed.set(true);
+ }
+ eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYING, getBundle(), getExtenderBundle()));
+ executors.shutdownNow();
+ if (handlerSet != null) {
+ handlerSet.removeListener(this);
+ handlerSet.destroy();
+ }
- untrackServiceReferences();
+ try {
+ executors.awaitTermination(5 * 60, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ LOGGER.debug("Interrupted waiting for executor to shut down");
+ }
- try {
- executors.awaitTermination(5 * 60, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- LOGGER.debug("Interrupted waiting for executor to shut down");
- }
+ tidyupComponents();
- eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYED, getBundle(), getExtenderBundle()));
- LOGGER.debug("Blueprint container destroyed: {}", this.bundleContext);
-// }
+ eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYED, getBundle(), getExtenderBundle()));
+ LOGGER.debug("Blueprint container destroyed: {}", this.bundleContext);
}
protected void quiesce() {
- destroyed = true;
+ destroyed.set(true);
eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYING, getBundle(), getExtenderBundle()));
cancelFutureIfPresent();
@@ -886,6 +889,9 @@ public class BlueprintContainerImpl
public void namespaceHandlerUnregistered(URI uri) {
if (namespaces != null && namespaces.contains(uri)) {
synchronized (scheduled) {
+ if (destroyed.get()) {
+ return;
+ }
tidyupComponents();
this.componentDefinitionRegistry.reset();
this.repository = null;
@@ -897,9 +903,9 @@ public class BlueprintContainerImpl
private void tidyupComponents()
{
+ untrackServiceReferences();
unregisterServices();
destroyComponents();
- untrackServiceReferences();
}
public void injectBeanInstance(BeanMetadata bmd, Object o)
Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java?rev=1422911&r1=1422910&r2=1422911&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java Mon Dec 17 12:48:38 2012
@@ -49,6 +49,7 @@ import org.osgi.framework.BundleEvent;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.blueprint.container.BlueprintContainer;
import org.osgi.service.blueprint.container.BlueprintEvent;
import org.osgi.util.tracker.BundleTrackerCustomizer;
@@ -60,7 +61,7 @@ import org.slf4j.LoggerFactory;
*
* @version $Rev$, $Date$
*/
-public class BlueprintExtender implements BundleActivator, BundleTrackerCustomizer {
+public class BlueprintExtender implements BundleActivator, BundleTrackerCustomizer, SynchronousBundleListener {
/** The QuiesceParticipant implementation class name */
private static final String QUIESCE_PARTICIPANT_CLASS = "org.apache.aries.quiesce.participant.QuiesceParticipant";
@@ -92,6 +93,12 @@ public class BlueprintExtender implement
});
eventDispatcher = new BlueprintEventDispatcher(ctx, executors);
+ // Ideally we'd want to only track STARTING and ACTIVE bundle, but this is not supported
+ // when using equinox composites. This would ensure that no STOPPING event is lost while
+ // tracking the initial bundles. To work around this issue, we need to register
+ // a synchronous bundle listener that will ensure the stopping event will be correctly
+ // handled.
+ context.addBundleListener(this);
int mask = Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.STOPPING | Bundle.ACTIVE;
bt = new RecursiveBundleTracker(ctx, mask, this);
@@ -101,7 +108,12 @@ public class BlueprintExtender implement
bt.open();
}
public void serviceLost() {
- // TODO we should probably close here, not sure.
+ while (!containers.isEmpty()) {
+ for (Bundle bundle : getBundlesToDestroy()) {
+ destroyContainer(bundle);
+ }
+ }
+ bt.close();
}
public void serviceReplaced() {
}
@@ -155,6 +167,20 @@ public class BlueprintExtender implement
}
/*
+ * SynchronousBundleListener
+ */
+
+ public void bundleChanged(BundleEvent event) {
+ Bundle bundle = event.getBundle();
+ if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) {
+ // The bundle is not in STARTING or ACTIVE state anymore
+ // so destroy the context
+ destroyContainer(bundle);
+ return;
+ }
+ }
+
+ /*
* BundleTrackerCustomizer
*/
@@ -198,11 +224,20 @@ public class BlueprintExtender implement
// This bundle is not a blueprint bundle, so ignore it
return false;
}
- BlueprintContainerImpl blueprintContainer = new BlueprintContainerImpl(bundle.getBundleContext(),
+ ProxyManager pm = proxyManager.getService();
+ if (pm == null) {
+ // The pm isn't available. It may be because it is being untracked
+ return false;
+ }
+ BundleContext bundleContext = bundle.getBundleContext();
+ if (bundleContext == null) {
+ // The bundle has been stopped in the mean time
+ return false;
+ }
+ BlueprintContainerImpl blueprintContainer = new BlueprintContainerImpl(bundle, bundleContext,
context.getBundle(), eventDispatcher,
handlers, getExecutorService(bundle),
- executors, paths,
- proxyManager.getService());
+ executors, paths, pm);
synchronized (containers) {
if (containers.putIfAbsent(bundle, blueprintContainer) != null) {
return false;
@@ -373,7 +408,9 @@ public class BlueprintExtender implement
}
}
}
- bundlesToDestroy.add(ref.getBundle());
+ if (ref != null) {
+ bundlesToDestroy.add(ref.getBundle());
+ }
LOGGER.debug("Selected bundle {} for destroy (lowest ranking service)", bundlesToDestroy);
}
return bundlesToDestroy;
Modified: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java?rev=1422911&r1=1422910&r2=1422911&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java Mon Dec 17 12:48:38 2012
@@ -44,7 +44,7 @@ public class TestBlueprintContainer exte
}
public TestBlueprintContainer(ComponentDefinitionRegistryImpl registry, ProxyManager proxyManager) throws Exception {
- super(new TestBundleContext(), null, null, null, null, null, null, proxyManager);
+ super(null, new TestBundleContext(), null, null, null, null, null, null, proxyManager);
this.registry = registry;
if (registry != null) {
registry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintContainer", this));
Modified: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java?rev=1422911&r1=1422910&r2=1422911&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java Mon Dec 17 12:48:38 2012
@@ -120,7 +120,7 @@ public class BeanRecipeTest {
@Test
public void parameterWithGenerics() throws Exception {
- BlueprintContainerImpl container = new BlueprintContainerImpl(null, null, null, null, null, null, null, null);
+ BlueprintContainerImpl container = new BlueprintContainerImpl(null, null, null, null, null, null, null, null, null);
BeanRecipe recipe = new BeanRecipe("example", container, ExampleService.class, false);
recipe.setArguments(Arrays.<Object>asList(new ExampleImpl()));
recipe.setArgTypes(Arrays.<String>asList((String) null));
@@ -195,7 +195,7 @@ public class BeanRecipeTest {
@Test
public void protectedClassAccess() throws Exception {
- BlueprintContainerImpl container = new BlueprintContainerImpl(null, null, null, null, null, null, null, null);
+ BlueprintContainerImpl container = new BlueprintContainerImpl(null, null, null, null, null, null, null, null, null);
BeanRecipe recipe = new BeanRecipe("a", container, null, false);
recipe.setFactoryComponent(new PassThroughRecipe("factory", new Factory().create()));
recipe.setFactoryMethod("getA");