/* * 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.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.manager.ComponentHolder; import org.apache.felix.scr.impl.manager.ComponentManager; import org.apache.felix.scr.impl.manager.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; import org.osgi.service.component.runtime.ServiceComponentRuntime; import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO; import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO; import org.osgi.service.component.runtime.dto.ReferenceDTO; import org.osgi.service.component.runtime.dto.SatisfiedReferenceDTO; import org.osgi.service.component.runtime.dto.UnsatisfiedReferenceDTO; import org.osgi.util.promise.Promise; import org.osgi.util.promise.Promises; public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime { private static final String[] EMPTY = {}; private final BundleContext context; private final ComponentRegistry componentRegistry; public ServiceComponentRuntimeImpl(BundleContext context,ComponentRegistry componentRegistry) { this.context = context; this.componentRegistry = componentRegistry; } /** * @see org.osgi.service.component.runtime.ServiceComponentRuntime#getComponentDescriptionDTOs(org.osgi.framework.Bundle[]) */ public Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles) { List<ComponentHolder<?>> holders; if (bundles == null || bundles.length == 0) { holders = componentRegistry.getComponentHolders(); } else { holders = componentRegistry.getComponentHolders(bundles); } List<ComponentDescriptionDTO> result = new ArrayList<ComponentDescriptionDTO>(holders.size()); for (ComponentHolder<?> holder: holders) { ComponentDescriptionDTO dto = holderToDescription(holder); if ( dto != null ) { result.add(dto); } } return result; } /** * @see org.osgi.service.component.runtime.ServiceComponentRuntime#getComponentDescriptionDTO(org.osgi.framework.Bundle, java.lang.String) */ public ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name) { ComponentHolder<?> holder = componentRegistry.getComponentHolder(bundle, name); if ( holder != null ) { return holderToDescription(holder); } else { return null; } } /** * @see org.osgi.service.component.runtime.ServiceComponentRuntime#getComponentConfigurationDTOs(org.osgi.service.component.runtime.dto.ComponentDescriptionDTO) */ public Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description) { if ( description == null) { return Collections.emptyList(); } try { ComponentHolder<?> holder = getHolderFromDescription( description); // Get a fully filled out valid description DTO description = holderToDescription(holder); if ( description == null) { return Collections.emptyList(); } List<? extends ComponentManager<?>> managers = holder.getComponents(); List<ComponentConfigurationDTO> result = new ArrayList<ComponentConfigurationDTO>(managers.size()); for (ComponentManager<?> manager: managers) { result.add(managerToConfiguration(manager, description)); } return result; } catch ( IllegalStateException ise) { return Collections.emptyList(); } } /** * @see org.osgi.service.component.runtime.ServiceComponentRuntime#isComponentEnabled(org.osgi.service.component.runtime.dto.ComponentDescriptionDTO) */ public boolean isComponentEnabled(ComponentDescriptionDTO description) { try { ComponentHolder<?> holder = getHolderFromDescription( description); return holder.isEnabled(); } catch ( IllegalStateException ise) { return false; } } /** * @see org.osgi.service.component.runtime.ServiceComponentRuntime#enableComponent(org.osgi.service.component.runtime.dto.ComponentDescriptionDTO) */ public Promise<Void> enableComponent(ComponentDescriptionDTO description) { try { ComponentHolder<?> holder = getHolderFromDescription( description); return holder.enableComponents(true); } catch ( IllegalStateException ise) { return Promises.failed(ise); } } /** * @see org.osgi.service.component.runtime.ServiceComponentRuntime#disableComponent(org.osgi.service.component.runtime.dto.ComponentDescriptionDTO) */ public Promise<Void> disableComponent(ComponentDescriptionDTO description) { try { ComponentHolder<?> holder = getHolderFromDescription( description); return holder.disableComponents(true); //synchronous } catch ( IllegalStateException ise) { return Promises.failed(ise); } } private ComponentConfigurationDTO managerToConfiguration(ComponentManager<?> manager, ComponentDescriptionDTO description) { ComponentConfigurationDTO dto = new ComponentConfigurationDTO(); dto.satisfiedReferences = satisfiedRefManagersToDTO(manager.getReferenceManagers()); dto.unsatisfiedReferences = unsatisfiedRefManagersToDTO(manager.getReferenceManagers()); dto.description = description; dto.id = manager.getId(); dto.properties = new HashMap<String, Object>(manager.getProperties());//TODO deep copy? dto.state = manager.getSpecState(); return dto; } private SatisfiedReferenceDTO[] satisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers) { List<SatisfiedReferenceDTO> dtos = new ArrayList<SatisfiedReferenceDTO>(); for (ReferenceManager<?, ?> ref: referenceManagers) { if (ref.isSatisfied()) { SatisfiedReferenceDTO dto = new SatisfiedReferenceDTO(); dto.name = ref.getName(); dto.target = ref.getTarget(); List<ServiceReference<?>> serviceRefs = ref.getServiceReferences(); ServiceReferenceDTO[] srDTOs = new ServiceReferenceDTO[serviceRefs.size()]; int j = 0; for (ServiceReference<?> serviceRef : serviceRefs) { ServiceReferenceDTO srefDTO = serviceReferenceToDTO(serviceRef); if (srefDTO != null) srDTOs[j++] = srefDTO; } dto.boundServices = srDTOs; dtos.add(dto); } } return dtos.toArray( new SatisfiedReferenceDTO[dtos.size()] ); } private UnsatisfiedReferenceDTO[] unsatisfiedRefManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers) { List<UnsatisfiedReferenceDTO> dtos = new ArrayList<UnsatisfiedReferenceDTO>(); for (ReferenceManager<?, ?> ref: referenceManagers) { if (!ref.isSatisfied()) { UnsatisfiedReferenceDTO dto = new UnsatisfiedReferenceDTO(); dto.name = ref.getName(); dto.target = ref.getTarget(); List<ServiceReference<?>> serviceRefs = ref.getServiceReferences(); ServiceReferenceDTO[] srDTOs = new ServiceReferenceDTO[serviceRefs.size()]; int j = 0; for (ServiceReference<?> serviceRef : serviceRefs) { ServiceReferenceDTO srefDTO = serviceReferenceToDTO(serviceRef); if (srefDTO != null) srDTOs[j++] = srefDTO; } dto.targetServices = srDTOs; dtos.add(dto); } } return dtos.toArray( new UnsatisfiedReferenceDTO[dtos.size()] ); } private ServiceReferenceDTO serviceReferenceToDTO( ServiceReference<?> serviceRef) { if (serviceRef == null) return null; ServiceReferenceDTO dto = new ServiceReferenceDTO(); Bundle bundle = serviceRef.getBundle(); if (bundle != null) dto.bundle = bundle.getBundleId(); else dto.bundle = -1; // No bundle ever has -1 as ID, so this indicates no bundle. 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; } /** * Return the component holder * @param description Component description DTO * @return The component holder * @throws IllegalStateException If the bundle is not active anymore */ private ComponentHolder<?> getHolderFromDescription(ComponentDescriptionDTO description) { if (description.bundle == null) { throw new IllegalArgumentException("No bundle supplied in ComponentDescriptionDTO named " + description.name); } long bundleId = description.bundle.id; Bundle b = context.getBundle(bundleId); String name = description.name; return componentRegistry.getComponentHolder(b, name); } private ComponentDescriptionDTO holderToDescription( ComponentHolder<?> holder ) { ComponentDescriptionDTO dto = new ComponentDescriptionDTO(); ComponentMetadata m = holder.getComponentMetadata(); dto.activate = m.getActivate(); dto.bundle = bundleToDTO(holder.getActivator().getBundleContext()); // immediately return if bundle is not active anymore if ( dto.bundle == null ) { return null; } dto.configurationPid = m.getConfigurationPid().toArray(new String[m.getConfigurationPid().size()]); dto.configurationPolicy = m.getConfigurationPolicy(); dto.deactivate = m.getDeactivate(); dto.defaultEnabled = m.isEnabled(); dto.factory = m.getFactoryIdentifier(); dto.immediate = m.isImmediate(); dto.implementationClass = m.getImplementationClassName(); dto.modified = m.getModified(); dto.name = m.getName(); 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 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) { ReferenceDTO dto = new ReferenceDTO(); dto.bind = r.getBind(); dto.cardinality = r.getCardinality(); dto.field = r.getField(); dto.fieldOption = r.getFieldOption(); dto.interfaceName = r.getInterface(); dto.name = r.getName(); dto.policy = r.getPolicy(); dto.policyOption = r.getPolicyOption(); dto.scope = r.getScope().name(); dto.target = r.getTarget(); dto.unbind = r.getUnbind(); dto.updated = r.getUpdated(); dtos[i++] = dto; } return dtos; } private BundleDTO bundleToDTO(BundleContext bundleContext) { if (bundleContext == null) { return null; } try { Bundle bundle = bundleContext.getBundle(); if (bundle == null) { return null; } BundleDTO b = new BundleDTO(); b.id = bundle.getBundleId(); b.lastModified = bundle.getLastModified(); b.state = bundle.getState(); b.symbolicName = bundle.getSymbolicName(); b.version = bundle.getVersion().toString(); return b; } catch (IllegalStateException e) { return null; } } }