Eclipse RCP p2更新无法正常工作

时间:2010-10-12 01:02:26

标签: eclipse eclipse-plugin eclipse-rcp p2

我有一个基于个人功能(com.example.product)的个人Eclipse RCP产品(com.example.feature),该产品由一个个人插件(com.example.plugin)和一堆来自Eclipse的其他人组成Helios(3.6)。我希望应用程序检查更新,并在必要时从p2站点更新自身。我希望它是无头的,即用户不会在更新过程中进行交互,但可能会在对话框中看到进度。

我的实施基于RCP Mail application的更新。我稍微更改了P2Util.checkForUpdates方法以包含一些日志记录,因此我可以看到那里出现了什么错误:

    static IStatus checkForUpdates(IProvisioningAgent agent,
        IProgressMonitor monitor) throws OperationCanceledException,
        InvocationTargetException {
    ProvisioningSession session = new ProvisioningSession(agent);
    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) {
        try {
            logger.info( "Status is " + status );
            Update[] updates = operation.getPossibleUpdates();              
            for( Update u : updates){
                logger.info( "Update is " + u );
            }               
            ProvisioningJob job = operation.getProvisioningJob(null);
            if( job == null ){
                logger.error( "Provisioning Job is null" );
            }
            status = job.runModal(sub.newChild(100));
            if (status.getSeverity() == IStatus.CANCEL) {
                throw new OperationCanceledException();
            }
        } catch ( Exception e ){
            logger.error( "Exception while trying to get updates", e);
        }
    }
    return status;
}

我的功能中的p2.inf文件与我的example.product文件处于同一级别。它包含:

