From 53200767475d22d75dafce7e1e1fdd4cffec69c8 Mon Sep 17 00:00:00 2001 From: Fryderyk Wysocki Date: Tue, 15 Sep 2026 21:49:36 +0200 Subject: [PATCH] Fixed various IntelliJ warnings in BaseActivator Added type parameters to generics Changed the class so that it explicitly implements ManagedService instead of sneakily registering itself as such Extracted the string splitting pattern to a static field so that the regex is compiled only once Changed getInterfaceNames so that it returns distinct classes in case any implemented interfaces extend the same superinterface Changed trackers map to use Class objects as keys instead of String names --- deployer/blueprint/pom.xml | 4 + deployer/features/pom.xml | 4 + deployer/kar/pom.xml | 4 + deployer/spring/pom.xml | 4 + deployer/wrap/pom.xml | 4 + docker/pom.xml | 4 + .../karaf-command-example-provider/pom.xml | 4 + .../karaf-mbean-example-provider/pom.xml | 4 + .../karaf-mbean-example-simple/pom.xml | 4 + instance/pom.xml | 4 + jndi/pom.xml | 4 + obr/pom.xml | 4 + package/pom.xml | 4 + pom.xml | 4 +- service/core/pom.xml | 4 + system/pom.xml | 4 + .../karaf/util/tracker/BaseActivator.java | 136 ++++++++++-------- .../util/tracker/SingleServiceTracker.java | 8 +- web/pom.xml | 4 + webconsole/features/pom.xml | 4 + webconsole/gogo/pom.xml | 4 + webconsole/http/pom.xml | 4 + webconsole/instance/pom.xml | 4 + wrapper/pom.xml | 4 + 24 files changed, 163 insertions(+), 69 deletions(-) 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