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