| /* |
| * 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 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.framework.wiring.dto.FrameworkWiringDTO; |
| 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 |
| } |
| |
| 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)); |
| } |
| else if (type == FrameworkWiringDTO.class && bundle instanceof Felix) |
| { |
| return type.cast(createFrameworkWiringDTO((Felix) 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 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 = ((BundleImpl) 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 = convertAttrsToDTO(framework.getConfig()); |
| |
| 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 FrameworkWiringDTO createFrameworkWiringDTO(Felix framework) |
| { |
| FrameworkWiringDTO dto = new FrameworkWiringDTO(); |
| |
| dto.resources = new HashSet<BundleRevisionDTO>(); |
| dto.wirings = new HashSet<NodeDTO>(); |
| |
| Set<Bundle> bundles = new LinkedHashSet<Bundle>(Arrays.asList(framework.getBundles())); |
| bundles.addAll(framework.getRemovalPendingBundles()); |
| |
| for (Bundle bundle : bundles) |
| { |
| addBundleWiring(bundle, dto.resources, dto.wirings); |
| } |
| |
| 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 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(); |
| } |
| } |