Equinox p2 详细图示讲解(Eclipse 4.3)

 

Equinox p2

Eclipsercp产品中通过配置Equinoxp2,从而实现新版本的检测,更新功能。

项目源码下载及文档说明:http://download.csdn.net/detail/luoww1/7693857

参考文章:

原文:http://javaarm.com/faces/display.xhtml?tid=3455&page=1

https://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application
https://wiki.eclipse.org/Equinox/p2/Adding_Self_Update_to_an_RCP_Application-3.5
http://www.vogella.com/tutorials/EclipseP2Update/article.html

运行环境

Eclipse4.3 kepler版本的Eclipse RCP IDE,可以从官网上下载

准备Eclipse RCP项目

  • com.ybxiang.equinox.p2.example.email.application:这是我们的Eclipse RCP Application的核心,其中com.ybxiang...Application实现了org.eclipse.equinox.app.IApplication接口。
  • com.ybxiang.equinox.p2.example.email.feature:这是一个feature项目,用于包含我们的应用程序所需的所有插件和features。
  • com.ybxiang.equinox.p2.example.email.product:这事一个product项目,用于将我们的应用程序导出成产品。

1.      创建com.ybxiang.equinox.p2.example.email.application项目

打开菜单

设置项目名字和存放位置:

设置插件ID等信息:

我们期望我们的应用程序带有“Help”和“Window”菜单,因此我们选择“RCP MailTemplate”这个带有基本菜单(“File”和“Help”)的模板:

点击上面Finish按钮之后,打开plugin.xml文件,选中“Dependencies”标签页,然后按照下面的图示,点击“Add按钮”并添加4个插件:

·        org.eclipse.equinox.p2.ui

·        org.eclipse.equinox.p2.ui.sdk

·        org.eclipse.equinox.p2.ui.sdk.scheduler

·        org.eclipse.equinox.p2.transport.ecf

如果不选中该插件,就会导致导出程序在“联系软件站点”时出现下面的错误:
(参见:http://www.eclipse.org/forums/index.php/t/367402/)

!ENTRY org.eclipse.core.jobs 4 2 2014-04-10 20:31:59.117
!MESSAGE An internal error occurred during: "Contacting Software Sites".
!STACK 0
java.lang.NullPointerException
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.loadIndexFile(AbstractRepositoryManager.java:735)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.loadRepository(AbstractRepositoryManager.java:657)
    at org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager.loadRepository(MetadataRepositoryManager.java:96)
    at org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager.loadRepository(MetadataRepositoryManager.java:92)
    at org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob.doLoad(LoadMetadataRepositoryJob.java:117)
    at org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob.runModal(LoadMetadataRepositoryJob.java:102)
    at org.eclipse.equinox.internal.p2.ui.sdk.PreloadingRepositoryHandler$2.runModal(PreloadingRepositoryHandler.java:83)
    at org.eclipse.equinox.p2.operations.ProvisioningJob.run(ProvisioningJob.java:177)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)

 

最终所有依赖如下:

 

提示:

经过我们测试,实际还需要添加“org.eclipse.equinox.p2.touchpoint.natives”这个插件,否则后面更新插件时,会出错;我们在这里不添加该插件,后面遇到错误后,会描述如何修复。如果读者不期望在后面的测试章节中出现该错误,请在上图中将“org.eclipse.equinox.p2.touchpoint.natives”插件添加进来。

 

状态栏和进度指示条

为了能够清楚地看到软件升级进度,我们需要修改ApplicationWorkbenchWindowAdvisor.java这个文件,使之显示状态栏和进度指示条。

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

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

    public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
        return new ApplicationActionBarAdvisor(configurer);
    }
    
    public void preWindowOpen() {
        IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
        configurer.setInitialSize(new Point(600, 400));
        configurer.setShowCoolBar(true);
        configurer.setShowStatusLine(true);
        configurer.setShowProgressIndicator(true);

    }
}

Window中添加Preferences子菜单

private IWorkbenchAction preferencesAction;

protected void makeActions(final IWorkbenchWindow window) {
      ……
       preferencesAction = ActionFactory.PREFERENCES.create(window);
        register(preferencesAction);
    }
protected void fillMenuBar(IMenuManager menuBar) {
      ……
        MenuManager windowMenu = new MenuManager("&Window", IWorkbenchActionConstants.M_WINDOW);
        menuBar.add(windowMenu);      
        windowMenu.add(preferencesAction);
    }

运行测试

我们Email的程序启动只有之后,请遵照下面的步骤,查看相关功能:

2.      创建com.ybxiang.equinox.p2.example.email.feature

创建一个 feature项目,用来包括我们的”整个Email应用程序“所需要的所有插件和其它Feature

选择”Feature Project“菜单:

输入Feature相关信息:

让该feature包含我们刚刚创建的Email应用程序插件:

注意:

