package org.eclipselabs.p2.rcpupdate.utils; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.operations.ProvisioningJob; import org.eclipse.equinox.p2.operations.ProvisioningSession; import org.eclipse.equinox.p2.operations.UpdateOperation; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipselabs.p2.rcpupdate.utils.plugin.Activator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; /** * @see http://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application * @see http://bugs.eclipse.org/281226 */ public class P2Util { public static void checkForUpdates() { try { ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(null); progressDialog.run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { doCheckForUpdates(new AccumulatingProgressMonitor(monitor, Display.getDefault())); } }); } catch (InvocationTargetException e) { Activator.log(e); } catch (InterruptedException e) { Activator.log(e); } } private static void doCheckForUpdates(IProgressMonitor monitor) { BundleContext bundleContext = Activator.getDefault().getBundle().getBundleContext(); ServiceReference reference = bundleContext.getServiceReference(IProvisioningAgent.SERVICE_NAME); if (reference == null) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "No provisioning agent found. This application is not set up for updates.")); return; } final IProvisioningAgent agent = (IProvisioningAgent) bundleContext.getService(reference); try { IStatus updateStatus = P2Util.checkForUpdates(agent, monitor); Activator.log(updateStatus); if (updateStatus.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) { return; } if (updateStatus.getSeverity() != IStatus.ERROR) PlatformUI.getWorkbench().restart(); } finally { bundleContext.ungetService(reference); } } static IStatus checkForUpdates(IProvisioningAgent agent, IProgressMonitor monitor) throws OperationCanceledException { ProvisioningSession session = new ProvisioningSession(agent); // the default update operation looks for updates to the currently // running profile, using the default profile root marker. To change // which installable units are being updated, use the more detailed // constructors. UpdateOperation operation = new UpdateOperation(session); SubMonitor sub = SubMonitor.convert(monitor, "Checking for application updates...", 200); IStatus status = operation.resolveModal(sub.newChild(100)); if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) { return status; } if (status.getSeverity() == IStatus.CANCEL) throw new OperationCanceledException(); if (status.getSeverity() != IStatus.ERROR) { // More complex status handling might include showing the user what // updates are available if there are multiples, differentiating // patches vs. updates, etc. In this example, we simply update as // suggested by the operation. ProvisioningJob job = operation.getProvisioningJob(monitor); if (job == null) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "ProvisioningJob could not be created - does this application support p2 software installation?"); } status = job.runModal(sub.newChild(100)); if (status.getSeverity() == IStatus.CANCEL) throw new OperationCanceledException(); } return status; } }