This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git
The following commit(s) were added to refs/heads/master by this push:
new f7804da SLING-12828 - Register the Feature service as soon as the
org.apache.sling.feature bundle is active (#47)
f7804da is described below
commit f7804dafc22843b926a65e5504e12bf5b87825a9
Author: Robert Munteanu <[email protected]>
AuthorDate: Mon Jun 16 11:08:39 2025 +0200
SLING-12828 - Register the Feature service as soon as the
org.apache.sling.feature bundle is active (#47)
Use a BundleListener to register the Feature service as soon as possible.
---
.../launcher/impl/launchers/AbstractRunner.java | 119 +++++++++++----------
1 file changed, 65 insertions(+), 54 deletions(-)
diff --git
a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
index b80b906..c2aa2b8 100644
---
a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
+++
b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
@@ -46,7 +46,9 @@ import java.util.function.Supplier;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.PrototypeServiceFactory;
@@ -251,6 +253,19 @@ public abstract class AbstractRunner implements
Callable<Integer> {
this.installerTracker.open();
}
+ if (this.featureSupplier != null) {
+ framework.getBundleContext().addBundleListener(new
BundleListener() {
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ Bundle bundle = event.getBundle();
+ if
(bundle.getSymbolicName().equals("org.apache.sling.feature")
+ && event.getType() == BundleEvent.STARTED) {
+ registerFeatureService(bundle);
+ }
+ }
+ });
+ }
+
this.install(framework, bundlesMap);
}
@@ -372,63 +387,59 @@ public abstract class AbstractRunner implements
Callable<Integer> {
}
}
- protected void finishStartup(final Framework framework) {
- Bundle featureBundle = null;
- for (final Bundle bundle : framework.getBundleContext().getBundles()) {
- if (featureSupplier != null &&
"org.apache.sling.feature".equals(bundle.getSymbolicName())) {
- featureBundle = bundle;
- }
- }
- if (featureBundle != null) {
- final Bundle bundle = featureBundle;
- // the feature is registered as a prototype to give each client a
copy as feature models are mutable
- final Dictionary<String, Object> properties = new Hashtable<>();
- properties.put("name", "org.apache.sling.feature.launcher");
- featureBundle
- .getBundleContext()
- .registerService(
- new String[] {"org.apache.sling.feature.Feature"},
- new PrototypeServiceFactory<Object>() {
-
- @Override
- public Object getService(
- final Bundle client, final
ServiceRegistration<Object> registration) {
- final ClassLoader cl =
-
bundle.adapt(BundleWiring.class).getClassLoader();
- final ClassLoader oldTCCL =
-
Thread.currentThread().getContextClassLoader();
-
Thread.currentThread().setContextClassLoader(cl);
- try {
- final Class<?> readerClass =
-
cl.loadClass("org.apache.sling.feature.io.json.FeatureJSONReader");
- final Method readMethod =
readerClass.getDeclaredMethod(
- "read", java.io.Reader.class,
String.class);
- try (final StringReader reader = new
StringReader(featureSupplier.get())) {
- return readMethod.invoke(null,
reader, null);
- }
- } catch (ClassNotFoundException
- | NoSuchMethodException
- | SecurityException
- | IllegalArgumentException
- | IllegalAccessException
- | InvocationTargetException e) {
- // ignore
- } finally {
-
Thread.currentThread().setContextClassLoader(oldTCCL);
+ protected void finishStartup(final Framework framework) {}
+
+ protected void registerFeatureService(Bundle featureBundle) {
+
+ logger.debug("Registering feature service");
+
+ // the feature is registered as a prototype to give each client a copy
as feature models are mutable
+ final Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put("name", "org.apache.sling.feature.launcher");
+ featureBundle
+ .getBundleContext()
+ .registerService(
+ new String[] {"org.apache.sling.feature.Feature"},
+ new PrototypeServiceFactory<Object>() {
+
+ @Override
+ public Object getService(
+ final Bundle client, final
ServiceRegistration<Object> registration) {
+ final ClassLoader cl =
+
featureBundle.adapt(BundleWiring.class).getClassLoader();
+ final ClassLoader oldTCCL =
+
Thread.currentThread().getContextClassLoader();
+
Thread.currentThread().setContextClassLoader(cl);
+ try {
+ final Class<?> readerClass =
+
cl.loadClass("org.apache.sling.feature.io.json.FeatureJSONReader");
+ final Method readMethod =
+
readerClass.getDeclaredMethod("read", java.io.Reader.class, String.class);
+ try (final StringReader reader = new
StringReader(featureSupplier.get())) {
+ return readMethod.invoke(null, reader,
null);
}
- return null;
+ } catch (ClassNotFoundException
+ | NoSuchMethodException
+ | SecurityException
+ | IllegalArgumentException
+ | IllegalAccessException
+ | InvocationTargetException e) {
+ // ignore
+ } finally {
+
Thread.currentThread().setContextClassLoader(oldTCCL);
}
+ return null;
+ }
- @Override
- public void ungetService(
- final Bundle client,
- final ServiceRegistration<Object>
registration,
- final Object service) {
- // nothing to do
- }
- },
- properties);
- }
+ @Override
+ public void ungetService(
+ final Bundle client,
+ final ServiceRegistration<Object>
registration,
+ final Object service) {
+ // nothing to do
+ }
+ },
+ properties);
}
/**