Home » Eclipse Projects » Equinox » Using P2 profiles in a non-RCP application
|
Re: Using P2 profiles in a non-RCP application [message #502565 is a reply to message #498152] |
Tue, 08 December 2009 20:05 |
Phil Denis Messages: 26 Registered: October 2009 |
Junior Member |
|
|
Well, to answer another one of my own questions, here's a class that can manage profiles, including starting profiles and switching profiles. It really seems odd to me that there is all this code in Equinox P2 for configuring profiles, but there's no code for starting/switching profiles.
Anyway, here's what I came up with. If anyone finds a better way, please let me know!
public interface ProfileManagerService {
void createProfile(String profileId, Properties properties);
void startProfile(String profileId);
}
public class ProfileManagerServiceImpl implements ProfileManagerService {
private static final boolean DEBUG = true;
/**
* @see ca.richer.equinox.provisioning.ProfileManagerService#createProfile(java.lang.String, java.util.Properties)
*/
public void createProfile(String profileId, Properties properties) {
try {
IProfileRegistry profileRegistry = (IProfileRegistry) ServiceHelper.getService(Activator.getContext(), IProfileRegistry.class.getName());
if (profileRegistry == null)
return;
IProfile profile = profileRegistry.getProfile(profileId);
if (profile != null)
return;
ProvisioningHelper.addProfile(profileId, properties);
} catch (ProvisionException e) {
System.out.println("add profile failed " + e.getMessage());
}
}
/**
* @see ca.richer.equinox.provisioning.ProfileManagerService#startProfile(java.lang.String)
*/
public void startProfile(String profileId) {
// Get the list of bundles that are expected in the profile
final IProfile profile = ProvisioningHelper.getProfile(profileId);
final Query query = new InstallableUnitQuery(null);
final Collector collector = profile.query(query, new Collector(), new NullProgressMonitor());
final List<BundleInfo> bundleInfoList = new ArrayList<BundleInfo>();
for (Object o : collector.toCollection()) {
final InstallableUnit unit = (InstallableUnit) o;
try {
if (unit.getId().equals("org.eclipse.osgi") || unit.getId().contains(".feature") || unit.getId().equals("a.jre")) continue; // Skip the system bundle (and features)
final URI location = new URI("reference:file:plugins/" + unit.getId() + "_" + unit.getVersion().toString() + ".jar");
final BundleInfo info = new BundleInfo(unit.getId(), unit.getVersion().toString(), location, 4, true);
bundleInfoList.add(info);
} catch (URISyntaxException uriException) {
uriException.printStackTrace();
}
}
BundleInfo[] expectedState = bundleInfoList.toArray(new BundleInfo[bundleInfoList.size()]);
// check for an update to the system bundle
String systemBundleSymbolicName = Activator.getContext().getBundle(0).getSymbolicName();
org.osgi.framework.Version systemBundleVersion = Activator.getContext().getBundle(0).getVersion();
if (systemBundleSymbolicName != null) {
for (int i = 0; i < expectedState.length; i++) {
String symbolicName = expectedState[i].getSymbolicName();
if (!systemBundleSymbolicName.equals(symbolicName))
continue;
Version version = Version.parseVersion(expectedState[i].getVersion());
if (!systemBundleVersion.equals(version))
throw new IllegalStateException("The System Bundle was updated. The framework must be restarted to finalize the configuration change");
}
}
final BundleInfo[] currentlyInstalledBundles = getCurrentlyInstalledBundles();
final HashSet toUninstall = new HashSet(Arrays.asList(currentlyInstalledBundles));
toUninstall.removeAll(Arrays.asList(expectedState));
final PackageAdmin packageAdminService = (PackageAdmin) Activator.getService(PackageAdmin.class.getName());
Collection prevouslyResolved = getResolvedBundles();
Collection toRefresh = new ArrayList();
Collection toStart = new ArrayList();
toRefresh.addAll(installBundles(expectedState, toStart));
toRefresh.addAll(uninstallBundles(expectedState, packageAdminService));
refreshPackages((Bundle[]) toRefresh.toArray(new Bundle[toRefresh.size()]), Activator.getContext());
if (toRefresh.size() > 0)
try {
Activator.getContext().getBundle().loadClass("org.eclipse.osgi.service.resolver.PlatformAdmin"); //$NON-NLS-1$
// now see if there are any currently resolved bundles with option imports which could be resolved or
// if there are fragments with additional constraints which conflict with an already resolved host
Bundle[] additionalRefresh = StateResolverUtils.getAdditionalRefresh(prevouslyResolved, Activator.getContext());
if (additionalRefresh.length > 0)
refreshPackages(additionalRefresh, Activator.getContext());
} catch (ClassNotFoundException cnfe) {
// do nothing; no resolver package available
}
startBundles((Bundle[]) toStart.toArray(new Bundle[toStart.size()]));
}
private BundleInfo[] getCurrentlyInstalledBundles() {
final List<BundleInfo> currentBundles = new ArrayList<BundleInfo>();
for (Bundle bundle : Activator.getContext().getBundles()) {
if (bundle.getSymbolicName().equals("org.eclipse.osgi")) continue;
currentBundles.add(new BundleInfo(bundle.getSymbolicName(), bundle.getVersion().toString(), null, -1, (bundle.getState() & Bundle.ACTIVE) == 0));
}
return currentBundles.toArray(new BundleInfo[currentBundles.size()]);
}
private List<BundleInfo> getResolvedBundles() {
final List<BundleInfo> resolvedBundles = new ArrayList<BundleInfo>();
for (Bundle bundle : Activator.getContext().getBundles()) {
if (bundle.getSymbolicName().equals("org.eclipse.osgi")) continue;
resolvedBundles.add(new BundleInfo(bundle.getSymbolicName(), bundle.getVersion().toString(), null, -1, (bundle.getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0));
}
return resolvedBundles;
}
private ArrayList installBundles(BundleInfo[] finalList, Collection toStart) {
ArrayList toRefresh = new ArrayList();
for (int i = 0; i < finalList.length; i++) {
if (finalList[i] == null)
continue;
//TODO here we do not deal with bundles that don't have a symbolic id
//TODO Need to handle the case where getBundles return multiple value
String symbolicName = finalList[i].getSymbolicName();
String version = finalList[i].getVersion();
final PackageAdmin packageAdminService = (PackageAdmin) Activator.getService(PackageAdmin.class.getName());
Bundle[] matches = null;
if (symbolicName != null && version != null)
matches = packageAdminService.getBundles(symbolicName, getVersionRange(version));
String bundleLocation = finalList[i].getLocation().toString();
Bundle current = matches == null ? null : (matches.length == 0 ? null : matches[0]);
if (current == null) {
try {
current = Activator.getContext().installBundle(bundleLocation);
if (DEBUG)
System.out.println("installed bundle:" + finalList[i]); //$NON-NLS-1$
toRefresh.add(current);
} catch (BundleException e) {
if (DEBUG) {
System.err.println("Can't install " + symbolicName + '/' + version + " from location " + finalList[i].getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
e.printStackTrace();
}
continue;
}
}
// Mark Started
if (finalList[i].isMarkedAsStarted()) {
toStart.add(current);
}
// Set Start Level
int startLevel = finalList[i].getStartLevel();
if (startLevel < 1)
continue;
if (current.getBundleId() == 0)
continue;
if (packageAdminService.getBundleType(current) == PackageAdmin.BUNDLE_TYPE_FRAGMENT)
continue;
try {
final StartLevel startLevelService = (StartLevel) Activator.getService(StartLevel.class.getName());
startLevelService.setBundleStartLevel(current, startLevel);
} catch (IllegalArgumentException ex) {
Utils.log(4, null, null, "Failed to set start level of Bundle:" + finalList[i], ex); //$NON-NLS-1$
}
}
return toRefresh;
}
private void refreshPackages(Bundle[] bundles, BundleContext context) {
final PackageAdmin packageAdminService = (PackageAdmin) Activator.getService(PackageAdmin.class.getName());
if (bundles.length == 0 || packageAdminService == null)
return;
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);
packageAdminService.refreshPackages(bundles);
synchronized (flag) {
while (!flag[0]) {
try {
flag.wait();
} catch (InterruptedException e) {
//ignore
}
}
}
// if (DEBUG) {
// for (int i = 0; i < bundles.length; i++) {
// System.out.println(SimpleConfiguratorUtils.getBundleStateString(bundles[i]));
// }
// }
context.removeFrameworkListener(listener);
}
private void startBundles(Bundle[] bundles) {
final PackageAdmin packageAdminService = (PackageAdmin) Activator.getService(PackageAdmin.class.getName());
for (int i = 0; i < bundles.length; i++) {
Bundle bundle = bundles[i];
if (bundle.getState() == Bundle.UNINSTALLED) {
System.err.println("Could not start: " + bundle.getSymbolicName() + '(' + bundle.getLocation() + ':' + bundle.getBundleId() + ')' + ". It's state is uninstalled.");
continue;
}
if (bundle.getState() == Bundle.STARTING && (bundle == Activator.getContext().getBundle() || bundle == Activator.getContext().getBundle()))
continue;
if (packageAdminService.getBundleType(bundle) == PackageAdmin.BUNDLE_TYPE_FRAGMENT)
continue;
try {
bundle.start();
if (DEBUG)
System.out.println("started Bundle:" + bundle.getSymbolicName() + '(' + bundle.getLocation() + ':' + bundle.getBundleId() + ')'); //$NON-NLS-1$
} catch (BundleException e) {
e.printStackTrace();
// FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_START, bundle.getLocation()), 0, e, null);
// log.log(entry);
}
}
}
/**
* Uninstall bundles which are not listed on finalList.
*
* @param finalList bundles list not to be uninstalled.
* @param packageAdmin package admin service.
* @return Collection HashSet of bundles finally installed.
*/
private Collection uninstallBundles(BundleInfo[] finalList, PackageAdmin packageAdmin) {
Bundle[] allBundles = Activator.getContext().getBundles();
//Build a set with all the bundles from the system
Set removedBundles = new HashSet(allBundles.length);
// configurator.setPrerequisiteBundles(allBundles);
for (int i = 0; i < allBundles.length; i++) {
if (allBundles[i].getBundleId() == 0)
continue;
removedBundles.add(allBundles[i]);
}
//Remove all the bundles appearing in the final list from the set of installed bundles
for (int i = 0; i < finalList.length; i++) {
if (finalList[i] == null)
continue;
Bundle[] toAdd = packageAdmin.getBundles(finalList[i].getSymbolicName(), getVersionRange(finalList[i].getVersion()));
for (int j = 0; toAdd != null && j < toAdd.length; j++) {
removedBundles.remove(toAdd[j]);
}
}
for (Iterator iter = removedBundles.iterator(); iter.hasNext();) {
try {
Bundle bundle = ((Bundle) iter.next());
bundle.uninstall();
} catch (BundleException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return removedBundles;
}
private String getVersionRange(String version) {
return version == null ? null : new StringBuffer().append('[').append(version).append(',').append(version).append(']').toString();
}
}
|
|
|
Goto Forum:
Current Time: Fri Apr 19 01:52:49 GMT 2024
Powered by FUDForum. Page generated in 0.02135 seconds
|