You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2020/09/18 07:17:12 UTC
[karaf-winegrower] branch master updated: First skeleton for
requirements support + OSGi-CDI cepage (#4)
This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf-winegrower.git
The following commit(s) were added to refs/heads/master by this push:
new b49ed9d First skeleton for requirements support + OSGi-CDI cepage (#4)
b49ed9d is described below
commit b49ed9d4eec6d4005abc8e02265a282f6a8e3270
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Fri Sep 18 09:14:44 2020 +0200
First skeleton for requirements support + OSGi-CDI cepage (#4)
---
winegrower-cepages/pom.xml | 1 +
winegrower-cepages/winegrower-cepage-http/pom.xml | 1 -
.../winegrower-cepage-osgi-cdi/pom.xml | 107 ++++++
.../manifest/OSGiCDIManifestContributor.java | 91 ++++++
...winegrower.scanner.manifest.ManifestContributor | 1 +
.../winegrower/cepage/osgicdi/OSGiCDITest.java | 59 ++++
.../src/test/resources/META-INF/beans.xml | 25 ++
.../winegrower/deployer/BundleCapabilityImpl.java | 59 ++++
.../org/apache/winegrower/deployer/BundleImpl.java | 358 +++++++++++++++++++--
.../winegrower/deployer/BundleRequirementImpl.java | 73 +++++
.../winegrower/deployer/BundleRevisionImpl.java | 6 +-
.../apache/winegrower/deployer/BundleWireImpl.java | 70 ++++
.../winegrower/deployer/BundleWiringImpl.java | 49 ++-
.../winegrower/deployer/OSGiBundleLifecycle.java | 2 +-
.../apache/winegrower/scanner/KnownJarsFilter.java | 1 +
.../java/org/apache/winegrower/RipenerTest.java | 3 +-
.../apache/winegrower/deployer/BundleImplTest.java | 4 +-
.../winegrower/service/ServiceListenerTest.java | 2 -
.../test/listener/filter/Registrator.java | 2 -
.../osgi-cdi}/pom.xml | 51 +--
.../winegrower/examples/osgicdi/HelloOsgiCdi.java | 25 ++
winegrower-examples/pom.xml | 5 +-
22 files changed, 930 insertions(+), 65 deletions(-)
diff --git a/winegrower-cepages/pom.xml b/winegrower-cepages/pom.xml
index a6916f0..a10d6a1 100644
--- a/winegrower-cepages/pom.xml
+++ b/winegrower-cepages/pom.xml
@@ -45,6 +45,7 @@
<module>winegrower-cepage-http</module>
<module>winegrower-cepage-cxf-rs</module>
<module>winegrower-cepage-jaxrs</module>
+ <module>winegrower-cepage-osgi-cdi</module>
</modules>
<build>
diff --git a/winegrower-cepages/winegrower-cepage-http/pom.xml b/winegrower-cepages/winegrower-cepage-http/pom.xml
index 97471ca..75755db 100644
--- a/winegrower-cepages/winegrower-cepage-http/pom.xml
+++ b/winegrower-cepages/winegrower-cepage-http/pom.xml
@@ -91,5 +91,4 @@
<version>${karaf.version}</version>
</dependency>
</dependencies>
-
</project>
diff --git a/winegrower-cepages/winegrower-cepage-osgi-cdi/pom.xml b/winegrower-cepages/winegrower-cepage-osgi-cdi/pom.xml
new file mode 100644
index 0000000..4f948a3
--- /dev/null
+++ b/winegrower-cepages/winegrower-cepage-osgi-cdi/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.winegrower.cepages</groupId>
+ <artifactId>winegrower-cepages</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>winegrower-cepage-osgi-cdi</artifactId>
+ <name>Apache Winegrower :: Cepages :: OSGi CDI</name>
+
+ <properties>
+ <aries-cdi.version>1.1.0</aries-cdi.version>
+ <owb.version>2.0.14</owb.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.winegrower</groupId>
+ <artifactId>winegrower-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.aries.cdi</groupId>
+ <artifactId>org.apache.aries.cdi.extender</artifactId>
+ <version>${aries-cdi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.cdi</groupId>
+ <artifactId>org.apache.aries.cdi.extension.servlet.owb</artifactId>
+ <version>${aries-cdi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.cdi</groupId>
+ <artifactId>org.apache.aries.cdi.owb</artifactId>
+ <version>${aries-cdi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans-spi</artifactId>
+ <version>${owb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans-impl</artifactId>
+ <version>${owb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans-web</artifactId>
+ <version>${owb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openwebbeans</groupId>
+ <artifactId>openwebbeans-el22</artifactId>
+ <version>${owb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.spifly</groupId>
+ <artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
+ <version>1.2.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-el_2.2_spec</artifactId>
+ <version>1.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.winegrower</groupId>
+ <artifactId>winegrower-testing-junit5</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/winegrower-cepages/winegrower-cepage-osgi-cdi/src/main/java/org/apache/winegrower/scanner/manifest/OSGiCDIManifestContributor.java b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/main/java/org/apache/winegrower/scanner/manifest/OSGiCDIManifestContributor.java
new file mode 100644
index 0000000..0e5501a
--- /dev/null
+++ b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/main/java/org/apache/winegrower/scanner/manifest/OSGiCDIManifestContributor.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.winegrower.scanner.manifest;
+
+import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.joining;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.stream.Stream;
+
+import org.apache.xbean.finder.AnnotationFinder;
+import org.apache.xbean.finder.archive.Archive;
+import org.apache.xbean.finder.archive.FileArchive;
+import org.osgi.framework.Constants;
+
+public class OSGiCDIManifestContributor implements ManifestContributor {
+ @Override
+ public void contribute(final AnnotationFinder finder, final Supplier<Manifest> manifest) {
+ final Archive archive = finder.getArchive();
+ if (!FileArchive.class.isInstance(archive) || !hasBeansXml(FileArchive.class.cast(archive))) {
+ return; // already a jar, its manifest is likely already good
+ }
+
+ final Attributes attributes = manifest.get().getMainAttributes();
+ final String newRequireCapability = toCapability(finder);
+ final String existing = attributes.getValue(Constants.REQUIRE_CAPABILITY);
+ final String ariesCdiExtensions = findCdiExtensions(finder);
+ attributes.putValue(Constants.REQUIRE_CAPABILITY, Stream.of(existing, newRequireCapability, ariesCdiExtensions)
+ .filter(Objects::nonNull)
+ .filter(it -> !it.isEmpty())
+ .collect(joining(",")));
+ }
+
+ // todo: drop and handle @Requirement transitively in core
+ private String findCdiExtensions(final AnnotationFinder finder) {
+ try {
+ final ClassLoader loader = ofNullable(Thread.currentThread().getContextClassLoader())
+ .orElseGet(ClassLoader::getSystemClassLoader);
+ final Class<? extends Annotation> singular = (Class<? extends Annotation>)
+ loader.loadClass("org.apache.aries.cdi.extra.RequireCDIExtension");
+ final Class<? extends Annotation> plural = (Class<? extends Annotation>)
+ loader.loadClass("org.apache.aries.cdi.extra.RequireCDIExtensions");
+ final Method value = singular.getMethod("value");
+ return Stream.concat(
+ finder.findAnnotatedClasses(plural).stream(),
+ finder.findAnnotatedClasses(singular).stream())
+ .distinct()
+ .flatMap(c -> Stream.of(c.getAnnotationsByType(singular)))
+ .map(rce -> {
+ try {
+ final Object extension = value.invoke(rce);
+ return "osgi.cdi.extension;filter:=\"(osgi.cdi.extension=" + extension + ")\"";
+ } catch (final IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ } catch (final InvocationTargetException e) {
+ throw new IllegalStateException(e.getTargetException());
+ }
+ })
+ .collect(joining(","));
+ } catch (final Exception cnfe) {
+ return null;
+ }
+ }
+
+ private String toCapability(final AnnotationFinder finder) {
+ return "osgi.extender;filter:=\"(osgi.extender=osgi.cdi)\";beans:List<String>=\"" +
+ String.join(",", finder.getAnnotatedClassNames()) + "\"";
+ }
+
+ private boolean hasBeansXml(final FileArchive archive) {
+ return Files.exists(archive.getDir().toPath().resolve("META-INF/beans.xml"));
+ }
+}
diff --git a/winegrower-cepages/winegrower-cepage-osgi-cdi/src/main/resources/META-INF/services/org.apache.winegrower.scanner.manifest.ManifestContributor b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/main/resources/META-INF/services/org.apache.winegrower.scanner.manifest.ManifestContributor
new file mode 100644
index 0000000..434c653
--- /dev/null
+++ b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/main/resources/META-INF/services/org.apache.winegrower.scanner.manifest.ManifestContributor
@@ -0,0 +1 @@
+org.apache.winegrower.scanner.manifest.OSGiCDIManifestContributor
diff --git a/winegrower-cepages/winegrower-cepage-osgi-cdi/src/test/java/org/apache/winegrower/cepage/osgicdi/OSGiCDITest.java b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/test/java/org/apache/winegrower/cepage/osgicdi/OSGiCDITest.java
new file mode 100644
index 0000000..017efa5
--- /dev/null
+++ b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/test/java/org/apache/winegrower/cepage/osgicdi/OSGiCDITest.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.winegrower.cepage.osgicdi;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.winegrower.Ripener;
+import org.apache.winegrower.api.InjectedService;
+import org.apache.winegrower.deployer.OSGiBundleLifecycle;
+import org.apache.winegrower.extension.testing.junit5.Winegrower;
+import org.junit.jupiter.api.Test;
+import org.osgi.service.cdi.runtime.CDIComponentRuntime;
+import org.osgi.service.cdi.runtime.dto.ContainerDTO;
+
+@Winegrower
+class OSGiCDITest {
+ @InjectedService
+ private Ripener ripener;
+
+ @InjectedService
+ private CDIComponentRuntime ccr;
+
+ @Test
+ void test() {
+ assertNotNull(ccr);
+
+ final Map<Long, OSGiBundleLifecycle> bundles = ripener.getRegistry().getBundles();
+ final long id = bundles.entrySet().stream()
+ .filter(e -> e.getValue().getBundle().getLocation().endsWith("test-classes"))
+ .findFirst()
+ .map(Map.Entry::getKey)
+ .orElseGet(() -> fail("no test-classes bundle"));
+
+ final Collection<ContainerDTO> containerDTOs = ccr.getContainerDTOs(bundles.get(id).getBundle());
+ assertNotNull(containerDTOs);
+ assertEquals(1, containerDTOs.size());
+
+ final ContainerDTO dto = containerDTOs.iterator().next();
+ assertNotNull(dto);
+ assertTrue(dto.errors.isEmpty(), () -> dto.errors.toString());
+ }
+}
diff --git a/winegrower-cepages/winegrower-cepage-osgi-cdi/src/test/resources/META-INF/beans.xml b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/test/resources/META-INF/beans.xml
new file mode 100644
index 0000000..1d9dae2
--- /dev/null
+++ b/winegrower-cepages/winegrower-cepage-osgi-cdi/src/test/resources/META-INF/beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<beans bean-discovery-mode="all" version="2.0"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://xmlns.jcp.org/xml/ns/javaee
+ http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd">
+ <trim/>
+</beans>
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleCapabilityImpl.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleCapabilityImpl.java
new file mode 100644
index 0000000..a00b1d5
--- /dev/null
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleCapabilityImpl.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.winegrower.deployer;
+
+import java.util.Map;
+
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class BundleCapabilityImpl implements BundleCapability {
+ private final BundleRevision revision;
+ private final String path;
+ private final Map<String, String> directives;
+ private final Map<String, Object> attributes;
+
+ public BundleCapabilityImpl(final BundleRevision revision, final String path,
+ final Map<String, String> directives, final Map<String, Object> attributes) {
+ this.revision = revision;
+ this.path = path;
+ this.directives = directives;
+ this.attributes = attributes;
+ }
+
+ @Override
+ public BundleRevision getRevision() {
+ return revision;
+ }
+
+ @Override
+ public String getNamespace() {
+ return path;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public BundleRevision getResource() {
+ return revision;
+ }
+}
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleImpl.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleImpl.java
index e1090cf..2e16b4f 100644
--- a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleImpl.java
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleImpl.java
@@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
@@ -44,15 +45,19 @@ import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import org.apache.winegrower.Ripener;
+import org.apache.winegrower.service.BundleRegistry;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
public class BundleImpl implements Bundle {
@@ -65,46 +70,86 @@ public class BundleImpl implements Bundle {
private final Dictionary<String, String> headers;
private final File dataFileBase;
private final Collection<String> includedResources;
+ private final List<BundleRequirementImpl> requirements;
+ private final List<BundleCapabilityImpl> capabilities;
+ private final BundleRegistry registry;
+
+ private volatile BundleRevision bundleRevision;
+ private volatile BundleWiring bundleWiring;
+
private int state = Bundle.UNINSTALLED;
BundleImpl(final Manifest manifest, final File file, final BundleContextImpl context,
final Ripener.Configuration configuration, final long id,
- final Collection<String> includedResources) {
+ final Collection<String> includedResources, final BundleRegistry registry) {
this.file = file;
this.dataFileBase = new File(configuration.getWorkDir(),
file == null ? Long.toString(System.identityHashCode(manifest)) : file.getName());
this.context = context;
this.id = id;
+ this.registry = registry;
this.loader = Thread.currentThread().getContextClassLoader();
this.includedResources = includedResources;
this.version = ofNullable(manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION))
- .map(Version::new)
- .orElse(Version.emptyVersion);
+ .map(Version::new)
+ .orElse(Version.emptyVersion);
this.symbolicName = manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
this.headers = manifest.getMainAttributes().entrySet().stream()
- .collect(Collector.of(
- Hashtable::new,
- (t, e) -> t.put(Attributes.Name.class.cast(e.getKey()).toString(), e.getValue().toString()),
- (t1, t2) -> {
- t1.putAll(t2);
- return t1;
- }));
+ .collect(Collector.of(
+ Hashtable::new,
+ (t, e) -> t.put(Attributes.Name.class.cast(e.getKey()).toString(), e.getValue().toString()),
+ (t1, t2) -> {
+ t1.putAll(t2);
+ return t1;
+ }));
+
+ final List<HeaderClause> requireClauses = Headers.parse(headers.get(Constants.REQUIRE_CAPABILITY));
+ Headers.coerceCapabilityClauses(requireClauses);
+ requirements = requireClauses.stream()
+ .flatMap(clause -> {
+ final String filterStr = clause.directives.get(Constants.FILTER_DIRECTIVE);
+ try {
+ final Filter filter = filterStr == null ? null : FrameworkUtil.createFilter(filterStr);
+ return clause.paths.stream()
+ .map(path -> new BundleRequirementImpl(
+ adapt(BundleRevision.class), path, clause.directives, clause.attributes, filter));
+ } catch (final InvalidSyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ })
+ .collect(toList());
+
+ final List<HeaderClause> provideClauses = Headers.parse(headers.get(Constants.PROVIDE_CAPABILITY));
+ Headers.coerceCapabilityClauses(provideClauses);
+ capabilities = provideClauses.stream()
+ .flatMap(clause -> clause.paths.stream()
+ .map(path -> new BundleCapabilityImpl(
+ adapt(BundleRevision.class), path, clause.directives, clause.attributes)))
+ .collect(toList());
}
ClassLoader getLoader() {
return loader;
}
+ List<BundleRequirementImpl> getRequirements() {
+ return requirements;
+ }
+
+ List<BundleCapabilityImpl> getCapabilities() {
+ return capabilities;
+ }
+
private Stream<BundleListener> allBundleListeners() {
return context.getRegistry().getBundles().values().stream()
- .flatMap(it -> BundleContextImpl.class.cast(it.getBundle().getBundleContext()).getBundleListeners().stream());
+ .flatMap(it -> BundleContextImpl.class.cast(it.getBundle().getBundleContext()).getBundleListeners().stream());
}
void onStart() {
start();
final BundleEvent event = new BundleEvent(BundleEvent.STARTED, this);
allBundleListeners()
- .forEach(listener -> listener.bundleChanged(event));
+ .forEach(listener -> listener.bundleChanged(event));
}
void onStop() {
@@ -266,9 +311,9 @@ public class BundleImpl implements Bundle {
if (includedResources != null) {
if (!recurse) {
return enumeration(includedResources.stream()
- .filter(it -> doFilterEntry(filter, prefix, it))
- .map(loader::getResource)
- .collect(toList()));
+ .filter(it -> doFilterEntry(filter, prefix, it))
+ .map(loader::getResource)
+ .collect(toList()));
}
}
@@ -309,8 +354,8 @@ public class BundleImpl implements Bundle {
} else {
try (final JarFile jar = new JarFile(file)) {
return enumeration(list(jar.entries()).stream().filter(it -> it.getName().startsWith(prefix))
- .map(ZipEntry::getName).filter(name -> !name.endsWith("/")) // folders
- .filter(name -> doFilterEntry(filter, prefix, name)).map(name -> {
+ .map(ZipEntry::getName).filter(name -> !name.endsWith("/")) // folders
+ .filter(name -> doFilterEntry(filter, prefix, name)).map(name -> {
try {
return new URL("jar", null, file.toURI().toURL().toExternalForm() + "!/" + name);
} catch (final MalformedURLException e) {
@@ -354,7 +399,24 @@ public class BundleImpl implements Bundle {
@Override
public <A> A adapt(final Class<A> type) {
if (BundleWiring.class == type) {
- return type.cast(new BundleWiringImpl(this));
+ if (bundleWiring == null) {
+ synchronized (this) {
+ if (bundleWiring == null) {
+ bundleWiring = new BundleWiringImpl(this, registry);
+ }
+ }
+ }
+ return type.cast(bundleWiring);
+ }
+ if (BundleRevision.class == type) {
+ if (bundleRevision == null) {
+ synchronized (this) {
+ if (bundleRevision == null) {
+ bundleRevision = new BundleRevisionImpl(this);
+ }
+ }
+ }
+ return type.cast(bundleRevision);
}
return null;
}
@@ -375,4 +437,264 @@ public class BundleImpl implements Bundle {
public String toString() {
return "BundleImpl{file=" + file + ", id=" + id + '}';
}
+
+ public static class HeaderClause {
+ public final List<String> paths;
+ public final Map<String, String> directives;
+ public final Map<String, Object> attributes;
+ public final Map<String, String> types;
+
+ public HeaderClause(
+ final List<String> paths, final Map<String, String> dirs, final Map<String, Object> attrs,
+ final Map<String, String> types) {
+ this.paths = paths;
+ this.directives = dirs;
+ this.attributes = attrs;
+ this.types = types;
+ }
+ }
+
+ // taken from felix
+ private static class Headers {
+ private static final char EOF = (char) -1;
+ private static final int CLAUSE_START = 0;
+ private static final int PARAMETER_START = 1;
+ private static final int KEY = 2;
+ private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
+ private static final int ARGUMENT = 8;
+ private static final int VALUE = 16;
+
+ private static List<HeaderClause> parse(final String header) {
+ final List<HeaderClause> clauses = new ArrayList<>();
+ if (header == null) {
+ return clauses;
+ }
+ HeaderClause clause = null;
+ String key = null;
+ Map targetMap = null;
+ int state = CLAUSE_START;
+ int currentPosition = 0;
+ int startPosition = 0;
+ int length = header.length();
+ boolean quoted = false;
+ boolean escaped = false;
+
+ char currentChar;
+ do {
+ currentChar = currentPosition >= length ? EOF : header.charAt(currentPosition);
+ switch (state) {
+ case CLAUSE_START:
+ clause = new HeaderClause(new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());
+ clauses.add(clause);
+ // not needed to be called but "logically" needed: state = PARAMETER_START;
+ case PARAMETER_START:
+ startPosition = currentPosition;
+ state = KEY;
+ case KEY:
+ switch (currentChar) {
+ case ':':
+ case '=':
+ key = header.substring(startPosition, currentPosition).trim();
+ startPosition = currentPosition + 1;
+ targetMap = clause.attributes;
+ state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
+ break;
+ case EOF:
+ case ',':
+ case ';':
+ clause.paths.add(header.substring(startPosition, currentPosition).trim());
+ state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
+ break;
+ default:
+ break;
+ }
+ currentPosition++;
+ break;
+ case DIRECTIVE_OR_TYPEDATTRIBUTE:
+ if (currentChar == '=') {
+ if (startPosition != currentPosition) {
+ clause.types.put(key, header.substring(startPosition, currentPosition).trim());
+ } else {
+ targetMap = clause.directives;
+ }
+ state = ARGUMENT;
+ startPosition = currentPosition + 1;
+ }
+ currentPosition++;
+ break;
+ case ARGUMENT:
+ if (currentChar == '\"') {
+ quoted = true;
+ currentPosition++;
+ } else {
+ quoted = false;
+ }
+ if (!Character.isWhitespace(currentChar)) {
+ state = VALUE;
+ } else {
+ currentPosition++;
+ }
+ break;
+ case VALUE:
+ if (escaped) {
+ escaped = false;
+ } else {
+ if (currentChar == '\\') {
+ escaped = true;
+ } else if (quoted && currentChar == '\"') {
+ quoted = false;
+ } else if (!quoted) {
+ String value;
+ switch (currentChar) {
+ case EOF:
+ case ';':
+ case ',':
+ value = header.substring(startPosition, currentPosition).trim();
+ if (value.startsWith("\"") && value.endsWith("\"")) {
+ value = value.substring(1, value.length() - 1);
+ }
+ if (targetMap.put(key, value) != null) {
+ throw new IllegalArgumentException(
+ "Duplicate '" + key + "' in: " + header);
+ }
+ state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ currentPosition++;
+ break;
+ default:
+ break;
+ }
+ } while (currentChar != EOF);
+
+ if (state > PARAMETER_START) {
+ throw new IllegalArgumentException("Unable to parse header: " + header);
+ }
+ return clauses;
+ }
+
+ public static List<String> parseDelimitedString(String value, String delim, boolean trim) {
+ if (value == null) {
+ value = "";
+ }
+
+ List<String> list = new ArrayList<String>();
+
+ int CHAR = 1;
+ int DELIMITER = 2;
+ int STARTQUOTE = 4;
+ int ENDQUOTE = 8;
+
+ StringBuilder sb = new StringBuilder();
+
+ int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+ boolean isEscaped = false;
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+
+ boolean isDelimiter = (delim.indexOf(c) >= 0);
+
+ if (!isEscaped && (c == '\\')) {
+ isEscaped = true;
+ continue;
+ }
+
+ if (isEscaped) {
+ sb.append(c);
+ } else if (isDelimiter && ((expecting & DELIMITER) > 0)) {
+ if (trim) {
+ list.add(sb.toString().trim());
+ } else {
+ list.add(sb.toString());
+ }
+ sb.delete(0, sb.length());
+ expecting = (CHAR | DELIMITER | STARTQUOTE);
+ } else if ((c == '"') && ((expecting & STARTQUOTE) > 0)) {
+ sb.append(c);
+ expecting = CHAR | ENDQUOTE;
+ } else if ((c == '"') && ((expecting & ENDQUOTE) > 0)) {
+ sb.append(c);
+ expecting = (CHAR | STARTQUOTE | DELIMITER);
+ } else if ((expecting & CHAR) > 0) {
+ sb.append(c);
+ } else {
+ throw new IllegalArgumentException("Invalid delimited string: " + value);
+ }
+
+ isEscaped = false;
+ }
+
+ if (sb.length() > 0) {
+ if (trim) {
+ list.add(sb.toString().trim());
+ } else {
+ list.add(sb.toString());
+ }
+ }
+
+ return list;
+ }
+
+ private static void coerceCapabilityClauses(final List<HeaderClause> clauses) {
+ clauses.forEach(clause -> clause.types.forEach((key, type) -> {
+ if (!type.equals("String")) {
+ if (type.equals("Double")) {
+ clause.attributes.put(
+ key,
+ new Double(clause.attributes.get(key).toString().trim()));
+ } else if (type.equals("Version")) {
+ clause.attributes.put(
+ key,
+ new Version(clause.attributes.get(key).toString().trim()));
+ } else if (type.equals("Long")) {
+ clause.attributes.put(
+ key,
+ Long.valueOf(clause.attributes.get(key).toString().trim()));
+ } else if (type.startsWith("List")) {
+ final int startIdx = type.indexOf('<');
+ final int endIdx = type.indexOf('>');
+ if ((startIdx > 0 && endIdx <= startIdx) || (startIdx < 0 && endIdx > 0)) {
+ throw new IllegalArgumentException("Invalid Provide-Capability attribute list type for '"
+ + key + "' : " + type);
+ }
+
+ final String listType;
+ if (endIdx > startIdx) {
+ listType = type.substring(startIdx + 1, endIdx).trim();
+ } else {
+ listType = "String";
+ }
+
+ final List<String> tokens = parseDelimitedString(
+ clause.attributes.get(key).toString(), ",", false);
+ clause.attributes.put(key, tokens.stream()
+ .map(token -> {
+ switch (listType) {
+ case "String":
+ return token;
+ case "Double":
+ return Double.valueOf(token.trim());
+ case "Version":
+ return new Version(token.trim());
+ case "Long":
+ return Long.valueOf(token.trim());
+ default:
+ throw new IllegalArgumentException(
+ "Unknown Provide-Capability attribute list type for '"
+ + key + "' : " + type);
+ }
+ }).collect(toList()));
+ } else {
+ throw new IllegalArgumentException("Unknown Provide-Capability attribute type for '" +
+ key + "' : " + type);
+ }
+ }
+ }));
+ }
+ }
}
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRequirementImpl.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRequirementImpl.java
new file mode 100644
index 0000000..1339b24
--- /dev/null
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRequirementImpl.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.winegrower.deployer;
+
+import java.util.Map;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class BundleRequirementImpl implements BundleRequirement {
+ private final BundleRevision revision;
+ private final String path;
+ private final Map<String, String> directives;
+ private final Map<String, Object> attributes;
+ private final Filter filter;
+
+ public BundleRequirementImpl(final BundleRevision revision, final String path,
+ final Map<String, String> directives, final Map<String, Object> attributes,
+ final Filter filter) {
+ this.revision = revision;
+ this.path = path;
+ this.directives = directives;
+ this.attributes = attributes;
+ this.filter = filter;
+ }
+
+ @Override
+ public boolean matches(final BundleCapability capability) {
+ return filter == null || filter.matches(capability.getAttributes());
+ }
+
+ @Override
+ public String getNamespace() {
+ return path;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public BundleRevision getRevision() {
+ return revision;
+ }
+
+ @Override
+ public BundleRevision getResource() {
+ return revision;
+ }
+
+ Filter getFilter() {
+ return filter;
+ }
+}
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRevisionImpl.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRevisionImpl.java
index 2e31e66..62d0322 100644
--- a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRevisionImpl.java
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleRevisionImpl.java
@@ -28,11 +28,9 @@ import org.osgi.resource.Requirement;
public class BundleRevisionImpl implements BundleRevision {
private final BundleImpl bundle;
- private final BundleWiringImpl wiring;
- BundleRevisionImpl(final BundleImpl bundle, final BundleWiringImpl bundleWiring) {
+ BundleRevisionImpl(final BundleImpl bundle) {
this.bundle = bundle;
- this.wiring = bundleWiring;
}
@Override
@@ -62,7 +60,7 @@ public class BundleRevisionImpl implements BundleRevision {
@Override
public BundleWiring getWiring() {
- return wiring;
+ return bundle.adapt(BundleWiring.class);
}
@Override
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWireImpl.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWireImpl.java
new file mode 100644
index 0000000..5ba9791
--- /dev/null
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWireImpl.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.winegrower.deployer;
+
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+public class BundleWireImpl implements BundleWire {
+ private final BundleRevision requirer;
+ private final BundleRevision provider;
+ private final BundleWiring requirerWiring;
+ private final BundleWiring providerWiring;
+ private final BundleRequirement requirement;
+ private final BundleCapability capability;
+
+ public BundleWireImpl(final BundleRevision requirer, final BundleRevision provider,
+ final BundleWiring requirerWiring, final BundleWiring providerWiring,
+ final BundleRequirement requirement, final BundleCapability capability) {
+ this.requirer = requirer;
+ this.provider = provider;
+ this.requirerWiring = requirerWiring;
+ this.providerWiring = providerWiring;
+ this.requirement = requirement;
+ this.capability = capability;
+ }
+
+ @Override
+ public BundleCapability getCapability() {
+ return capability;
+ }
+
+ @Override
+ public BundleRequirement getRequirement() {
+ return requirement;
+ }
+
+ @Override
+ public BundleWiring getProviderWiring() {
+ return providerWiring;
+ }
+
+ @Override
+ public BundleWiring getRequirerWiring() {
+ return requirerWiring;
+ }
+
+ @Override
+ public BundleRevision getProvider() {
+ return provider;
+ }
+
+ @Override
+ public BundleRevision getRequirer() {
+ return requirer;
+ }
+}
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWiringImpl.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWiringImpl.java
index 0d6d010..598efa8 100644
--- a/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWiringImpl.java
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/BundleWiringImpl.java
@@ -21,7 +21,10 @@ import java.net.URL;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.winegrower.service.BundleRegistry;
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
@@ -34,11 +37,11 @@ import org.osgi.resource.Wire;
public class BundleWiringImpl implements BundleWiring {
private final BundleImpl bundle;
- private final BundleRevision revision;
+ private final BundleRegistry registry;
- BundleWiringImpl(final BundleImpl bundle) {
+ BundleWiringImpl(final BundleImpl bundle, final BundleRegistry registry) {
this.bundle = bundle;
- this.revision = new BundleRevisionImpl(bundle, this);
+ this.registry = registry;
}
@Override
@@ -53,12 +56,22 @@ public class BundleWiringImpl implements BundleWiring {
@Override
public List<BundleCapability> getCapabilities(final String namespace) {
- return emptyList();
+ return bundle.getCapabilities().stream()
+ .filter(c -> Objects.equals(c.getNamespace(), namespace))
+ .map(capability -> new BundleCapabilityImpl(
+ bundle.adapt(BundleRevision.class), capability.getNamespace(),
+ capability.getDirectives(), capability.getAttributes()))
+ .collect(toList());
}
@Override
public List<BundleRequirement> getRequirements(final String namespace) {
- return emptyList();
+ return bundle.getRequirements().stream()
+ .filter(r -> Objects.equals(r.getNamespace(), namespace))
+ .map(requirement -> new BundleRequirementImpl(
+ bundle.adapt(BundleRevision.class), requirement.getNamespace(),
+ requirement.getDirectives(), requirement.getAttributes(), requirement.getFilter()))
+ .collect(toList());
}
@Override
@@ -68,12 +81,15 @@ public class BundleWiringImpl implements BundleWiring {
@Override
public List<BundleWire> getRequiredWires(final String namespace) {
- return emptyList();
+ return bundle.getRequirements().stream()
+ .map(requirement -> toWire(requirement, registry.getBundles()))
+ .filter(Objects::nonNull)
+ .collect(toList());
}
@Override
public BundleRevision getRevision() {
- return revision;
+ return bundle.adapt(BundleRevision.class);
}
@Override
@@ -125,11 +141,28 @@ public class BundleWiringImpl implements BundleWiring {
@Override
public BundleRevision getResource() {
- return revision;
+ return bundle.adapt(BundleRevision.class);
}
@Override
public Bundle getBundle() {
return bundle;
}
+
+ private BundleWire toWire(final BundleRequirementImpl requirement, final Map<Long, OSGiBundleLifecycle> bundles) {
+ return bundles.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .filter(e -> e.getValue().getBundle().getCapabilities().stream()
+ .anyMatch(requirement::matches))
+ .findFirst()
+ .map(e -> e.getValue().getBundle())
+ .map(bundle -> new BundleWireImpl(
+ this.bundle.adapt(BundleRevision.class), bundle.adapt(BundleRevision.class),
+ this.bundle.adapt(BundleWiring.class), bundle.adapt(BundleWiring.class), requirement,
+ bundle.getCapabilities().stream()
+ .filter(requirement::matches).findFirst()
+ .orElseThrow(() -> new IllegalArgumentException(
+ "Missing capability " + requirement + " in " + bundle))))
+ .orElse(null);
+ }
}
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/deployer/OSGiBundleLifecycle.java b/winegrower-core/src/main/java/org/apache/winegrower/deployer/OSGiBundleLifecycle.java
index 82efc3c..910cd3e 100644
--- a/winegrower-core/src/main/java/org/apache/winegrower/deployer/OSGiBundleLifecycle.java
+++ b/winegrower-core/src/main/java/org/apache/winegrower/deployer/OSGiBundleLifecycle.java
@@ -37,7 +37,7 @@ public class OSGiBundleLifecycle {
final BundleRegistry registry, final Ripener.Configuration configuration,
final long id, final Collection<String> includedResources) {
this.context = new BundleContextImpl(manifest, services, this::getBundle, registry);
- this.bundle = new BundleImpl(manifest, file, context, configuration, id, includedResources);
+ this.bundle = new BundleImpl(manifest, file, context, configuration, id, includedResources, registry);
}
public BundleActivatorHandler getActivator() {
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/scanner/KnownJarsFilter.java b/winegrower-core/src/main/java/org/apache/winegrower/scanner/KnownJarsFilter.java
index 2a92ff0..13bbb61 100644
--- a/winegrower-core/src/main/java/org/apache/winegrower/scanner/KnownJarsFilter.java
+++ b/winegrower-core/src/main/java/org/apache/winegrower/scanner/KnownJarsFilter.java
@@ -25,6 +25,7 @@ import org.apache.winegrower.Ripener;
public class KnownJarsFilter implements Predicate<String> {
private final Collection<String> forceIncludes = new HashSet<String>() {{
add("winegrower-cdi");
+ add("org.apache.aries.cdi");
}};
private final Collection<String> excludes = new HashSet<String>() {{
add("activation-");
diff --git a/winegrower-core/src/test/java/org/apache/winegrower/RipenerTest.java b/winegrower-core/src/test/java/org/apache/winegrower/RipenerTest.java
index 6e09724..623b537 100644
--- a/winegrower-core/src/test/java/org/apache/winegrower/RipenerTest.java
+++ b/winegrower-core/src/test/java/org/apache/winegrower/RipenerTest.java
@@ -110,7 +110,8 @@ class RipenerTest {
@Test
@WithRipener(includeResources = @Entry(path = "org.apache.winegrower.test.simpleactivator"))
void simpleActivator(@Service final Ripener ripener) {
- assertEquals(11, ripener.getRegistry().getBundles().size());
+ final Map<Long, OSGiBundleLifecycle> bundles = ripener.getRegistry().getBundles();
+ assertEquals(11 /*includes junit5 with v >= 5.6*/, bundles.size());
final BundleActivatorHandler activatorHandler = ripener.getRegistry().getBundles().values().stream()
.filter(it -> it.getActivator() != null)
diff --git a/winegrower-core/src/test/java/org/apache/winegrower/deployer/BundleImplTest.java b/winegrower-core/src/test/java/org/apache/winegrower/deployer/BundleImplTest.java
index c14736b..c1e50e2 100644
--- a/winegrower-core/src/test/java/org/apache/winegrower/deployer/BundleImplTest.java
+++ b/winegrower-core/src/test/java/org/apache/winegrower/deployer/BundleImplTest.java
@@ -53,13 +53,13 @@ class BundleImplTest {
registry = new BundleRegistry(services, configuration);
context = new BundleContextImpl(manifest, services, () -> bundle, registry);
final File file = new File(registry.getFramework().getParentFile(), "test-classes");
- bundle = new BundleImpl(manifest, file, context, configuration, 1, null);
+ bundle = new BundleImpl(manifest, file, context, configuration, 1, null, null);
registry.getBundles().put(bundle.getBundleId(), new OSGiBundleLifecycle(manifest, file, services, registry, configuration, 1, null));
}
@Test
void noEmptyLocation() {
- assertNotNull(new BundleImpl(manifest, null, context, configuration, 1, null).getLocation());
+ assertNotNull(new BundleImpl(manifest, null, context, configuration, 1, null, null).getLocation());
}
@Test
diff --git a/winegrower-core/src/test/java/org/apache/winegrower/service/ServiceListenerTest.java b/winegrower-core/src/test/java/org/apache/winegrower/service/ServiceListenerTest.java
index 4cf1688..09045a3 100644
--- a/winegrower-core/src/test/java/org/apache/winegrower/service/ServiceListenerTest.java
+++ b/winegrower-core/src/test/java/org/apache/winegrower/service/ServiceListenerTest.java
@@ -1,6 +1,4 @@
/**
- * Copyright (C) 2006-2019 Talend Inc. - www.talend.com
- * <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
diff --git a/winegrower-core/src/test/java/org/apache/winegrower/test/listener/filter/Registrator.java b/winegrower-core/src/test/java/org/apache/winegrower/test/listener/filter/Registrator.java
index 346a04d..a78f304 100644
--- a/winegrower-core/src/test/java/org/apache/winegrower/test/listener/filter/Registrator.java
+++ b/winegrower-core/src/test/java/org/apache/winegrower/test/listener/filter/Registrator.java
@@ -1,6 +1,4 @@
/**
- * Copyright (C) 2006-2019 Talend Inc. - www.talend.com
- * <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
diff --git a/winegrower-cepages/pom.xml b/winegrower-examples/osgi-cdi/pom.xml
similarity index 56%
copy from winegrower-cepages/pom.xml
copy to winegrower-examples/osgi-cdi/pom.xml
index a6916f0..0711bd2 100644
--- a/winegrower-cepages/pom.xml
+++ b/winegrower-examples/osgi-cdi/pom.xml
@@ -24,39 +24,42 @@
<modelVersion>4.0.0</modelVersion>
<parent>
- <groupId>org.apache.winegrower</groupId>
- <artifactId>winegrower</artifactId>
+ <groupId>org.apache.winegrower.examples</groupId>
+ <artifactId>winegrower-examples</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
- <groupId>org.apache.winegrower.cepages</groupId>
- <artifactId>winegrower-cepages</artifactId>
- <name>Apache Winegrower :: Cepages</name>
- <packaging>pom</packaging>
+ <artifactId>osgi-cdi</artifactId>
+ <name>Apache Winegrower :: Examples :: OSGi CDI</name>
- <properties>
- <karaf.version>4.2.8</karaf.version>
- <cxf.version>3.4.0</cxf.version>
- </properties>
-
- <modules>
- <module>winegrower-cepage-shell</module>
- <module>winegrower-cepage-http</module>
- <module>winegrower-cepage-cxf-rs</module>
- <module>winegrower-cepage-jaxrs</module>
- </modules>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.winegrower</groupId>
+ <artifactId>winegrower-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.winegrower.cepages</groupId>
+ <artifactId>winegrower-cepage-osgi-cdi</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.winegrower.cepages</groupId>
+ <artifactId>winegrower-cepage-http</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
<build>
<plugins>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>3.1.0</version>
- <configuration>
- <skipIfEmpty>true</skipIfEmpty>
- </configuration>
+ <groupId>org.apache.winegrower</groupId>
+ <artifactId>winegrower-maven-plugin</artifactId>
+ <version>${project.version}</version>
</plugin>
</plugins>
</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/winegrower-examples/osgi-cdi/src/main/java/org/apache/winegrower/examples/osgicdi/HelloOsgiCdi.java b/winegrower-examples/osgi-cdi/src/main/java/org/apache/winegrower/examples/osgicdi/HelloOsgiCdi.java
new file mode 100644
index 0000000..217c9fe
--- /dev/null
+++ b/winegrower-examples/osgi-cdi/src/main/java/org/apache/winegrower/examples/osgicdi/HelloOsgiCdi.java
@@ -0,0 +1,25 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.winegrower.examples.osgicdi;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Initialized;
+import javax.enterprise.event.Observes;
+
+@ApplicationScoped
+public class HelloOsgiCdi {
+ public void onStart(@Observes @Initialized(ApplicationScoped.class) final Object start) {
+ System.out.println("Hi");
+ }
+}
diff --git a/winegrower-examples/pom.xml b/winegrower-examples/pom.xml
index 0b94ddc..04cac3a 100644
--- a/winegrower-examples/pom.xml
+++ b/winegrower-examples/pom.xml
@@ -38,13 +38,14 @@
<modules>
<module>simple</module>
<module>bundle</module>
- <!-- <module>services</module> -->
- <!-- <module>scr</module> -->
<module>config</module>
<module>shell</module>
<module>http</module>
<module>jaxrs</module>
<module>jaxrs-whiteboard</module>
+ <module>osgi-cdi</module>
+ <!-- <module>services</module> -->
+ <!-- <module>scr</module> -->
<!-- <module>monitoring</module> -->
<!-- <module>cdi</module> -->
<!-- <module>spring</module> -->