package edu.ualberta.med.biobank.rcp;
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.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.PlatformUI;
import edu.ualberta.med.biobank.BiobankPlugin;
import edu.ualberta.med.biobank.gui.common.BgcLogger;
/**
* This class shows an example for checking for updates and performing the
* update synchronously. It is up to the caller to run this in a job if a
* background update check is desired. This is a reasonable way to run an
* operation when user intervention is not required. Another approach is to
* separately perform the resolution and provisioning steps, deciding whether to
* perform these synchronously or in a job.
*
* Any p2 operation can be run modally (synchronously), or the job can be
* requested and scheduled by the caller.
*
* @see UpdateOperation#resolveModal(IProgressMonitor)
* @see UpdateOperation#getResolveJob(IProgressMonitor)
* @see UpdateOperation#getProvisioningJob(IProgressMonitor)
*
* @see "http://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application"
*/
public class P2Util {
private static final String JUSTUPDATED = "justUpdated"; //$NON-NLS-1$
private static BgcLogger logger = BgcLogger.getLogger(P2Util.class
.getName());
@SuppressWarnings("restriction")
public static void checkForUpdates() {
if (BiobankPlugin.getDefault().isDebugging()) {
// do not try to update the client if running in debug mode
return;
}
final IProvisioningAgent agent = (IProvisioningAgent) org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper
.getService(BiobankPlugin.bundleContext,
IProvisioningAgent.SERVICE_NAME);
if (agent == null) {
logger.addRcpLogStatus(IStatus.ERROR,
Messages.P2Util_update_noprovisioning_error_msg, null);
}
// XXX if we're restarting after updating, don't check again.
final IPreferenceStore prefStore = BiobankPlugin.getDefault()
.getPreferenceStore();
if (prefStore.getBoolean(JUSTUPDATED)) {
prefStore.setValue(JUSTUPDATED, false);
return;
}
// XXX check for updates before starting up.
// If an update is performed, restart. Otherwise log
// the status.
IRunnableWithProgress runnable = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
IStatus updateStatus = checkForUpdates(agent, monitor);
if (updateStatus.getCode() != UpdateOperation.STATUS_NOTHING_TO_UPDATE
&& updateStatus.getSeverity() != IStatus.ERROR) {
prefStore.setValue(JUSTUPDATED, true);
PlatformUI.getWorkbench().restart();
} else {
logger.addRcpLogStatus(updateStatus);
}
}
};
try {
new ProgressMonitorDialog(null).run(true, true, runnable);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
}
}
// Check for updates to this application and return a status.
private 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,
Messages.P2Util_update_checking, 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(null);
if (job == null)
return new Status(IStatus.ERROR, BiobankPlugin.PLUGIN_ID,
Messages.P2Util_update_notfound_msg);
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openInformation(null,
Messages.P2Util_update_info_title,
Messages.P2Util_update_info_msg);
}
});
status = job.runModal(sub.newChild(100));
if (status.getSeverity() == IStatus.CANCEL)
throw new OperationCanceledException();
}
return status;
}
}