| /* |
| * 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.config; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Dictionary; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.felix.scr.Component; |
| import org.apache.felix.scr.impl.Activator; |
| import org.apache.felix.scr.impl.BundleComponentActivator; |
| import org.apache.felix.scr.impl.TargetedPID; |
| import org.apache.felix.scr.impl.helper.ComponentMethods; |
| import org.apache.felix.scr.impl.helper.SimpleLogger; |
| import org.apache.felix.scr.impl.manager.SingleComponentManager; |
| import org.apache.felix.scr.impl.manager.ServiceFactoryComponentManager; |
| import org.apache.felix.scr.impl.metadata.ComponentMetadata; |
| import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope; |
| import org.osgi.service.component.ComponentConstants; |
| import org.osgi.service.log.LogService; |
| |
| |
| /** |
| * The <code>ImmediateComponentHolder</code> class is a |
| * {@link ComponentHolder} for automatically configured components instances |
| * that may or may not be configured through Config Admin. |
| * <p> |
| * The holder copes with three situations: |
| * <ul> |
| * <li>No configuration is available for the held component. That is there is |
| * no configuration whose <code>service.pid</code> or |
| * <code>service.factoryPid</code> equals the component name.</li> |
| * <li>A singleton configuration is available whose <code>service.pid</code> |
| * equals the component name.</li> |
| * <li>One or more factory configurations exist whose |
| * <code>service.factoryPid</code> equals the component name.</li> |
| * </ul> |
| */ |
| public class ConfigurableComponentHolder<S> implements ComponentHolder<S>, SimpleLogger |
| { |
| |
| /** |
| * The activator owning the per-bundle components |
| */ |
| private final BundleComponentActivator m_activator; |
| |
| /** |
| * The {@link ComponentMetadata} describing the held component(s) |
| */ |
| private final ComponentMetadata m_componentMetadata; |
| |
| /** the targeted pids corresponding to the pids specified in the config metadata, except possibly for the single |
| * factory pid |
| */ |
| private final List<TargetedPID> m_targetedPids; |
| |
| private final List<Long> m_changeCount; |
| |
| private final Map<String, Long> m_factoryChangeCount = new HashMap<String, Long>(); |
| |
| /** |
| * the index in metadata.getConfigurationPid() of the base factory pid, if any. Each component created from a factory configuration |
| * might have a different targeted pid. |
| */ |
| private Integer m_factoryPidIndex; |
| |
| /** |
| * the non-factory configurations shared between all instances. |
| */ |
| private final List<Dictionary<String, Object>> m_configurations; |
| |
| /** |
| * the factory configurations indexed by pid (which cannot be a TargetedPID since it's generated by CA). We have to track these since |
| * other required configs may not yet be present so we can't create the component manager yet. |
| */ |
| private final Map<String, Dictionary<String, Object>> m_factoryConfigurations = new HashMap<String, Dictionary<String, Object>>(); |
| |
| /** |
| * Each factory config may be from a different TargetedPID (sharing the same base service pid, but with different level of detail) |
| */ |
| private final Map<String, TargetedPID> m_factoryTargetedPids = new HashMap<String, TargetedPID>(); |
| /** |
| * A map of components configured with factory configuration. The indices |
| * are the PIDs (<code>service.pid</code>) of the configuration objects. |
| * The values are the {@link SingleComponentManager<S> component instances} |
| * created on behalf of the configurations. |
| */ |
| private final Map<String, SingleComponentManager<S>> m_components; |
| |
| /** |
| * The special component used if there is no configuration or a singleton |
| * configuration. This field is only <code>null</code> once all components |
| * held by this holder have been disposed of by |
| * {@link #disposeComponents(int)} and is first created in the constructor. |
| * As factory configurations are provided this instance may be configured |
| * or "deconfigured". |
| * <p> |
| * Expected invariants: |
| * <ul> |
| * <li>This field is only <code>null</code> after disposal of all held |
| * components</li> |
| * <li>The {@link #m_components} map is empty or the component pointed to |
| * by this field is also contained in the map</li> |
| * <ul> |
| */ |
| private SingleComponentManager<S> m_singleComponent; |
| |
| /** |
| * Whether components have already been enabled by calling the |
| * {@link #enableComponents(boolean)} method. If this field is <code>true</code> |
| * component instances created per configuration by the |
| * {@link #configurationUpdated(TargetedPID, TargetedPID, Dictionary, long)} method are also |
| * enabled. Otherwise they are not enabled immediately. |
| */ |
| private volatile boolean m_enabled; |
| |
| private final ComponentMethods m_componentMethods; |
| |
| public ConfigurableComponentHolder( final BundleComponentActivator activator, final ComponentMetadata metadata ) |
| { |
| this.m_activator = activator; |
| this.m_componentMetadata = metadata; |
| int pidCount = metadata.getConfigurationPid().size(); |
| this.m_targetedPids = new ArrayList<TargetedPID>(pidCount); |
| this.m_configurations = new ArrayList<Dictionary<String, Object>>(pidCount); |
| this.m_changeCount = new ArrayList<Long>(pidCount); |
| for (int i = 0; i < pidCount; i++) |
| { |
| m_targetedPids.add(null); |
| m_configurations.add(null); |
| m_changeCount.add(null); |
| } |
| this.m_components = new HashMap<String, SingleComponentManager<S>>(); |
| this.m_componentMethods = new ComponentMethods(); |
| this.m_enabled = false; |
| } |
| |
| protected SingleComponentManager<S> createComponentManager() |
| { |
| |
| SingleComponentManager<S> manager; |
| if ( m_componentMetadata.isFactory() ) |
| { |
| throw new IllegalArgumentException( "Cannot create component factory for " + m_componentMetadata.getName() ); |
| } |
| else if ( m_componentMetadata.getServiceScope() == Scope.bundle ) |
| { |
| manager = new ServiceFactoryComponentManager<S>( m_activator, this, m_componentMetadata, m_componentMethods ); |
| } |
| |
| else if ( m_componentMetadata.getServiceScope() == Scope.prototype ) |
| { |
| manager = null;// NYI |
| // manager = new ServiceFactoryComponentManager<S>( m_activator, this, m_componentMetadata, m_componentMethods ); |
| } |
| |
| else |
| { |
| //immediate or delayed |
| manager = new SingleComponentManager<S>( m_activator, this, m_componentMetadata, m_componentMethods ); |
| } |
| |
| return manager; |
| } |
| |
| |
| public final BundleComponentActivator getActivator() |
| { |
| return m_activator; |
| } |
| |
| |
| public final ComponentMetadata getComponentMetadata() |
| { |
| return m_componentMetadata; |
| } |
| |
| |
| /** |
| * The configuration with the given <code>pid</code> |
| * (<code>service.pid</code> of the configuration object) is deleted. |
| * <p> |
| * The following situations are supported: |
| * <ul> |
| * <li>The configuration was a singleton configuration (pid equals the |
| * component name). In this case the internal component map is empty and |
| * the single component has been configured by the singleton configuration |
| * and is no "deconfigured".</li> |
| * <li>A factory configuration object has been deleted and the configured |
| * object is set as the single component. If the single component held the |
| * last factory configuration object, it is deconfigured. Otherwise the |
| * single component is disposed off and replaced by another component in |
| * the map of existing components.</li> |
| * <li>A factory configuration object has been deleted and the configured |
| * object is not set as the single component. In this case the component is |
| * simply disposed off and removed from the internal map.</li> |
| * </ul> |
| */ |
| public void configurationDeleted( final String pid ) |
| { |
| log( LogService.LOG_DEBUG, "ImmediateComponentHolder configuration deleted for pid {0}", |
| new Object[] {pid}, null); |
| |
| // component to deconfigure or dispose of |
| final SingleComponentManager icm; |
| boolean deconfigure = false; |
| |
| synchronized ( m_components ) |
| { |
| // FELIX-2231: nothing to do any more, all components have been disposed off |
| if (m_singleComponent == null) |
| { |
| return; |
| } |
| |
| if ( pid.equals( getComponentMetadata().getConfigurationPid() ) ) |
| { |
| // singleton configuration has pid equal to component name |
| icm = m_singleComponent; |
| deconfigure = true; |
| } |
| else |
| { |
| // remove the component configured with the deleted configuration |
| icm = m_components.remove( pid ); |
| if ( icm == null ) |
| { |
| // we already removed the component with the deleted configuration |
| return; |
| } |
| |
| // special casing if the single component is deconfigured |
| if ( m_singleComponent == icm ) |
| { |
| |
| // if the single component is the last remaining, deconfig |
| if ( m_components.isEmpty() ) |
| { |
| |
| // if the single component is the last remaining |
| // deconfigure it |
| deconfigure = true; |
| |
| } |
| else |
| { |
| |
| // replace the single component field with another |
| // entry from the map |
| m_singleComponent = m_components.values().iterator().next(); |
| |
| } |
| } |
| } |
| } |
| |
| // icm may be null if the last configuration deleted was the |
| // single component's configuration. Otherwise the component |
| // is not the "last" and has to be disposed off |
| if ( deconfigure ) |
| { |
| icm.reconfigure( null ); |
| } |
| else |
| { |
| icm.dispose( ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED ); |
| } |
| } |
| |
| |
| /** |
| * Configures a component with the given configuration. This configuration |
| * update may happen in various situations: |
| * <ul> |
| * <li>The <code>pid</code> equals the component name. Hence we have a |
| * singleton configuration for the single component held by this holder</li> |
| * <li>The configuration is a factory configuration and is the first |
| * configuration provided. In this case the single component is provided |
| * with the configuration and also stored in the map.</li> |
| * <li>The configuration is a factory configuration but not the first. In |
| * this case a new component is created, configured and stored in the map</li> |
| * </ul> |
| * @return true if a new configuration was created, false otherwise. //TODO there are now 3 states..... still not satisfied, existing, and new |
| */ |
| public boolean configurationUpdated( TargetedPID pid, TargetedPID factoryPid, final Dictionary<String, Object> props, long changeCount ) |
| { |
| log( LogService.LOG_DEBUG, "ConfigurableComponentHolder configuration updated for pid {0} with properties {1}", |
| new Object[] {pid, props}, null); |
| |
| // component to update or create |
| final SingleComponentManager scm; |
| final String message; |
| Object[] notEnabledArguments = null; |
| boolean created = false; |
| |
| Map<String, Object> properties; |
| //TODO better change count tracking |
| synchronized (m_components) { |
| //Find or create the component manager, or return if not satisfied. |
| if (factoryPid != null) { |
| int index = m_componentMetadata.getPidIndex(factoryPid); |
| if (index == -1) { |
| log(LogService.LOG_ERROR, |
| "Unrecognized factory pid {0], expected one of {1}", |
| new Object[] { factoryPid, |
| m_componentMetadata.getConfigurationPid() }, |
| null); |
| throw new IllegalArgumentException( |
| "Unrecognized factory pid " + factoryPid); |
| } |
| if (m_configurations.get(index) != null) { |
| log(LogService.LOG_ERROR, |
| "factory pid {0], but this pids already supplied as a singleton: {1}", |
| new Object[] { factoryPid, m_targetedPids }, null); |
| throw new IllegalStateException( |
| "Factory pid supplied after all non-factory configurations supplied " |
| + factoryPid); |
| } |
| if (m_factoryPidIndex == null) { |
| m_factoryPidIndex = index; |
| } else if (index != m_factoryPidIndex) { |
| log(LogService.LOG_ERROR, |
| "factory pid {0] supplied for index {1}, but a factory pid previously supplied at index {2}", |
| new Object[] { factoryPid, index, m_factoryPidIndex }, |
| null); |
| throw new IllegalStateException( |
| "Factory pid supplied at wrong index " + factoryPid); |
| } |
| m_factoryConfigurations.put(pid.getServicePid(), props); |
| m_factoryTargetedPids.put(pid.getServicePid(), factoryPid); |
| m_factoryChangeCount.put(pid.getServicePid(), changeCount); |
| if (isSatisfied()) { |
| if (m_singleComponent != null) { |
| scm = m_singleComponent; |
| m_singleComponent = null; |
| m_components.put(pid.getServicePid(), scm); |
| } else if (m_components.containsKey(pid.getServicePid())) { |
| scm = m_components.get(pid.getServicePid()); |
| } else { |
| scm = createComponentManager(); |
| m_components.put(pid.getServicePid(), scm); |
| created = true; |
| } |
| } else { |
| return created; //still false |
| } |
| |
| } else { |
| //singleton pid |
| int index = m_componentMetadata.getPidIndex(pid); |
| if (index == -1) { |
| log(LogService.LOG_ERROR, |
| "Unrecognized pid {0], expected one of {1}", |
| new Object[] { pid, |
| m_componentMetadata.getConfigurationPid() }, |
| null); |
| throw new IllegalArgumentException("Unrecognized pid " |
| + pid); |
| } |
| if (m_factoryPidIndex != null && index == m_factoryPidIndex) { |
| log(LogService.LOG_ERROR, |
| "singleton pid {0] supplied, but matches an existing factory pid at index: {1}", |
| new Object[] { pid, m_factoryPidIndex }, null); |
| throw new IllegalStateException( |
| "Singleton pid supplied matching a previous factory pid " |
| + pid); |
| } |
| m_targetedPids.set(index, pid); |
| m_changeCount.set(index, changeCount); |
| m_configurations.set(index, props); |
| if (isSatisfied()) { |
| if (m_singleComponent != null) { |
| scm = m_singleComponent; |
| } else { |
| m_singleComponent = createComponentManager(); |
| scm = m_singleComponent; |
| created = true; |
| } |
| } else { |
| return created; //false |
| } |
| |
| } |
| properties = new HashMap<String, Object>(); |
| copyTo(properties, m_componentMetadata.getProperties()); |
| for (int i = 0; i < m_configurations.size(); i++) |
| { |
| if ( m_factoryPidIndex != null && i == m_factoryPidIndex) |
| { |
| copyTo(properties, props); |
| } |
| else if ( m_configurations.get(i) != null ) |
| { |
| copyTo(properties, m_configurations.get(i)); |
| } |
| } |
| |
| } |
| |
| |
| // we have the icm. |
| //properties is all the configs merged together (without any possible component factory info. |
| // synchronized ( m_components ) |
| // { |
| // // FELIX-2231: nothing to do any more, all components have been disposed off |
| // if (m_singleComponent == null) |
| // { |
| // return false; |
| // } |
| // |
| // if ( pid.equals( getComponentMetadata().getConfigurationPid() ) ) |
| // { |
| // // singleton configuration has pid equal to component name |
| // scm = m_singleComponent; |
| // message = "ImmediateComponentHolder reconfiguring single component for pid {0} "; |
| // enable = false; |
| // } |
| // else |
| // { |
| // final SingleComponentManager existingIcm = m_components.get( pid ); |
| // if ( existingIcm != null ) |
| // { |
| // // factory configuration updated for existing component instance |
| // scm = existingIcm; |
| // message = "ImmediateComponentHolder reconfiguring existing component for pid {0} "; |
| // enable = false; |
| // } |
| // else |
| // { |
| // // factory configuration created |
| // created = true; |
| // if ( !m_singleComponent.hasConfiguration() ) |
| // { |
| // // configure the single instance if this is not configured |
| // scm = m_singleComponent; |
| // message = "ImmediateComponentHolder configuring the unconfigured single component for pid {0} "; |
| // } |
| // else |
| // { |
| // // otherwise create a new instance to provide the config to |
| // scm = createComponentManager(); |
| // message = "ImmediateComponentHolder configuring a new component for pid {0} "; |
| // } |
| // |
| // // enable the component if it is initially enabled |
| // if ( m_enabled && getComponentMetadata().isEnabled() ) |
| // { |
| // enable = true; |
| // } |
| // else |
| // { |
| // enable = false; |
| // notEnabledArguments = new Object[] {pid, m_enabled, getComponentMetadata().isEnabled()}; |
| // } |
| // |
| // // store the component in the map |
| // m_components.put( pid, scm ); |
| // } |
| // } |
| // } |
| // log( LogService.LOG_DEBUG, message, new Object[] {pid}, null); |
| |
| final boolean enable = created && m_enabled && getComponentMetadata().isEnabled(); |
| // configure the component |
| scm.reconfigure( properties ); |
| log( LogService.LOG_DEBUG, "ImmediateComponentHolder Finished configuring the dependency managers for component for pid {0} ", |
| new Object[] {pid}, null ); |
| |
| if (enable) |
| { |
| scm.enable( false ); |
| log( LogService.LOG_DEBUG, "ImmediateComponentHolder Finished enabling component for pid {0} ", |
| new Object[] {pid}, null ); |
| } |
| else |
| { |
| log( LogService.LOG_DEBUG, "ImmediateComponentHolder Will not enable component for pid {0}: holder enabled state: {1}, metadata enabled: {2} ", |
| new Object[] { pid, m_enabled, m_componentMetadata.isEnabled()}, null ); |
| } |
| return created; |
| } |
| |
| protected static void copyTo( Map<String, Object> target, Dictionary<String, ?> source ) |
| { |
| |
| for ( Enumeration<String> keys = source.keys(); keys.hasMoreElements(); ) |
| { |
| String key = keys.nextElement(); |
| Object value = source.get(key); |
| target.put(key, value); |
| } |
| } |
| |
| /** |
| * Determine if the holder is satisfied with configurations |
| * @return true if configuration optional or all pids supplied with configurations |
| */ |
| private boolean isSatisfied() { |
| if ( m_componentMetadata.isConfigurationOptional()) |
| { |
| return true; |
| } |
| boolean satisfied = true; |
| for ( int i = 0; i < m_componentMetadata.getConfigurationPid().size(); i++) |
| { |
| if ( m_configurations.get(i) != null) |
| { |
| continue; |
| } |
| if ( m_factoryPidIndex != null && m_factoryPidIndex == i) |
| { |
| continue; |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * @param pid the Targeted PID we need the change count for |
| * @return pid for this service pid. |
| */ |
| public long getChangeCount( TargetedPID pid) |
| { |
| int index = m_componentMetadata.getPidIndex(pid); |
| Long result; |
| if ( index == -1 ) |
| { |
| throw new IllegalArgumentException("pid not recognized as for this component: " + pid); |
| } |
| if ( m_factoryPidIndex != null && index == m_factoryPidIndex ) |
| { |
| result = m_factoryChangeCount.get(pid.getServicePid()); |
| } |
| else |
| { |
| result = m_changeCount.get(index); |
| } |
| return result == null? -1: result; |
| |
| } |
| |
| public List<? extends Component> getComponents() |
| { |
| synchronized ( m_components ) |
| { |
| return getComponentManagers( false ); |
| } |
| } |
| |
| |
| public void enableComponents( final boolean async ) |
| { |
| List<SingleComponentManager<S>> cms; |
| synchronized ( m_components ) |
| { |
| if (m_singleComponent == null && m_factoryPidIndex == null && |
| (m_componentMetadata.isConfigurationIgnored() || m_componentMetadata.isConfigurationOptional())) |
| { |
| m_singleComponent = createComponentManager(); |
| } |
| m_enabled = true; |
| cms = getComponentManagers( false ); |
| } |
| for ( SingleComponentManager<S> cm : cms ) |
| { |
| cm.enable( async ); |
| } |
| } |
| |
| |
| public void disableComponents( final boolean async ) |
| { |
| List<SingleComponentManager<S>> cms; |
| synchronized ( m_components ) |
| { |
| m_enabled = false; |
| |
| cms = getComponentManagers( false ); |
| if (m_singleComponent != null && m_factoryPidIndex == null && |
| (m_componentMetadata.isConfigurationIgnored() || m_componentMetadata.isConfigurationOptional())) |
| { |
| m_singleComponent = null; |
| } |
| } |
| for ( SingleComponentManager<S> cm : cms ) |
| { |
| cm.disable( async ); |
| } |
| } |
| |
| |
| public void disposeComponents( final int reason ) |
| { |
| List<SingleComponentManager<S>> cms; |
| synchronized ( m_components ) |
| { |
| cms = getComponentManagers( true ); |
| } |
| for ( SingleComponentManager cm : cms ) |
| { |
| cm.dispose( reason ); |
| } |
| } |
| |
| |
| public void disposed( SingleComponentManager component ) |
| { |
| // ensure the component is removed from the components map |
| synchronized ( m_components ) |
| { |
| if ( !m_components.isEmpty() ) |
| { |
| for ( Iterator vi = m_components.values().iterator(); vi.hasNext(); ) |
| { |
| if ( component == vi.next() ) |
| { |
| vi.remove(); |
| break; |
| } |
| } |
| } |
| |
| // if the component is the single component, we have to replace it |
| // by another entry in the map |
| if ( component == m_singleComponent ) |
| { |
| if ( m_components.isEmpty() ) |
| { |
| // now what ?? |
| // is it correct to create a new manager ??? |
| m_singleComponent = createComponentManager(); |
| } |
| else |
| { |
| m_singleComponent = m_components.values().iterator().next(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Compares this {@code ImmediateComponentHolder} object to another object. |
| * |
| * <p> |
| * A ImmediateComponentHolder is considered to be <b>equal to </b> another |
| * ImmediateComponentHolder if the component names are equal(using |
| * {@code String.equals}) and they have the same bundle activator |
| * |
| * @param object The {@code ImmediateComponentHolder} object to be compared. |
| * @return {@code true} if {@code object} is a |
| * {@code ImmediateComponentHolder} and is equal to this object; |
| * {@code false} otherwise. |
| */ |
| public boolean equals(Object object) |
| { |
| if (!(object instanceof ConfigurableComponentHolder)) |
| { |
| return false; |
| } |
| |
| ConfigurableComponentHolder other = (ConfigurableComponentHolder) object; |
| return m_activator == other.m_activator |
| && getName().equals(other.getName()); |
| } |
| |
| /** |
| * Returns a hash code value for the object. |
| * |
| * @return An integer which is a hash code value for this object. |
| */ |
| @Override |
| public int hashCode() |
| { |
| return getName().hashCode(); |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "[ImmediateComponentHolder:" + getName() + "]"; |
| } |
| |
| String getName() |
| { |
| return m_componentMetadata.getName(); |
| } |
| |
| //---------- internal |
| |
| /** |
| * Returns all component managers from the map and the single component manager, optionally also removing them |
| * from the map. If there are no component managers, <code>null</code> |
| * is returned. Must be called synchronized on m_components. |
| * |
| * @param clear If true, clear the map and the single component manager. |
| */ |
| List<SingleComponentManager<S>> getComponentManagers( final boolean clear ) |
| { |
| List<SingleComponentManager<S>> cm; |
| if ( m_components.isEmpty() ) |
| { |
| if ( m_singleComponent != null) |
| { |
| cm = Collections.singletonList(m_singleComponent); |
| } |
| else |
| { |
| cm = Collections.emptyList(); |
| } |
| } |
| |
| else |
| { |
| cm = new ArrayList<SingleComponentManager<S>>(m_components.values()); |
| } |
| if ( clear ) |
| { |
| m_components.clear(); |
| m_singleComponent = null; |
| } |
| return cm; |
| } |
| |
| public boolean isLogEnabled( int level ) |
| { |
| return Activator.isLogEnabled( level ); |
| } |
| |
| public void log( int level, String message, Throwable ex ) |
| { |
| BundleComponentActivator activator = getActivator(); |
| if ( activator != null ) |
| { |
| activator.log( level, message, getComponentMetadata(), null, ex ); |
| } |
| } |
| |
| public void log( int level, String message, Object[] arguments, Throwable ex ) |
| { |
| BundleComponentActivator activator = getActivator(); |
| if ( activator != null ) |
| { |
| activator.log( level, message, arguments, getComponentMetadata(), null, ex ); |
| } |
| } |
| |
| public TargetedPID getConfigurationTargetedPID(TargetedPID pid, TargetedPID factoryPid) |
| { |
| if ( factoryPid == null ) |
| { |
| int index = m_componentMetadata.getPidIndex(pid); |
| if (index != -1) |
| { |
| return m_targetedPids.get(index); |
| } |
| return null; |
| } |
| //each factory configured component may have a different factory targeted pid. |
| synchronized (m_components) |
| { |
| return m_factoryTargetedPids.get(pid.getServicePid()); |
| } |
| } |
| |
| } |