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);
+    }
+
 }


Reply via email to