blob: 70465b3936de2dd998f331fd19311183bc02f76c [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.scr.impl.compat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import org.apache.felix.scr.Component;
import org.apache.felix.scr.Reference;
import org.apache.felix.scr.ScrService;
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.dto.ServiceReferenceDTO;
import org.osgi.service.component.ComponentInstance;
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;
public class ScrServiceImpl implements ScrService
{
private static final String[] EMPTY = {};
private final BundleContext context;
private final ServiceComponentRuntime runtime;
public ScrServiceImpl(BundleContext context, final ServiceComponentRuntime runtime)
{
// we always use the system bundle to avoid problems if subsystems etc.
// are used and the SCR implemented extends those "invisible" bundles
this.context = context.getBundle(0).getBundleContext();
this.runtime = runtime;
}
// ScrService
/**
* @see org.apache.felix.scr.ScrService#getComponents()
*/
public Component[] getComponents()
{
return this.getComponents((Bundle)null);
}
/**
* @see org.apache.felix.scr.ScrService#getComponents(org.osgi.framework.Bundle)
*/
public Component[] getComponents( final Bundle bundle )
{
List<Component> result = new ArrayList<Component>();
final Collection<ComponentDescriptionDTO> descriptions = (bundle == null ? this.runtime.getComponentDescriptionDTOs() : this.runtime.getComponentDescriptionDTOs(bundle));
for(final ComponentDescriptionDTO descDTO : descriptions )
{
final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
ComponentConfigurationDTO configDTO = null;
if ( !configs.isEmpty() )
{
configDTO = configs.iterator().next();
}
result.add(new ComponentWrapper(this.context, this.runtime, descDTO, configDTO));
}
return result.isEmpty() ? null : result.toArray( new Component[result.size()] );
}
/**
* @see org.apache.felix.scr.ScrService#getComponent(long)
*/
public Component getComponent( long componentId )
{
final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs();
for(final ComponentDescriptionDTO descDTO : descriptions )
{
final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
for(final ComponentConfigurationDTO configDTO : configs)
{
if ( configDTO.id == componentId )
{
return new ComponentWrapper(this.context, this.runtime, descDTO, configDTO);
}
}
}
return null;
}
/**
* @see org.apache.felix.scr.ScrService#getComponents(java.lang.String)
*/
public Component[] getComponents( final String componentName )
{
List<Component> result = new ArrayList<Component>();
final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs();
for(final ComponentDescriptionDTO descDTO : descriptions )
{
if ( descDTO.name.equals(componentName) ) {
final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
ComponentConfigurationDTO configDTO = null;
if ( !configs.isEmpty() )
{
configDTO = configs.iterator().next();
}
result.add(new ComponentWrapper(this.context, this.runtime, descDTO, configDTO));
}
}
return result.isEmpty() ? null : result.toArray( new Component[result.size()] );
}
private static final class ComponentWrapper implements Component
{
private final ComponentDescriptionDTO description;
private final ComponentConfigurationDTO configuration;
private final BundleContext bundleContext;
private final ServiceComponentRuntime runtime;
public ComponentWrapper(final BundleContext bundleContext,
final ServiceComponentRuntime runtime,
final ComponentDescriptionDTO description,
final ComponentConfigurationDTO configuration)
{
this.bundleContext = bundleContext;
this.description = description;
this.configuration = configuration;
this.runtime = runtime;
}
public long getId()
{
return configuration != null ? configuration.id : -1;
}
public String getName()
{
return description.name;
}
public int getState()
{
if ( configuration == null )
{
return Component.STATE_UNSATISFIED; // TODO Check!
}
final int s = configuration.state;
switch ( s )
{
case ComponentConfigurationDTO.ACTIVE : return Component.STATE_ACTIVE;
case ComponentConfigurationDTO.SATISFIED : return Component.STATE_ENABLED;
case ComponentConfigurationDTO.UNSATISFIED_CONFIGURATION : return Component.STATE_UNSATISFIED;
case ComponentConfigurationDTO.UNSATISFIED_REFERENCE : return Component.STATE_UNSATISFIED;
default: // satisfied
return Component.STATE_ENABLED;
}
}
public Bundle getBundle()
{
return this.bundleContext.getBundle(this.description.bundle.id);
}
public String getFactory()
{
return this.description.factory;
}
public boolean isServiceFactory()
{
return !"singleton".equals(this.description.scope);
}
public String getClassName()
{
return this.description.implementationClass;
}
public boolean isDefaultEnabled()
{
return this.description.defaultEnabled;
}
public boolean isImmediate()
{
return this.description.immediate;
}
public String[] getServices()
{
return this.description.serviceInterfaces.length == 0 ? null : this.description.serviceInterfaces;
}
public Dictionary getProperties()
{
return new Hashtable<String, Object>(this.description.properties);
}
public Reference[] getReferences()
{
if ( this.configuration == null )
{
return null;
}
final List<Reference> result = new ArrayList<Reference>();
for(final ReferenceDTO dto : this.description.references)
{
SatisfiedReferenceDTO sRef = null;
for(final SatisfiedReferenceDTO r : this.configuration.satisfiedReferences)
{
if ( r.name.equals(dto.name) )
{
sRef = r;
break;
}
}
result.add(new ReferenceWrapper(this.bundleContext, dto, sRef));
}
if ( result.isEmpty() )
{
return null;
}
return result.toArray(new Reference[result.size()]);
}
public ComponentInstance getComponentInstance()
{
// returning null as we should have never returned this in the first place
return null;
}
public String getActivate()
{
return this.description.activate;
}
public boolean isActivateDeclared()
{
return this.description.activate != null;
}
public String getDeactivate()
{
return this.description.deactivate;
}
public boolean isDeactivateDeclared()
{
return this.description.deactivate != null;
}
public String getModified()
{
return this.description.modified;
}
public String getConfigurationPolicy()
{
return this.description.configurationPolicy;
}
public String getConfigurationPid()
{
final String[] pids = this.description.configurationPid;
return pids[0];
}
public boolean isConfigurationPidDeclared()
{
return true;
}
public void enable()
{
// noop as the old model was broken
}
public void disable()
{
// noop as the old model was broken
}
}
private static final class ReferenceWrapper implements Reference
{
// constant for option single reference - 0..1
private static final String CARDINALITY_0_1 = "0..1";
// constant for option multiple reference - 0..n
private static final String CARDINALITY_0_N = "0..n";
// constant for required multiple reference - 1..n
private static final String CARDINALITY_1_N = "1..n";
// constant for static policy
private static final String POLICY_STATIC = "static";
// constant for reluctant policy option
private static final String POLICY_OPTION_RELUCTANT = "reluctant";
private final ReferenceDTO dto;
private final SatisfiedReferenceDTO satisfiedDTO;
private final BundleContext bundleContext;
public ReferenceWrapper(
final BundleContext bundleContext,
final ReferenceDTO dto,
final SatisfiedReferenceDTO satisfied)
{
this.bundleContext = bundleContext;
this.dto = dto;
this.satisfiedDTO = satisfied;
}
public String getName()
{
return dto.name;
}
public String getServiceName()
{
return dto.interfaceName;
}
public ServiceReference[] getServiceReferences()
{
if ( this.satisfiedDTO == null )
{
return null;
}
final List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>();
for(ServiceReferenceDTO dto : this.satisfiedDTO.boundServices)
{
try
{
final ServiceReference<?>[] serviceRefs = this.bundleContext.getServiceReferences((String)null,
"(" + Constants.SERVICE_ID + "=" + String.valueOf(dto.id) + ")");
if ( serviceRefs != null && serviceRefs.length > 0 )
{
refs.add(serviceRefs[0]);
}
}
catch ( final InvalidSyntaxException ise)
{
// ignore
}
}
return refs.toArray(new ServiceReference<?>[refs.size()]);
}
public ServiceReference<?>[] getBoundServiceReferences()
{
return this.getServiceReferences();
}
public boolean isSatisfied()
{
return this.satisfiedDTO != null;
}
public boolean isOptional()
{
return CARDINALITY_0_1.equals(dto.cardinality) || CARDINALITY_0_N.equals(dto.cardinality);
}
public boolean isMultiple()
{
return CARDINALITY_1_N.equals(dto.cardinality) || CARDINALITY_0_N.equals(dto.cardinality);
}
public boolean isStatic()
{
return POLICY_STATIC.equals(dto.policy);
}
public boolean isReluctant()
{
return POLICY_OPTION_RELUCTANT.equals(dto.policyOption);
}
public String getTarget()
{
return this.dto.target;
}
public String getBindMethodName()
{
return this.dto.bind;
}
public String getUnbindMethodName()
{
return this.dto.unbind;
}
public String getUpdatedMethodName()
{
return this.dto.unbind;
}
}
}