Skip to content

Commit

Permalink
Implement the OSGi-Framework-Connect on top of Plexus
Browse files Browse the repository at this point in the history
OSGi provides a new specification that allows powerful integration of
"outside" bundles into a framework.

Tycho can leverage this to have a seamless integration with the P2 code
that requires OSGi to run but still interact with the OSGi parts without
additional integration/conversion patterns.
  • Loading branch information
laeubi committed Jul 20, 2022
1 parent a2ae0da commit fe2ce13
Show file tree
Hide file tree
Showing 15 changed files with 901 additions and 256 deletions.
32 changes: 32 additions & 0 deletions RELEASE_NOTES.md
Expand Up @@ -4,6 +4,38 @@ This page describes the noteworthy improvements provided by each release of Ecli

## 3.0.0 (under development)

### new sisu-osgi-connect

The new sisu-osgi-connect provides an implementation for plexus according to the [Connect Specification](http://docs.osgi.org/specification/osgi.core/8.0.0/framework.connect.html#framework.connect) that allows to run an embedded OSGi Framework from the classpath of a maven-plugin.
As both, the maven plugin and the embedded framework, share the same classlaoder you can use the best of both worlds and interact seamless with them.

This can be used in the following way:

```
@Component(role = MyPlexusComponent.class)
public class MyPlexusComponent {
@Requirement(hint = "connect")
private EquinoxServiceFactory serviceFactory;
public void helloConnect() {
serviceFactory.getService(HelloWorldService.class).sayHello();
}
}
```

For the setup you need to do the following:

1. include any bundle you like to make up your plexus-osgi-connect framework as a dependency of your maven plugin
2. include a file `META-INF/sisu-connect.bundles` that list all your bundles you like to have installed in the format `bsn[,true]`, where `bsn` is the symbolid name and optionally you can control if your bundle has to be started or not
3. include the following additional dependency
```
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>sisu-osgi-connect</artifactId>
<version>${tycho-version}</version>
</dependency>
```

### Deprecated Features

The `tycho-compiler:compile` and `tycho-compiler:testCompile` option `requireJREPackageImports` is deprecated now and will produce a warning when used, bundles currently rely on this option should migrate to proper importing packages from the non java.* namespace.
Expand Down
115 changes: 112 additions & 3 deletions p2-maven-plugin/pom.xml
Expand Up @@ -72,9 +72,19 @@
<version>1.4.100</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.frameworkadmin</artifactId>
<version>2.2.0</version>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.frameworkadmin</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.preferences</artifactId>
<version>3.10.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.security</artifactId>
<version>1.3.800</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
Expand Down Expand Up @@ -102,11 +112,110 @@
<artifactId>org.eclipse.equinox.p2.updatesite</artifactId>
<version>1.2.300</version>
</dependency>
<!-- used API packages from Tycho -->
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-embedder-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>sisu-osgi-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>sisu-osgi-connect</artifactId>
<version>${project.version}</version>
</dependency>
<!-- P2 -->
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.p2.jarprocessor</artifactId>
<version>1.2.300</version>
</dependency>
<!-- Equinox -->
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.concurrent</artifactId>
<version>1.2.100</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.simpleconfigurator</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.app</artifactId>
<version>1.6.100</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.frameworkadmin.equinox</artifactId>
<version>1.2.200</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.simpleconfigurator.manipulator</artifactId>
<version>2.2.0</version>
</dependency>
<!-- ECF -->
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.p2.transport.ecf</artifactId>
<version>1.3.300</version>
</dependency>
<dependency>
<groupId>org.eclipse.ecf</groupId>
<artifactId>org.eclipse.ecf.identity</artifactId>
<version>3.9.402</version>
</dependency>
<dependency>
<groupId>org.eclipse.ecf</groupId>
<artifactId>org.eclipse.ecf.provider.filetransfer</artifactId>
<version>3.2.800</version>
</dependency>
<dependency>
<groupId>org.eclipse.ecf</groupId>
<artifactId>org.eclipse.ecf.filetransfer</artifactId>
<version>5.1.102</version>
</dependency>
<dependency>
<groupId>org.eclipse.ecf</groupId>
<artifactId>org.eclipse.ecf</artifactId>
<version>3.10.0</version>
</dependency>

<!-- felix -->
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>2.2.2</version>
</dependency>
<!-- OSGi API -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component</artifactId>
<version>1.5.0</version>
</dependency>
<!-- others -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

</dependencies>

<build>
Expand Down
Expand Up @@ -12,54 +12,39 @@
*******************************************************************************/
package org.eclipse.tycho.p2maven;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory;
import org.osgi.framework.BundleContext;
import org.eclipse.sisu.equinox.EquinoxServiceFactory;

@Component(role = IProvisioningAgent.class)
public class DefaultProvisioningAgent implements IProvisioningAgent {

@Requirement
private Logger log;

@Requirement(hint = "plexus")
private BundleContext bundleContext;

@Requirement(role = IAgentServiceFactory.class)
private Map<String, IAgentServiceFactory> factoryMap;

private Map<String, Object> services = new ConcurrentHashMap<String, Object>();
@Requirement(hint = "connect")
private EquinoxServiceFactory serviceFactory;

@Override
public Object getService(String serviceName) {
return services.computeIfAbsent(serviceName, role -> {
IAgentServiceFactory serviceFactory = factoryMap.get(role);
if (serviceFactory != null) {
return serviceFactory.createService(DefaultProvisioningAgent.this);
}
return null;
});
return serviceFactory.getService(IProvisioningAgent.class).getService(serviceName);
}

@Override
public void registerService(String serviceName, Object service) {
throw new UnsupportedOperationException();
serviceFactory.getService(IProvisioningAgent.class).registerService(serviceName, service);
}

@Override
public void stop() {

throw new UnsupportedOperationException();
}

@Override
public void unregisterService(String serviceName, Object service) {
throw new UnsupportedOperationException();
serviceFactory.getService(IProvisioningAgent.class).unregisterService(serviceName, service);
}

}
Expand Up @@ -41,10 +41,12 @@
import org.eclipse.equinox.internal.p2.publisher.eclipse.IProductDescriptor;
import org.eclipse.equinox.internal.p2.updatesite.CategoryParser;
import org.eclipse.equinox.internal.p2.updatesite.SiteModel;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.publisher.IPublisherAction;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.equinox.p2.publisher.eclipse.Feature;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.tycho.PackagingType;
import org.eclipse.tycho.p2maven.actions.AuthoredIUAction;
import org.eclipse.tycho.p2maven.actions.CategoryDependenciesAction;
Expand All @@ -53,7 +55,6 @@
import org.eclipse.tycho.p2maven.actions.ProductFile2;
import org.eclipse.tycho.p2maven.helper.PluginRealmHelper;
import org.eclipse.tycho.p2maven.io.MetadataIO;
import org.osgi.framework.BundleContext;
import org.xml.sax.SAXException;

/**
Expand All @@ -71,9 +72,8 @@ public class InstallableUnitGenerator {

private static final String KEY_UNITS = "InstallableUnitGenerator.units";

// this requirement is here to bootstrap P2 service access
@Requirement(hint = "plexus")
private BundleContext bundleContext;
@Requirement
private IProvisioningAgent provisioningAgent;

@Requirement(role = InstallableUnitProvider.class)
private Map<String, InstallableUnitProvider> additionalUnitProviders;
Expand All @@ -97,6 +97,7 @@ public class InstallableUnitGenerator {
public Map<MavenProject, Collection<IInstallableUnit>> getInstallableUnits(Collection<MavenProject> projects,
MavenSession session)
throws CoreException {
init();
Objects.requireNonNull(session);
List<CoreException> errors = new CopyOnWriteArrayList<CoreException>();
Map<MavenProject, Collection<IInstallableUnit>> result = new ConcurrentHashMap<MavenProject, Collection<IInstallableUnit>>();
Expand All @@ -120,6 +121,13 @@ public Map<MavenProject, Collection<IInstallableUnit>> getInstallableUnits(Colle
throw new CoreException(multiStatus);
}

private void init() {
// this requirement is here to bootstrap P2 service access
// see https://github.com/eclipse-equinox/p2/issues/100
// then this would not be required anymore
provisioningAgent.getService(IArtifactRepositoryManager.class);
}

/**
* Computes the {@link IInstallableUnit}s for the given project, the computation
* is cached unless forceUpdate is <code>true</code> meaning data is always
Expand All @@ -136,6 +144,7 @@ public Map<MavenProject, Collection<IInstallableUnit>> getInstallableUnits(Colle
public Collection<IInstallableUnit> getInstallableUnits(MavenProject project, MavenSession session,
boolean forceUpdate)
throws CoreException {
init();
Objects.requireNonNull(session);
log.debug("Computing installable units for " + project + ", force update = " + forceUpdate);
synchronized (project) {
Expand Down

0 comments on commit fe2ce13

Please sign in to comment.