FELIX-4403 complete ServiceReferenceDTO info, with what the spec says about type conversions, however implausible that is, and update SCRCommand appropriately
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1617027 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java b/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
index ca29a8e..ff5074a 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
@@ -19,6 +19,7 @@
package org.apache.felix.scr.impl;
import java.io.PrintWriter;
+import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -392,11 +393,22 @@
Object prop = entry.getValue();
if ( prop.getClass().isArray() )
{
- prop = Arrays.asList( ( Object[] ) prop );
+ out.print("[");
+ int length = Array.getLength(prop);
+ for (int i = 0; i< length; i++)
+ {
+ out.print(Array.get(prop, i));
+ if ( i < length - 1)
+ {
+ out.print(", ");
+ }
+ }
+ out.println("]");
+ }
+ else
+ {
+ out.println( prop );
}
- out.print( prop );
-
- out.println();
}
}
}
@@ -422,6 +434,7 @@
{
out.print( " " );
out.println( sr.id );
+ propertyInfo(sr.properties, out, " ");
}
}
else
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
index 2d375bb..ba00533 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
@@ -18,11 +18,13 @@
*/
package org.apache.felix.scr.impl.runtime;
+import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.felix.scr.impl.ComponentRegistry;
import org.apache.felix.scr.impl.config.ComponentHolder;
@@ -30,8 +32,10 @@
import org.apache.felix.scr.impl.config.ReferenceManager;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.osgi.dto.DTO;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.dto.BundleDTO;
import org.osgi.framework.dto.ServiceReferenceDTO;
@@ -43,7 +47,8 @@
import org.osgi.service.component.runtime.dto.UnsatisfiedReferenceDTO;
import org.osgi.util.promise.Promise;
-public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime {
+public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime
+{
private static final String[] EMPTY = {};
@@ -51,14 +56,14 @@
private final ComponentRegistry componentRegistry;
- public ServiceComponentRuntimeImpl(BundleContext context,
- ComponentRegistry componentRegistry) {
+ public ServiceComponentRuntimeImpl(BundleContext context,ComponentRegistry componentRegistry)
+ {
this.context = context;
this.componentRegistry = componentRegistry;
}
- public Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(
- Bundle... bundles) {
+ public Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles)
+ {
List<ComponentHolder<?>> holders;
if (bundles == null || bundles.length == 0)
{
@@ -77,7 +82,8 @@
return result;
}
- public ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name) {
+ public ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name)
+ {
ComponentHolder<?> holder = componentRegistry.getComponentHolder(bundle, name);
if ( holder != null )
{
@@ -89,8 +95,8 @@
}
}
- public Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(
- ComponentDescriptionDTO description) {
+ public Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description)
+ {
if ( description == null)
{
return Collections.emptyList();
@@ -107,23 +113,26 @@
return result;
}
- public boolean isComponentEnabled(ComponentDescriptionDTO description) {
+ public boolean isComponentEnabled(ComponentDescriptionDTO description)
+ {
ComponentHolder<?> holder = getHolderFromDescription( description);
return holder.isEnabled();
}
- public Promise<Void> enableComponent(ComponentDescriptionDTO description) {
+ public Promise<Void> enableComponent(ComponentDescriptionDTO description)
+ {
ComponentHolder<?> holder = getHolderFromDescription( description);
return holder.enableComponents(true);
}
- public Promise<Void> disableComponent(ComponentDescriptionDTO description) {
+ public Promise<Void> disableComponent(ComponentDescriptionDTO description)
+ {
ComponentHolder<?> holder = getHolderFromDescription( description);
return holder.disableComponents(true); //synchronous
}
- private ComponentConfigurationDTO managerToConfiguration(
- ComponentManager<?> manager, ComponentDescriptionDTO description) {
+ private ComponentConfigurationDTO managerToConfiguration(ComponentManager<?> manager, ComponentDescriptionDTO description)
+ {
ComponentConfigurationDTO dto = new ComponentConfigurationDTO();
dto.satisfiedReferences = satisfiedRefManagersToDTO(manager.getReferenceManagers());
dto.unsatisfiedReferences = unsatisfiedRefManagersToDTO(manager.getReferenceManagers());
@@ -134,7 +143,8 @@
return dto;
}
- private SatisfiedReferenceDTO[] satisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers) {
+ private SatisfiedReferenceDTO[] satisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers)
+ {
List<SatisfiedReferenceDTO> dtos = new ArrayList<SatisfiedReferenceDTO>();
for (ReferenceManager<?, ?> ref: referenceManagers)
{
@@ -157,7 +167,8 @@
return dtos.toArray( new SatisfiedReferenceDTO[dtos.size()] );
}
- private UnsatisfiedReferenceDTO[] unsatisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers) {
+ private UnsatisfiedReferenceDTO[] unsatisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers)
+ {
List<UnsatisfiedReferenceDTO> dtos = new ArrayList<UnsatisfiedReferenceDTO>();
for (ReferenceManager<?, ?> ref: referenceManagers)
{
@@ -180,17 +191,27 @@
return dtos.toArray( new UnsatisfiedReferenceDTO[dtos.size()] );
}
- private ServiceReferenceDTO serviceReferenceToDTO(
- ServiceReference<?> serviceRef) {
+ private ServiceReferenceDTO serviceReferenceToDTO( ServiceReference<?> serviceRef)
+ {
ServiceReferenceDTO dto = new ServiceReferenceDTO();
dto.bundle = serviceRef.getBundle().getBundleId();
- dto.id = (Long) serviceRef.getProperty("service.id"); //TODO use proper constant
- //TODO service properties, using bundles
- return dto;
+ dto.id = (Long) serviceRef.getProperty(Constants.SERVICE_ID);
+ dto.properties = deepCopy( serviceRef );
+ Bundle[] usingBundles = serviceRef.getUsingBundles();
+ if (usingBundles != null)
+ {
+ long[] usingBundleIds = new long[usingBundles.length];
+ for (int i = 0; i < usingBundles.length; i++)
+ {
+ usingBundleIds[i] = usingBundles[i].getBundleId();
+ }
+ dto.usingBundles = usingBundleIds;
+ }
+ return dto;
}
- private ComponentHolder<?> getHolderFromDescription(
- ComponentDescriptionDTO description) {
+ private ComponentHolder<?> getHolderFromDescription(ComponentDescriptionDTO description)
+ {
if (description.bundle == null)
{
throw new IllegalArgumentException("No bundle supplied in ComponentDescriptionDTO named " + description.name);
@@ -216,14 +237,72 @@
dto.implementationClass = m.getImplementationClassName();
dto.modified = m.getModified();
dto.name = m.getName();
- dto.properties = new HashMap<String, Object>(m.getProperties());// TODO deep copy of arrays
+ dto.properties = deepCopy(m.getProperties());
dto.references = refsToDTO(m.getDependencies());
dto.scope = m.getServiceMetadata() == null? null: m.getServiceMetadata().getScope().name();
dto.serviceInterfaces = m.getServiceMetadata() == null? EMPTY: m.getServiceMetadata().getProvides();
return dto;
}
+
+ private Map<String, Object> deepCopy(Map<String, Object> source)
+ {
+ HashMap<String, Object> result = new HashMap<String, Object>(source.size());
+ for (Map.Entry<String, Object> entry: source.entrySet())
+ {
+ result.put(entry.getKey(), convert(entry.getValue()));
+ }
+ return result;
+ }
- private ReferenceDTO[] refsToDTO(List<ReferenceMetadata> dependencies) {
+ private Map<String, Object> deepCopy(ServiceReference<?> source)
+ {
+ String[] keys = source.getPropertyKeys();
+ HashMap<String, Object> result = new HashMap<String, Object>(keys.length);
+ for (int i = 0; i< keys.length; i++)
+ {
+ result.put(keys[i], convert(source.getProperty(keys[i])));
+ }
+ return result;
+ }
+
+ Object convert(Object source)
+ {
+ if (source.getClass().isArray())
+ {
+ Class<?> type = source.getClass().getComponentType();
+ if (checkType(type))
+ {
+ return source;
+ }
+ return String.valueOf(source);
+ /* array copy code in case it turns out to be needed
+ int length = Array.getLength(source);
+ Object copy = Array.newInstance(type, length);
+ for (int i = 0; i<length; i++)
+ {
+ Array.set(copy, i, Array.get(source, i));
+ }
+ return copy;
+ */
+ }
+ if (checkType(source.getClass()))
+ {
+ return source;
+ }
+ return String.valueOf(source);
+ }
+
+ boolean checkType(Class<?> type)
+ {
+ if (type == String.class) return true;
+ if (type == Boolean.class) return true;
+ if (Number.class.isAssignableFrom(type)) return true;
+ if (DTO.class.isAssignableFrom(type)) return true;
+ return false;
+ }
+
+ private ReferenceDTO[] refsToDTO(List<ReferenceMetadata> dependencies)
+ {
ReferenceDTO[] dtos = new ReferenceDTO[dependencies.size()];
int i = 0;
for (ReferenceMetadata r: dependencies)
@@ -244,7 +323,8 @@
return dtos;
}
- private BundleDTO bundleToDTO(BundleContext bundleContext) {
+ private BundleDTO bundleToDTO(BundleContext bundleContext)
+ {
if (bundleContext == null)
{
return null;
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/SCRCommandlTest.java b/scr/src/test/java/org/apache/felix/scr/impl/SCRCommandlTest.java
new file mode 100644
index 0000000..b93c7a9
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/SCRCommandlTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+import junit.framework.TestCase;
+
+public class SCRCommandlTest extends TestCase
+{
+
+
+ public void testPropertyInfo()
+ {
+ ScrCommand scr = new ScrCommand(null, null, null);
+ check(scr, " Properties:\n key = [1, 2]\n", new int[] {1, 2});
+ check(scr, " Properties:\n key = [1, 2]\n", new String[] {"1", "2"});
+ check(scr, " Properties:\n key = [true, false]\n", new Boolean[] {true, false});
+ check(scr, " Properties:\n key = foo\n", "foo");
+ check(scr, " Properties:\n key = true\n", true);
+ }
+
+ private PrintWriter check(ScrCommand scr, String expected, Object o)
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ scr.propertyInfo(Collections.<String, Object>singletonMap("key", o), pw, "");
+ assertEquals(expected, sw.toString());
+ return pw;
+ }
+
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImplTest.java b/scr/src/test/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImplTest.java
new file mode 100644
index 0000000..c52521f
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImplTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl.runtime;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+import junit.framework.TestCase;
+
+public class ServiceComponentRuntimeImplTest extends TestCase
+{
+
+ /* in case behavior is supposed to actually involve copying
+ public void testCopy()
+ {
+ ServiceComponentRuntimeImpl scr = new ServiceComponentRuntimeImpl(null, null);
+ assertEquals(1, scr.convert(1));
+ assertEquals("foo", scr.convert("foo"));
+ equalCopy(new int[] {1, 2, 3}, scr);
+ equalCopy(new byte[] {1, 2, 3}, scr);
+ equalCopy(new String[] {"1", "2", "3"}, scr);
+ equalCopy(new Long[] {1l, 2l, 3l}, scr);
+ }
+
+ private void equalCopy(Object o1, ServiceComponentRuntimeImpl scr)
+ {
+ Object o2 = scr.convert(o1);
+ assertEquals("expected same length", Array.getLength(o1), Array.getLength(o2));
+ assertEquals("expceted same component type", o1.getClass().getComponentType(), o2.getClass().getComponentType());
+ for (int i = 0; i < Array.getLength(o1); i++)
+ {
+ assertEquals("expected same value at " + i, Array.get(o1, i), Array.get(o2, i));
+ }
+
+ }
+ */
+
+ public void testConvert()
+ {
+ ServiceComponentRuntimeImpl scr = new ServiceComponentRuntimeImpl(null, null);
+ same("foo", scr);
+ same(Boolean.TRUE, scr);
+ same(1, scr);
+ same(1l, scr);
+ same(new ServiceReferenceDTO(), scr);
+ same( new String[] {"foo", "bar"}, scr);
+ same( new Boolean[] {true, false}, scr);
+ same( new Long[] {1l, 2l}, scr);
+ same( new DTO[] {new ServiceReferenceDTO(), new BundleDTO()}, scr);
+ equalsToString(new int[] {1, 2}, scr);
+ equalsToString(Arrays.asList(new int[] {1, 2}), scr);
+ equalsToString(Arrays.asList(new String[] {"foo", "bar"}), scr);
+ }
+
+ private void equalsToString(Object o, ServiceComponentRuntimeImpl scr)
+ {
+ assertEquals(String.valueOf(o), scr.convert(o));
+ }
+
+ private void same(Object o, ServiceComponentRuntimeImpl scr)
+ {
+ assertSame(o, scr.convert(o));
+ }
+
+}