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