eclipse rcp 启动自动更新(Headless Updating on Startup)

eclipse rcp 需要增加自动update功能,希望使用Equinox P2的api来做相应的自动启动更新,不需要用户的干预.

参考:https://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application

https://git.eclipse.org/c/equinox/rt.equinox.p2.git/tree/examples/org.eclipse.equinox.p2.examples.rcp.prestartupdate

查看官方文档,下载git代码,就是跑不通.

偶尔发现一片文章:http://javaarm.com/faces/display.xhtml?tid=3455&page=1

讲的非常详细,一步一步下来,基本上实现了菜单更新.

下面需要实现无干预的更新,

参考:http://www.vogella.com/tutorials/EclipseP2Update/article.html#tutorial_updatelocation

最终实现代码如下:

ApplicationWorkbenchWindowAdvisor:

package com.xsej.office;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
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.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;

import com.xsej.office.utils.P2Util;

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
	private static final String JUSTUPDATED = "justUpdated";
	

	public ApplicationWorkbenchWindowAdvisor(
			IWorkbenchWindowConfigurer configurer) {
		super(configurer);
	}

	public ActionBarAdvisor createActionBarAdvisor(
			IActionBarConfigurer configurer) {
		return new ApplicationActionBarAdvisor(configurer);
	}

	public void preWindowOpen() {
		IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
		int screenWidth = Display.getCurrent().getBounds().width;
		int screenHeight = Display.getCurrent().getBounds().height;
		configurer.setInitialSize(new Point(screenWidth, screenHeight));
		configurer.setShowCoolBar(true);
		configurer.setShowStatusLine(true);
		configurer.setShowProgressIndicator(true);
		configurer.setTitle("example");
	}

	public void postWindowOpen() {
		IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
		configurer.getWindow().getShell().setMaximized(true);
		
		
		final IProvisioningAgent agent = (IProvisioningAgent) ServiceHelper
				.getService(Activator.bundleContext,
						IProvisioningAgent.SERVICE_NAME);
		if (agent == null) {
			LogHelper
					.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
							"No provisioning agent found.  This application is not set up for updates."));
		}
		// XXX if we're restarting after updating, don't check again.
		final IPreferenceStore prefStore = Activator.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() {
			public void run(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException {
				IStatus updateStatus = P2Util.checkForUpdates(agent, monitor);
				if (updateStatus.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) {
//					PlatformUI.getWorkbench().getDisplay()
//							.asyncExec(new Runnable() {
//								public void run() {
//									MessageDialog.openInformation(null, "提示",
//											"已经是最新版本");
//								}
//							});
				} else if (updateStatus.getSeverity() != IStatus.ERROR) {
					prefStore.setValue(JUSTUPDATED, true);
					PlatformUI.getWorkbench().getDisplay()
							.asyncExec(new Runnable() {
								public void run() {
									MessageDialog.openInformation(null, "提示",
											"更新完成,现在重启");
									PlatformUI.getWorkbench().restart();
								}
							});

					// PlatformUI.getWorkbench().restart();
				} else {
					LogHelper.log(updateStatus);
				}
			}
		};
		try {
			new ProgressMonitorDialog(null).run(true, true, runnable);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			LogUtil.log(this.getClass(),e.toString() );
		} catch (InterruptedException e) {
			e.printStackTrace();
			LogUtil.log(this.getClass(),e.toString() );
		} catch (Exception e) {
			e.printStackTrace();
			LogUtil.log(this.getClass(),e.toString() );
		}
	}

	public boolean preWindowShellClose() {
		return true;
	}

}

 P2Util:

package com.xsej.office.utils;

import java.net.URI;
import java.net.URISyntaxException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
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;

public class P2Util {

	private static final String REPOSITORY_LOC = System.getProperty(
			"P2Util.Repo", "http://127.0.0.1:8080/repository");

	// XXX Check for updates to this application and return a status.
	public 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);
		configureUpdate(operation);
		SubMonitor sub = SubMonitor.convert(monitor, "正在检查更新...", 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);
			status = job.runModal(sub.newChild(100));
			if (status.getSeverity() == IStatus.CANCEL)
				throw new OperationCanceledException();
		}
		return status;
	}

	private static UpdateOperation configureUpdate(
			final UpdateOperation operation) {
		// create uri and check for validity
		URI uri = null;
		try {
			uri = new URI(REPOSITORY_LOC);
		} catch (final URISyntaxException e) {
			return null;
		}
		LogUtil.log("更新地址:"+uri.toString() );
		// set location of artifact and metadata repo
		operation.getProvisioningContext().setArtifactRepositories(
				new URI[] { uri });
		operation.getProvisioningContext().setMetadataRepositories(
				new URI[] { uri });
		return operation;
	}
}

 总结:

1.构建整理,原来只是一个plugin工程,但是最后演变成三个工程,原来的plugin工程,feature工程,product工程.

    主要p2需要针对feature进行update.

2.自动更新需要使用equinox p2的api进行无干预更新,那么在plugin中就需要导入相关的插件

Plug-in Description
org.eclipse.equinox.p2.core Core p2 functionality
org.eclipse.equinox.p2.engine The engine carries out the provisioning operation.
org.eclipse.equinox.p2.operations Layer over the core and engine API to describe updates as an atomic install.
org.eclipse.equinox.p2.metadata.repository Contains the definition of p2 repositories.

需要添加另外更新需要使用的插件;

  org.eclipse.equinox.p2.touchpoint.natives

  org.eclipse.equinox.p2.transport.ecf

在feature中包含整个p2的featrue包

org.eclipse.equinox.p2.core.feature Feature containing the p2 bundles.

 开发过程因为没有加入org.eclipse.equinox.p2.metadata.repository,导致无法下载新的版本,但是日志没有任何显示,浪费很多时间

猜你喜欢

转载自kevin-xzj.iteye.com/blog/2298792