Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java22
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java84
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java56
3 files changed, 98 insertions, 64 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
index 84860b719..5102ae3c9 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
@@ -54,12 +54,30 @@ public class AbstractBundleTests extends CoreTest {
}
static public void compareResults(Object[] expectedEvents, Object[] actualEvents) {
- assertEquals("compareResults length", expectedEvents.length, actualEvents.length);
+ String expectedActual = " -- EXPECTED:" + toStringEventArray(expectedEvents) + " ACTUAL:" + toStringEventArray(actualEvents);
+ assertEquals("compareResults length" + expectedActual, expectedEvents.length, actualEvents.length);
for (int i = 0; i < expectedEvents.length; i++) {
- assertEquals("compareResults " + i, expectedEvents[i], actualEvents[i]);
+ String assertMsg = "compareResults: " + i + expectedActual;
+ assertEquals(assertMsg, expectedEvents[i], actualEvents[i]);
}
}
+ static public String toStringEventArray(Object[] events) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append('[');
+ for (Object event : events) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(toString(event));
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
static public void assertEquals(String message, Object expected, Object actual) {
if (expected == null && actual == null)
return;
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 434e7f983..fea52f993 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
@@ -19,8 +19,7 @@ import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Service;
-import junit.framework.Test;
-import junit.framework.TestSuite;
+import junit.framework.*;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.osgi.framework.*;
@@ -222,14 +221,14 @@ public class ClassLoadingBundleTests extends AbstractBundleTests {
expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestC);
expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestD);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTest);
+ expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
+ expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestB);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestB);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestC);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestC);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestA);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestA);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTest);
actualFrameworkEvents = syncListenerResults.getResults(14);
@@ -289,14 +288,14 @@ public class ClassLoadingBundleTests extends AbstractBundleTests {
expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestC);
expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestD);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTest);
+ expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
+ expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestB);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestB);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestC);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestC);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestA);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestA);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTest);
actualFrameworkEvents = syncListenerResults.getResults(14);
@@ -312,7 +311,7 @@ public class ClassLoadingBundleTests extends AbstractBundleTests {
}
}
- public void testBug405918() throws BundleException {
+ public void testBug408629() throws BundleException {
Bundle chainTest = installer.installBundle("chain.test"); //$NON-NLS-1$
Bundle chainTestA = installer.installBundle("chain.test.a"); //$NON-NLS-1$
Bundle chainTestB = installer.installBundle("chain.test.b"); //$NON-NLS-1$
@@ -333,15 +332,15 @@ public class ClassLoadingBundleTests extends AbstractBundleTests {
// eager start chainTestD
chainTestD.start();
- Object[] expectedEvents = new Object[5];
- expectedEvents[0] = new BundleEvent(BundleEvent.RESOLVED, chainTestD);
- expectedEvents[1] = new BundleEvent(BundleEvent.RESOLVED, chainTestC);
- expectedEvents[2] = new BundleEvent(BundleEvent.RESOLVED, chainTestB);
- expectedEvents[3] = new BundleEvent(BundleEvent.RESOLVED, chainTestA);
- expectedEvents[4] = new BundleEvent(BundleEvent.RESOLVED, chainTest);
+ Object[] expectedEvents1 = new Object[5];
+ expectedEvents1[0] = new BundleEvent(BundleEvent.RESOLVED, chainTestD);
+ expectedEvents1[1] = new BundleEvent(BundleEvent.RESOLVED, chainTestC);
+ expectedEvents1[2] = new BundleEvent(BundleEvent.RESOLVED, chainTestB);
+ expectedEvents1[3] = new BundleEvent(BundleEvent.RESOLVED, chainTestA);
+ expectedEvents1[4] = new BundleEvent(BundleEvent.RESOLVED, chainTest);
Object[] actualEvents = syncListenerResults.getResults(5);
- compareResults(expectedEvents, actualEvents);
+ compareResults(expectedEvents1, actualEvents);
try {
System.setProperty("test.bug300692", "true");
System.setProperty("test.bug300692.listener", "true");
@@ -352,26 +351,47 @@ public class ClassLoadingBundleTests extends AbstractBundleTests {
Object[] actualFrameworkEvents = frameworkListenerResults.getResults(1);
compareResults(expectedFrameworkEvents, actualFrameworkEvents);
- expectedEvents = new Object[14];
- int i = 0;
-
- expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestA);
- expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestB);
- expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestC);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTest);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestB);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestB);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestC);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestC);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestA);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestA);
- expectedEvents[i++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestD);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
- expectedEvents[i++] = new BundleEvent(BundleEvent.STARTED, chainTest);
+ expectedEvents1 = new Object[14];
+ Object[] expectedEvents2 = new Object[14];
+ int i1 = 0;
+ int i2 = 0;
+
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestA);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestA);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestB);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestB);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestC);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestC);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTING, chainTest);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTING, chainTest);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestD);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTING, chainTestB);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTING, chainTestB);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTED, chainTestB);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTED, chainTestB);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.LAZY_ACTIVATION, chainTestD);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTING, chainTestD);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTED, chainTestD);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTING, chainTestC);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTING, chainTestC);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTED, chainTestC);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTED, chainTestC);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTING, chainTestA);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTING, chainTestA);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTED, chainTestA);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTED, chainTestA);
+ expectedEvents1[i1++] = new BundleEvent(BundleEvent.STARTED, chainTest);
+ expectedEvents2[i2++] = new BundleEvent(BundleEvent.STARTED, chainTest);
actualFrameworkEvents = syncListenerResults.getResults(14);
- compareResults(expectedEvents, actualFrameworkEvents);
+ try {
+ compareResults(expectedEvents1, actualFrameworkEvents);
+ } catch (AssertionFailedError e) {
+ // try the second alternative
+ compareResults(expectedEvents2, actualFrameworkEvents);
+ }
} finally {
System.getProperties().remove("test.bug300692");
System.getProperties().remove("test.bug300692.listener");
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java
index 3f419d07c..db636e962 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hooks/EclipseLazyStarter.java
@@ -30,8 +30,10 @@ public class EclipseLazyStarter extends ClassLoaderHook {
private static final EnumSet<State> alreadyActive = EnumSet.of(State.ACTIVE, State.STOPPING, State.UNINSTALLED);
private static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
- // holds the current activation trigger class and the ClasspathManagers that need to be activated
- private final ThreadLocal<List<Object>> activationStack = new ThreadLocal<List<Object>>();
+ // holds the initiating class name
+ private final ThreadLocal<String> initiatingClassName = new ThreadLocal<String>();
+ // holds the ClasspathManagers that need to be activated
+ private final ThreadLocal<Deque<ClasspathManager>> activationStack = new ThreadLocal<Deque<ClasspathManager>>();
// used to store exceptions that occurred while activating a bundle
// keyed by ClasspathManager->Exception
// WeakHashMap is used to prevent pinning the ClasspathManager objects.
@@ -45,6 +47,9 @@ public class EclipseLazyStarter extends ClassLoaderHook {
@Override
public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
+ if (initiatingClassName.get() == null) {
+ initiatingClassName.set(name);
+ }
ModuleRevision revision = manager.getGeneration().getRevision();
Module module = revision.getRevisions().getModule();
// If the bundle is active, uninstalled or stopping then the bundle has already
@@ -54,46 +59,37 @@ public class EclipseLazyStarter extends ClassLoaderHook {
// The bundle is not active and does not require activation, just return the class
if (!shouldActivateFor(name, module, revision, manager))
return;
- List<Object> stack = activationStack.get();
+ Deque<ClasspathManager> stack = activationStack.get();
if (stack == null) {
- stack = new ArrayList<Object>(6);
+ stack = new ArrayDeque<ClasspathManager>(6);
activationStack.set(stack);
}
- // the first element in the stack is the name of the trigger class,
- // each element after the trigger class is a classpath manager
- // that must be activated after the trigger class has been defined (see postFindLocalClass)
- int size = stack.size();
- if (size > 1) {
- for (int i = size - 1; i >= 1; i--)
- if (manager == stack.get(i))
- // the manager is already on the stack in which case we are already in the process of loading the trigger class
- return;
+ // each element is a classpath manager that must be activated after
+ // the initiating class has been defined (see postFindLocalClass)
+ if (!stack.contains(manager)) {
+ // only add the manager if it has not been added already
+ stack.addFirst(manager);
}
- if (size == 0)
- stack.add(name);
- stack.add(manager);
}
@Override
public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) throws ClassNotFoundException {
- List<Object> stack = activationStack.get();
- if (stack == null)
+ if (initiatingClassName.get() != name)
return;
- int size = stack.size();
- if (size <= 1 || stack.get(0) != name)
+ initiatingClassName.set(null);
+ Deque<ClasspathManager> stack = activationStack.get();
+ if (stack == null || stack.isEmpty())
return;
+
// if we have a stack we must clear it even if (clazz == null)
- ClasspathManager[] managers = null;
- managers = new ClasspathManager[size - 1];
- for (int i = 1; i < size; i++)
- managers[i - 1] = (ClasspathManager) stack.get(i);
+ List<ClasspathManager> managers = new ArrayList<ClasspathManager>(stack);
stack.clear();
if (clazz == null)
return;
- for (int i = managers.length - 1; i >= 0; i--) {
- if (errors.get(managers[i]) != null) {
+ for (ClasspathManager managerElement : managers) {
+ if (errors.get(managerElement) != null) {
if (container.getConfiguration().throwErrorOnFailedStart)
- throw errors.get(managers[i]);
+ throw errors.get(managerElement);
continue;
}
@@ -101,12 +97,12 @@ public class EclipseLazyStarter extends ClassLoaderHook {
// Note that another thread may already be starting this bundle;
// In this case we will timeout after a default of 5 seconds and record the BundleException
long startTime = System.currentTimeMillis();
- Module m = managers[i].getGeneration().getRevision().getRevisions().getModule();
+ Module m = managerElement.getGeneration().getRevision().getRevisions().getModule();
try {
// do not persist the start of this bundle
secureAction.start(m, StartOptions.LAZY_TRIGGER);
} catch (BundleException e) {
- Bundle bundle = managers[i].getGeneration().getRevision().getBundle();
+ Bundle bundle = managerElement.getGeneration().getRevision().getBundle();
if (e.getType() == BundleException.STATECHANGE_ERROR) {
String message = NLS.bind(Msg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object[] {Thread.currentThread(), name, m.getStateChangeOwner(), bundle, new Long(System.currentTimeMillis() - startTime)});
container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, message, e);
@@ -114,7 +110,7 @@ public class EclipseLazyStarter extends ClassLoaderHook {
}
String message = NLS.bind(Msg.ECLIPSE_CLASSLOADER_ACTIVATION, bundle.getSymbolicName(), Long.toString(bundle.getBundleId()));
ClassNotFoundException error = new ClassNotFoundException(message, e);
- errors.put(managers[i], error);
+ errors.put(managerElement, error);
if (container.getConfiguration().throwErrorOnFailedStart) {
container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, message, e, null);
throw error;

Back to the top