Skip to content

Commit d381c9c

Browse files
committed
FELIX-6444 Contribute a compatible implementation of OSGi Features
This implementation was initially made in the Apache Sling Whiteboard component at https://github.com/apache/sling-whiteboard/tree/master/osgi-featuremodel
1 parent fc5e365 commit d381c9c

14 files changed

+1931
-0
lines changed

features/pom.xml

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?xml version="1.0" encoding="ISO-8859-1"?>
2+
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
3+
license agreements. See the NOTICE file distributed with this work for additional
4+
information regarding copyright ownership. The ASF licenses this file to
5+
you under the Apache License, Version 2.0 (the "License"); you may not use
6+
this file except in compliance with the License. You may obtain a copy of
7+
the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
8+
by applicable law or agreed to in writing, software distributed under the
9+
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
10+
OF ANY KIND, either express or implied. See the License for the specific
11+
language governing permissions and limitations under the License. -->
12+
<project xmlns="http://maven.apache.org/POM/4.0.0"
13+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
14+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
15+
16+
<modelVersion>4.0.0</modelVersion>
17+
<parent>
18+
<groupId>org.apache.felix</groupId>
19+
<artifactId>felix-parent</artifactId>
20+
<version>7</version>
21+
<relativePath />
22+
</parent>
23+
24+
<artifactId>org.apache.felix.feature</artifactId>
25+
<version>0.0.1-SNAPSHOT</version>
26+
<packaging>jar</packaging>
27+
28+
<name>OSGi Feature Model API</name>
29+
30+
<properties>
31+
<felix.java.version>11</felix.java.version>
32+
</properties>
33+
34+
<repositories>
35+
<repository>
36+
<id>sonatype.snapshots</id>
37+
<name>OSGi Snapshot</name>
38+
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
39+
</repository>
40+
</repositories>
41+
42+
<build>
43+
<plugins>
44+
<plugin>
45+
<groupId>biz.aQute.bnd</groupId>
46+
<artifactId>bnd-maven-plugin</artifactId>
47+
<version>5.3.0</version>
48+
<executions>
49+
<execution>
50+
<goals>
51+
<goal>bnd-process</goal>
52+
</goals>
53+
</execution>
54+
</executions>
55+
</plugin>
56+
<plugin>
57+
<groupId>org.apache.maven.plugins</groupId>
58+
<artifactId>maven-jar-plugin</artifactId>
59+
<configuration>
60+
<archive>
61+
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
62+
</archive>
63+
</configuration>
64+
</plugin>
65+
<plugin>
66+
<groupId>org.apache.rat</groupId>
67+
<artifactId>apache-rat-plugin</artifactId>
68+
<configuration>
69+
<excludes>
70+
<exclude>*.md</exclude>
71+
<exclude>src/main/resources/META-INF/services/*</exclude>
72+
</excludes>
73+
</configuration>
74+
</plugin>
75+
</plugins>
76+
</build>
77+
<dependencies>
78+
<dependency>
79+
<groupId>org.osgi</groupId>
80+
<artifactId>osgi.annotation</artifactId>
81+
<version>8.0.0</version>
82+
<scope>provided</scope>
83+
</dependency>
84+
<dependency>
85+
<groupId>org.osgi</groupId>
86+
<artifactId>osgi.core</artifactId>
87+
<version>8.0.0</version>
88+
<scope>provided</scope>
89+
</dependency>
90+
<dependency>
91+
<groupId>org.osgi</groupId>
92+
<artifactId>org.osgi.service.feature</artifactId>
93+
<version>1.0.0-SNAPSHOT</version>
94+
<scope>provided</scope>
95+
</dependency>
96+
<dependency>
97+
<groupId>org.osgi</groupId>
98+
<artifactId>org.osgi.util.function</artifactId>
99+
<version>1.0.0</version>
100+
<scope>provided</scope>
101+
</dependency>
102+
<dependency>
103+
<groupId>org.apache.geronimo.specs</groupId>
104+
<artifactId>geronimo-json_1.1_spec</artifactId>
105+
<version>1.3</version>
106+
<scope>provided</scope>
107+
</dependency>
108+
<dependency>
109+
<groupId>org.apache.felix</groupId>
110+
<artifactId>org.apache.felix.converter</artifactId>
111+
<version>1.0.18</version>
112+
<scope>provided</scope>
113+
</dependency>
114+
<dependency>
115+
<groupId>org.apache.felix</groupId>
116+
<artifactId>org.apache.felix.cm.json</artifactId>
117+
<version>1.0.6</version>
118+
<scope>provided</scope>
119+
</dependency>
120+
121+
<!-- Testing -->
122+
<dependency>
123+
<groupId>junit</groupId>
124+
<artifactId>junit</artifactId>
125+
<version>4.13.2</version>
126+
<scope>test</scope>
127+
</dependency>
128+
<dependency>
129+
<groupId>org.mockito</groupId>
130+
<artifactId>mockito-core</artifactId>
131+
<version>2.8.9</version>
132+
<scope>test</scope>
133+
</dependency>
134+
<dependency>
135+
<groupId>org.apache.johnzon</groupId>
136+
<artifactId>johnzon-core</artifactId>
137+
<version>1.2.2</version>
138+
<scope>test</scope>
139+
</dependency>
140+
</dependencies>
141+
</project>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with this
4+
* work for additional information regarding copyright ownership. The ASF
5+
* licenses this file to You under the Apache License, Version 2.0 (the
6+
* "License"); you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations under
15+
* the License.
16+
*/
17+
package org.apache.felix.feature.impl;
18+
19+
import java.util.Collections;
20+
import java.util.LinkedHashMap;
21+
import java.util.Map;
22+
import java.util.Objects;
23+
24+
import org.osgi.service.feature.FeatureArtifact;
25+
import org.osgi.service.feature.FeatureArtifactBuilder;
26+
import org.osgi.service.feature.ID;
27+
28+
class ArtifactBuilderImpl implements FeatureArtifactBuilder {
29+
private final ID id;
30+
31+
private final Map<String,Object> metadata = new LinkedHashMap<>();
32+
33+
ArtifactBuilderImpl(ID id) {
34+
this.id = id;
35+
}
36+
37+
@Override
38+
public FeatureArtifactBuilder addMetadata(String key, Object value) {
39+
this.metadata.put(key, value);
40+
return this;
41+
}
42+
43+
@Override
44+
public FeatureArtifactBuilder addMetadata(Map<String,Object> md) {
45+
this.metadata.putAll(md);
46+
return this;
47+
}
48+
49+
@Override
50+
public FeatureArtifact build() {
51+
return new ArtifactImpl(id, metadata);
52+
}
53+
54+
private static class ArtifactImpl implements FeatureArtifact {
55+
private final ID id;
56+
private final Map<String, Object> metadata;
57+
58+
private ArtifactImpl(ID id, Map<String, Object> metadata) {
59+
this.id = id;
60+
this.metadata = Collections.unmodifiableMap(metadata);
61+
}
62+
63+
@Override
64+
public ID getID() {
65+
return id;
66+
}
67+
68+
@Override
69+
public Map<String, Object> getMetadata() {
70+
return metadata;
71+
}
72+
73+
@Override
74+
public int hashCode() {
75+
return Objects.hash(id, metadata);
76+
}
77+
78+
@Override
79+
public boolean equals(Object obj) {
80+
if (this == obj)
81+
return true;
82+
if (obj == null)
83+
return false;
84+
if (getClass() != obj.getClass())
85+
return false;
86+
ArtifactImpl other = (ArtifactImpl) obj;
87+
return Objects.equals(id, other.id) && Objects.equals(metadata, other.metadata);
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return "ArtifactImpl [getID()=" + getID() + "]";
93+
}
94+
}
95+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with this
4+
* work for additional information regarding copyright ownership. The ASF
5+
* licenses this file to You under the Apache License, Version 2.0 (the
6+
* "License"); you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations under
15+
* the License.
16+
*/
17+
package org.apache.felix.feature.impl;
18+
19+
import org.osgi.service.feature.BuilderFactory;
20+
import org.osgi.service.feature.FeatureArtifactBuilder;
21+
import org.osgi.service.feature.FeatureBuilder;
22+
import org.osgi.service.feature.FeatureBundleBuilder;
23+
import org.osgi.service.feature.FeatureConfigurationBuilder;
24+
import org.osgi.service.feature.FeatureExtension.Kind;
25+
import org.osgi.service.feature.FeatureExtension.Type;
26+
import org.osgi.service.feature.FeatureExtensionBuilder;
27+
import org.osgi.service.feature.ID;
28+
29+
class BuilderFactoryImpl implements BuilderFactory {
30+
@Override
31+
public FeatureArtifactBuilder newArtifactBuilder(ID id) {
32+
return new ArtifactBuilderImpl(id);
33+
}
34+
35+
@Override
36+
public FeatureBundleBuilder newBundleBuilder(ID id) {
37+
return new BundleBuilderImpl(id);
38+
}
39+
40+
@Override
41+
public FeatureConfigurationBuilder newConfigurationBuilder(String pid) {
42+
return new ConfigurationBuilderImpl(pid);
43+
}
44+
45+
@Override
46+
public FeatureConfigurationBuilder newConfigurationBuilder(String factoryPid, String name) {
47+
return new ConfigurationBuilderImpl(factoryPid, name);
48+
}
49+
50+
@Override
51+
public FeatureBuilder newFeatureBuilder(ID id) {
52+
return new FeatureBuilderImpl(id);
53+
}
54+
55+
@Override
56+
public FeatureExtensionBuilder newExtensionBuilder(String name, Type type, Kind kind) {
57+
return new ExtensionBuilderImpl(name, type, kind);
58+
}
59+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with this
4+
* work for additional information regarding copyright ownership. The ASF
5+
* licenses this file to You under the Apache License, Version 2.0 (the
6+
* "License"); you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations under
15+
* the License.
16+
*/
17+
package org.apache.felix.feature.impl;
18+
19+
import java.util.Collections;
20+
import java.util.LinkedHashMap;
21+
import java.util.Map;
22+
import java.util.Objects;
23+
24+
import org.osgi.service.feature.FeatureBundle;
25+
import org.osgi.service.feature.FeatureBundleBuilder;
26+
import org.osgi.service.feature.ID;
27+
28+
class BundleBuilderImpl implements FeatureBundleBuilder {
29+
private final ID id;
30+
31+
private final Map<String,Object> metadata = new LinkedHashMap<>();
32+
33+
BundleBuilderImpl(ID id) {
34+
this.id = id;
35+
}
36+
37+
@Override
38+
public FeatureBundleBuilder addMetadata(String key, Object value) {
39+
this.metadata.put(key, value);
40+
return this;
41+
}
42+
43+
@Override
44+
public FeatureBundleBuilder addMetadata(Map<String,Object> md) {
45+
this.metadata.putAll(md);
46+
return this;
47+
}
48+
49+
@Override
50+
public FeatureBundle build() {
51+
return new BundleImpl(id, metadata);
52+
}
53+
54+
private static class BundleImpl implements FeatureBundle {
55+
private final ID id;
56+
private final Map<String, Object> metadata;
57+
58+
private BundleImpl(ID id, Map<String, Object> metadata) {
59+
this.id = id;
60+
this.metadata = Collections.unmodifiableMap(metadata);
61+
}
62+
63+
@Override
64+
public ID getID() {
65+
return id;
66+
}
67+
68+
@Override
69+
public Map<String, Object> getMetadata() {
70+
return metadata;
71+
}
72+
73+
@Override
74+
public int hashCode() {
75+
return Objects.hash(id, metadata);
76+
}
77+
78+
@Override
79+
public boolean equals(Object obj) {
80+
if (this == obj)
81+
return true;
82+
if (obj == null)
83+
return false;
84+
if (getClass() != obj.getClass())
85+
return false;
86+
BundleImpl other = (BundleImpl) obj;
87+
return Objects.equals(id, other.id) && Objects.equals(metadata, other.metadata);
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return "BundleImpl [getID()=" + getID() + "]";
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)