【问题标题】:Eclipse P2 - Declarative Services with various P2 components?Eclipse P2 - 具有各种 P2 组件的声明式服务?
【发布时间】:2012-07-31 10:08:06
【问题描述】:

所以当我尝试使用以下方法从供应代理获取元数据和工件存储库管理器时,我一直遇到这个问题:

ServiceReference<?> sr = Activator.getContext().getServiceReference(IProvisioningAgentProvider.SERVICE_NAME);
IProvisioningAgentProvider agentProvider = null;

if (sr == null)return;

agentProvider = (IProvisioningAgentProvider) Activator.getContext().getService(sr);
final IProvisioningAgent agent = agentProvider.createAgent(new URI("some place"));
IMetadataRepositoryManager manager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);

如果这些服务已经启动,则效果很好。但是,很多时候工件管理器会返回 null,因为它的服务还不存在。我已经能够通过将包含上述代码的捆绑包的启动级别设置为 5 来破解它,因此在我尝试获取它们的服务引用之前所有服务都已启动。

我真的不想搞乱起始关卡。我想做的是使用声明性服务来设置这些不同的组件,从而延迟我的服务的启动。唯一的问题是我不知道要引用哪些服务,所以我可以将它们放在我的 component.xml 文件中。这在 eclipse 3.7.2 中是否可能?

【问题讨论】:

    标签: eclipse equinox p2 declarative-services


    【解决方案1】:

    到目前为止,这是我能找到的最好的方法。这并不完美,因为我必须解决一些循环依赖,这些依赖是在我的声明式服务绑定方法上检查服务名称时附带的。

    基本上我将 IAgentServiceFactory 设置为我的 component.xml

    中的依赖项
    <?xml version="1.0" encoding="UTF-8"?>
    <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="com.company.updateManager">
       <implementation class="com.company.updatemanager.UpdateManager"/>
       <service>
          <provide interface="com.company.updatemanager.IUpdateManager"/>
       </service>
       <reference bind="addAgentService" cardinality="1..n" interface="org.eclipse.equinox.p2.core.spi.IAgentServiceFactory" name="IAgentServiceFactory" policy="dynamic"/>
    </scr:component>
    

     

    然后我就有了实现上述组件的类(下面稍微解释一下) com.company.updatemanager.UpdateManager

    package com.company.updatemanager;
    
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Map;
    
    import org.eclipse.core.runtime.IStatus;
    import org.eclipse.core.runtime.NullProgressMonitor;
    import org.eclipse.core.runtime.jobs.IJobChangeEvent;
    import org.eclipse.core.runtime.jobs.Job;
    import org.eclipse.core.runtime.jobs.JobChangeAdapter;
    import org.eclipse.equinox.p2.core.IProvisioningAgent;
    import org.eclipse.equinox.p2.core.IProvisioningAgentProvider;
    import org.eclipse.equinox.p2.core.ProvisionException;
    import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory;
    import org.eclipse.equinox.p2.engine.IProfile;
    import org.eclipse.equinox.p2.engine.IProfileRegistry;
    import org.eclipse.equinox.p2.metadata.IInstallableUnit;
    import org.eclipse.equinox.p2.operations.InstallOperation;
    import org.eclipse.equinox.p2.operations.ProvisioningSession;
    import org.eclipse.equinox.p2.query.QueryUtil;
    import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
    import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
    import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
    import org.osgi.framework.ServiceReference;
    
    public class UpdateManager implements IUpdateManager {
    
        URI updateURI;
    
        boolean alreadyAutoUpdated;
    
        boolean hasMetaDataRepoMan;
        boolean hasArtifactRepoMan;
    
    
        /*
         * I have to hack around some sort of circular dependency that happens when I try to reference
         * the repoManager classes in the addAgentService method.  It doesn't happen when run from
         * the IDE, but does when everything is compiled. It works fine if I access these properties
         * in a constructor or right here or somewhere else, but whatever object in OSGI is binding
         * with the addAgentService method creates a circular dependency.  
         */
        String artifactServiceName = IArtifactRepositoryManager.SERVICE_NAME;
        String metaDataServiceName = IMetadataRepositoryManager.SERVICE_NAME;
    
        public void addAgentService(IAgentServiceFactory serv, Map properties){
            System.out.println("Got Agent Service " + (String) properties.get("p2.agent.servicename"));
            String serviceName = (String) properties.get("p2.agent.servicename");
    
            if(serviceName.equals(this.metaDataServiceName)){
                this.hasMetaDataRepoMan = true;
            }else if(serviceName.equals(this.artifactServiceName)){
                this.hasArtifactRepoMan = true;
            }
    
            if(checkAllServices()){
                autoUpdate();
            }
        }
    
        private void autoUpdate(){
            if(!alreadyAutoUpdated){
                try {
                    alreadyAutoUpdated = true;
                    update();
                } catch (ProvisionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (URISyntaxException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    
        private boolean checkAllServices(){
            if(this.hasMetaDataRepoMan && 
                    this.hasArtifactRepoMan){
                return true;
            }else{
                return false;
            }
        }
    
        public void update(){
            ServiceReference<?> sr = Activator.getContext().getServiceReference(IProvisioningAgentProvider.SERVICE_NAME);
            IProvisioningAgentProvider agentProvider = null;
    
            if (sr == null)return;
    
            agentProvider = (IProvisioningAgentProvider) Activator.getContext().getService(sr);
            final IProvisioningAgent agent = agentProvider.createAgent(new URI("some place"));
            IMetadataRepositoryManager manager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
            IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
    
            //rest of your update code
        }
    }
    

    代码中解释了循环依赖。我宁愿解决这个问题,也不愿搞砸运行级别。我真的很讨厌处理运行级别。

    但基本上 IAgentServiceFactory 似乎是负责创建各种 P2 服务的组件,包括 MetaData 和 Artifact 存储库管理器。我基本上只是检查工厂提供的包含服务名称的每个服务的属性。如果我获得了我想要注册的所有服务,那么我继续运行我在原始帖子中使用的更新代码。这至少给了我一些保证,当我尝试从服务注册表中获取服务时,服务不会返回 null。

    【讨论】:

      猜你喜欢
      • 2016-02-27
      • 2013-09-26
      • 2015-09-12
      • 2013-10-30
      • 2011-01-20
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      • 2016-02-02
      相关资源
      最近更新 更多