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

本文介绍了如何在Eclipse RCP应用中添加自动更新功能,通过Equinox P2 API实现启动时的无干预更新。参考了官方文档、相关博客及教程,解决了在实施过程中遇到的问题,如构建结构的演变、依赖插件的添加等。最终在ApplicationWorkbenchWindowAdvisor和P2Util类中实现了自动更新功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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-inDescription
org.eclipse.equinox.p2.coreCore p2 functionality
org.eclipse.equinox.p2.engineThe engine carries out the provisioning operation.
org.eclipse.equinox.p2.operationsLayer over the core and engine API to describe updates as an atomic install.
org.eclipse.equinox.p2.metadata.repositoryContains 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.featureFeature containing the p2 bundles.

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

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值