You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2019/04/30 16:18:48 UTC
svn commit: r1858441 -
/felix/trunk/connect/src/main/java/org/apache/felix/connect/felix/framework/DTOFactory.java
Author: pauls
Date: Tue Apr 30 16:18:47 2019
New Revision: 1858441
URL: http://svn.apache.org/viewvc?rev=1858441&view=rev
Log:
FELIX-6114: Implement DTO support in connect.
Added:
felix/trunk/connect/src/main/java/org/apache/felix/connect/felix/framework/DTOFactory.java
Added: felix/trunk/connect/src/main/java/org/apache/felix/connect/felix/framework/DTOFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/connect/src/main/java/org/apache/felix/connect/felix/framework/DTOFactory.java?rev=1858441&view=auto
==============================================================================
--- felix/trunk/connect/src/main/java/org/apache/felix/connect/felix/framework/DTOFactory.java (added)
+++ felix/trunk/connect/src/main/java/org/apache/felix/connect/felix/framework/DTOFactory.java Tue Apr 30 16:18:47 2019
@@ -0,0 +1,544 @@
+/*
+ * 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.connect.felix.framework;
+
+import org.apache.felix.connect.Revision;
+import org.osgi.dto.DTO;
+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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Creates various DTOs provided by the core framework.
+ */
+public class DTOFactory
+{
+ private DTOFactory()
+ {
+ // Only static methods
+ }
+
+ public 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)
+ {
+ return type.cast(createFrameworkDTO(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);
+
+ return createBundleRevisionDTO(bundle, 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++)
+ {
+ dtos[i] = createBundleRevisionDTO(bundle,revisions.get(i), new HashSet<BundleRevisionDTO>());
+ }
+ return dtos;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(BundleRevision revision, Set<BundleRevisionDTO> resources)
+ {
+ return createBundleRevisionDTO(revision.getBundle(), revision, resources);
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle, BundleRevision 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 bw != null ? createBundleWiringDTO(bw) : null;
+ }
+
+ 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);
+
+ addNodeDTO(node, nodes);
+
+ 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(Bundle framework)
+ {
+ FrameworkDTO dto = new FrameworkDTO();
+ dto.properties = new HashMap<String, Object>();
+
+ 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 addBundleWiring(Bundle bundle, Set<BundleRevisionDTO> resources, Set<NodeDTO> wirings)
+ {
+ BundleRevisions brs = bundle.adapt(BundleRevisions.class);
+
+ for (BundleRevision revision : brs.getRevisions())
+ {
+ BundleWiring wiring = revision.getWiring();
+ if (wiring != null)
+ {
+ createBundleWiringNodeDTO(wiring, resources, wirings);
+ }
+ }
+ }
+
+ 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 addNodeDTO(NodeDTO dto, Set<NodeDTO> nodes)
+ {
+ for (NodeDTO nodeDTO : nodes)
+ {
+ if (nodeDTO.id == dto.id)
+ return;
+ }
+ nodes.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())
+ {
+ Object value = convertAttrToDTO(entry.getValue());
+ if (value != null)
+ {
+ m.put(entry.getKey(), value);
+ }
+ }
+ return m;
+ }
+
+ private static Object convertAttrToDTO(Object value)
+ {
+ if (value instanceof Version)
+ {
+ return value.toString();
+ }
+ else if (isPermissibleAttribute(value.getClass())
+ || (value.getClass().isArray()
+ && isPermissibleAttribute(value.getClass().getComponentType())))
+ {
+ return value;
+ }
+ else if (value instanceof List)
+ {
+ List result = new ArrayList();
+ for (Object v : ((List) value))
+ {
+ Object vv = convertAttrToDTO(v);
+ if (vv != null)
+ {
+ result.add(vv);
+ }
+ }
+ return result.isEmpty() ? null : result;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private static boolean isPermissibleAttribute(Class clazz)
+ {
+ return clazz == Boolean.class || clazz == String.class
+ || DTO.class.isAssignableFrom(clazz) || Number.class.isAssignableFrom(clazz);
+ }
+
+ private static int getWiringID(Wiring bw)
+ {
+ Resource res = bw.getResource();
+ if (res != null)
+ {
+ return getResourceIDAndAdd(res, null);
+ }
+ 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 Revision)
+ {
+ int id = res.hashCode();
+
+ if (resources == null)
+ return id;
+
+ for (BundleRevisionDTO rdto : resources)
+ {
+ if (rdto.id == id)
+ return id;
+ }
+ createBundleRevisionDTO((BundleRevision) res, resources);
+ return id;
+ }
+ return res.hashCode();
+ }
+
+ private static int getRevisionID(BundleRevision revision)
+ {
+ return revision.hashCode();
+ }
+}