Search code examples
osgiequinoxp2

How can I resolve and start a bundle after provisioning into running profile


My application is currently using equinox's IProvisioningAgent to find and provision a bundle into my running profile. The code is along the lines of the following;

// Look up agent provider using OSGI service
IProvisioningAgentProvider provider = ...;
IProvisioningAgent = provider.createAgent(null); // Use currently running agent

// Define IU
IInstallableUnit iu = ...; // found using remote repository queries

// Find profile
IProfileRegistry registry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME);
IProfile profile = registry.getProfile(IProfileRegistry.SELF);

// Create change request
IPlanner planner = (IPlanner) agent.getService(IPlanner.SERVICE_NAME);
IProfileChangeRequest request = planner.createChangeRequest(profile);
request.add(iu);

// Create plan and perform
IProvisioningPlan plan = planner.getProvisioningPlan(request, ctx, monitor);
IEngine engine = (IEngine) agent.getService(IEngine.SERVICE_NAME);
IStatus status = engine.perform(plan,  PhaseSetFactory.createDefaultPhaseSet(), monitor);

This works fine and I can see that the IU (with dependencies) has been installed on disk.

I now need to install the bundle(s) into the running environment without restarting. All examples that I can find online just restart the platform which isn't suitable in this case. I have used BundleContext.installBundle() previously, but it seems too low level and I can't find how to get the URL from the provisioning API.

Is there another part of the provisioning API that I can use? I have read up on using org.eclipse.equinox.internal.provisional.configurator.Configurator, but it's internal and doesn't seem to solve the problem anyway.

My question is: What is the correct step to install, resolve and start the bundles that I have just provisioned without restarting.


Solution

  • I found an additional service that exposed the IU's artifacts as a java.io.File so can replace Ilya's especially stinky part.

    IAgentLocation location = (IAgentLocation) agent.getService(IAgentLocation.SERVICE_NAME);
    URI bundlePool = location.getDataArea(ECLIPSE_TOUCHPOINT_ID);
    IArtifactRepositoryManager manager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
    // XXX Bit of a smell to cast here, but I know they are files now.
    IFileArtifactRepository repository = (IFileArtifactRepository) manager.loadRepository(
                    bundlePool, monitor);
    
    
    // I can get the artifact and then query the repository
    for (IArtifactKey artifact : iu.getArtifacts()) {
      File file = repository.getArtifactFile(artifact);
      URI uri = file.toURI();
    
      // Install the bundle
      ctx.installBundle(uri.toString());
    }
    

    For the most part, this works. The code here has been stripped of error handling and probably won't compile without tweaks. It should work for different profiles and different agents.

    I believe there is a better solution that involves using eclipse touchpoints to auto install the bundle in the correct phase. If I find a better solution, I will try to update here.