blob: 2ff406ad8ca8be103234a291a1150b4b1a8cd86e [file] [log] [blame]
/*
* 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.FrameworkWiringDTO;
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));
}
else if (type == FrameworkWiringDTO.class)
{
return type.cast(createFrameworkWiringDTO(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 FrameworkWiringDTO createFrameworkWiringDTO(Bundle framework)
{
FrameworkWiringDTO dto = new FrameworkWiringDTO();
dto.resources = new HashSet<BundleRevisionDTO>();
dto.wirings = new HashSet<NodeDTO>();
Set<Bundle> bundles = new LinkedHashSet<Bundle>(Arrays.asList(framework.getBundleContext().getBundles()));
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 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();
}
}