Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 90323 invoked from network); 28 Jul 2009 14:06:11 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 28 Jul 2009 14:06:11 -0000 Received: (qmail 40220 invoked by uid 500); 28 Jul 2009 14:07:28 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 40178 invoked by uid 500); 28 Jul 2009 14:07:28 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 40169 invoked by uid 99); 28 Jul 2009 14:07:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 Jul 2009 14:07:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 Jul 2009 14:07:21 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 9F00C2388878; Tue, 28 Jul 2009 14:06:59 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r798531 - in /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl: ./ config/ manager/ metadata/ Date: Tue, 28 Jul 2009 14:06:59 -0000 To: commits@felix.apache.org From: fmeschbe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090728140659.9F00C2388878@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: fmeschbe Date: Tue Jul 28 14:06:58 2009 New Revision: 798531 URL: http://svn.apache.org/viewvc?rev=798531&view=rev Log: FELIX-1416 Implement new ComponentHolder abstraction and adapt uses. Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java (with props) felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java (with props) felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java (with props) felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java (with props) felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java (with props) felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java (with props) Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java Tue Jul 28 14:06:58 2009 @@ -26,6 +26,7 @@ import java.util.Iterator; import java.util.Map; +import org.apache.felix.scr.impl.config.ConfigurationComponentRegistry; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -78,7 +79,7 @@ { m_context = context; m_componentBundles = new HashMap(); - m_componentRegistry = new ComponentRegistry( m_context ); + m_componentRegistry = createComponentRegistry( context); // require the log service m_logService = new ServiceTracker( context, LOGSERVICE_CLASS, null ); @@ -135,7 +136,7 @@ // 112.8.2 dispose off all active components disposeAllComponents(); - // dispose off the component registry + // dispose component registry m_componentRegistry.dispose(); // terminate the actor thread and wait for it for a limited time @@ -293,6 +294,22 @@ } + public static ComponentRegistry createComponentRegistry( BundleContext bundleContext ) + { + try + { + return new ConfigurationComponentRegistry( bundleContext ); + } + catch ( Throwable t ) + { + log( LogService.LOG_INFO, bundleContext.getBundle(), + "ConfigurationAdmin supporting ComponentRegistry not available, not using ConfigurationAdmin", t ); + } + + return new ComponentRegistry( bundleContext ); + } + + /** * Returns the BundleContext of the bundle. *

