diff --git a/deployer/blueprint/pom.xml b/deployer/blueprint/pom.xml
index fcfece58b25..33e71300397 100644
--- a/deployer/blueprint/pom.xml
+++ b/deployer/blueprint/pom.xml
@@ -70,6 +70,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
org.osgi.service.url
diff --git a/deployer/features/pom.xml b/deployer/features/pom.xml
index b912d5537e3..04e15c151ad 100644
--- a/deployer/features/pom.xml
+++ b/deployer/features/pom.xml
@@ -68,6 +68,10 @@
org.osgi
org.osgi.annotation.versioning
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
org.osgi.service.url
diff --git a/deployer/kar/pom.xml b/deployer/kar/pom.xml
index fe3297c3fba..f6221bb4efa 100644
--- a/deployer/kar/pom.xml
+++ b/deployer/kar/pom.xml
@@ -64,6 +64,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.apache.karaf.features
diff --git a/deployer/spring/pom.xml b/deployer/spring/pom.xml
index 3bd4f6c73f2..3de67bfbc7c 100644
--- a/deployer/spring/pom.xml
+++ b/deployer/spring/pom.xml
@@ -69,6 +69,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
org.osgi.service.url
diff --git a/deployer/wrap/pom.xml b/deployer/wrap/pom.xml
index f37a16d44e4..ca8729c8138 100644
--- a/deployer/wrap/pom.xml
+++ b/deployer/wrap/pom.xml
@@ -59,6 +59,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
org.osgi.service.url
diff --git a/docker/pom.xml b/docker/pom.xml
index f4b16c45833..3fc48fbd5f5 100644
--- a/docker/pom.xml
+++ b/docker/pom.xml
@@ -54,6 +54,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
com.fasterxml.jackson.core
jackson-databind
diff --git a/examples/karaf-command-example/karaf-command-example-provider/pom.xml b/examples/karaf-command-example/karaf-command-example-provider/pom.xml
index c96d85ed8e5..b8ca1341859 100644
--- a/examples/karaf-command-example/karaf-command-example-provider/pom.xml
+++ b/examples/karaf-command-example/karaf-command-example-provider/pom.xml
@@ -54,6 +54,10 @@
org.apache.karaf
org.apache.karaf.util
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
osgi.core
diff --git a/examples/karaf-mbean-example/karaf-mbean-example-provider/pom.xml b/examples/karaf-mbean-example/karaf-mbean-example-provider/pom.xml
index 15aaeae86cc..e598738c2a9 100644
--- a/examples/karaf-mbean-example/karaf-mbean-example-provider/pom.xml
+++ b/examples/karaf-mbean-example/karaf-mbean-example-provider/pom.xml
@@ -54,6 +54,10 @@
org.apache.karaf
org.apache.karaf.util
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
osgi.core
diff --git a/examples/karaf-mbean-example/karaf-mbean-example-simple/pom.xml b/examples/karaf-mbean-example/karaf-mbean-example-simple/pom.xml
index 975af797d1d..3a2a3d35683 100644
--- a/examples/karaf-mbean-example/karaf-mbean-example-simple/pom.xml
+++ b/examples/karaf-mbean-example/karaf-mbean-example-simple/pom.xml
@@ -54,6 +54,10 @@
org.apache.karaf
org.apache.karaf.util
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
osgi.core
diff --git a/instance/pom.xml b/instance/pom.xml
index e85f569627c..aba52cfcd28 100644
--- a/instance/pom.xml
+++ b/instance/pom.xml
@@ -56,6 +56,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.slf4j
diff --git a/jndi/pom.xml b/jndi/pom.xml
index ca80fbfa34a..385c6e91b92 100644
--- a/jndi/pom.xml
+++ b/jndi/pom.xml
@@ -59,6 +59,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.apache.aries.proxy
org.apache.aries.proxy.api
diff --git a/obr/pom.xml b/obr/pom.xml
index 79ff723b4c6..7efd7d50caa 100644
--- a/obr/pom.xml
+++ b/obr/pom.xml
@@ -55,6 +55,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.apache.felix
org.apache.felix.bundlerepository
diff --git a/package/pom.xml b/package/pom.xml
index 3d97c1b0520..c61c771f348 100644
--- a/package/pom.xml
+++ b/package/pom.xml
@@ -62,6 +62,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
org.osgi.resource
diff --git a/pom.xml b/pom.xml
index 6b83c9e2657..64ff3ec4649 100644
--- a/pom.xml
+++ b/pom.xml
@@ -150,7 +150,7 @@
1695310533
- 11
+ 17
scm:git:https://gitbox.apache.org/repos/asf/karaf.git
scm:git:https://gitbox.apache.org/repos/asf/karaf.git
@@ -631,7 +631,7 @@
[3.8.8,4)
- [17,)
+ [${javaVersion},)
diff --git a/service/core/pom.xml b/service/core/pom.xml
index 1d609837b6d..8362772f813 100644
--- a/service/core/pom.xml
+++ b/service/core/pom.xml
@@ -54,6 +54,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.osgi
org.osgi.util.tracker
diff --git a/system/pom.xml b/system/pom.xml
index d0ce7dd3b68..d20a0908205 100644
--- a/system/pom.xml
+++ b/system/pom.xml
@@ -57,6 +57,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.slf4j
slf4j-api
diff --git a/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java b/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
index de39cb0844c..7f328334ffa 100644
--- a/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
+++ b/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
@@ -16,15 +16,17 @@
*/
package org.apache.karaf.util.tracker;
+import static java.util.function.Predicate.not;
+
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
-import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -35,29 +37,37 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-
-import org.osgi.framework.*;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class BaseActivator implements BundleActivator, Runnable, ThreadFactory {
+public class BaseActivator implements BundleActivator, ManagedService, Runnable, ThreadFactory {
+
+ private static final Pattern STRING_ARRAY_SPLITTER = Pattern.compile("\\s*,\\s*");
protected final Logger logger = LoggerFactory.getLogger(getClass());
protected BundleContext bundleContext;
protected ExecutorService executor = new ThreadPoolExecutor(0, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(), this);
- private AtomicBoolean scheduled = new AtomicBoolean();
+ private final AtomicBoolean scheduled = new AtomicBoolean();
private long schedulerStopTimeout = TimeUnit.MILLISECONDS.convert(30, TimeUnit.SECONDS);
- private final Queue registrations = new ConcurrentLinkedQueue<>();
- private Map trackers = new HashMap<>();
- private ServiceRegistration managedServiceRegistration;
+ private final Queue> registrations = new ConcurrentLinkedQueue<>();
+ private final Map, SingleServiceTracker>> trackers = new HashMap<>();
+ private ServiceRegistration managedServiceRegistration;
private Dictionary configuration;
private static final AtomicInteger poolNumber = new AtomicInteger(1);
@@ -86,8 +96,9 @@ public void start(BundleContext context) throws Exception {
doOpen();
scheduled.set(false);
if (managedServiceRegistration == null
- && trackers.values().stream()
- .allMatch(t -> t.getService() != null)) {
+ && trackers.values().stream()
+ .map(SingleServiceTracker::getService)
+ .allMatch(Objects::nonNull)) {
try {
doStart();
} catch (Throwable e) {
@@ -104,7 +115,9 @@ public void stop(BundleContext context) throws Exception {
scheduled.set(true);
doClose();
executor.shutdown();
- executor.awaitTermination(schedulerStopTimeout, TimeUnit.MILLISECONDS);
+ if (!executor.awaitTermination(schedulerStopTimeout, TimeUnit.MILLISECONDS)) {
+ logger.warn("Executor did not terminate within {} milliseconds", schedulerStopTimeout);
+ }
doStop();
}
@@ -129,20 +142,15 @@ protected void doClose() {
if (managedServiceRegistration != null) {
managedServiceRegistration.unregister();
}
- for (SingleServiceTracker tracker : trackers.values()) {
- tracker.close();
- }
+ trackers.values().forEach(SingleServiceTracker::close);
}
protected void doStart() throws Exception {
}
protected void doStop() {
- while (true) {
- ServiceRegistration reg = registrations.poll();
- if (reg == null) {
- break;
- }
+ ServiceRegistration> reg;
+ while ((reg = registrations.poll()) != null) {
reg.unregister();
}
}
@@ -173,9 +181,10 @@ protected void manage(String pid) {
Hashtable props = new Hashtable<>();
props.put(Constants.SERVICE_PID, pid);
managedServiceRegistration = bundleContext.registerService(
- "org.osgi.service.cm.ManagedService", this, props);
+ ManagedService.class, this, props);
}
+ @Override
public void updated(Dictionary properties) {
this.configuration = properties;
reconfigure();
@@ -276,25 +285,24 @@ protected Class>[] getClassesArray(String key, String def) {
.toArray(Class[]::new);
}
- protected String[] getStringArray(String key, String def) {
- Object val = null;
+ protected String[] getStringArray(String configKey, String defaultValue) {
+ Object value = null;
if (configuration != null) {
- val = configuration.get(key);
+ value = configuration.get(configKey);
}
- if (val == null) {
- val = def;
+ if (value == null) {
+ value = defaultValue;
}
- if (val == null) {
+ if (value == null) {
return null;
}
- Stream s;
- if (val instanceof String[]) {
- return (String[]) val;
- } else if (val instanceof Iterable) {
- return StreamSupport.stream(((Iterable>) val).spliterator(), false)
+ if (value instanceof String[]) {
+ return (String[]) value;
+ } else if (value instanceof Iterable> iterableValue) {
+ return StreamSupport.stream(iterableValue.spliterator(), false)
.map(Object::toString).toArray(String[]::new);
} else {
- return val.toString().split("\\s*,\\s*");
+ return STRING_ARRAY_SPLITTER.split(value.toString());
}
}
@@ -320,14 +328,11 @@ public void run() {
* Called in {@link #doOpen()}.
*
* @param clazz The service interface to track.
+ * @param Generic type of the service to track
* @throws InvalidSyntaxException If the tracker syntax is not correct.
*/
- protected void trackService(Class> clazz) throws InvalidSyntaxException {
- if (!trackers.containsKey(clazz.getName())) {
- SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, (u, v) -> reconfigure());
- tracker.open();
- trackers.put(clazz.getName(), tracker);
- }
+ protected void trackService(Class clazz) throws InvalidSyntaxException {
+ trackService(clazz, null);
}
/**
@@ -335,25 +340,27 @@ protected void trackService(Class> clazz) throws InvalidSyntaxException {
*
* @param clazz The service interface to track.
* @param filter The filter to use to select the services to track.
+ * @param Generic type of the service to track
* @throws InvalidSyntaxException If the tracker syntax is not correct (in the filter especially).
*/
- protected void trackService(Class> clazz, String filter) throws InvalidSyntaxException {
- if (!trackers.containsKey(clazz.getName())) {
+ protected void trackService(Class clazz, String filter) throws InvalidSyntaxException {
+ if (!trackers.containsKey(clazz)) {
if (filter != null && filter.isEmpty()) {
filter = null;
}
- SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, filter, (u, v) -> reconfigure());
+ SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, filter, (u, v) -> reconfigure());
tracker.open();
- trackers.put(clazz.getName(), tracker);
+ trackers.put(clazz, tracker);
}
}
protected void trackService(String className, String filter) throws InvalidSyntaxException {
- if (!trackers.containsKey(className)) {
- SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, className, filter, (u, v) -> reconfigure());
- tracker.open();
- trackers.put(className, tracker);
- }
+ try {
+ Class> clazz = Class.forName(className);
+ trackService(clazz, filter);
+ } catch (ClassNotFoundException e) {
+ logger.warn("Unable to track class '{}' - class not found.", className);
+ }
}
/**
@@ -364,15 +371,17 @@ protected void trackService(String className, String filter) throws InvalidSynta
* @return The actual tracker service object.
*/
protected T getTrackedService(Class clazz) {
- SingleServiceTracker tracker = trackers.get(clazz.getName());
+ @SuppressWarnings("unchecked")
+ SingleServiceTracker tracker = (SingleServiceTracker) trackers.get(clazz);
if (tracker == null) {
throw new IllegalStateException("Service not tracked for class " + clazz);
}
- return clazz.cast(tracker.getService());
+ return tracker.getService();
}
protected ServiceReference getTrackedServiceRef(Class clazz) {
- SingleServiceTracker tracker = trackers.get(clazz.getName());
+ @SuppressWarnings("unchecked")
+ SingleServiceTracker tracker = (SingleServiceTracker) trackers.get(clazz);
if (tracker == null) {
throw new IllegalStateException("Service not tracked for class " + clazz);
}
@@ -431,7 +440,7 @@ protected void register(Class clazz, T service, Dictionary pro
* @param clazz The service interfaces to register.
* @param service The actual service instance to register.
*/
- protected void register(Class[] clazz, Object service) {
+ protected void register(Class>[] clazz, Object service) {
register(clazz, service, null);
}
@@ -442,7 +451,7 @@ protected void register(Class[] clazz, Object service) {
* @param service The actual service instance to register.
* @param props The service properties to register.
*/
- protected void register(Class[] clazz, Object service, Dictionary props) {
+ protected void register(Class>[] clazz, Object service, Dictionary props) {
String[] names = new String[clazz.length];
for (int i = 0; i < clazz.length; i++) {
names[i] = clazz[i].getName();
@@ -450,23 +459,24 @@ protected void register(Class[] clazz, Object service, Dictionary pro
trackRegistration(bundleContext.registerService(names, service, props));
}
- private void trackRegistration(ServiceRegistration registration) {
+ private void trackRegistration(ServiceRegistration> registration) {
registrations.add(registration);
}
protected String[] getInterfaceNames(Object object) {
- List names = new ArrayList<>();
- for (Class cl = object.getClass(); cl != Object.class; cl = cl.getSuperclass()) {
- addSuperInterfaces(names, cl);
+ if (object == null) {
+ return new String[0];
}
- return names.toArray(new String[names.size()]);
+ return Stream.>iterate(object.getClass(), not(Object.class::equals), Class::getSuperclass)
+ .flatMap(this::getAllInterfaces)
+ .distinct()
+ .map(Class::getName)
+ .toArray(String[]::new);
}
- private void addSuperInterfaces(List names, Class clazz) {
- for (Class cl : clazz.getInterfaces()) {
- names.add(cl.getName());
- addSuperInterfaces(names, cl);
- }
+ private Stream> getAllInterfaces(Class> clazz) {
+ return Arrays.stream(clazz.getInterfaces())
+ .flatMap(iface -> Stream.concat(Stream.of(iface), getAllInterfaces(iface)));
}
@Override
diff --git a/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java b/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
index b4393512b74..9b7f85e595c 100644
--- a/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
+++ b/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
@@ -68,7 +68,7 @@ public T getService() {
return service.get();
}
- public ServiceReference getServiceReference() {
+ public ServiceReference getServiceReference() {
return ref.get();
}
@@ -89,7 +89,7 @@ public void serviceChanged(ServiceEvent event) {
if (open.get()) {
if (event.getType() == ServiceEvent.UNREGISTERING) {
@SuppressWarnings("unchecked")
- ServiceReference deadRef = (ServiceReference) event.getServiceReference();
+ ServiceReference deadRef = (ServiceReference) event.getServiceReference();
if (deadRef.equals(ref.get())) {
findMatchingReference(deadRef);
}
@@ -108,7 +108,7 @@ private void findMatchingReference(ServiceReference original) {
Arrays.sort(refs);
}
@SuppressWarnings("unchecked")
- ServiceReference r = (ServiceReference) refs[0];
+ ServiceReference r = (ServiceReference) refs[0];
T service = ctx.getService(r);
if (service != null) {
clear = false;
@@ -164,7 +164,7 @@ public void close() {
if (open.compareAndSet(true, false)) {
ctx.removeServiceListener(this);
- ServiceReference deadRef;
+ ServiceReference deadRef;
T prev;
synchronized (this) {
deadRef = ref.getAndSet(null);
diff --git a/web/pom.xml b/web/pom.xml
index a6d280c0ea1..70cbd25e96e 100644
--- a/web/pom.xml
+++ b/web/pom.xml
@@ -57,6 +57,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.ops4j.pax.web
pax-web-spi
diff --git a/webconsole/features/pom.xml b/webconsole/features/pom.xml
index 541790a8afe..c498942fadd 100644
--- a/webconsole/features/pom.xml
+++ b/webconsole/features/pom.xml
@@ -54,6 +54,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.slf4j
slf4j-api
diff --git a/webconsole/gogo/pom.xml b/webconsole/gogo/pom.xml
index 6feeafec6cd..e2f2117ad7a 100644
--- a/webconsole/gogo/pom.xml
+++ b/webconsole/gogo/pom.xml
@@ -54,6 +54,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.apache.felix
diff --git a/webconsole/http/pom.xml b/webconsole/http/pom.xml
index 5e9d6469670..771fcc158d3 100644
--- a/webconsole/http/pom.xml
+++ b/webconsole/http/pom.xml
@@ -54,6 +54,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.slf4j
slf4j-api
diff --git a/webconsole/instance/pom.xml b/webconsole/instance/pom.xml
index 241eb3e139b..92a6c2e16c3 100644
--- a/webconsole/instance/pom.xml
+++ b/webconsole/instance/pom.xml
@@ -59,6 +59,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.apache.felix
org.apache.felix.webconsole
diff --git a/wrapper/pom.xml b/wrapper/pom.xml
index 9e21431d36d..04b8434d295 100644
--- a/wrapper/pom.xml
+++ b/wrapper/pom.xml
@@ -58,6 +58,10 @@
org.osgi
org.osgi.framework
+
+ org.osgi
+ org.osgi.service.cm
+
org.apache.karaf
org.apache.karaf.main