blob: 37880a7fd7e9e17fbb64484d3bc45d48d9458e72 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.tests.runtime;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.core.runtime.*;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
public class DynamicPluginTest extends RuntimeTest {
private static final String PLUGIN_TESTING_ROOT = "Plugin_Testing";
public DynamicPluginTest(String name) {
super(name);
}
/**
* Allows test cases to wait for event notification so they can make assertions on the event.
*/
protected static class TestRegistryChangeListener implements IRegistryChangeListener {
private IRegistryChangeEvent event;
private String xpNamespace;
private String xpId;
private String extNamespace;
private String extId;
/**
* Creates a new listener. The parameters allow filtering of events based on extension point/extension's
* namespaces/ids.
*
* @param xpNamespace extension point namespace. If <code>null</code>, xpId must also be null
* @param xpId extension point simple id. May be <code>null</code>
* @param extNamespace extension namespace. If <code>null</code>, extId must also be null
* @param extIdextension id. May be <code>null</code>
*/
public TestRegistryChangeListener(String xpNamespace, String xpId, String extNamespace, String extId) {
this.xpNamespace = xpNamespace;
this.xpId = xpId;
this.extNamespace = extNamespace;
this.extId = extId;
}
/**
* @see IRegistryChangeListener#registryChanged
*/
public synchronized void registryChanged(IRegistryChangeEvent newEvent) {
if (this.event != null)
return;
if (xpNamespace != null) {
if (extNamespace != null) {
if (newEvent.getExtensionDelta(xpNamespace, xpId, extNamespace + '.' + extId) == null)
return;
} else if (newEvent.getExtensionDeltas(xpNamespace, xpId).length == 0)
return;
}
this.event = newEvent;
notify();
}
/**
* Returns the first event that is received, blocking for at most <code>timeout</code> milliseconds.
* Returns <code>null</code> if a event was not received for the time allowed.
*
* @param timeout the maximum time to wait in milliseconds. If zero, this method will
* block until an event is received
* @return the first event received, or <code>null</code> if none was received
*/
public synchronized IRegistryChangeEvent getEvent(long timeout) {
IRegistryChangeEvent result = event;
if (event != null) {
event = null;
return result;
}
try {
wait(timeout);
} catch (InterruptedException e) {
// who cares?
}
result = event;
event = null;
return result;
}
}
protected void registerListener(TestRegistryChangeListener listener, String namespace) {
InternalPlatform.getDefault().getRegistry().addRegistryChangeListener(listener, namespace);
}
protected void unregisterListener(TestRegistryChangeListener listener) {
InternalPlatform.getDefault().getRegistry().removeRegistryChangeListener(listener);
}
public Bundle installBundle(String location) throws BundleException, MalformedURLException, IOException {
URL entry = InternalPlatform.getDefault().getBundle(PI_RUNTIME_TESTS).getEntry(PLUGIN_TESTING_ROOT + '/' + location);
Bundle installed = InternalPlatform.getDefault().getBundleContext().installBundle(Platform.asLocalURL(entry).toExternalForm());
refreshPackages(InternalPlatform.getDefault().getBundleContext(), new Bundle[] {installed});
return installed;
}
/**
* Do PackageAdmin.refreshPackages() in a synchronous way. After installing
* all the requested bundles we need to do a refresh and want to ensure that
* everything is done before returning.
* @param bundles
*/
private void refreshPackages(BundleContext context, Bundle[] bundles) {
if (bundles.length == 0)
return;
ServiceReference packageAdminRef = context.getServiceReference(PackageAdmin.class.getName());
PackageAdmin packageAdmin = null;
if (packageAdminRef != null) {
packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
if (packageAdmin == null)
return;
}
// TODO this is such a hack it is silly. There are still cases for race conditions etc
// but this should allow for some progress...
// (patch from John A.)
final boolean[] flag = new boolean[] {false};
FrameworkListener listener = new FrameworkListener() {
public void frameworkEvent(FrameworkEvent event) {
if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED)
synchronized (flag) {
flag[0] = true;
flag.notifyAll();
}
}
};
context.addFrameworkListener(listener);
packageAdmin.refreshPackages(bundles);
synchronized (flag) {
while (!flag[0]) {
try {
flag.wait();
} catch (InterruptedException e) {
// who cares....
}
}
}
context.removeFrameworkListener(listener);
context.ungetService(packageAdminRef);
}
}