@@ -426,7 +443,7 @@ * @param ex An optional Throwable whose stack trace is written, * or null to not log a stack trace. */ - static void log( int level, Bundle bundle, String message, Throwable ex ) + public static void log( int level, Bundle bundle, String message, Throwable ex ) { if ( m_logLevel >= level ) { Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java Tue Jul 28 14:06:58 2009 @@ -29,17 +29,13 @@ import java.util.List; import java.util.StringTokenizer; +import org.apache.felix.scr.impl.config.ComponentHolder; import org.apache.felix.scr.impl.helper.Logger; import org.apache.felix.scr.impl.manager.AbstractComponentManager; -import org.apache.felix.scr.impl.manager.ComponentFactoryImpl; -import org.apache.felix.scr.impl.manager.DelayedComponentManager; -import org.apache.felix.scr.impl.manager.ImmediateComponentManager; -import org.apache.felix.scr.impl.manager.ServiceFactoryComponentManager; import org.apache.felix.scr.impl.metadata.ComponentMetadata; import org.apache.felix.scr.impl.metadata.XmlHandler; import org.apache.felix.scr.impl.parser.KXml2SAXParser; import org.osgi.framework.BundleContext; -import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentException; import org.osgi.service.log.LogService; import org.osgi.util.tracker.ServiceTracker; @@ -62,9 +58,6 @@ private List m_managers = new ArrayList(); // The Configuration Admin tracker providing configuration for components - private ServiceTracker m_configurationAdmin; - - // The Configuration Admin tracker providing configuration for components private ServiceTracker m_logService; // thread acting upon configurations @@ -88,8 +81,8 @@ * * @throws ComponentException if any error occurrs initializing this class */ - BundleComponentActivator( ComponentRegistry componentRegistry, ComponentActorThread componentActor, - BundleContext context, int logLevel ) throws ComponentException + BundleComponentActivator( ComponentRegistry componentRegistry, + ComponentActorThread componentActor, BundleContext context, int logLevel ) throws ComponentException { // keep the parameters for later m_componentRegistry = componentRegistry; @@ -99,10 +92,6 @@ // mark this instance active m_active = true; - // have the Configuration Admin Service handy (if available) - m_configurationAdmin = new ServiceTracker( context, ConfigurationAdmin.class.getName(), null ); - m_configurationAdmin.open(); - // have the LogService handy (if available) m_logService = new ServiceTracker( context, Activator.LOGSERVICE_CLASS, null ); m_logService.open(); @@ -176,46 +165,18 @@ metadata.validate( this ); // Request creation of the component manager - AbstractComponentManager manager; - if ( metadata.isFactory() ) - { - // 112.2.4 SCR must register a Component Factory - // service on behalf ot the component - // as soon as the component factory is satisfied - manager = new ComponentFactoryImpl( this, metadata, m_componentRegistry ); - } - else if ( metadata.isImmediate() ) - { - manager = new ImmediateComponentManager( this, metadata, m_componentRegistry ); - } - else if ( metadata.getServiceMetadata() != null ) - { - if ( metadata.getServiceMetadata().isServiceFactory() ) - { - manager = new ServiceFactoryComponentManager( this, metadata, m_componentRegistry ); - } - else - { - manager = new DelayedComponentManager( this, metadata, m_componentRegistry ); - } - } - else - { - // if we get here, which is not expected after all, we fail - throw new IllegalArgumentException( "Cannot create a component manager for " - + metadata.getName() ); - } + ComponentHolder holder = m_componentRegistry.createComponentHolder( this, metadata ); // register the component after validation - m_componentRegistry.registerComponent( metadata.getName(), manager ); - m_managers.add( manager ); + m_componentRegistry.registerComponent( metadata.getName(), holder ); + m_managers.add( holder ); // enable the component if ( metadata.isEnabled() ) { - manager.enable(); + holder.enableComponents(); } - } + } catch ( Throwable t ) { // There is a problem with this particular component, we'll log the error @@ -275,30 +236,24 @@ while ( m_managers.size() != 0 ) { - AbstractComponentManager manager = ( AbstractComponentManager ) m_managers.get( 0 ); + ComponentHolder holder = ( ComponentHolder ) m_managers.get( 0 ); try { - m_managers.remove( manager ); - manager.dispose( reason ); + m_managers.remove( holder ); + holder.disposeComponents( reason ); } catch ( Exception e ) { - log( LogService.LOG_ERROR, "BundleComponentActivator : Exception invalidating", manager + log( LogService.LOG_ERROR, "BundleComponentActivator : Exception invalidating", holder .getComponentMetadata(), e ); } finally { - m_componentRegistry.unregisterComponent( manager.getComponentMetadata().getName() ); + m_componentRegistry.unregisterComponent( holder.getComponentMetadata().getName() ); } } - // close the Configuration Admin tracker - if ( m_configurationAdmin != null ) - { - m_configurationAdmin.close(); - } - log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [" + m_context.getBundle().getBundleId() + "] STOPPED", null, null ); @@ -319,17 +274,6 @@ /** - * Returns the list of instance references currently associated to this activator - * - * @return the list of instance references - */ - public List getInstanceReferences() - { - return m_managers; - } - - - /** * Returns the BundleContext * * @return the BundleContext @@ -341,18 +285,6 @@ /** - * Returns the ConfigurationAdmin service used to retrieve - * configuration data for components managed by this activator or - * null if no Configuration Admin Service is available in the - * framework. - */ - protected ConfigurationAdmin getConfigurationAdmin() - { - return ( ConfigurationAdmin ) m_configurationAdmin.getService(); - } - - - /** * Implements the ComponentContext.enableComponent(String) * method by first finding the component(s) for the name and * then starting a thread to actually enable all components found. @@ -365,21 +297,21 @@ */ public void enableComponent( String name ) { - final AbstractComponentManager[] cm = getSelectedComponents( name ); - if ( cm == null ) + final ComponentHolder[] holder = getSelectedComponents( name ); + if ( holder == null ) { return; } - for ( int i = 0; i < cm.length; i++ ) + for ( int i = 0; i < holder.length; i++ ) { try { - cm[i].enable(); + holder[i].enableComponents(); } catch ( Throwable t ) { - log( LogService.LOG_ERROR, "Cannot enable component", cm[i].getComponentMetadata(), t ); + log( LogService.LOG_ERROR, "Cannot enable component", holder[i].getComponentMetadata(), t ); } } } @@ -398,22 +330,22 @@ */ public void disableComponent( String name ) { - final AbstractComponentManager[] cm = getSelectedComponents( name ); - if ( cm == null ) + final ComponentHolder[] holder = getSelectedComponents( name ); + if ( holder == null ) { return; } - for ( int i = 0; i < cm.length; i++ ) + for ( int i = 0; i < holder.length; i++ ) { try { - log( LogService.LOG_DEBUG, "Disabling Component", cm[i].getComponentMetadata(), null ); - cm[i].disable(); + log( LogService.LOG_DEBUG, "Disabling Component", holder[i].getComponentMetadata(), null ); + holder[i].disableComponents(); } catch ( Throwable t ) { - log( LogService.LOG_ERROR, "Cannot disable component", cm[i].getComponentMetadata(), t ); + log( LogService.LOG_ERROR, "Cannot disable component", holder[i].getComponentMetadata(), t ); } } } @@ -434,12 +366,12 @@ * to the name parameter or null if no * component manager with the given name is currently registered. */ - private AbstractComponentManager[] getSelectedComponents( String name ) + private ComponentHolder[] getSelectedComponents( String name ) { // if all components are selected if ( name == null ) { - return (org.apache.felix.scr.impl.manager.AbstractComponentManager[] ) m_managers.toArray( new AbstractComponentManager[m_managers.size()] ); + return ( ComponentHolder[] ) m_managers.toArray( new ComponentHolder[m_managers.size()] ); } if ( m_componentRegistry.getComponent( name ) != null ) @@ -448,10 +380,10 @@ Iterator it = m_managers.iterator(); while ( it.hasNext() ) { - AbstractComponentManager cm = ( AbstractComponentManager ) it.next(); + ComponentHolder cm = ( ComponentHolder ) it.next(); if ( name.equals( cm.getComponentMetadata().getName() ) ) { - return new AbstractComponentManager[] + return new ComponentHolder[] { cm }; } } @@ -462,6 +394,16 @@ } + //---------- Component ID support + + public long registerComponentId(AbstractComponentManager componentManager) { + return m_componentRegistry.registerComponentId(componentManager); + } + + public void unregisterComponentId(AbstractComponentManager componentManager) { + m_componentRegistry.unregisterComponentId(componentManager.getId()); + } + //---------- Asynchronous Component Handling ------------------------------ /** Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java?rev=798531&view=auto ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java (added) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java Tue Jul 28 14:06:58 2009 @@ -0,0 +1,327 @@ +/* + * 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; + + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.felix.scr.Component; +import org.apache.felix.scr.ScrService; +import org.apache.felix.scr.impl.config.ComponentHolder; +import org.apache.felix.scr.impl.config.UnconfiguredComponentHolder; +import org.apache.felix.scr.impl.manager.AbstractComponentManager; +import org.apache.felix.scr.impl.manager.ComponentFactoryImpl; +import org.apache.felix.scr.impl.metadata.ComponentMetadata; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.ComponentException; + + +/** + * The ComponentRegistry class acts as the global registry for + * components by name and by component ID. As such the component registry also + * registers itself as the {@link ScrService} to support access to the + * registered components. + */ +public class ComponentRegistry implements ScrService +{ + + /** + * The map of known components indexed by component name. The values are + * either the component names (for name reservations) or implementations + * of the {@link ComponentHolder} interface. + *

+ * The {@link #checkComponentName(String)} will first add an entry to this + * map being the name of the component to reserve the name. After setting up + * the component, the {@link #registerComponent(String, ComponentHolder)} + * method replaces the value of the named entry with the actual + * {@link ComponentHolder}. + * + * @see #checkComponentName(String) + * @see #registerComponent(String, ComponentHolder) + * @see #unregisterComponent(String) + */ + private Map m_componentsByName; + + /** + * Map of components by component ID. This map indexed by the component + * ID number (java.lang.Long) contains the actual + * {@link AbstractComponentManager} instances existing in the system. + * + * @see #registerComponentId(AbstractComponentManager) + * @see #unregisterComponentId(long) + */ + private Map m_componentsById; + + /** + * Counter to setup the component IDs as issued by the + * {@link #registerComponentId(AbstractComponentManager)} method. This + * counter is only incremented. + */ + private volatile long m_componentCounter; + + /** + * The OSGi service registration for the ScrService provided by this + * instance. + */ + private ServiceRegistration m_registration; + + + protected ComponentRegistry( BundleContext context ) + { + m_componentsByName = new HashMap(); + m_componentsById = new HashMap(); + m_componentCounter = -1; + + // register as ScrService + Dictionary props = new Hashtable(); + props.put( Constants.SERVICE_DESCRIPTION, "Declarative Services Management Agent" ); + props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" ); + m_registration = context.registerService( new String[] + { ScrService.class.getName(), }, this, props ); + } + + + public void dispose() + { + if ( m_registration != null ) + { + m_registration.unregister(); + m_registration = null; + } + } + + + //---------- ScrService interface + + public Component[] getComponents() + { + if ( m_componentsById.isEmpty() ) + { + return null; + } + + return ( org.apache.felix.scr.Component[] ) m_componentsById.values().toArray( + new Component[m_componentsById.size()] ); + } + + + public Component[] getComponents( Bundle bundle ) + { + Component[] all = getComponents(); + if ( all == null || all.length == 0 ) + { + return null; + } + + // compare the bundle by its id + long bundleId = bundle.getBundleId(); + + // scan the components for the the desired components + List perBundle = new ArrayList(); + for ( int i = 0; i < all.length; i++ ) + { + if ( all[i].getBundle().getBundleId() == bundleId ) + { + perBundle.add( all[i] ); + } + } + + // nothing to return + if ( perBundle.isEmpty() ) + { + return null; + } + + return ( org.apache.felix.scr.Component[] ) perBundle.toArray( new Component[perBundle.size()] ); + } + + + public Component getComponent( long componentId ) + { + return ( Component ) m_componentsById.get( new Long( componentId ) ); + } + + + //---------- ComponentManager registration by component Id + + /** + * Assigns a unique ID to the component, internally registers the + * component under that ID and returns the assigned component ID. + * + * @param componentManager The {@link AbstractComponentManager} for which + * to assign a component ID and which is to be internally registered + * + * @return the assigned component ID + */ + final long registerComponentId( final AbstractComponentManager componentManager ) + { + long componentId; + synchronized ( this ) + { + m_componentCounter++; + componentId = m_componentCounter; + } + + m_componentsById.put( new Long( componentId ), componentManager ); + + return componentId; + } + + + /** + * Unregisters the component with the given component ID from the internal + * registry. After unregistration, the component ID should be considered + * invalid. + * + * @param componentId The ID of the component to be removed from the + * internal component registry. + */ + final void unregisterComponentId( final long componentId ) + { + m_componentsById.remove( new Long( componentId ) ); + } + + + //---------- ComponentHolder registration by component name + + /** + * Checks whether the component name is "globally" unique or not. If it is + * unique, it is reserved until the actual component is registered with + * {@link #registerComponent(String, AbstractComponentManager)} or until + * it is unreserved by calling {@link #unregisterComponent(String)}. + * If a component with the same name has already been reserved or registered + * a ComponentException is thrown with a descriptive message. + * + * @param name the component name to check and reserve + * @throws ComponentException if the name is already in use by another + * component. + */ + final void checkComponentName( String name ) + { + if ( m_componentsByName.containsKey( name ) ) + { + String message = "The component name '" + name + "' has already been registered"; + + Object co = m_componentsByName.get( name ); + if ( co instanceof ComponentHolder ) + { + ComponentHolder c = ( ComponentHolder ) co; + Bundle cBundle = c.getActivator().getBundleContext().getBundle(); + ComponentMetadata cMeta = c.getComponentMetadata(); + + StringBuffer buf = new StringBuffer( message ); + buf.append( " by Bundle " ).append( cBundle.getBundleId() ); + if ( cBundle.getSymbolicName() != null ) + { + buf.append( " (" ).append( cBundle.getSymbolicName() ).append( ")" ); + } + buf.append( " as Component of Class " ).append( cMeta.getImplementationClassName() ); + message = buf.toString(); + } + + throw new ComponentException( message ); + } + + // reserve the name + m_componentsByName.put( name, name ); + } + + + /** + * Registers the given component under the given name. If the name has not + * already been reserved calling {@link #checkComponentName(String)} this + * method throws a {@link ComponentException}. + * + * @param name The name to register the component under + * @param component The component to register + * + * @throws ComponentException if the name has not been reserved through + * {@link #checkComponentName(String)} yet. + */ + final void registerComponent( String name, ComponentHolder component ) + { + // only register the component if there is a m_registration for it ! + if ( !name.equals( m_componentsByName.get( name ) ) ) + { + // this is not expected if all works ok + throw new ComponentException( "The component name '" + name + "' has already been registered." ); + } + + m_componentsByName.put( name, component ); + } + + + /** + * Returns the component registered under the given name or null + * if no component is registered yet. + */ + public final ComponentHolder getComponent( String name ) + { + Object entry = m_componentsByName.get( name ); + + // only return the entry if non-null and not a reservation + if ( entry instanceof ComponentHolder ) + { + return ( ComponentHolder ) entry; + } + + return null; + } + + + /** + * Removes the component registered under that name. If no component is + * yet registered but the name is reserved, it is unreserved. + *

+ * After calling this method, the name can be reused by other components. + */ + final void unregisterComponent( String name ) + { + m_componentsByName.remove( name ); + } + + + //---------- base configuration support + + /** + * Factory method to issue {@link ComponentHolder} instances to manage + * components described by the given component metadata. + */ + public ComponentHolder createComponentHolder( BundleComponentActivator activator, ComponentMetadata metadata ) + { + if ( metadata.isFactory() ) + { + // 112.2.4 SCR must register a Component Factory + // service on behalf ot the component + // as soon as the component factory is satisfied + return new ComponentFactoryImpl( activator, metadata ); + } + + return new UnconfiguredComponentHolder( activator, metadata ); + } + +} Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java ------------------------------------------------------------------------------ svn:mergeinfo = Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java?rev=798531&view=auto ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java (added) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java Tue Jul 28 14:06:58 2009 @@ -0,0 +1,94 @@ +/* + * 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 org.apache.felix.scr.impl.BundleComponentActivator; +import org.apache.felix.scr.impl.manager.DelayedComponentManager; +import org.apache.felix.scr.impl.manager.ImmediateComponentManager; +import org.apache.felix.scr.impl.manager.ServiceFactoryComponentManager; +import org.apache.felix.scr.impl.metadata.ComponentMetadata; + + +abstract class AbstractComponentHolder implements ComponentHolder +{ + + private final BundleComponentActivator m_activator; + + private final ComponentMetadata m_componentMetadata; + + + public AbstractComponentHolder( final BundleComponentActivator activator, final ComponentMetadata metadata ) + { + this.m_activator = activator; + this.m_componentMetadata = metadata; + } + + + protected ImmediateComponentManager createComponentManager() + { + + ImmediateComponentManager manager; + if ( m_componentMetadata.isFactory() ) + { + throw new IllegalArgumentException( "Cannot create component factory for " + m_componentMetadata.getName() ); + } + else if ( m_componentMetadata.isImmediate() ) + { + manager = new ImmediateComponentManager( m_activator, m_componentMetadata ); + } + else if ( m_componentMetadata.getServiceMetadata() != null ) + { + if ( m_componentMetadata.getServiceMetadata().isServiceFactory() ) + { + manager = new ServiceFactoryComponentManager( m_activator, m_componentMetadata ); + } + else + { + manager = new DelayedComponentManager( m_activator, m_componentMetadata ); + } + } + else + { + // if we get here, which is not expected after all, we fail + throw new IllegalArgumentException( "Cannot create a component manager for " + + m_componentMetadata.getName() ); + } + + return manager; + } + + + public final BundleComponentActivator getActivator() + { + return m_activator; + } + + + public final ComponentMetadata getComponentMetadata() + { + return m_componentMetadata; + } + + + protected final String getComponentName() + { + return getComponentMetadata().getName(); + } +} Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/AbstractComponentHolder.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev Url Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java?rev=798531&view=auto ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java (added) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java Tue Jul 28 14:06:58 2009 @@ -0,0 +1,89 @@ +/* + * 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.Dictionary; + +import org.apache.felix.scr.impl.BundleComponentActivator; +import org.apache.felix.scr.impl.metadata.ComponentMetadata; + + +/** + * The ComponentHolder interface provides the API for supporting + * component instances configured through either singleton configurations (or + * no configuration at all) and factory configurations. + *

+ * Instances of this interface are managed by the {@link ConfigurationSupport} + * class on behalf of the + * {@link org.apache.felix.scr.impl.BundleComponentActivator} and the + * {@link org.apache.felix.scr.impl.ComponentRegistry}. + */ +public interface ComponentHolder +{ + + /** + * Returns the {@link BundleComponentActivator} owning this component + * holder. + */ + BundleComponentActivator getActivator(); + + + /** + * Returns the {@link ComponentMetadata} describing and declaring this + * component. + */ + ComponentMetadata getComponentMetadata(); + + + /** + * The configuration with the given PID has been deleted from the + * Configuration Admin service. + * + * @param pid The PID of the deleted configuration + */ + void configurationDeleted( String pid ); + + + /** + * Configure a component with configuration from the given PID. + * + * @param pid The PID of the configuration used to configure the component + */ + void configurationUpdated( String pid, Dictionary props ); + + + /** + * Enables all components of this holder. + */ + void enableComponents(); + + + /** + * Disables all components of this holder. + */ + void disableComponents(); + + + /** + * Disposes off all components of this holder. + * @param reason + */ + void disposeComponents( int reason ); +} Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev Url Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java?rev=798531&view=auto ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java (added) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java Tue Jul 28 14:06:58 2009 @@ -0,0 +1,263 @@ +/* + * 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.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; + +import org.apache.felix.scr.impl.Activator; +import org.apache.felix.scr.impl.BundleComponentActivator; +import org.apache.felix.scr.impl.ComponentRegistry; +import org.apache.felix.scr.impl.manager.ComponentFactoryImpl; +import org.apache.felix.scr.impl.metadata.ComponentMetadata; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.cm.ConfigurationEvent; +import org.osgi.service.cm.ConfigurationListener; +import org.osgi.service.log.LogService; + + +public class ConfigurationComponentRegistry extends ComponentRegistry implements ConfigurationListener +{ + + // the service m_registration of the ConfigurationListener service + private ServiceRegistration m_registration; + + + public ConfigurationComponentRegistry( final BundleContext context ) + { + super( context ); + + // register as ScrService + Dictionary props = new Hashtable(); + props.put( Constants.SERVICE_DESCRIPTION, "Declarative Services Configuration Support Listener" ); + props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" ); + m_registration = context.registerService( new String[] + { ConfigurationListener.class.getName() }, this, props ); + } + + + public void dispose() + { + if ( m_registration != null ) + { + m_registration.unregister(); + m_registration = null; + } + + super.dispose(); + } + + + //---------- BaseConfigurationSupport overwrites + + public ComponentHolder createComponentHolder( final BundleComponentActivator activator, + final ComponentMetadata metadata ) + { + // 112.7 configure unless configuration not required + if ( metadata.isConfigurationIgnored() ) + { + return super.createComponentHolder( activator, metadata ); + } + + // prepare the configuration holder + final ComponentHolder holder; + if ( metadata.isFactory() ) + { + holder = new ComponentFactoryImpl( activator, metadata ); + } + else + { + holder = new ConfiguredComponentHolder( activator, metadata ); + } + + final BundleContext bundleContext = activator.getBundleContext(); + final String bundleLocation = bundleContext.getBundle().getLocation(); + final String name = metadata.getName(); + + final ServiceReference caRef = bundleContext.getServiceReference( ConfigurationAdmin.class.getName() ); + if ( caRef != null ) + { + final ConfigurationAdmin ca = ( ConfigurationAdmin ) bundleContext.getService( caRef ); + if ( ca != null ) + { + final Configuration[] factory = findFactoryConfigurations( ca, name ); + if ( factory != null ) + { + for ( int i = 0; i < factory.length; i++ ) + { + final String pid = factory[i].getPid(); + final Dictionary props = getConfiguration( ca, pid, bundleLocation ); + holder.configurationUpdated( pid, props ); + } + } + else + { + // check for configuration and configure the holder + final Configuration singleton = findSingletonConfiguration( ca, name ); + if ( singleton != null ) + { + final Dictionary props = getConfiguration( ca, name, bundleLocation ); + holder.configurationUpdated( name, props ); + } + } + } + } + + return holder; + } + + + //---------- ConfigurationListener + + public void configurationEvent( ConfigurationEvent event ) + { + final String pid = event.getPid(); + final String factoryPid = event.getFactoryPid(); + + final ComponentHolder cm; + if ( factoryPid == null ) + { + cm = getComponent( pid ); + } + else + { + cm = getComponent( factoryPid ); + } + + if ( cm != null && !cm.getComponentMetadata().isConfigurationIgnored() ) + { + switch ( event.getType() ) + { + case ConfigurationEvent.CM_DELETED: + cm.configurationDeleted( pid ); + break; + + case ConfigurationEvent.CM_UPDATED: + final BundleContext bundleContext = cm.getActivator().getBundleContext(); + final ServiceReference caRef = bundleContext.getServiceReference( ConfigurationAdmin.class + .getName() ); + if ( caRef != null ) + { + final ConfigurationAdmin ca = ( ConfigurationAdmin ) bundleContext.getService( caRef ); + if ( ca != null ) + { + try + { + final Dictionary dict = getConfiguration( ca, pid, bundleContext.getBundle().getLocation() ); + if ( dict != null ) + { + cm.configurationUpdated( pid, dict ); + } + } + finally + { + bundleContext.ungetService( caRef ); + } + } + } + break; + + default: + Activator.log( LogService.LOG_WARNING, null, "Unknown ConfigurationEvent type " + event.getType(), + null ); + } + } + } + + + private Dictionary getConfiguration( final ConfigurationAdmin ca, final String pid, final String bundleLocation ) + { + try + { + final Configuration cfg = ca.getConfiguration( pid ); + if ( bundleLocation.equals( cfg.getBundleLocation() ) ) + { + return cfg.getProperties(); + } + + // configuration belongs to another bundle, cannot be used here + Activator.log( LogService.LOG_ERROR, null, "Cannot use configuration pid=" + pid + " for bundle " + + bundleLocation + " because it belongs to bundle " + cfg.getBundleLocation(), null ); + } + catch ( IOException ioe ) + { + Activator.log( LogService.LOG_WARNING, null, "Failed reading configuration for pid=" + pid, ioe ); + } + + return null; + } + + + /** + * Returns the configuration whose PID equals the given pid. If no such + * configuration exists, null is returned. + * @param ctx + * @param pid + * @return + */ + public Configuration findSingletonConfiguration( final ConfigurationAdmin ca, final String pid ) + { + final String filter = "(service.pid=" + pid + ")"; + final Configuration[] cfg = findConfigurations( ca, filter ); + return ( cfg == null || cfg.length == 0 ) ? null : cfg[0]; + } + + + /** + * Returns all configurations whose factory PID equals the given factory PID + * or null if no such configurations exist + * @param ctx + * @param factoryPid + * @return + */ + public Configuration[] findFactoryConfigurations( final ConfigurationAdmin ca, final String factoryPid ) + { + final String filter = "(service.factoryPid=" + factoryPid + ")"; + return findConfigurations( ca, filter ); + } + + + private Configuration[] findConfigurations( final ConfigurationAdmin ca, final String filter ) + { + try + { + return ca.listConfigurations( filter ); + } + catch ( IOException ioe ) + { + Activator + .log( LogService.LOG_WARNING, null, "Problem listing configurations for filter=" + filter, ioe ); + } + catch ( InvalidSyntaxException ise ) + { + Activator.log( LogService.LOG_ERROR, null, "Invalid Configuration selection filter " + filter, ise ); + } + + // no factories in case of problems + return null; + } +} Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationComponentRegistry.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev Url Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java?rev=798531&view=auto ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java (added) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java Tue Jul 28 14:06:58 2009 @@ -0,0 +1,336 @@ +/* + * 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.Dictionary; +import java.util.HashMap; +import java.util.Map; + +import org.apache.felix.scr.impl.BundleComponentActivator; +import org.apache.felix.scr.impl.manager.ImmediateComponentManager; +import org.apache.felix.scr.impl.metadata.ComponentMetadata; +import org.osgi.service.component.ComponentConstants; + + +/** + * The ConfiguredComponentHolder class is a + * {@link ComponentHolder} for one or more components instances configured by + * singleton or factory configuration objects received from the Configuration + * Admin service. + *

+ * This holder is used only for components configured (optionally or required) + * by the Configuration Admin service. It is not used for components declared + * as ignoring configuration or if no Configuration Admin service is available. + *

+ * The holder copes with three situations: + *

    + *
  • No configuration is available for the held component. That is there is + * no configuration whose service.pid or + * service.factoryPid equals the component name.
  • + *
  • A singleton configuration is available whose service.pid + * equals the component name.
  • + *
  • One or more factory configurations exist whose + * service.factoryPid equals the component name.
  • + *
+ */ +public class ConfiguredComponentHolder extends AbstractComponentHolder +{ + + /** + * A map of components configured with factory configuration. The indices + * are the PIDs (service.pid) of the configuration objects. + * The values are the {@link ImmediateComponentManager component instances} + * created on behalf of the configurations. + */ + private final Map m_components; + + /** + * The special component used if there is no configuration or a singleton + * configuration. This field is always non-null and is first + * created in the constructor. As factory configurations are provided this + * instance may be configured or "deconfigured". + *

+ * Expected invariants: + *

    + *
  • This field is never null
  • + *
  • The {@link #m_components} map is empty or the component pointed to + * by this field is also contained in the map
  • + *
      + */ + private ImmediateComponentManager m_singleComponent; + + /** + * Whether components have already been enabled by calling the + * {@link #enableComponents()} method. If this field is true + * component instances created per configuration by the + * {@link #configurationUpdated(String, Dictionary)} method are also + * enabled. Otherwise they are not enabled immediately. + */ + private boolean m_enabled; + + + ConfiguredComponentHolder( final BundleComponentActivator activator, final ComponentMetadata metadata ) + { + super( activator, metadata ); + + this.m_components = new HashMap(); + this.m_singleComponent = createComponentManager(); + this.m_enabled = false; + } + + + /** + * The configuration with the given pid + * (service.pid of the configuration object) is deleted. + *

      + * The following situations are supported: + *

        + *
      • 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".
      • + *
      • 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.
      • + *
      • 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.
      • + *
      + */ + public void configurationDeleted( final String pid ) + { + if ( pid.equals( getComponentName() ) ) + { + // singleton configuration deleted + m_singleComponent.reconfigure( null ); + } + else + { + // remove the component configured with the deleted configuration + ImmediateComponentManager icm = removeComponentManager( pid ); + if ( icm != null ) + { + // special casing if the single component is deconfigured + if ( m_singleComponent == icm ) + { + + // if the single component is the last remaining, deconfi + if ( m_components.isEmpty() ) + { + + // if the single component is the last remaining + // deconfigure it + icm.reconfigure( null ); + icm = null; + + } + else + { + + // replace the single component field with another + // entry from the map + m_singleComponent = ( ImmediateComponentManager ) 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 ( icm != null ) + { + icm.dispose( ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED ); + } + } + } + } + + + /** + * Configures a component with the given configuration. This configuration + * update may happen in various situations: + *
        + *
      • The pid equals the component name. Hence we have a + * singleton configuration for the single component held by this holder
      • + *
      • 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.
      • + *
      • The configuration is a factory configuration but not the first. In + * this case a new component is created, configured and stored in the map
      • + *
      + */ + public void configurationUpdated( final String pid, final Dictionary props ) + { + if ( pid.equals( getComponentName() ) ) + { + // singleton configuration has pid equal to component name + m_singleComponent.reconfigure( props ); + } + else + { + // factory configuration update or created + final ImmediateComponentManager icm = getComponentManager( pid ); + if ( icm != null ) + { + // factory configuration updated for existing component instance + icm.reconfigure( props ); + } + else + { + // factory configuration created + final ImmediateComponentManager newIcm; + if ( !m_singleComponent.hasConfiguration() ) + { + // configure the single instance if this is not configured + newIcm = m_singleComponent; + } + else + { + // otherwise create a new instance to provide the config to + newIcm = createComponentManager(); + } + + // configure the component + newIcm.reconfigure( props ); + + // enable the component if it is initially enabled + if ( m_enabled && getComponentMetadata().isEnabled() ) + { + newIcm.enable(); + } + + // store the component in the map + putComponentManager( pid, newIcm ); + } + } + } + + + public void enableComponents() + { + final ImmediateComponentManager[] cms = getComponentManagers( false ); + if ( cms == null ) + { + m_singleComponent.enable(); + } + else + { + for ( int i = 0; i < cms.length; i++ ) + { + cms[i].enable(); + } + } + + m_enabled = true; + } + + + public void disableComponents() + { + final ImmediateComponentManager[] cms = getComponentManagers( false ); + if ( cms == null ) + { + m_singleComponent.disable(); + } + else + { + for ( int i = 0; i < cms.length; i++ ) + { + cms[i].disable(); + } + } + } + + + public void disposeComponents( final int reason ) + { + final ImmediateComponentManager[] cms = getComponentManagers( true ); + if ( cms == null ) + { + m_singleComponent.dispose( reason ); + } + else + { + for ( int i = 0; i < cms.length; i++ ) + { + cms[i].dispose( reason ); + } + } + } + + + //---------- internal + + private ImmediateComponentManager getComponentManager( String pid ) + { + synchronized ( m_components ) + { + return ( ImmediateComponentManager ) m_components.get( pid ); + } + } + + + private ImmediateComponentManager removeComponentManager( String pid ) + { + synchronized ( m_components ) + { + return ( ImmediateComponentManager ) m_components.remove( pid ); + } + } + + + private void putComponentManager( String pid, ImmediateComponentManager componentManager ) + { + synchronized ( m_components ) + { + m_components.put( pid, componentManager ); + } + } + + + /** + * Returns all components from the map, optionally also removing them + * from the map. If there are no components in the map, null + * is returned. + */ + private ImmediateComponentManager[] getComponentManagers( final boolean clear ) + { + synchronized ( m_components ) + { + // fast exit if there is no component in the map + if ( m_components.isEmpty() ) + { + return null; + } + + final ImmediateComponentManager[] cm = new ImmediateComponentManager[m_components.size()]; + m_components.values().toArray( cm ); + + if ( clear ) + { + m_components.clear(); + } + + return cm; + } + } +} Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/ConfiguredComponentHolder.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev Url Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java?rev=798531&view=auto ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java (added) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java Tue Jul 28 14:06:58 2009 @@ -0,0 +1,74 @@ +/* + * 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.Dictionary; + +import org.apache.felix.scr.impl.BundleComponentActivator; +import org.apache.felix.scr.impl.manager.ImmediateComponentManager; +import org.apache.felix.scr.impl.metadata.ComponentMetadata; + + +/** + * The SingletonHolder class is {@link ComponentHolder} for a + * component configured by a singleton configuration or no configuration + * at all. + */ +public class UnconfiguredComponentHolder extends AbstractComponentHolder +{ + + private final ImmediateComponentManager m_component; + + + public UnconfiguredComponentHolder( BundleComponentActivator activator, ComponentMetadata metadata ) + { + super( activator, metadata ); + + m_component = createComponentManager(); + } + + + public void configurationDeleted( String pid ) + { + } + + + public void configurationUpdated( String pid, Dictionary props ) + { + } + + + public void enableComponents() + { + m_component.enable(); + } + + + public void disableComponents() + { + m_component.disable(); + } + + + public void disposeComponents( int reason ) + { + m_component.dispose( reason ); + } +} Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/config/UnconfiguredComponentHolder.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev Url Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Tue Jul 28 14:06:58 2009 @@ -29,7 +29,6 @@ import org.apache.felix.scr.Reference; import org.apache.felix.scr.impl.BundleComponentActivator; import org.apache.felix.scr.impl.ComponentActivatorTask; -import org.apache.felix.scr.impl.ComponentRegistry; import org.apache.felix.scr.impl.metadata.ComponentMetadata; import org.apache.felix.scr.impl.metadata.ReferenceMetadata; import org.osgi.framework.Bundle; @@ -273,6 +272,16 @@ acm.log( LogService.LOG_DEBUG, "Activating component", componentMetadata, null ); // Before creating the implementation object, we are going to + // test if we have configuration if such is required + if ( !acm.hasConfiguration() && acm.getComponentMetadata().isConfigurationRequired() ) + { + acm.log( LogService.LOG_INFO, "Missing required configuration, cannot activate", componentMetadata, + null ); + acm.changeState( Unsatisfied.getInstance() ); + return; + } + + // Before creating the implementation object, we are going to // test if all the mandatory dependencies are satisfied if ( !acm.verifyDependencyManagers( acm.getProperties()) ) { @@ -458,14 +467,14 @@ * * @param activator * @param metadata - * @param componentId */ - protected AbstractComponentManager( BundleComponentActivator activator, ComponentMetadata metadata, - ComponentRegistry componentRegistry ) + protected AbstractComponentManager( BundleComponentActivator activator, ComponentMetadata metadata ) { m_activator = activator; m_componentMetadata = metadata; - m_componentId = componentRegistry.createComponentId(); + + // for some testing, the activator may be null + m_componentId = ( activator != null ) ? activator.registerComponentId( this ) : -1; m_state = Disabled.getInstance(); loadDependencyManagers( metadata ); @@ -753,12 +762,20 @@ return m_serviceRegistration; } + void clear() { - m_activator = null; + // for some testing, the activator may be null + if ( m_activator != null ) + { + m_activator.unregisterComponentId( this ); + m_activator = null; + } + m_dependencyManagers.clear(); } + void log( int level, String message, ComponentMetadata metadata, Throwable ex ) { BundleComponentActivator activator = getActivator(); @@ -785,17 +802,6 @@ } /** - * Reconfigures this component by deactivating and activating it. During - * activation the new configuration data is retrieved from the Configuration - * Admin Service. - */ - public final void reconfigure( final int reason ) - { - log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure", m_componentMetadata, null ); - reactivate( reason ); - } - - /** * Cycles this component by deactivating it and - if still satisfied - * activating it again asynchronously. *

      @@ -851,7 +857,7 @@ } } - private boolean verifyDependencyManagers( Dictionary properties ) + protected boolean verifyDependencyManagers( Dictionary properties ) { // indicates whether all dependencies are satisfied boolean satisfied = true; @@ -914,6 +920,8 @@ */ public abstract Object getInstance(); + public abstract boolean hasConfiguration(); + public abstract Dictionary getProperties(); /** Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java Tue Jul 28 14:06:58 2009 @@ -50,7 +50,7 @@ return m_componentManager; } - public Dictionary getProperties() + public final Dictionary getProperties() { // 112.11.3.5 The Dictionary is read-only and cannot be modified return new ReadOnlyDictionary( m_componentManager.getProperties() ); Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java Tue Jul 28 14:06:58 2009 @@ -25,11 +25,10 @@ import java.util.Map; import org.apache.felix.scr.impl.BundleComponentActivator; -import org.apache.felix.scr.impl.ComponentRegistry; +import org.apache.felix.scr.impl.config.ComponentHolder; import org.apache.felix.scr.impl.metadata.ComponentMetadata; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; -import org.osgi.service.cm.Configuration; import org.osgi.service.component.ComponentConstants; import org.osgi.service.component.ComponentFactory; import org.osgi.service.component.ComponentInstance; @@ -38,12 +37,9 @@ /** * The ComponentFactoryImpl TODO */ -public class ComponentFactoryImpl extends AbstractComponentManager implements ComponentFactory +public class ComponentFactoryImpl extends AbstractComponentManager implements ComponentFactory, ComponentHolder { - // The component registry used to retrieve component IDs - private ComponentRegistry m_componentRegistry; - // The map of components created from Configuration objects // maps PID to ImmediateComponentManager for configuration updating // this map is lazily created @@ -53,13 +49,20 @@ // no IdentityHashSet and HashSet internally uses a HashMap anyway private final Map m_createdComponents; + // configuration of the component factory + private Dictionary m_configuration; + + // whether this instance supports creating component instances for factory + // configuration instances. This is backwards compatibility behaviour and + // contradicts the specification (Section 112.7) + private final boolean m_isConfigurationFactory; + - public ComponentFactoryImpl( BundleComponentActivator activator, ComponentMetadata metadata, - ComponentRegistry componentRegistry ) + public ComponentFactoryImpl( BundleComponentActivator activator, ComponentMetadata metadata ) { - super( activator, metadata, componentRegistry ); - m_componentRegistry = componentRegistry; + super( activator, metadata ); m_createdComponents = new IdentityHashMap(); + m_isConfigurationFactory = "true".equals( activator.getBundleContext().getProperty( "ds.factory.enabled" ) ); } @@ -94,16 +97,6 @@ { log( LogService.LOG_DEBUG, "registering component factory", getComponentMetadata(), null ); - Configuration[] cfg = m_componentRegistry.getConfigurations( getActivator().getBundleContext(), - getComponentMetadata().getName() ); - if ( cfg != null ) - { - for ( int i = 0; i < cfg.length; i++ ) - { - updated( cfg[i].getPid(), cfg[i].getProperties() ); - } - } - Dictionary serviceProperties = getProperties(); return getActivator().getBundleContext().registerService( new String[] { ComponentFactory.class.getName() }, getService(), serviceProperties ); @@ -117,6 +110,12 @@ } + public boolean hasConfiguration() + { + return true; + } + + public Dictionary getProperties() { Dictionary props = new Hashtable(); @@ -143,63 +142,129 @@ } - //---------- ManagedServiceFactory interface ------------------------------ + public String getName() + { + return "Component Factory " + getComponentMetadata().getName(); + } + + + //---------- ComponentHolder interface - public void updated( String pid, Dictionary configuration ) + public void configurationDeleted( String pid ) { - if ( getState() == STATE_FACTORY ) + if ( pid.equals( getComponentMetadata().getName() ) ) { - ImmediateComponentManager cm; - if ( m_configuredServices != null ) - { - cm = ( ImmediateComponentManager ) m_configuredServices.get( pid ); - } - else + m_configuration = null; + reconfigureComponents( null ); + } + else if ( m_isConfigurationFactory && getState() == STATE_FACTORY && m_configuredServices != null ) + { + ImmediateComponentManager cm = ( ImmediateComponentManager ) m_configuredServices.remove( pid ); + if ( cm != null ) { - m_configuredServices = new HashMap(); - cm = null; + log( LogService.LOG_DEBUG, "Disposing component after configuration deletion", getComponentMetadata(), + null ); + + disposeComponentManager( cm, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED ); } + } + } - if ( cm == null ) - { - // create a new instance with the current configuration - cm = createComponentManager( configuration, false ); - // keep a reference for future updates - m_configuredServices.put( pid, cm ); - } - else + public void configurationUpdated( String pid, Dictionary configuration ) + { + if ( pid.equals( getComponentMetadata().getName() ) ) + { + m_configuration = configuration; + reconfigureComponents( configuration ); + } + else if ( m_isConfigurationFactory ) + { + if ( getState() == STATE_FACTORY ) { - // update the configuration as if called as ManagedService - cm.reconfigure( configuration ); + // configuration for factory configuration instances + + ImmediateComponentManager cm; + if ( m_configuredServices != null ) + { + cm = ( ImmediateComponentManager ) m_configuredServices.get( pid ); + } + else + { + m_configuredServices = new HashMap(); + cm = null; + } + + if ( cm == null ) + { + // create a new instance with the current configuration + cm = createComponentManager( configuration, false ); + + // keep a reference for future updates + m_configuredServices.put( pid, cm ); + } + else + { + // update the configuration as if called as ManagedService + cm.reconfigure( configuration ); + } } } + else + { + // 112.7 Factory Configuration not allowed for factory component + getActivator().log( LogService.LOG_ERROR, + "Component Factory cannot be configured by factory configuration", getComponentMetadata(), null ); + } } - public void deleted( String pid ) + + // TODO: correct ??? + public void enableComponents() { - if ( getState() == STATE_FACTORY && m_configuredServices != null ) + ImmediateComponentManager[] cms = getComponentManagers( false ); + for ( int i = 0; i < cms.length; i++ ) { - ImmediateComponentManager cm = ( ImmediateComponentManager ) m_configuredServices.remove( pid ); - if ( cm != null ) - { - log( LogService.LOG_DEBUG, "Disposing component after configuration deletion", getComponentMetadata(), - null ); + cms[i].enable(); + } + } - disposeComponentManager( cm, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED ); - } + + // update components with this configuration + private void reconfigureComponents( Dictionary configuration ) + { + ImmediateComponentManager[] cms = getComponentManagers( false ); + for ( int i = 0; i < cms.length; i++ ) + { + cms[i].reconfigure( configuration ); } + } + + // TODO: correct ??? + public void disableComponents() + { + ImmediateComponentManager[] cms = getComponentManagers( false ); + for ( int i = 0; i < cms.length; i++ ) + { + cms[i].disable(); + } } - public String getName() + // TODO: correct ??? + public void disposeComponents( int reason ) { - return "Component Factory " + getComponentMetadata().getName(); + ImmediateComponentManager[] cms = getComponentManagers( true ); + for ( int i = 0; i < cms.length; i++ ) + { + cms[i].dispose( reason ); + } } - //---------- internal ----------------------------------------------------- + //---------- internal + /** * ComponentManager instances created by this method are not registered * with the ComponentRegistry. Therefore, any configuration update to these @@ -218,11 +283,7 @@ */ private ImmediateComponentManager createComponentManager( Dictionary configuration, boolean isNewInstance ) { - ImmediateComponentManager cm = new ImmediateComponentManager( getActivator(), getComponentMetadata(), - m_componentRegistry ); - - // add the new component to the activators instances - getActivator().getInstanceReferences().add( cm ); + ImmediateComponentManager cm = new ImmediateComponentManager( getActivator(), getComponentMetadata() ); // register with the internal set of created components m_createdComponents.put( cm, cm ); @@ -231,6 +292,7 @@ if ( isNewInstance ) { cm.setFactoryProperties( configuration ); + cm.reconfigure( m_configuration ); // enable synchronously cm.enableInternal(); cm.activateInternal(); @@ -252,10 +314,24 @@ // remove from created components m_createdComponents.remove( cm ); - // remove from activators list - getActivator().getInstanceReferences().remove( cm ); - // finally dispose it cm.dispose( reason ); } + + + private ImmediateComponentManager[] getComponentManagers( boolean clear ) + { + synchronized ( m_createdComponents ) + { + ImmediateComponentManager[] cm = new ImmediateComponentManager[m_createdComponents.size()]; + m_createdComponents.keySet().toArray( cm ); + + if ( clear ) + { + m_createdComponents.clear(); + } + + return cm; + } + } } Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java Tue Jul 28 14:06:58 2009 @@ -20,7 +20,6 @@ import org.apache.felix.scr.impl.BundleComponentActivator; -import org.apache.felix.scr.impl.ComponentRegistry; import org.apache.felix.scr.impl.metadata.ComponentMetadata; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceFactory; @@ -36,12 +35,10 @@ /** * @param activator * @param metadata - * @param componentId */ - public DelayedComponentManager( BundleComponentActivator activator, ComponentMetadata metadata, - ComponentRegistry componentRegistry ) + public DelayedComponentManager( BundleComponentActivator activator, ComponentMetadata metadata ) { - super( activator, metadata, componentRegistry ); + super( activator, metadata ); } Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java Tue Jul 28 14:06:58 2009 @@ -22,7 +22,6 @@ import java.util.IdentityHashMap; import org.apache.felix.scr.impl.BundleComponentActivator; -import org.apache.felix.scr.impl.ComponentRegistry; import org.apache.felix.scr.impl.metadata.ComponentMetadata; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceFactory; @@ -47,12 +46,10 @@ /** * @param activator * @param metadata - * @param componentId */ - public ServiceFactoryComponentManager( BundleComponentActivator activator, ComponentMetadata metadata, - ComponentRegistry componentRegistry ) + public ServiceFactoryComponentManager( BundleComponentActivator activator, ComponentMetadata metadata ) { - super( activator, metadata, componentRegistry ); + super( activator, metadata ); } Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java?rev=798531&r1=798530&r2=798531&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java Tue Jul 28 14:06:58 2009 @@ -494,6 +494,36 @@ /** + * Returns true if the configuration policy is configured to + * {@link #CONFIGURATION_POLICY_REQUIRE}. + */ + public boolean isConfigurationRequired() + { + return CONFIGURATION_POLICY_REQUIRE.equals( m_configurationPolicy ); + } + + + /** + * Returns true if the configuration policy is configured to + * {@link #CONFIGURATION_POLICY_IGNORE}. + */ + public boolean isConfigurationIgnored() + { + return CONFIGURATION_POLICY_IGNORE.equals( m_configurationPolicy ); + } + + + /** + * Returns true if the configuration policy is configured to + * {@link #CONFIGURATION_POLICY_OPTIONAL}. + */ + public boolean isConfigurationOptional() + { + return CONFIGURATION_POLICY_OPTIONAL.equals( m_configurationPolicy ); + } + + + /** * Method used to verify if the semantics of this metadata are correct */ public void validate( Logger logger )