diff options
author | Thomas Watson | 2012-01-31 20:27:12 +0000 |
---|---|---|
committer | Thomas Watson | 2012-01-31 20:27:12 +0000 |
commit | 3c44a9bf479eca906fbba996777583acf40d6721 (patch) | |
tree | 5e4dda18c34f545c750ebf88c4d7e5fcb4219e7e | |
parent | a05b273883a39de44a4e65c1eaea59e9d749a95e (diff) | |
download | rt.equinox.framework-3c44a9bf479eca906fbba996777583acf40d6721.tar.gz rt.equinox.framework-3c44a9bf479eca906fbba996777583acf40d6721.tar.xz rt.equinox.framework-3c44a9bf479eca906fbba996777583acf40d6721.zip |
Bug 370258 - [R5] Clarification for calls to ResolverHook.endv20120131-2027
3 files changed, 152 insertions, 17 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java index 1c537882b..aed625b6c 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2011 IBM Corporation and others. + * Copyright (c) 2006, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -1697,6 +1697,120 @@ public class ClassLoadingBundleTests extends AbstractBundleTests { } } + public void testBug370258_beginException() { + final boolean[] endCalled = {false}; + ResolverHookFactory endHook = new ResolverHookFactory() { + public ResolverHook begin(Collection triggers) { + return new ResolverHook() { + public void filterSingletonCollisions(BundleCapability singleton, Collection collisionCandidates) { + // Nothing + } + + public void filterResolvable(Collection candidates) { + throw new RuntimeException("Error"); + } + + public void filterMatches(BundleRequirement requirement, Collection candidates) { + // Nothing + } + + public void end() { + endCalled[0] = true; + } + }; + } + }; + ResolverHookFactory error = new ResolverHookFactory() { + public ResolverHook begin(Collection triggers) { + throw new RuntimeException("Error"); + } + }; + + ServiceRegistration endReg = OSGiTestsActivator.getContext().registerService(ResolverHookFactory.class, endHook, null); + ServiceRegistration errorReg = OSGiTestsActivator.getContext().registerService(ResolverHookFactory.class, error, null); + try { + Bundle test = installer.installBundle("test"); //$NON-NLS-1$ + try { + test.start(); + fail("Should not be able to start this bundle"); + } catch (BundleException e) { + // expected + assertEquals("Wrong exception type.", BundleException.REJECTED_BY_HOOK, e.getType()); + } + } catch (BundleException e) { + fail("Unexpected install fail", e); + } finally { + errorReg.unregister(); + endReg.unregister(); + } + assertTrue("end is not called", endCalled[0]); + } + + public void testBug370258_endException() { + final boolean[] endCalled = {false}; + ResolverHookFactory endHook = new ResolverHookFactory() { + public ResolverHook begin(Collection triggers) { + return new ResolverHook() { + public void filterSingletonCollisions(BundleCapability singleton, Collection collisionCandidates) { + // Nothing + } + + public void filterResolvable(Collection candidates) { + throw new RuntimeException("Error"); + } + + public void filterMatches(BundleRequirement requirement, Collection candidates) { + // Nothing + } + + public void end() { + endCalled[0] = true; + } + }; + } + }; + ResolverHookFactory error = new ResolverHookFactory() { + public ResolverHook begin(Collection triggers) { + return new ResolverHook() { + public void filterSingletonCollisions(BundleCapability singleton, Collection collisionCandidates) { + // Nothing + } + + public void filterResolvable(Collection candidates) { + // Nothing + } + + public void filterMatches(BundleRequirement requirement, Collection candidates) { + // Nothing + } + + public void end() { + throw new RuntimeException("Error"); + } + }; + } + }; + + ServiceRegistration errorReg = OSGiTestsActivator.getContext().registerService(ResolverHookFactory.class, error, null); + ServiceRegistration endReg = OSGiTestsActivator.getContext().registerService(ResolverHookFactory.class, endHook, null); + try { + Bundle test = installer.installBundle("test"); //$NON-NLS-1$ + try { + test.start(); + fail("Should not be able to start this bundle"); + } catch (BundleException e) { + // expected + assertEquals("Wrong exception type.", BundleException.REJECTED_BY_HOOK, e.getType()); + } + } catch (BundleException e) { + fail("Unexpected install fail", e); + } finally { + errorReg.unregister(); + endReg.unregister(); + } + assertTrue("end is not called", endCalled[0]); + } + private void doTestArrayTypeLoad(String name) { try { Class arrayType = OSGiTestsActivator.getContext().getBundle().loadClass(name); diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java index 3e5b3cffc..986de041d 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 IBM Corporation and others. + * Copyright (c) 2010, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,7 +15,6 @@ import org.eclipse.osgi.framework.debug.Debug; import org.eclipse.osgi.internal.serviceregistry.*; import org.eclipse.osgi.service.resolver.ResolverHookException; import org.eclipse.osgi.util.NLS; -import org.osgi.framework.Bundle; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.framework.hooks.resolver.ResolverHookFactory; @@ -50,7 +49,7 @@ public class CoreResolverHookFactory implements ResolverHookFactory { this.registry = registry; } - void handleHookException(Throwable t, Object hook, String method, Bundle hookBundle, List<HookReference> hookRefs) { + void handleHookException(Throwable t, Object hook, String method) { if (Debug.DEBUG_HOOKS) { Debug.println(hook.getClass().getName() + "." + method + "() exception:"); //$NON-NLS-1$ //$NON-NLS-2$ if (t != null) @@ -87,7 +86,13 @@ public class CoreResolverHookFactory implements ResolverHookFactory { if (hook != null) hookRefs.add(new HookReference(hookRef, hook)); } catch (Throwable t) { - handleHookException(t, factory, "begin", hookRef.getBundle(), hookRefs); //$NON-NLS-1$ + // need to force an end call on the ResolverHooks we got and release them + try { + new CoreResolverHook(hookRefs).end(); + } catch (Throwable endError) { + // we are already in failure mode; just continue + } + handleHookException(t, factory, "begin"); //$NON-NLS-1$ } } } @@ -117,12 +122,12 @@ public class CoreResolverHookFactory implements ResolverHookFactory { for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) { HookReference hookRef = iHooks.next(); if (hookRef.reference.getBundle() == null) { - handleHookException(null, hookRef.hook, "filterResolvable", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + handleHookException(null, hookRef.hook, "filterResolvable"); //$NON-NLS-1$ } else { try { hookRef.hook.filterResolvable(candidates); } catch (Throwable t) { - handleHookException(t, hookRef.hook, "filterResolvable", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + handleHookException(t, hookRef.hook, "filterResolvable"); //$NON-NLS-1$ } } } @@ -138,12 +143,12 @@ public class CoreResolverHookFactory implements ResolverHookFactory { for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) { HookReference hookRef = iHooks.next(); if (hookRef.reference.getBundle() == null) { - handleHookException(null, hookRef.hook, "filterSingletonCollisions", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + handleHookException(null, hookRef.hook, "filterSingletonCollisions"); //$NON-NLS-1$ } else { try { hookRef.hook.filterSingletonCollisions(singleton, collisionCandidates); } catch (Throwable t) { - handleHookException(t, hookRef.hook, "filterSingletonCollisions", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + handleHookException(t, hookRef.hook, "filterSingletonCollisions"); //$NON-NLS-1$ } } } @@ -159,12 +164,12 @@ public class CoreResolverHookFactory implements ResolverHookFactory { for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) { HookReference hookRef = iHooks.next(); if (hookRef.reference.getBundle() == null) { - handleHookException(null, hookRef.hook, "filterMatches", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + handleHookException(null, hookRef.hook, "filterMatches"); //$NON-NLS-1$ } else { try { hookRef.hook.filterMatches(requirement, candidates); } catch (Throwable t) { - handleHookException(t, hookRef.hook, "filterMatches", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + handleHookException(t, hookRef.hook, "filterMatches"); //$NON-NLS-1$ } } } @@ -177,18 +182,32 @@ public class CoreResolverHookFactory implements ResolverHookFactory { if (hooks.isEmpty()) return; try { + HookReference missingHook = null; + Throwable endError = null; + HookReference endBadHook = null; for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) { HookReference hookRef = iHooks.next(); - // We do not remove unregistered services here because we are going to remove of of them at the end - if (hookRef.reference.getBundle() != null) { + // We do not remove unregistered services here because we are going to remove all of them at the end + if (hookRef.reference.getBundle() == null) { + if (missingHook == null) + missingHook = hookRef; + } else { try { hookRef.hook.end(); } catch (Throwable t) { - handleHookException(t, hookRef.hook, "end", hookRef.reference.getBundle(), hooks); //$NON-NLS-1$ + // Must continue on to the next hook.end method + // save the error for throwing at the end + if (endError == null) { + endError = t; + endBadHook = hookRef; + } } - } } + if (missingHook != null) + handleHookException(null, missingHook.hook, "end"); //$NON-NLS-1$ + if (endError != null) + handleHookException(endError, endBadHook.hook, "end"); //$NON-NLS-1$ } finally { releaseHooks(hooks); } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java index a57207539..346a7eda9 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java @@ -494,6 +494,10 @@ public class ResolverImpl implements Resolver { current.end(); } + // set the resolved status of the bundles in the State + // Note this must be done after calling end above in case end throws errors + stateResolveBundles(bundleMapping.values().toArray(new ResolverBundle[bundleMapping.size()])); + for (ResolverBundle bundle : optionalResolved) { state.resolveBundle(bundle.getBundleDescription(), false, null, null, null, null, null, null, null, null); stateResolveBundle(bundle); @@ -649,8 +653,6 @@ public class ResolverImpl implements Resolver { resolveBundles0(bundles, platformProperties); if (DEBUG_WIRING) printWirings(); - // set the resolved status of the bundles in the State - stateResolveBundles(bundleMapping.values().toArray(new ResolverBundle[bundleMapping.size()])); } private void selectSingletons(ResolverBundle[] bundles) { |