org.eclipse.equinox.p2.touchpoint.eclipse.addRepository": 
instructions.configure=\ 
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:file${#58}/C${#58}/workspace/updatesite/);\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:file${#58}/C${#58}/workspace/updatesite/);

我使用插件,功能和产品ID设置为1.0.0来构建产品。 我可以使用产品导出向导从eclipse导出和运行我的产品。我这样做时勾选generate metadata repository

我使用Feature Manfiest Editor中的Create an Update Site Project选项创建更新站点。我添加了我的`com.example.feature'并构建它。只是为了看它是否有效我尝试通过eclipse IDE安装新软件选项浏览它,我可以看到那里的功能。

我构建了更新站点,并将所有3个ID更改为1.0.1。当我启动应用程序时,它表示没有安装更新,日志中没有错误。

我不知道为什么它不会从更新站点更新,但我想到的事情是:

1)我可能需要p2.inf文件中的更多信息,但我不确定是什么,可能是命名空间,名称和范围,但我找不到一个好的实用示例

2)checkForUpdates方法中,我可能需要对配置文件执行某些操作来更改正在更新的可安装单元。同样,我只发现了暗示这一点的评论,而不是任何显示如何的示例代码。

这里非常感谢任何提示或想法,这需要花费很多时间。

3 个答案:

答案 0 :(得分:2)

看看这段代码。使用新产品版本重建产品并尝试设置http服务器。它对我来说无法使用文件回购。只是发布该功能将无法正常工作。

final IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

sub = SubMonitor.convert(monitor, Messages.getString("UpdateManager.searchforupdates"), 200); //$NON-NLS-1$
final Update update = getUpdate(profile, provisioningContext, engine, context);

status = operation.resolveModal(sub.newChild(100));
LogHelper.log(status);
if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) {
 status = null;
 return;
}
if (status.getSeverity() == IStatus.CANCEL)
 throw new OperationCanceledException();
if (status.getSeverity() != IStatus.ERROR) {
 log(IStatus.INFO, "Checking for available update matches", null); //$NON-NLS-1$
 Update[] selected = new Update[1];
 operation.setSelectedUpdates(new Update[0]);
 for (Update available : operation.getPossibleUpdates()) {
  if (available.equals(update)) {
   log(IStatus.INFO, "Update matches available: " + update, null); //$NON-NLS-1$
   selected[0] = available;
   operation.setSelectedUpdates(selected);
  }
 }
 if (selected[0] == null) {
  status = null;
  monitor.setCanceled(true);

  log(IStatus.WARNING, "No Update matches selected", null); //$NON-NLS-1$
  return;
 }
 ProvisioningJob job = operation.getProvisioningJob(monitor);
 if (job != null) {
  status = job.runModal(sub.newChild(100));
  if (status.getSeverity() != IStatus.ERROR) {
   prefStore.setValue(JUSTUPDATED, true);
   Display.getDefault().syncExec(new Runnable() {
    public void run() {
     PlatformUI.getWorkbench().restart();
    }
   });

  } else {
   LogHelper.log(status);
  }

 } else {
  log(IStatus.INFO, "getJob returned null", null); //$NON-NLS-1$
  status = null;
 }
 if (status != null && status.getSeverity() == IStatus.CANCEL)
  throw new OperationCanceledException();
 }
 }
};

Display.getDefault().asyncExec(new Runnable() {
public void run() {
try {
 new ProgressMonitorDialog(null).run(true, true, runnable);
} catch (InvocationTargetException x) {
 log(IStatus.ERROR, "Runnable failure", x); //$NON-NLS-1$
} catch (InterruptedException e) {
}
}
});

答案 1 :(得分:1)

@ user473284的回答有一些我曾经使用的建议,但我不知道它们是否是明确的要求

1)使用本地Web服务器而不是尝试指向文件 2)增加产品版本并使用导出产品向导生成的更新存储库。

我从来没有找到从代码示例中引用的getUpdate方法的实现,因此我无法使用该代码段。

在上述更改之后,我仍然留下应用程序检测到启动时没有更新。调试显示我的存储库没有出现在会话中。我必须在代码中明确添加更新URL,尽管它在p2.inf和功能清单编辑器表单字段中设置。这是代码:

    public static void addUpdateSite(IProvisioningAgent provisioningAgent)
        throws InvocationTargetException {
    // Load repository manager
    IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) provisioningAgent
            .getService(IMetadataRepositoryManager.SERVICE_NAME);
    if (metadataManager == null) {
        logger.error( "Metadata manager was null");
         Throwable throwable = new
         Throwable("Could not load Metadata Repository Manager");
         throwable.fillInStackTrace();
         throw new InvocationTargetException(throwable);
    }

    // Load artifact manager
    IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) provisioningAgent
            .getService(IArtifactRepositoryManager.SERVICE_NAME);
    if (artifactManager == null) {
        logger.error( "Artifact manager was null");
        Throwable throwable = new Throwable(
                "Could not load Artifact Repository Manager");
        throwable.fillInStackTrace();
        throw new InvocationTargetException(throwable);
    }

    // Load repo
    try {
        URI repoLocation = new URI("http://localhost/respository");
        logger.info( "Adding repository " + repoLocation );
        metadataManager.loadRepository(repoLocation, null);
        artifactManager.loadRepository(repoLocation, null);
    } catch (ProvisionException pe) {
        logger.error( "Caught provisioning exception " + pe.getMessage(), pe);
        throw new InvocationTargetException(pe);
    } catch (URISyntaxException e) {
        logger.error( "Caught URI syntax exception " + e.getMessage(), e);
        throw new InvocationTargetException(e);
    }
}

我现在在原始问题的checkForUpdates方法中首先调用它。在此更改后,我的应用程序至少现在看到更新并尝试安装它。我仍然遇到问题,但我应该在https://stackoverflow.com/questions/3944953/error-during-p2-eclipse-rcp-app-headless-update

创建一个独立的问题。

答案 2 :(得分:0)

  1. Web服务器不是必需的,您可以通过文件位置获取更新。
  2. 也必须更改产品版本。
  3. 您无法使用随产品导出的更新站点项目构建更新这些功能,但是您可以通过对导出产品进行一些黑客攻击来实现这些功能。
  4. 如果您使用(安装新软件)选项添加一些其他功能,则可以使用更新站点项目构建更新这些功能。
  5. 希望这会有所帮助。如果您需要更多说明,可以询问。