Object lock = bundle.getStateChangeLock();
	public Class findLocalClass(String className) throws ClassNotFoundException {		if (StatsManager.MONITOR_CLASSES) //Suport for performance analysis			ClassloaderStats.startLoadingClass(getClassloaderId(), className);		boolean found = true;		try {			AbstractBundle bundle = (AbstractBundle) hostdata.getBundle();			// If the bundle is active, uninstalled or stopping then the bundle has already			// been initialized (though it may have been destroyed) so just return the class.			if ((bundle.getState() & (Bundle.ACTIVE | Bundle.UNINSTALLED | Bundle.STOPPING)) != 0)				return basicFindLocalClass(className);			// The bundle is not active and does not require activation, just return the class			if (!shouldActivateFor(className))				return basicFindLocalClass(className);			// The bundle is starting.  Note that if the state changed between the tests 			// above and this test (e.g., it was not ACTIVE but now is), that's ok, we will 			// just try to start it again (else case).			// TODO need an explanation here of why we duplicated the mechanism 			// from the framework rather than just calling start() and letting it sort it out.			if (bundle.getState() == Bundle.STARTING) {				// If the thread trying to load the class is the one trying to activate the bundle, then return the class 				if (bundle.testStateChanging(Thread.currentThread()) || bundle.testStateChanging(null))					return basicFindLocalClass(className);				// If it's another thread, we wait and try again. In any case the class is returned. 				// The difference is that an exception can be logged.				// TODO do we really need this test?  We just did it on the previous line?				if (!bundle.testStateChanging(Thread.currentThread())) {					Thread threadChangingState = bundle.getStateChanging();					if (StatsManager.TRACE_BUNDLES && threadChangingState != null) {						System.out.println("Concurrent startup of bundle " + bundle.getSymbolicName() + " by " + Thread.currentThread() + " and " + threadChangingState.getName() + ". Waiting up to 5000ms for " + threadChangingState + " to finish the initialization."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$					}					Object lock = bundle.getStateChangeLock();					long start = System.currentTimeMillis();					long delay = 5000;					long timeLeft = delay;					while (true) {						if (bundle.testStateChanging(null) || timeLeft <= 0)							break;						try {							synchronized (lock) {								lock.wait(timeLeft);							}						} catch (InterruptedException e) {							//Ignore and keep waiting						}						timeLeft = start + delay - System.currentTimeMillis();					}					if (timeLeft <= 0 || bundle.getState() != Bundle.ACTIVE) {						String bundleName = bundle.getSymbolicName() == null ? Long.toString(bundle.getBundleId()) : bundle.getSymbolicName();						String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP, new Object[] {Thread.currentThread().getName(), className, threadChangingState.getName(), bundleName, Long.toString(delay)});						EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, new Exception(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_GENERATED_EXCEPTION), null));					}					return basicFindLocalClass(className);				}			}			//The bundle must be started.			try {				hostdata.getBundle().start();			} catch (BundleException e) {				String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CLASSLOADER_ACTIVATION, bundle.getSymbolicName(), Long.toString(bundle.getBundleId())); //$NON-NLS-1$				EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, e, null));				throw new ClassNotFoundException(className, e);			}			return basicFindLocalClass(className);		} catch (ClassNotFoundException e) {			found = false;			throw e;		} finally {			if (StatsManager.MONITOR_CLASSES)				ClassloaderStats.endLoadingClass(getClassloaderId(), className, found);		}	}