FELIX-4504 Support Core R6 Framework DTOs
Some unit tests included. This code passes all the Core R6 DTO tests.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1640076 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index 280bc85..b9ac3ab 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -42,6 +42,7 @@
import org.apache.felix.framework.util.ShrinkableCollection;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
+import org.osgi.dto.DTO;
import org.osgi.framework.AdaptPermission;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
@@ -1114,6 +1115,11 @@
return (A) new AccessControlContext(new ProtectionDomain[] {pd});
}
+ else if (DTO.class.isAssignableFrom(type) ||
+ DTO[].class.isAssignableFrom(type))
+ {
+ return DTOFactory.createDTO(this, type);
+ }
return null;
}
diff --git a/framework/src/main/java/org/apache/felix/framework/DTOFactory.java b/framework/src/main/java/org/apache/felix/framework/DTOFactory.java
new file mode 100644
index 0000000..e3cb64f
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/DTOFactory.java
@@ -0,0 +1,480 @@
+/*
+ * 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.framework;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.FrameworkDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleRevisions;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.framework.wiring.dto.BundleRevisionDTO;
+import org.osgi.framework.wiring.dto.BundleWireDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO.NodeDTO;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.resource.Wiring;
+import org.osgi.resource.dto.CapabilityDTO;
+import org.osgi.resource.dto.CapabilityRefDTO;
+import org.osgi.resource.dto.RequirementDTO;
+import org.osgi.resource.dto.RequirementRefDTO;
+import org.osgi.resource.dto.WireDTO;
+
+/**
+ * Creates various DTOs provided by the core framework.
+ */
+public class DTOFactory
+{
+ private DTOFactory()
+ {
+ // Only static methods
+ }
+
+ static <T> T createDTO(Bundle bundle, Class<T> type)
+ {
+ if (Bundle.UNINSTALLED == bundle.getState())
+ return null;
+
+ if (type == BundleDTO.class)
+ {
+ return type.cast(createBundleDTO(bundle));
+ }
+ else if (type == BundleStartLevelDTO.class)
+ {
+ return type.cast(createBundleStartLevelDTO(bundle));
+ }
+ else if (type == BundleRevisionDTO.class)
+ {
+ return type.cast(createBundleRevisionDTO(bundle));
+ }
+ else if (type == BundleRevisionDTO[].class)
+ {
+ return type.cast(createBundleRevisionDTOArray(bundle));
+ }
+ else if (type == BundleWiringDTO.class)
+ {
+ return type.cast(createBundleWiringDTO(bundle));
+ }
+ else if (type == BundleWiringDTO[].class)
+ {
+ return type.cast(createBundleWiringDTOArray(bundle));
+ }
+ else if (type == ServiceReferenceDTO[].class)
+ {
+ return type.cast(createServiceReferenceDTOArray(bundle));
+ }
+ else if (type == FrameworkDTO.class && bundle instanceof Felix)
+ {
+ return type.cast(createFrameworkDTO((Felix) bundle));
+ }
+ else if (type == FrameworkStartLevelDTO.class && bundle instanceof Framework)
+ {
+ return type.cast(createFrameworkStartLevelDTO((Framework) bundle));
+ }
+ return null;
+ }
+
+ private static BundleDTO createBundleDTO(Bundle bundle)
+ {
+ BundleDTO dto = new BundleDTO();
+ dto.id = bundle.getBundleId();
+ dto.lastModified = bundle.getLastModified();
+ dto.state = bundle.getState();
+ dto.symbolicName = bundle.getSymbolicName();
+ dto.version = "" + bundle.getVersion();
+ return dto;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle)
+ {
+ BundleRevision br = bundle.adapt(BundleRevision.class);
+ if (!(br instanceof BundleRevisionImpl))
+ return null;
+
+ return createBundleRevisionDTO(bundle, (BundleRevisionImpl) br, new HashSet<BundleRevisionDTO>());
+ }
+
+ private static BundleRevisionDTO[] createBundleRevisionDTOArray(Bundle bundle)
+ {
+ BundleRevisions brs = bundle.adapt(BundleRevisions.class);
+ if (brs == null || brs.getRevisions() == null)
+ return null;
+
+ List<BundleRevision> revisions = brs.getRevisions();
+ BundleRevisionDTO[] dtos = new BundleRevisionDTO[revisions.size()];
+ for (int i=0; i < revisions.size(); i++)
+ {
+ if (revisions.get(i) instanceof BundleRevisionImpl)
+ dtos[i] = createBundleRevisionDTO(bundle, (BundleRevisionImpl) revisions.get(i), new HashSet<BundleRevisionDTO>());
+ }
+ return dtos;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(BundleRevision revision, Set<BundleRevisionDTO> resources)
+ {
+ if (revision instanceof BundleRevisionImpl)
+ return createBundleRevisionDTO(revision.getBundle(), (BundleRevisionImpl) revision, resources);
+ else
+ return null;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle, BundleRevisionImpl revision, Set<BundleRevisionDTO> resources)
+ {
+ BundleRevisionDTO dto = new BundleRevisionDTO();
+ dto.id = getRevisionID(revision);
+ addBundleRevisionDTO(dto, resources);
+
+ dto.bundle = bundle.getBundleId();
+ dto.symbolicName = revision.getSymbolicName();
+ dto.type = revision.getTypes();
+ dto.version = revision.getVersion().toString();
+
+ dto.capabilities = new ArrayList<CapabilityDTO>();
+ for (Capability cap : revision.getCapabilities(null))
+ {
+ CapabilityDTO cdto = new CapabilityDTO();
+ cdto.id = getCapabilityID(cap);
+ cdto.namespace = cap.getNamespace();
+ cdto.attributes = convertAttrsToDTO(cap.getAttributes());
+ cdto.directives = new HashMap<String, String>(cap.getDirectives());
+ cdto.resource = getResourceIDAndAdd(cap.getResource(), resources);
+
+ dto.capabilities.add(cdto);
+ }
+
+ dto.requirements = new ArrayList<RequirementDTO>();
+ for (Requirement req : revision.getRequirements(null))
+ {
+ RequirementDTO rdto = new RequirementDTO();
+ rdto.id = getRequirementID(req);
+ rdto.namespace = req.getNamespace();
+ rdto.attributes = convertAttrsToDTO(req.getAttributes());
+ rdto.directives = new HashMap<String, String>(req.getDirectives());
+ rdto.resource = getResourceIDAndAdd(req.getResource(), resources);
+
+ dto.requirements.add(rdto);
+ }
+ return dto;
+ }
+
+ private static BundleWiringDTO createBundleWiringDTO(Bundle bundle)
+ {
+ BundleWiring bw = bundle.adapt(BundleWiring.class);
+ return createBundleWiringDTO(bw);
+ }
+
+ private static BundleWiringDTO createBundleWiringDTO(BundleWiring wiring)
+ {
+ BundleWiringDTO dto = new BundleWiringDTO();
+ dto.bundle = wiring.getBundle().getBundleId();
+ dto.root = getWiringID(wiring);
+ dto.nodes = new HashSet<BundleWiringDTO.NodeDTO>();
+ dto.resources = new HashSet<BundleRevisionDTO>();
+
+ createBundleRevisionDTO(wiring.getRevision(), dto.resources);
+ createBundleWiringNodeDTO(wiring, dto.resources, dto.nodes);
+
+ return dto;
+ }
+
+ private static BundleWiringDTO[] createBundleWiringDTOArray(Bundle bundle)
+ {
+ BundleRevisions brs = bundle.adapt(BundleRevisions.class);
+ if (brs == null || brs.getRevisions() == null)
+ return null;
+
+ List<BundleRevision> revisions = brs.getRevisions();
+ BundleWiringDTO[] dtos = new BundleWiringDTO[revisions.size()];
+ for (int i=0; i < revisions.size(); i++)
+ {
+ BundleWiring wiring = revisions.get(i).getWiring();
+ dtos[i] = createBundleWiringDTO(wiring);
+ }
+ return dtos;
+ }
+
+ private static void createBundleWiringNodeDTO(BundleWiring bw, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
+ {
+ NodeDTO node = new BundleWiringDTO.NodeDTO();
+ node.id = getWiringID(bw);
+ nodes.add(node);
+
+ node.current = bw.isCurrent();
+ node.inUse = bw.isInUse();
+ node.resource = getResourceIDAndAdd(bw.getResource(), resources);
+
+ node.capabilities = new ArrayList<CapabilityRefDTO>();
+ for (Capability cap : bw.getCapabilities(null))
+ {
+ CapabilityRefDTO cdto = new CapabilityRefDTO();
+ cdto.capability = getCapabilityID(cap);
+ cdto.resource = getResourceIDAndAdd(cap.getResource(), resources);
+ node.capabilities.add(cdto);
+ }
+
+ node.requirements = new ArrayList<RequirementRefDTO>();
+ for (Requirement req : bw.getRequirements(null))
+ {
+ RequirementRefDTO rdto = new RequirementRefDTO();
+ rdto.requirement = getRequirementID(req);
+ rdto.resource = getResourceIDAndAdd(req.getResource(), resources);
+ node.requirements.add(rdto);
+ }
+
+ node.providedWires = new ArrayList<WireDTO>();
+ for (Wire pw : bw.getProvidedWires(null))
+ {
+ node.providedWires.add(createBundleWireDTO(pw, resources, nodes));
+ }
+
+ node.requiredWires = new ArrayList<WireDTO>();
+ for (Wire rw : bw.getRequiredWires(null))
+ {
+ node.requiredWires.add(createBundleWireDTO(rw, resources, nodes));
+ }
+ }
+
+ private static BundleWireDTO createBundleWireDTO(Wire wire, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
+ {
+ BundleWireDTO wdto = new BundleWireDTO();
+ if (wire instanceof BundleWire)
+ {
+ BundleWire w = (BundleWire) wire;
+
+ BundleWiring pw = w.getProviderWiring();
+ addWiringNodeIfNotPresent(pw, resources, nodes);
+ wdto.providerWiring = getWiringID(pw);
+
+ BundleWiring rw = w.getRequirerWiring();
+ addWiringNodeIfNotPresent(rw, resources, nodes);
+ wdto.requirerWiring = getWiringID(rw);
+ }
+ wdto.provider = getResourceIDAndAdd(wire.getProvider(), resources);
+ wdto.requirer = getResourceIDAndAdd(wire.getRequirer(), resources);
+ wdto.capability = new CapabilityRefDTO();
+ wdto.capability.capability = getCapabilityID(wire.getCapability());
+ wdto.capability.resource = getResourceIDAndAdd(wire.getCapability().getResource(), resources);
+ wdto.requirement = new RequirementRefDTO();
+ wdto.requirement.requirement = getRequirementID(wire.getRequirement());
+ wdto.requirement.resource = getResourceIDAndAdd(wire.getRequirement().getResource(), resources);
+ return wdto;
+ }
+
+ private static BundleStartLevelDTO createBundleStartLevelDTO(Bundle bundle)
+ {
+ BundleStartLevelDTO dto = new BundleStartLevelDTO();
+ dto.bundle = bundle.getBundleId();
+
+ BundleStartLevel sl = bundle.adapt(BundleStartLevel.class);
+ dto.activationPolicyUsed = sl.isActivationPolicyUsed();
+ dto.persistentlyStarted = sl.isPersistentlyStarted();
+ dto.startLevel = sl.getStartLevel();
+
+ return dto;
+ }
+
+ private static ServiceReferenceDTO[] createServiceReferenceDTOArray(Bundle bundle)
+ {
+ BundleContext ctx = bundle.getBundleContext();
+ if (ctx == null)
+ return null;
+
+ ServiceReference<?>[] svcs = bundle.getRegisteredServices();
+ if (svcs == null)
+ return new ServiceReferenceDTO[0];
+
+ ServiceReferenceDTO[] dtos = new ServiceReferenceDTO[svcs.length];
+ for (int i=0; i < svcs.length; i++)
+ {
+ dtos[i] = createServiceReferenceDTO(svcs[i]);
+ }
+ return dtos;
+ }
+
+ private static ServiceReferenceDTO createServiceReferenceDTO(ServiceReference<?> svc)
+ {
+ ServiceReferenceDTO dto = new ServiceReferenceDTO();
+ dto.bundle = svc.getBundle().getBundleId();
+ dto.id = (Long) svc.getProperty(Constants.SERVICE_ID);
+ Map<String, Object> props = new HashMap<String, Object>();
+ for (String key : svc.getPropertyKeys())
+ {
+ props.put(key, svc.getProperty(key));
+ }
+ dto.properties = new HashMap<String, Object>(props);
+
+ Bundle[] ubs = svc.getUsingBundles();
+ if (ubs == null)
+ {
+ dto.usingBundles = new long[0];
+ }
+ else
+ {
+ dto.usingBundles = new long[ubs.length];
+ for (int j=0; j < ubs.length; j++)
+ {
+ dto.usingBundles[j] = ubs[j].getBundleId();
+ }
+ }
+ return dto;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static FrameworkDTO createFrameworkDTO(Felix framework)
+ {
+ FrameworkDTO dto = new FrameworkDTO();
+ dto.properties = framework.getConfig(); // This map is immutable, so it's fine to share
+
+ dto.bundles = new ArrayList<BundleDTO>();
+ for (Bundle b : framework.getBundleContext().getBundles())
+ {
+ dto.bundles.add(DTOFactory.createDTO(b, BundleDTO.class));
+ }
+
+ dto.services = new ArrayList<ServiceReferenceDTO>();
+
+ ServiceReference<?>[] refs = null;
+ try
+ {
+ refs = framework.getBundleContext().getAllServiceReferences(null, null);
+ }
+ catch (InvalidSyntaxException e)
+ {
+ // No filter, should never happen
+ }
+
+ for (ServiceReference<?> sr : refs)
+ {
+ dto.services.add(createServiceReferenceDTO(sr));
+ }
+
+ return dto;
+ }
+
+ private static FrameworkStartLevelDTO createFrameworkStartLevelDTO(Framework framework)
+ {
+ FrameworkStartLevel fsl = framework.adapt(FrameworkStartLevel.class);
+
+ FrameworkStartLevelDTO dto = new FrameworkStartLevelDTO();
+ dto.initialBundleStartLevel = fsl.getInitialBundleStartLevel();
+ dto.startLevel = fsl.getStartLevel();
+
+ return dto;
+ }
+
+ private static void addBundleRevisionDTO(BundleRevisionDTO dto, Set<BundleRevisionDTO> resources)
+ {
+ for (BundleRevisionDTO r : resources)
+ {
+ if (r.id == dto.id)
+ return;
+ }
+ resources.add(dto);
+ }
+
+ private static void addWiringNodeIfNotPresent(BundleWiring bw, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
+ {
+ int wiringID = getWiringID(bw);
+ for (NodeDTO n : nodes)
+ {
+ if (n.id == wiringID)
+ return;
+ }
+ createBundleWiringNodeDTO(bw, resources, nodes);
+ }
+
+ // Attributes contain Version values which are not supported for DTOs, so if
+ // these are found they need to be converted to String values.
+ private static Map<String, Object> convertAttrsToDTO(Map<String, Object> map)
+ {
+ Map<String, Object> m = new HashMap<String, Object>();
+ for (Map.Entry<String, Object> entry : map.entrySet())
+ {
+ if (entry.getValue() instanceof Version)
+ // DTOs don't support Version objects
+ m.put(entry.getKey(), entry.getValue().toString());
+ else
+ m.put(entry.getKey(), entry.getValue());
+ }
+ return m;
+ }
+
+ private static int getWiringID(Wiring bw)
+ {
+ return bw.hashCode();
+ }
+
+ private static int getCapabilityID(Capability capability)
+ {
+ return capability.hashCode();
+ }
+
+ private static int getRequirementID(Requirement requirement)
+ {
+ return requirement.hashCode();
+ }
+
+ private static int getResourceIDAndAdd(Resource res, Set<BundleRevisionDTO> resources)
+ {
+ if (res instanceof BundleRevisionImpl)
+ {
+ BundleRevisionImpl bres = (BundleRevisionImpl) res;
+ int id = bres.getId().hashCode();
+
+ if (resources == null)
+ return id;
+
+ for (BundleRevisionDTO rdto : resources)
+ {
+ if (rdto.id == id)
+ return id;
+ }
+ createBundleRevisionDTO(bres, resources);
+ return id;
+ }
+ return res.hashCode();
+ }
+
+ private static int getRevisionID(BundleRevisionImpl revision)
+ {
+ return revision.getId().hashCode();
+ }
+}
diff --git a/framework/src/test/java/org/apache/felix/framework/DTOFactoryTest.java b/framework/src/test/java/org/apache/felix/framework/DTOFactoryTest.java
new file mode 100644
index 0000000..fc897bf
--- /dev/null
+++ b/framework/src/test/java/org/apache/felix/framework/DTOFactoryTest.java
@@ -0,0 +1,272 @@
+/*
+ * 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.framework;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.felix.framework.Felix;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+import org.osgi.framework.wiring.dto.BundleRevisionDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO;
+import org.osgi.resource.dto.CapabilityDTO;
+
+public class DTOFactoryTest
+{
+ private int counter;
+ private Framework framework;
+ private File testDir;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ String path = "/" + getClass().getName().replace('.', '/') + ".class";
+ String url = getClass().getResource(path).getFile();
+ String baseDir = url.substring(0, url.length() - path.length());
+ String rndStr = Long.toString(System.nanoTime(), Character.MAX_RADIX);
+ rndStr = rndStr.substring(rndStr.length() - 6, rndStr.length() - 1);
+ testDir = new File(baseDir, getClass().getSimpleName() + "_" + rndStr);
+
+ File cacheDir = new File(testDir, "cache");
+ cacheDir.mkdirs();
+ String cache = cacheDir.getAbsolutePath();
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("felix.cache.profiledir", cache);
+ params.put("felix.cache.dir", cache);
+ params.put(Constants.FRAMEWORK_STORAGE, cache);
+
+ framework = new Felix(params);
+ framework.init();
+ framework.start();
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ framework.stop();
+ }
+
+ @Test
+ public void testBundleStartLevelDTO() throws Exception
+ {
+ String mf = "Bundle-SymbolicName: tb1\n"
+ + "Bundle-Version: 1.0.0\n"
+ + "Bundle-ManifestVersion: 2\n";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+
+ BundleStartLevel sl = bundle.adapt(BundleStartLevel.class);
+ sl.setStartLevel(7);
+
+ BundleStartLevelDTO dto = bundle.adapt(BundleStartLevelDTO.class);
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ assertEquals(7, dto.startLevel);
+ }
+
+ @Test
+ public void testServiceReferenceDTOArray() throws Exception
+ {
+ ServiceRegistration<String> reg = framework.getBundleContext().registerService(String.class, "hi", null);
+ Long sid = (Long) reg.getReference().getProperty(Constants.SERVICE_ID);
+
+ ServiceReferenceDTO[] dtos = framework.adapt(ServiceReferenceDTO[].class);
+ assertTrue(dtos.length > 0);
+
+ boolean found = false;
+ for (ServiceReferenceDTO dto : dtos)
+ {
+ if (dto.id == sid)
+ {
+ found = true;
+ assertEquals(0L, dto.bundle);
+ assertEquals(sid, dto.properties.get(Constants.SERVICE_ID));
+ assertTrue(Arrays.equals(new String [] {String.class.getName()},
+ (String []) dto.properties.get(Constants.OBJECTCLASS)));
+ assertEquals(0L, dto.properties.get(Constants.SERVICE_BUNDLEID));
+ assertEquals(Constants.SCOPE_SINGLETON, dto.properties.get(Constants.SERVICE_SCOPE));
+ assertEquals(0, dto.usingBundles.length);
+ }
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testBundleRevisionDTO() throws Exception
+ {
+ String mf = "Bundle-SymbolicName: tb2\n"
+ + "Bundle-Version: 1.2.3\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Import-Package: org.osgi.framework;version=\"[1.1,2)\"";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+ bundle.start();
+ assertEquals("Precondition", Bundle.ACTIVE, bundle.getState());
+
+ BundleRevisionDTO dto = bundle.adapt(BundleRevisionDTO.class);
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ assertTrue(dto.id != 0);
+ assertEquals("tb2", dto.symbolicName);
+ assertEquals("1.2.3", dto.version);
+ assertEquals(0, dto.type);
+
+ boolean foundBundle = false;
+ boolean foundHost = false;
+ boolean foundIdentity = false;
+ int resource = 0;
+ for (CapabilityDTO cap : dto.capabilities)
+ {
+ assertTrue(cap.id != 0);
+ if (resource == 0)
+ resource = cap.resource;
+ else
+ assertEquals(resource, cap.resource);
+
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(cap.namespace))
+ {
+ foundBundle = true;
+ assertEquals("tb2", cap.attributes.get(BundleNamespace.BUNDLE_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (HostNamespace.HOST_NAMESPACE.equals(cap.namespace))
+ {
+ foundHost = true;
+ assertEquals("tb2", cap.attributes.get(HostNamespace.HOST_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (IdentityNamespace.IDENTITY_NAMESPACE.equals(cap.namespace))
+ {
+ foundIdentity = true;
+ assertEquals("tb2", cap.attributes.get(IdentityNamespace.IDENTITY_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ assertEquals(IdentityNamespace.TYPE_BUNDLE, cap.attributes.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+ }
+ }
+ assertTrue(foundBundle);
+ assertTrue(foundHost);
+ assertTrue(foundIdentity);
+ }
+
+ @Test
+ public void testBundleRevisionDTOArray() throws Exception {
+ String mf = "Bundle-SymbolicName: tb2\n"
+ + "Bundle-Version: 1.2.3\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Import-Package: org.osgi.framework;version=\"[1.1,2)\"";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+ bundle.start();
+ assertEquals("Precondition", Bundle.ACTIVE, bundle.getState());
+
+ BundleRevisionDTO[] dtos = bundle.adapt(BundleRevisionDTO[].class);
+ assertEquals(1, dtos.length);
+ BundleRevisionDTO dto = dtos[0];
+
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ assertTrue(dto.id != 0);
+ assertEquals("tb2", dto.symbolicName);
+ assertEquals("1.2.3", dto.version);
+ assertEquals(0, dto.type);
+
+ boolean foundBundle = false;
+ boolean foundHost = false;
+ boolean foundIdentity = false;
+ int resource = 0;
+ for (CapabilityDTO cap : dto.capabilities)
+ {
+ assertTrue(cap.id != 0);
+ if (resource == 0)
+ resource = cap.resource;
+ else
+ assertEquals(resource, cap.resource);
+
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(cap.namespace))
+ {
+ foundBundle = true;
+ assertEquals("tb2", cap.attributes.get(BundleNamespace.BUNDLE_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (HostNamespace.HOST_NAMESPACE.equals(cap.namespace))
+ {
+ foundHost = true;
+ assertEquals("tb2", cap.attributes.get(HostNamespace.HOST_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (IdentityNamespace.IDENTITY_NAMESPACE.equals(cap.namespace))
+ {
+ foundIdentity = true;
+ assertEquals("tb2", cap.attributes.get(IdentityNamespace.IDENTITY_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ assertEquals(IdentityNamespace.TYPE_BUNDLE, cap.attributes.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+ }
+ }
+ assertTrue(foundBundle);
+ assertTrue(foundHost);
+ assertTrue(foundIdentity);
+ }
+
+ @Test
+ public void testBundleWiringDTO() throws Exception {
+ String mf = "Bundle-SymbolicName: tb2\n"
+ + "Bundle-Version: 1.2.3\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Import-Package: org.osgi.framework;version=\"[1.1,2)\"";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+ bundle.start();
+ assertEquals("Precondition", Bundle.ACTIVE, bundle.getState());
+
+ BundleWiringDTO dto = bundle.adapt(BundleWiringDTO.class);
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ }
+
+ private File createBundle(String manifest) throws IOException
+ {
+ File f = File.createTempFile("felix-bundle" + counter++, ".jar", testDir);
+
+ Manifest mf = new Manifest(new ByteArrayInputStream(manifest.getBytes("utf-8")));
+ mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+ JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
+
+ os.close();
+ return f;
+ }
+}