Author: tjwatson
Date: Tue Jan 29 16:58:42 2019
New Revision: 1852464
URL: http://svn.apache.org/viewvc?rev=1852464&view=rev
Log:
FELIX-6041 - allow scr commands to work when gogo.runtime resolves later
Remove the optional dependency on org.apache.felix.service.command
package to allow gogo.runtime to be installed and resolved after the SCR
bundle. This allows the scr gogo commands to work while avoiding a wire
from the SCR bundle to the gogo packages.
This is achieved by generating a proxy instance of the Converter service
and registering it with the gogo.runtime BundleContext (or what ever
bundle registers the CommandProcessor service.
Removed:
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentConverterFactory.java
Modified:
felix/trunk/scr/bnd.bnd
felix/trunk/scr/pom.xml
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentCommands.java
Modified: felix/trunk/scr/bnd.bnd
URL:
http://svn.apache.org/viewvc/felix/trunk/scr/bnd.bnd?rev=1852464&r1=1852463&r2=1852464&view=diff
==============================================================================
--- felix/trunk/scr/bnd.bnd (original)
+++ felix/trunk/scr/bnd.bnd Tue Jan 29 16:58:42 2019
@@ -29,7 +29,6 @@ Private-Package: org.apache.felix.scr.im
# PackageAdmin is used to find reference types if the component's bundle does
not import it.
# R4.0 version 1.2 is sufficient.
# optional import for Gogo annotations
-# The Felix Shell support is optional
Import-Package: \
org.osgi.service.cm;version="[1.6,2)";resolution:=optional, \
org.osgi.service.log;version="[1.3,2)";resolution:=optional, \
@@ -38,7 +37,6 @@ Import-Package: \
org.osgi.util.function;version="[1.0,2)", \
org.osgi.util.promise;version="[1.0,2)", \
org.apache.felix.service.command;resolution:=optional, \
- org.apache.felix.shell;provide:=true;resolution:=optional, \
*
DynamicImport-Package: \
Modified: felix/trunk/scr/pom.xml
URL:
http://svn.apache.org/viewvc/felix/trunk/scr/pom.xml?rev=1852464&r1=1852463&r2=1852464&view=diff
==============================================================================
--- felix/trunk/scr/pom.xml (original)
+++ felix/trunk/scr/pom.xml Tue Jan 29 16:58:42 2019
@@ -118,18 +118,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>org.apache.felix.shell</artifactId>
- <version>1.0.0</version>
- <scope>provided</scope>
- <exclusions>
- <exclusion>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.osgi.core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.gogo.runtime</artifactId>
<version>1.0.0</version>
Modified:
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentCommands.java
URL:
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentCommands.java?rev=1852464&r1=1852463&r2=1852464&view=diff
==============================================================================
---
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentCommands.java
(original)
+++
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentCommands.java
Tue Jan 29 16:58:42 2019
@@ -18,6 +18,9 @@
*/
package org.apache.felix.scr.impl;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -46,6 +49,8 @@ import org.osgi.framework.InvalidSyntaxE
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentFactory;
import org.osgi.service.component.runtime.ServiceComponentRuntime;
@@ -54,16 +59,18 @@ import org.osgi.service.component.runtim
import org.osgi.service.component.runtime.dto.ReferenceDTO;
import org.osgi.service.component.runtime.dto.SatisfiedReferenceDTO;
import org.osgi.service.component.runtime.dto.UnsatisfiedReferenceDTO;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
-public class ComponentCommands {
+public class ComponentCommands implements ServiceTrackerCustomizer<Object,
ServiceRegistration<?>> {
private static final String INDENT_1 = " ";
private static final String INDENT_2 = INDENT_1 + INDENT_1;
- private static final String INDENT_3 = INDENT_2 + INDENT_1;
private final BundleContext context;
private final ServiceComponentRuntime scr;
private final ScrConfiguration scrConfig;
+ private final ServiceTracker<Object, ServiceRegistration<?>>
gogoRuntimeTracker;
private final Comparator<ComponentConfigurationDTO> configDtoComparator =
new Comparator<ComponentConfigurationDTO>() {
@Override
@@ -81,7 +88,6 @@ public class ComponentCommands {
};
private ServiceRegistration<ComponentCommands> commandsReg = null;
- private ServiceRegistration<?> converterReg = null;
private ServiceRegistration<ScrInfo> scrInfoReg = null;
synchronized void register() {
@@ -104,18 +110,11 @@ public class ComponentCommands {
svcProps.put(Constants.SERVICE_VENDOR, "The Apache Software
Foundation");
commandsReg = context.registerService(ComponentCommands.class, this,
svcProps);
- svcProps = new Hashtable<>();
- svcProps.put("osgi.converter.classes", new String[] {
- ComponentDescriptionDTO.class.getName(),
- ComponentConfigurationDTO.class.getName()
- });
- svcProps.put(Constants.SERVICE_DESCRIPTION, "SCR Runtime DTO
Converter");
- svcProps.put(Constants.SERVICE_VENDOR, "The Apache Software
Foundation");
- converterReg =
context.registerService("org.apache.felix.service.command.Converter", new
ComponentConverterFactory(this), svcProps);
+ gogoRuntimeTracker.open(true);
}
synchronized void unregister() {
- safeUnregister(converterReg);
+ gogoRuntimeTracker.close();
safeUnregister(commandsReg);
safeUnregister(scrInfoReg);
}
@@ -138,6 +137,7 @@ public class ComponentCommands {
this.context = context;
this.scr = scr;
this.scrConfig = scrConfig;
+ this.gogoRuntimeTracker = new ServiceTracker<>(context,
"org.apache.felix.service.command.CommandProcessor", this);
}
@Descriptor("List all components")
@@ -223,6 +223,7 @@ public class ComponentCommands {
return changed;
}
+ @SuppressWarnings("deprecation")
@Descriptor("Show the current SCR configuration")
public String config() {
Map<String,String> out = new LinkedHashMap<>();
@@ -240,7 +241,7 @@ public class ComponentCommands {
}
public Object convert(Class<?> desiredType, Object in) throws Exception {
- throw new UnsupportedOperationException("Not implemented");
+ return null;
}
public CharSequence format(Object target, int level) throws Exception {
@@ -587,4 +588,64 @@ public class ComponentCommands {
}
}
+ @Override
+ public ServiceRegistration<?> addingService(ServiceReference<Object>
reference) {
+ Bundle b = reference.getBundle();
+ BundleRevision rev = b == null ? null : b.adapt(BundleRevision.class);
+ if (rev != null) {
+ Object converter = createConverter(b);
+ if (converter != null) {
+ Dictionary<String, Object> svcProps = new Hashtable<>();
+ svcProps.put("osgi.converter.classes", new String[] {
+ ComponentDescriptionDTO.class.getName(),
+ ComponentConfigurationDTO.class.getName()
+ });
+ svcProps.put(Constants.SERVICE_DESCRIPTION, "SCR Runtime DTO
Converter");
+ svcProps.put(Constants.SERVICE_VENDOR, "The Apache Software
Foundation");
+
+ return
b.getBundleContext().registerService("org.apache.felix.service.command.Converter",
converter, svcProps);
+ }
+ }
+ return null;
+ }
+
+ private Object createConverter(Bundle bundle) {
+ BundleWiring wiring = bundle.adapt(BundleWiring.class);
+ if (wiring != null) {
+ ClassLoader cl = wiring.getClassLoader();
+ if (cl != null) {
+ try {
+ Class<?>[] types = new Class[]
{cl.loadClass("org.apache.felix.service.command.Converter")};
+ return Proxy.newProxyInstance(cl, types, new
InvocationHandler() {
+
+ @Override
+ public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
+ if ("convert".equals(method.getName())) {
+ return convert((Class<?>) args[0], args[1]);
+ }
+ if ("format".equals(method.getName())) {
+ return format(args[0], (int) args[1]);
+ }
+ return method.invoke(this, args);
+ }
+ });
+ } catch (ClassNotFoundException e) {
+
+ }
+
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Object> reference,
ServiceRegistration<?> reg) {
+ // nothing
+ }
+
+ @Override
+ public void removedService(ServiceReference<Object> reference,
ServiceRegistration<?> reg) {
+ safeUnregister(reg);
+ }
+
}