上图中没有必要勾中“com.ybxiang.equinox.p2.example.email.application”所依赖的那些插件(比如 org.eclipse.equinox.p2.ui,org.eclipse.equinox.p2.ui.sdk,org.eclipse.equinox.p2.ui.sdk.scheduler和org.eclipse.equinox.p2.transport.ecf),我们在后面会点击Feature插件的“Compute”按钮来计算出间接依赖的插件!

 

我们的应用程序当然应该包含 org.eclipse.rcp 这个大feature。如下图添加该feature:

最后,进入“Dependencies”标签页,点击“Compute按钮”,这样IDE就会计算并更新“com.ybxiang.equinox.p2.example.email.feature”所需要的所有插件:

 

3.      创建com.ybxiang.equinox.p2.example.email.product

创建项目

选择参考项目(我们不选择任何项目):

l  创建 productconfiguration文件:

选择参考项目(我们不选择任何项目):

输入product configuration文件的相关信息:

l  修改版本信息,定义product

注意:上图中,需要选中“Features”这个选择按钮!

添加该product所依赖的features:

注意:上图中,只需要添加“com.ybxiang.equinox.p2.example.email.feature”就可以了!该feature已经包含了该应用程序所需要的所有其它插件和features。

l  创建p2.inf

注意:p2.inf这个文件必须和 xxx.product文件位于相同目录之下,否则,导出产品的菜单“Window” >"Preferences" > "Install/Update"节点对应的页面中,就不会包含我们在p2.inf中所设置的软件站点(http${#58}//127.0.0.1:8080/repository)

正确的效果应该是这样:

 

l  运行product测试

打开“windows.product”文件,点击其中的“Launch an EclipseApplication”链接,我们会看到出错:

这是由于IDE运行 “windows.product”时,会为之创建一个runtime,而该runtime没有包含所有的所有插件所致,这应该是IDE的一个小bug。

该问题的修正办法如下:

左边选择“windows.product”,右边选中“Plug-ins”,然后点击“Add RequiredPlug-ins”按钮:

我们可以看到上图是“64 out of 620selected”,而下图是 “113 out of 620 selected”:

点击上图的Apply按钮之后,再点击上图中的“Debug”按钮,重新运行“windows.product”就不会出错了!

注意:

请总是点击工具条上的 "Debugas..."或"Run as..."下拉框,然后选择我们的产品,本文为“windows.product”,运行该产品!不要点击“windows.product”文件中的“Launch an EclipseApplication”链接来运行该产品,因为这样做的话,IDE会重建“windows.product”的runtime配置,也就是说覆盖掉我们在上面通过点击"Add RequiredPlug-ins"得到的配置!操作如下:

           

软件升级测试

1.      导出1.0.0版本的产品

点击下图中的“Eclipse Productexport wizrard”链接将我们的第一版产品导出:

设置导出配置:

导出结果:

运行 export-v1.0.0 下的 eclipse.exe文件,效果如下:

2.      修改产品版本为2.0.0

windows.product文件中,有2个地方需要修改:

针对项目com.ybxiang.equinox.p2.example.email.application中功能或显示进行修改,用于区分不同版本的功能。

3.      导出2.0.0版的产品

导出方法和上面一样,注意导出目录名字修改为 export-v2.0.0

4.      部署export-v2.0.0\repository

将C:\Users\yingbinx\Desktop\tmp\test\export-v2.0.0\repository 这个目录拷贝到 web 容器(本文使用tomcat)的web部署目录之下,然后启动web容器:

5.      更新export-v1.0.0/eclipse.exe

启动export-v1.0.0/eclipse.exe,然后点击菜单“Help” >"Check for Updates"子菜单:

我们可以看到我们的导出产品正在联系软件站点:

找到了更新版本(2.0.0)的程序:

接受许可证:

列举出将要安装的产品:

上图中,点击Next按钮之后,若出现如下图的错误:

解决方法:

打开com.ybxiang.equinox.p2.example.email.application/plugin.xml,在 Dependencies标签页中,添加“org.eclipse.equinox.p2.touchpoint.natives”插件。在com.ybxiang.equinox.p2.example.email.feature,点击feature.xml,进入“Dependencies”标签页,点击“Compute按钮”,这样IDE就会计算并更新“com.ybxiang.equinox.p2.example.email.feature”所需要的所有插件。然后重新打包产品1.0.0,2.0.0,然后在继续执行更新操作。

 

更新完毕后会提示你重新启动:

查看本产品所安装的插件/features:

可以看到2.0.0版本的产品已经安装好了:

也可以看到版本2.0.0中新添加的功能,或显示。

最后,我们可以看到 export-v1.0.0\eclipse\plugins 目录下已经有新版本的插件了:

设置产品启动时自动更新

打开产品的菜单”Window“ >"Preferences",选中节点 "Install/Update"> "Automatic Updates",然后在右侧按需设置自动更新既可。如下图:

 

错误总汇:

Eclipse 4.3中有项目设置过Bundle jre forthis environment with the product.

存在一个Bug,就是即使你去掉了对Bundle JRE forthis enviroment with the product的勾选,打包时照样会生成jre目录

这样会导致更新出错。

解决方法:

1、  重新下载Eclipse4.3版本,永远都不要勾选Bundle JRE forthis enviroment with the product。

2、  在导出的产品项目中,若要执行更新,就先删除jre文件夹,删除jre后会使用系统中的运行环境,在执行更新的时候会又会创建jre(主要是导出产品的时候在repository中记录了对jre的更新)

编程实现产品启动时软件更新检

根据 http://www.vogella.com/tutorials/EclipseP2Update/article.html#tutorial_updatelocation 一文的描述,我们可以在com.ybxiang.equinox.p2.example.email.application插件中,添加UpdateHandler.java,这样产品启动的时候,就会启动软件更新检查。

package org.jtang.synergy.handler;

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.Status;

import org.eclipse.core.runtime.jobs.IJobChangeEvent;

import org.eclipse.core.runtime.jobs.Job;

import org.eclipse.core.runtime.jobs.JobChangeAdapter;

import org.eclipse.e4.core.di.annotations.Execute;

import org.eclipse.e4.ui.di.UISynchronize;

import org.eclipse.e4.ui.workbench.IWorkbench;

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.Update;

import org.eclipse.equinox.p2.operations.UpdateOperation;

import org.eclipse.jface.dialogs.MessageDialog;

import org.eclipse.swt.widgets.Shell;

/**

 * 用于自动更新

 * @author lww

 *

 */

public class UpdateHandler {

  private static final String REPOSITORY_LOC =

      System.getProperty("UpdateHandler.Repo",

      "file://home/vogella/repository");

  @Execute

  public void execute(final IProvisioningAgent agent, final Shell parent,

      final UISynchronize sync, final IWorkbench workbench) {

    Job j = new Job("Update Job") {

      private boolean doInstall = false;

      @Override

      protected IStatus run(final IProgressMonitor monitor) {

        /* 1. Prepare update plumbing */

        final ProvisioningSession session = new ProvisioningSession(agent);

        final UpdateOperation operation = new UpdateOperation(session);

        // create uri

        URI uri = null;

        try {

          uri = new URI(REPOSITORY_LOC);

        } catch (final URISyntaxException e) {

          sync.syncExec(new Runnable() {

            @Override

            public void run() {

              MessageDialog

              .openError(parent, "URI invalid", e.getMessage());

            }

          });

          return Status.CANCEL_STATUS;

        }

        // set location of artifact and metadata repo

        operation.getProvisioningContext().setArtifactRepositories(new URI[] { uri });

        operation.getProvisioningContext().setMetadataRepositories(new URI[] { uri });

        /* 2. check for updates */

        // run update checks causing I/O

        final IStatus status = operation.resolveModal(monitor);

        // failed to find updates (inform user and exit)

        if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) {

          sync.syncExec(new Runnable() {

            @Override

            public void run() {

              MessageDialog

                  .openWarning(parent, "No update",

                      "No updates for the current installation have been found");

            }

          });

          return Status.CANCEL_STATUS;

        }

        /* 3. Ask if updates should be installed and run installation */

        // found updates, ask user if to install?

        if (status.isOK() && status.getSeverity() != IStatus.ERROR) {

          sync.syncExec(new Runnable() {

            @Override

            public void run() {

              String updates = "";

              Update[] possibleUpdates = operation

                  .getPossibleUpdates();

              for (Update update : possibleUpdates) {

                updates += update + "\n";

              }

              doInstall = MessageDialog.openQuestion(parent,

                  "Really install updates?", updates);

            }

          });

        }

        // start installation

        if (doInstall) {

          final ProvisioningJob provisioningJob = operation

              .getProvisioningJob(monitor);

          // updates cannot run from within Eclipse IDE!!!

          if (provisioningJob == null) {

            System.err

                .println("Running update from within Eclipse IDE? This won't work!!!");

            throw new NullPointerException();

          }

          // register a job change listener to track

          // installation progress and notify user upon success

          provisioningJob

              .addJobChangeListener(new JobChangeAdapter() {

                @Override

                public void done(IJobChangeEvent event) {

                  if (event.getResult().isOK()) {

                    sync.syncExec(new Runnable() {

 

                      @Override

                      public void run() {

                        boolean restart = MessageDialog

                            .openQuestion(parent,

                                "Updates installed, restart?",

                                "Updates have been installed successfully, do you want to restart?");

                        if (restart) {

                          workbench.restart();

                        }

                      }

                    });

                  }

                  super.done(event);

                }

              });

          provisioningJob.schedule();

        }

        return Status.OK_STATUS;

      }

    };

    j.schedule();

  }

}

需要添加依赖插件(com.ybxiang.equinox.p2.example.email.application)

Plugin.xml中添加

在com.ybxiang.equinox.p2.example.email.feature项目 feature.xml中添加org.eclipse.equinox.p2.core.feature,并点击Compute按钮,把com.ybxiang.equinox.p2.example.email.application中新添加的插件添加进来。

       把版本1.0.0的产品启动,就会有提示

点击,就可以进行更新操作。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值