FELIX-4964 Activate a component at most once from a service event
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1691760 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index 14b2142..b6c8d77 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -18,7 +18,6 @@
*/
package org.apache.felix.scr.impl;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -28,8 +27,11 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.StringTokenizer;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -39,23 +41,29 @@
import org.apache.felix.scr.impl.helper.Logger;
import org.apache.felix.scr.impl.manager.AbstractComponentManager;
import org.apache.felix.scr.impl.manager.DependencyManager;
+import org.apache.felix.scr.impl.manager.ExtendedServiceEvent;
+import org.apache.felix.scr.impl.manager.ExtendedServiceListener;
+import org.apache.felix.scr.impl.manager.ExtendedServiceListenerContext;
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.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentException;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
-
/**
* The BundleComponentActivator is helper class to load and unload Components of
* a single bundle. It will read information from the metadata.xml file
* descriptors and create the corresponding managers.
*/
-public class BundleComponentActivator implements Logger
+public class BundleComponentActivator implements Logger, ExtendedServiceListenerContext<ExtendedServiceEvent>
{
// global component registration
private final ComponentRegistry m_componentRegistry;
@@ -82,10 +90,149 @@
// the configuration
private final ScrConfiguration m_configuration;
+ private final Map<String, ListenerInfo> listenerMap = new HashMap<String, ListenerInfo>();
+
+ private static class ListenerInfo implements ServiceListener
+ {
+ private Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>();
+
+ public void serviceChanged(ServiceEvent event)
+ {
+ ServiceReference<?> ref = event.getServiceReference();
+ ExtendedServiceEvent extEvent = null;
+ ExtendedServiceEvent endMatchEvent = null;
+ Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap;
+ synchronized (this)
+ {
+ filterMap = this.filterMap;
+ }
+ for (Map.Entry<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> entry : filterMap.entrySet())
+ {
+ Filter filter = entry.getKey();
+ if (filter == null || filter.match(ref))
+ {
+ if (extEvent == null)
+ {
+ extEvent = new ExtendedServiceEvent(event);
+ }
+ for (ExtendedServiceListener<ExtendedServiceEvent> forwardTo : entry.getValue())
+ {
+ forwardTo.serviceChanged(extEvent);
+ }
+ }
+ else if (event.getType() == ServiceEvent.MODIFIED)
+ {
+ if (endMatchEvent == null)
+ {
+ endMatchEvent = new ExtendedServiceEvent(
+ ServiceEvent.MODIFIED_ENDMATCH, ref);
+ }
+ for (ExtendedServiceListener<ExtendedServiceEvent> forwardTo : entry.getValue())
+ {
+ forwardTo.serviceChanged(endMatchEvent);
+ }
+ }
+ }
+ if (extEvent != null)
+ {
+ extEvent.activateManagers();
+ }
+ if (endMatchEvent != null)
+ {
+ endMatchEvent.activateManagers();
+ }
+ }
+
+ public synchronized void add(Filter filter,
+ ExtendedServiceListener<ExtendedServiceEvent> listener)
+ {
+ filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>(
+ filterMap);
+ List<ExtendedServiceListener<ExtendedServiceEvent>> listeners = filterMap.get(filter);
+ if (listeners == null)
+ {
+ listeners = Collections.<ExtendedServiceListener<ExtendedServiceEvent>> singletonList(listener);
+ }
+ else
+ {
+ listeners = new ArrayList<ExtendedServiceListener<ExtendedServiceEvent>>(
+ listeners);
+ listeners.add(listener);
+ }
+ filterMap.put(filter, listeners);
+ }
+
+ public synchronized boolean remove(Filter filter,
+ ExtendedServiceListener<ExtendedServiceEvent> listener)
+ {
+ List<ExtendedServiceListener<ExtendedServiceEvent>> listeners = filterMap.get(filter);
+ if (listeners != null)
+ {
+ filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>(
+ filterMap);
+ listeners = new ArrayList<ExtendedServiceListener<ExtendedServiceEvent>>(
+ listeners);
+ listeners.remove(listener);
+ if (listeners.isEmpty())
+ {
+ filterMap.remove(filter);
+ }
+ else
+ {
+ filterMap.put(filter, listeners);
+ }
+ }
+ return filterMap.isEmpty();
+ }
+ }
+
+ public void addServiceListener(String classNameFilter, Filter eventFilter,
+ ExtendedServiceListener<ExtendedServiceEvent> listener)
+ {
+ ListenerInfo listenerInfo;
+ synchronized (listenerMap)
+ {
+ log(LogService.LOG_DEBUG, "classNameFilter: " + classNameFilter
+ + " event filter: " + eventFilter, null, null, null);
+ listenerInfo = listenerMap.get(classNameFilter);
+ if (listenerInfo == null)
+ {
+ listenerInfo = new ListenerInfo();
+ listenerMap.put(classNameFilter, listenerInfo);
+ try
+ {
+ m_context.addServiceListener(listenerInfo, classNameFilter);
+ }
+ catch (InvalidSyntaxException e)
+ {
+ throw (IllegalArgumentException) new IllegalArgumentException(
+ "invalid class name filter").initCause(e);
+ }
+ }
+ }
+ listenerInfo.add(eventFilter, listener);
+ }
+
+ public void removeServiceListener(String className, Filter filter,
+ ExtendedServiceListener<ExtendedServiceEvent> listener)
+ {
+ synchronized (listenerMap)
+ {
+ ListenerInfo listenerInfo = listenerMap.get(className);
+ if (listenerInfo != null)
+ {
+ if (listenerInfo.remove(filter, listener))
+ {
+ listenerMap.remove(className);
+ m_context.removeServiceListener(listenerInfo);
+ }
+ }
+ }
+ }
/**
* Called upon starting of the bundle. This method invokes initialize() which
- * parses the metadata and creates the instance managers
+ * parses the metadata and creates the holders
*
* @param componentRegistry The <code>ComponentRegistry</code> used to
* register components with to ensure uniqueness of component names
@@ -94,8 +241,7 @@
*
* @throws ComponentException if any error occurrs initializing this class
*/
- BundleComponentActivator( ComponentRegistry componentRegistry,
- ComponentActorThread componentActor, BundleContext context, ScrConfiguration configuration ) throws ComponentException
+ BundleComponentActivator(ComponentRegistry componentRegistry, ComponentActorThread componentActor, BundleContext context, ScrConfiguration configuration) throws ComponentException
{
// keep the parameters for later
m_componentRegistry = componentRegistry;
@@ -104,24 +250,26 @@
m_bundle = context.getBundle();
// have the LogService handy (if available)
- m_logService = new ServiceTracker<LogService, LogService>( context, Activator.LOGSERVICE_CLASS, null );
+ m_logService = new ServiceTracker<LogService, LogService>(context,
+ Activator.LOGSERVICE_CLASS, null);
m_logService.open();
m_configuration = configuration;
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] active",
- new Object[] {m_bundle.getBundleId()}, null, null, null );
+ log(LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] active",
+ new Object[] { m_bundle.getBundleId() }, null, null, null);
// Get the Metadata-Location value from the manifest
- String descriptorLocations = ( String ) m_bundle.getHeaders().get( "Service-Component" );
- if ( descriptorLocations == null )
+ String descriptorLocations = (String) m_bundle.getHeaders().get(
+ "Service-Component");
+ if (descriptorLocations == null)
{
- throw new ComponentException( "Service-Component entry not found in the manifest" );
+ throw new ComponentException(
+ "Service-Component entry not found in the manifest");
}
- initialize( descriptorLocations );
+ initialize(descriptorLocations);
}
-
/**
* Gets the MetaData location, parses the meta data and requests the processing
* of binder instances
@@ -131,37 +279,38 @@
*
* @throws IllegalStateException If the bundle has already been uninstalled.
*/
- private void initialize( String descriptorLocations )
+ private void initialize(String descriptorLocations)
{
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] descriptor locations {1}",
- new Object[] {m_bundle.getBundleId(), descriptorLocations}, null, null, null );
+ log(LogService.LOG_DEBUG,
+ "BundleComponentActivator : Bundle [{0}] descriptor locations {1}",
+ new Object[] { m_bundle.getBundleId(), descriptorLocations }, null, null,
+ null);
// 112.4.1: The value of the the header is a comma separated list of XML entries within the Bundle
- StringTokenizer st = new StringTokenizer( descriptorLocations, ", " );
+ StringTokenizer st = new StringTokenizer(descriptorLocations, ", ");
- while ( st.hasMoreTokens() )
+ while (st.hasMoreTokens())
{
String descriptorLocation = st.nextToken();
- URL[] descriptorURLs = findDescriptors( m_bundle, descriptorLocation );
- if ( descriptorURLs.length == 0 )
+ URL[] descriptorURLs = findDescriptors(m_bundle, descriptorLocation);
+ if (descriptorURLs.length == 0)
{
// 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
// fragments, SCR must log an error message with the Log Service, if present, and continue.
- log( LogService.LOG_ERROR, "Component descriptor entry ''{0}'' not found", new Object[]
- { descriptorLocation }, null, null, null );
+ log(LogService.LOG_ERROR, "Component descriptor entry ''{0}'' not found",
+ new Object[] { descriptorLocation }, null, null, null);
continue;
}
// load from the descriptors
- for ( URL descriptorURL : descriptorURLs )
+ for (URL descriptorURL : descriptorURLs)
{
- loadDescriptor( descriptorURL );
+ loadDescriptor(descriptorURL);
}
}
}
-
/**
* Called outside the constructor so that the m_managers field is completely initialized.
* A component might possibly start a thread to enable other components, which could access m_managers
@@ -169,21 +318,27 @@
void initialEnable()
{
//enable all the enabled components
- for ( ComponentHolder<?> componentHolder : m_managers )
+ for (ComponentHolder<?> componentHolder : m_managers)
{
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] May enable component holder {1}",
- new Object[] {m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName()}, null, null, null );
+ log(LogService.LOG_DEBUG,
+ "BundleComponentActivator : Bundle [{0}] May enable component holder {1}",
+ new Object[] { m_bundle.getBundleId(),
+ componentHolder.getComponentMetadata().getName() }, null, null,
+ null);
- if ( componentHolder.getComponentMetadata().isEnabled() )
+ if (componentHolder.getComponentMetadata().isEnabled())
{
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] Enabling component holder {1}",
- new Object[] {m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName()}, null, null, null );
+ log(LogService.LOG_DEBUG,
+ "BundleComponentActivator : Bundle [{0}] Enabling component holder {1}",
+ new Object[] { m_bundle.getBundleId(),
+ componentHolder.getComponentMetadata().getName() }, null,
+ null, null);
try
{
- componentHolder.enableComponents( false );
+ componentHolder.enableComponents(false);
}
- catch ( Throwable t )
+ catch (Throwable t)
{
// caught on unhandled RuntimeException or Error
// (e.g. ClassDefNotFoundError)
@@ -191,26 +346,30 @@
// make sure the component is properly disabled, just in case
try
{
- componentHolder.disableComponents( false );
+ componentHolder.disableComponents(false);
}
- catch ( Throwable ignore )
+ catch (Throwable ignore)
{
}
- log( LogService.LOG_ERROR,
+ log(LogService.LOG_ERROR,
"BundleComponentActivator : Bundle [{0}] Unexpected failure enabling component holder {1}",
- new Object[] { m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName() }, null, null, t );
+ new Object[] { m_bundle.getBundleId(),
+ componentHolder.getComponentMetadata().getName() }, null,
+ null, t);
}
}
else
{
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] Will not enable component holder {1}",
- new Object[] {m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName()}, null, null, null );
+ log(LogService.LOG_DEBUG,
+ "BundleComponentActivator : Bundle [{0}] Will not enable component holder {1}",
+ new Object[] { m_bundle.getBundleId(),
+ componentHolder.getComponentMetadata().getName() }, null,
+ null, null);
}
}
}
-
/**
* Finds component descriptors based on descriptor location.
*
@@ -218,21 +377,22 @@
* @param descriptorLocation descriptor location
* @return array of descriptors or empty array if none found
*/
- static URL[] findDescriptors( final Bundle bundle, final String descriptorLocation )
+ static URL[] findDescriptors(final Bundle bundle, final String descriptorLocation)
{
- if ( bundle == null || descriptorLocation == null || descriptorLocation.trim().length() == 0 )
+ if (bundle == null || descriptorLocation == null
+ || descriptorLocation.trim().length() == 0)
{
return new URL[0];
}
// split pattern and path
- final int lios = descriptorLocation.lastIndexOf( "/" );
+ final int lios = descriptorLocation.lastIndexOf("/");
final String path;
final String filePattern;
- if ( lios > 0 )
+ if (lios > 0)
{
- path = descriptorLocation.substring( 0, lios );
- filePattern = descriptorLocation.substring( lios + 1 );
+ path = descriptorLocation.substring(0, lios);
+ filePattern = descriptorLocation.substring(lios + 1);
}
else
{
@@ -241,23 +401,22 @@
}
// find the entries
- final Enumeration<URL> entries = bundle.findEntries( path, filePattern, false );
- if ( entries == null || !entries.hasMoreElements() )
+ final Enumeration<URL> entries = bundle.findEntries(path, filePattern, false);
+ if (entries == null || !entries.hasMoreElements())
{
return new URL[0];
}
// create the result list
List<URL> urls = new ArrayList<URL>();
- while ( entries.hasMoreElements() )
+ while (entries.hasMoreElements())
{
- urls.add( entries.nextElement() );
+ urls.add(entries.nextElement());
}
- return urls.toArray( new URL[urls.size()] );
+ return urls.toArray(new URL[urls.size()]);
}
-
- private void loadDescriptor( final URL descriptorURL )
+ private void loadDescriptor(final URL descriptorURL)
{
// simple path for log messages
final String descriptorLocation = descriptorURL.getPath();
@@ -267,117 +426,125 @@
{
stream = descriptorURL.openStream();
- BufferedReader in = new BufferedReader( new InputStreamReader( stream, "UTF-8" ) );
- XmlHandler handler = new XmlHandler( m_bundle, this, getConfiguration().isFactoryEnabled(), getConfiguration().keepInstances() );
+ BufferedReader in = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
+ XmlHandler handler = new XmlHandler(m_bundle, this,
+ getConfiguration().isFactoryEnabled(), getConfiguration().keepInstances());
KXml2SAXParser parser;
- parser = new KXml2SAXParser( in );
+ parser = new KXml2SAXParser(in);
- parser.parseXML( handler );
+ parser.parseXML(handler);
// 112.4.2 Component descriptors may contain a single, root component element
// or one or more component elements embedded in a larger document
- for ( Object o : handler.getComponentMetadataList() )
+ for (Object o : handler.getComponentMetadataList())
{
- ComponentMetadata metadata = ( ComponentMetadata ) o;
+ ComponentMetadata metadata = (ComponentMetadata) o;
ComponentRegistryKey key = null;
try
{
// check and reserve the component name (if not null)
- if ( metadata.getName() != null )
+ if (metadata.getName() != null)
{
- key = m_componentRegistry.checkComponentName( m_bundle, metadata.getName() );
+ key = m_componentRegistry.checkComponentName(m_bundle,
+ metadata.getName());
}
// validate the component metadata
- metadata.validate( this );
+ metadata.validate(this);
// Request creation of the component manager
- ComponentHolder<?> holder = m_componentRegistry.createComponentHolder( this, metadata );
+ ComponentHolder<?> holder = m_componentRegistry.createComponentHolder(
+ this, metadata);
// register the component after validation
- m_componentRegistry.registerComponentHolder( key, holder );
- m_managers.add( holder );
+ m_componentRegistry.registerComponentHolder(key, holder);
+ m_managers.add(holder);
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] ComponentHolder created for {1}",
- new Object[] {m_bundle.getBundleId(), metadata.getName()}, null, null, null );
+ log(LogService.LOG_DEBUG,
+ "BundleComponentActivator : Bundle [{0}] ComponentHolder created for {1}",
+ new Object[] { m_bundle.getBundleId(), metadata.getName() },
+ null, null, null);
}
- catch ( Throwable t )
+ catch (Throwable t)
{
// There is a problem with this particular component, we'll log the error
// and proceed to the next one
- log( LogService.LOG_ERROR, "Cannot register Component", metadata, null, t );
+ log(LogService.LOG_ERROR, "Cannot register Component", metadata,
+ null, t);
// make sure the name is not reserved any more
- if ( key != null )
+ if (key != null)
{
- m_componentRegistry.unregisterComponentHolder( key );
+ m_componentRegistry.unregisterComponentHolder(key);
}
}
}
}
- catch ( IOException ex )
+ catch (IOException ex)
{
// 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
// fragments, SCR must log an error message with the Log Service, if present, and continue.
- log( LogService.LOG_ERROR, "Problem reading descriptor entry ''{0}''", new Object[]
- { descriptorLocation }, null, null, ex );
+ log(LogService.LOG_ERROR, "Problem reading descriptor entry ''{0}''",
+ new Object[] { descriptorLocation }, null, null, ex);
}
- catch ( Exception ex )
+ catch (Exception ex)
{
- log( LogService.LOG_ERROR, "General problem with descriptor entry ''{0}''", new Object[]
- { descriptorLocation }, null, null, ex );
+ log(LogService.LOG_ERROR, "General problem with descriptor entry ''{0}''",
+ new Object[] { descriptorLocation }, null, null, ex);
}
finally
{
- if ( stream != null )
+ if (stream != null)
{
try
{
stream.close();
}
- catch ( IOException ignore )
+ catch (IOException ignore)
{
}
}
}
}
-
/**
* Dispose of this component activator instance and all the component
* managers.
*/
- void dispose( int reason )
+ void dispose(int reason)
{
- if ( m_active.compareAndSet( true, false ))
+ if (m_active.compareAndSet(true, false))
{
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] will destroy {1} instances", new Object[]
- { m_bundle.getBundleId(), m_managers.size() }, null, null, null );
+ log(LogService.LOG_DEBUG,
+ "BundleComponentActivator : Bundle [{0}] will destroy {1} instances",
+ new Object[] { m_bundle.getBundleId(), m_managers.size() }, null, null,
+ null);
- for (ComponentHolder<?> holder: m_managers )
+ for (ComponentHolder<?> holder : m_managers)
{
try
{
- holder.disposeComponents( reason );
+ holder.disposeComponents(reason);
}
- catch ( Exception e )
+ catch (Exception e)
{
- log( LogService.LOG_ERROR, "BundleComponentActivator : Exception invalidating", holder
- .getComponentMetadata(), null, e );
+ log(LogService.LOG_ERROR,
+ "BundleComponentActivator : Exception invalidating",
+ holder.getComponentMetadata(), null, e);
}
finally
{
- m_componentRegistry.unregisterComponentHolder( m_bundle, holder.getComponentMetadata()
- .getName() );
+ m_componentRegistry.unregisterComponentHolder(m_bundle,
+ holder.getComponentMetadata().getName());
}
}
- log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] STOPPED", new Object[]
- {m_bundle.getBundleId()}, null, null, null );
+ log(LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] STOPPED",
+ new Object[] { m_bundle.getBundleId() }, null, null, null);
m_logService.close();
m_closeLatch.countDown();
@@ -388,7 +555,7 @@
{
m_closeLatch.await(m_configuration.lockTimeout(), TimeUnit.MILLISECONDS);
}
- catch ( InterruptedException e )
+ catch (InterruptedException e)
{
//ignore interruption during concurrent shutdown.
}
@@ -396,7 +563,6 @@
}
-
/**
* Returns <true> if this instance is active, that is if components
* may be activated for this component. The active flag is set early
@@ -409,7 +575,6 @@
return m_active.get();
}
-
/**
* Returns the BundleContext
*
@@ -420,13 +585,11 @@
return m_context;
}
-
public ScrConfiguration getConfiguration()
{
return m_configuration;
}
-
/**
* Implements the <code>ComponentContext.enableComponent(String)</code>
* method by first finding the component(s) for the <code>name</code> and
@@ -436,24 +599,25 @@
* @param name The name of the component to enable or <code>null</code> to
* enable all components.
*/
- public void enableComponent( final String name )
+ public void enableComponent(final String name)
{
- final List<ComponentHolder<?>> holder = getSelectedComponents( name );
- for ( ComponentHolder<?> aHolder : holder )
+ final List<ComponentHolder<?>> holder = getSelectedComponents(name);
+ for (ComponentHolder<?> aHolder : holder)
{
try
{
- log( LogService.LOG_DEBUG, "Enabling Component", aHolder.getComponentMetadata(), null, null );
- aHolder.enableComponents( true );
+ log(LogService.LOG_DEBUG, "Enabling Component",
+ aHolder.getComponentMetadata(), null, null);
+ aHolder.enableComponents(true);
}
- catch ( Throwable t )
+ catch (Throwable t)
{
- log( LogService.LOG_ERROR, "Cannot enable component", aHolder.getComponentMetadata(), null, t );
+ log(LogService.LOG_ERROR, "Cannot enable component",
+ aHolder.getComponentMetadata(), null, t);
}
}
}
-
/**
* Implements the <code>ComponentContext.disableComponent(String)</code>
* method by first finding the component(s) for the <code>name</code> and
@@ -463,24 +627,25 @@
* @param name The name of the component to disable or <code>null</code> to
* disable all components.
*/
- public void disableComponent( final String name )
+ public void disableComponent(final String name)
{
- final List<ComponentHolder<?>> holder = getSelectedComponents( name );
- for ( ComponentHolder<?> aHolder : holder )
+ final List<ComponentHolder<?>> holder = getSelectedComponents(name);
+ for (ComponentHolder<?> aHolder : holder)
{
try
{
- log( LogService.LOG_DEBUG, "Disabling Component", aHolder.getComponentMetadata(), null, null );
- aHolder.disableComponents( true );
+ log(LogService.LOG_DEBUG, "Disabling Component",
+ aHolder.getComponentMetadata(), null, null);
+ aHolder.disableComponents(true);
}
- catch ( Throwable t )
+ catch (Throwable t)
{
- log( LogService.LOG_ERROR, "Cannot disable component", aHolder.getComponentMetadata(), null, t );
+ log(LogService.LOG_ERROR, "Cannot disable component",
+ aHolder.getComponentMetadata(), null, t);
}
}
}
-
/**
* Returns an array of {@link ComponentHolder} instances which match the
* <code>name</code>. If the <code>name</code> is <code>null</code> an
@@ -496,32 +661,34 @@
* to the <code>name</code> parameter or <code>null</code> if no
* component manager with the given name is currently registered.
*/
- private List<ComponentHolder<?>> getSelectedComponents( String name )
+ private List<ComponentHolder<?>> getSelectedComponents(String name)
{
// if all components are selected
- if ( name == null )
+ if (name == null)
{
return m_managers;
}
- ComponentHolder<?> componentHolder = m_componentRegistry.getComponentHolder( m_bundle, name );
+ ComponentHolder<?> componentHolder = m_componentRegistry.getComponentHolder(
+ m_bundle, name);
if (componentHolder != null)
{
- return Collections.<ComponentHolder<?>>singletonList( componentHolder );
+ return Collections.<ComponentHolder<?>> singletonList(componentHolder);
}
// if the component is not known
return Collections.emptyList();
}
-
//---------- Component ID support
- public long registerComponentId(AbstractComponentManager<?> componentManager) {
+ public long registerComponentId(AbstractComponentManager<?> componentManager)
+ {
return m_componentRegistry.registerComponentId(componentManager);
}
- public void unregisterComponentId(AbstractComponentManager<?> componentManager) {
+ public void unregisterComponentId(AbstractComponentManager<?> componentManager)
+ {
m_componentRegistry.unregisterComponentId(componentManager.getId());
}
@@ -534,48 +701,50 @@
*
* @param task The component task to execute
*/
- public void schedule( Runnable task )
+ public void schedule(Runnable task)
{
- if ( isActive() )
+ if (isActive())
{
ComponentActorThread cat = m_componentActor;
- if ( cat != null )
+ if (cat != null)
{
- cat.schedule( task );
+ cat.schedule(task);
}
else
{
- log( LogService.LOG_DEBUG, "Component Actor Thread not running, calling synchronously", null, null, null );
+ log(LogService.LOG_DEBUG,
+ "Component Actor Thread not running, calling synchronously", null,
+ null, null);
try
{
- synchronized ( this )
+ synchronized (this)
{
task.run();
}
}
- catch ( Throwable t )
+ catch (Throwable t)
{
- log( LogService.LOG_WARNING, "Unexpected problem executing task", null, null, t );
+ log(LogService.LOG_WARNING, "Unexpected problem executing task",
+ null, null, t);
}
}
}
else
{
- log( LogService.LOG_WARNING, "BundleComponentActivator is not active; not scheduling {0}", new Object[]
- { task }, null, null, null );
+ log(LogService.LOG_WARNING,
+ "BundleComponentActivator is not active; not scheduling {0}",
+ new Object[] { task }, null, null, null);
}
}
-
/**
* Returns <code>true</code> if logging for the given level is enabled.
*/
- public boolean isLogEnabled( int level )
+ public boolean isLogEnabled(int level)
{
return m_configuration.getLogLevel() >= level;
}
-
/**
* Method to actually emit the log message. If the LogService is available,
* the message will be logged through the LogService. Otherwise the message
@@ -585,20 +754,20 @@
* @param pattern The <code>java.text.MessageFormat</code> message format
* string for preparing the message
* @param arguments The format arguments for the <code>pattern</code>
- * string.
+ * string.
* @param componentId
* @param ex An optional <code>Throwable</code> whose stack trace is written,
*/
- public void log( int level, String pattern, Object[] arguments, ComponentMetadata metadata, Long componentId, Throwable ex )
+ public void log(int level, String pattern, Object[] arguments,
+ ComponentMetadata metadata, Long componentId, Throwable ex)
{
- if ( isLogEnabled( level ) )
+ if (isLogEnabled(level))
{
- final String message = MessageFormat.format( pattern, arguments );
- log( level, message, metadata, componentId, ex );
+ final String message = MessageFormat.format(pattern, arguments);
+ log(level, message, metadata, componentId, ex);
}
}
-
/**
* Method to actually emit the log message. If the LogService is available,
* the message will be logged through the LogService. Otherwise the message
@@ -609,16 +778,18 @@
* @param componentId
* @param ex An optional <code>Throwable</code> whose stack trace is written,
*/
- public void log( int level, String message, ComponentMetadata metadata, Long componentId, Throwable ex )
+ public void log(int level, String message, ComponentMetadata metadata,
+ Long componentId, Throwable ex)
{
- if ( isLogEnabled( level ) )
+ if (isLogEnabled(level))
{
// prepend the metadata name to the message
- if ( metadata != null )
+ if (metadata != null)
{
- if ( componentId != null )
+ if (componentId != null)
{
- message = "[" + metadata.getName() + "(" + componentId + ")] " + message;
+ message = "[" + metadata.getName() + "(" + componentId + ")] "
+ + message;
}
else
{
@@ -627,33 +798,35 @@
}
ServiceTracker<LogService, LogService> logService = m_logService;
- if ( logService != null )
+ if (logService != null)
{
LogService logger = logService.getService();
- if ( logger == null )
+ if (logger == null)
{
- Activator.log( level, m_bundle, message, ex );
+ Activator.log(level, m_bundle, message, ex);
}
else
{
- logger.log( level, message, ex );
+ logger.log(level, message, ex);
}
}
else
{
// BCA has been disposed off, bundle context is probably invalid. Try to log something.
- Activator.log( level, null, message, ex );
+ Activator.log(level, null, message, ex);
}
}
}
- public void missingServicePresent( ServiceReference<?> serviceReference )
+ public void missingServicePresent(ServiceReference<?> serviceReference)
{
- m_componentRegistry.missingServicePresent( serviceReference, m_componentActor );
+ m_componentRegistry.missingServicePresent(serviceReference, m_componentActor);
}
- public <T> void registerMissingDependency( DependencyManager<?, T> dependencyManager, ServiceReference<T> serviceReference, int trackingCount )
+ public <T> void registerMissingDependency(DependencyManager<?, T> dependencyManager,
+ ServiceReference<T> serviceReference, int trackingCount)
{
- m_componentRegistry.registerMissingDependency(dependencyManager, serviceReference, trackingCount );
+ m_componentRegistry.registerMissingDependency(dependencyManager,
+ serviceReference, trackingCount);
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 8500fe5..a668e1d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -74,14 +74,11 @@
private volatile ReferenceMethods m_bindMethods;
//reset on filter change
- private volatile ServiceTracker<T, RefPair<S, T>> m_tracker;
+ private volatile ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> m_tracker;
// the target service filter string
private volatile String m_target;
- // the target service filter
- private volatile Filter m_targetFilter;
-
private volatile int m_minCardinality;
/**
@@ -127,7 +124,7 @@
m_bindMethods = bindMethods;
}
- private interface Customizer<S, T> extends ServiceTrackerCustomizer<T, RefPair<S, T>>
+ private interface Customizer<S, T> extends ServiceTrackerCustomizer<T, RefPair<S, T>, ExtendedServiceEvent>
{
/**
* attempt to obtain the services from the tracked service references that will be used in inital bind calls
@@ -143,7 +140,7 @@
boolean isSatisfied();
- void setTracker( ServiceTracker<T, RefPair<S, T>> tracker );
+ void setTracker( ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker );
void setTrackerOpened();
@@ -158,7 +155,7 @@
private volatile Map<ServiceReference<T>, RefPair<S, T>> previousRefMap = EMPTY_REF_MAP;
- public void setTracker( ServiceTracker<T, RefPair<S, T>> tracker )
+ public void setTracker( ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker )
{
m_tracker = tracker;
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracker reset (closed)", new Object[] {getName()}, null );
@@ -167,7 +164,7 @@
public boolean isSatisfied()
{
- ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
if ( tracker == null)
{
return false;
@@ -175,7 +172,7 @@
return cardinalitySatisfied( tracker.getServiceCount() );
}
- protected ServiceTracker<T, RefPair<S, T>> getTracker()
+ protected ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> getTracker()
{
return m_tracker;
}
@@ -202,7 +199,7 @@
protected void deactivateTracker()
{
- ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
if ( tracker != null )
{
tracker.deactivate();
@@ -256,7 +253,7 @@
return refPair;
}
- public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
if ( cardinalityJustSatisfied( serviceCount ) )
{
@@ -264,11 +261,11 @@
}
}
- public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
}
- public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
refPair.markDeleted();
if ( !cardinalitySatisfied( getTracker().getServiceCount() ) )
@@ -310,7 +307,7 @@
return refPair;
}
- public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
boolean tracked = false;
@@ -344,7 +341,7 @@
}
}
- public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
if (isActive())
@@ -355,7 +352,7 @@
tracked( trackingCount );
}
- public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
refPair.markDeleted();
@@ -415,7 +412,7 @@
{
if ( lastRefPair == null )
{
- ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
if (tracker == null) {
trackingCount.set( lastRefPairTrackingCount );
return Collections.emptyList();
@@ -439,7 +436,7 @@
return refPair;
}
- public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
tracked( trackingCount );
@@ -449,7 +446,11 @@
"Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
{getName(), m_dependencyMetadata.getInterface()}, null );
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
- m_componentManager.activateInternal( );
+ //event may be null during initial operations.
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
else if ( isTrackerOpened() && cardinalityJustSatisfied( serviceCount ) )
@@ -459,7 +460,7 @@
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
- public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
boolean reactivate = false;
@@ -471,12 +472,15 @@
if ( reactivate )
{
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
- public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
refPair.markDeleted();
@@ -489,7 +493,10 @@
{getName(), m_dependencyMetadata.getInterface()}, null );
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
//try to reactivate after ref is no longer tracked.
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
else if ( !cardinalitySatisfied( getTracker().getServiceCount() ) ) //may be called from an old tracker, so getTracker() may give a different answer
{
@@ -507,7 +514,7 @@
{
int serviceCount = 0;
AtomicInteger trackingCount = new AtomicInteger( );
- final ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+ final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked( cardinalitySatisfied( tracker.getServiceCount() ), trackingCount );
for (RefPair<S, T> refPair: tracked.values())
{
@@ -536,7 +543,7 @@
public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
{
- ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
if (tracker == null) {
return Collections.emptyList();
}
@@ -555,7 +562,7 @@
return refPair;
}
- public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
tracked( trackingCount );
@@ -566,7 +573,7 @@
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
- public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
boolean reactivate = false;
@@ -579,12 +586,15 @@
if ( reactivate )
{
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
- public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
refPair.markDeleted();
@@ -601,7 +611,10 @@
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
// FELIX-2368: immediately try to reactivate
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
}
@@ -695,7 +708,7 @@
return refPair;
}
- public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
boolean tracked = false;
@@ -744,7 +757,7 @@
}
}
- public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
boolean invokeUpdated;
@@ -761,7 +774,7 @@
tracked( trackingCount );
}
- public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
refPair.markDeleted();
@@ -907,7 +920,7 @@
return refPair;
}
- public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
this.trackingCount = trackingCount;
@@ -922,7 +935,10 @@
if ( reactivate )
{
m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
else
{
@@ -940,7 +956,7 @@
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
- public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
boolean invokeUpdated;
@@ -966,12 +982,15 @@
this.refPair = null;
}
}
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
- public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+ public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
{
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
refPair.markDeleted();
@@ -996,7 +1015,10 @@
this.refPair = null;
}
}
- m_componentManager.activateInternal( );
+ if (event != null)
+ {
+ event.addComponentManager(m_componentManager);
+ }
}
m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
}
@@ -1032,7 +1054,7 @@
public void close()
{
- ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
if ( tracker != null )
{
RefPair<S, T> ref;
@@ -1089,7 +1111,7 @@
return isOptional();
}
- public void setTracker( ServiceTracker<T, RefPair<S, T>> tRefPairServiceTracker )
+ public void setTracker( ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tRefPairServiceTracker )
{
}
@@ -1106,15 +1128,15 @@
return null;
}
- public void addedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, int serviceCount )
+ public void addedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, int serviceCount, ExtendedServiceEvent event )
{
}
- public void modifiedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount )
+ public void modifiedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, ExtendedServiceEvent event )
{
}
- public void removedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount )
+ public void removedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, ExtendedServiceEvent event )
{
}
}
@@ -1316,7 +1338,7 @@
*/
private RefPair<S, T> getRefPair( ServiceReference<T> serviceReference )
{
- final ServiceTracker<T, RefPair<S, T>> tracker = m_tracker;
+ final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
if ( tracker != null )
{
AtomicInteger trackingCount = new AtomicInteger( );
@@ -1873,6 +1895,8 @@
return minimumCardinality;
}
+ private static final String OBJECTCLASS_CLAUSE = "(" + Constants.OBJECTCLASS + "=";
+ private static final String PROTOTYPE_SCOPE_CLAUSE = "(" + Constants.SERVICE_SCOPE + "=" + Constants.SCOPE_PROTOTYPE + ")";
/**
* Sets the target filter of this dependency to the new filter value. If the
@@ -1904,41 +1928,45 @@
}
m_target = target;
final boolean multipleExpr = m_target != null || m_dependencyMetadata.getScope() == ReferenceScope.prototype_required;
- final StringBuilder filterSB = new StringBuilder();
+ final boolean allExpr = m_target != null && m_dependencyMetadata.getScope() == ReferenceScope.prototype_required;
+ final StringBuilder initialReferenceFilterSB = new StringBuilder();
if (multipleExpr )
{
- filterSB.append("(&");
+ initialReferenceFilterSB.append("(&");
}
// "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")"
- filterSB.append('(');
- filterSB.append(Constants.OBJECTCLASS);
- filterSB.append('=');
- filterSB.append(m_dependencyMetadata.getInterface());
- filterSB.append(')');
+ String classFilterString = OBJECTCLASS_CLAUSE + m_dependencyMetadata.getInterface() + ")";
+ initialReferenceFilterSB.append(classFilterString);
// if reference scope is prototype_required, we simply add
- // service.scope=prototype to the filter
+ // (service.scope=prototype) to the filter
if ( m_dependencyMetadata.getScope() == ReferenceScope.prototype_required )
{
- filterSB.append('(');
- filterSB.append(Constants.SERVICE_SCOPE);
- filterSB.append('=');
- filterSB.append(Constants.SCOPE_PROTOTYPE);
- filterSB.append(')');
+ initialReferenceFilterSB.append(PROTOTYPE_SCOPE_CLAUSE);
}
// append target
if ( m_target != null )
{
- filterSB.append(m_target);
+ initialReferenceFilterSB.append(m_target);
}
if (multipleExpr )
{
- filterSB.append(')');
+ initialReferenceFilterSB.append(')');
}
- String filterString = filterSB.toString();
+ String initialReferenceFilterString= initialReferenceFilterSB.toString();
+ String eventFilterString;
+ if (allExpr)
+ {
+ StringBuilder sb = new StringBuilder("(&").append(PROTOTYPE_SCOPE_CLAUSE).append(m_target).append(")");
+ eventFilterString = sb.toString();
+ }
+ else
+ {
+ eventFilterString = m_target;
+ }
- final ServiceTracker<T, RefPair<S, T>> oldTracker = m_tracker;
+ final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> oldTracker = m_tracker;
AtomicInteger trackingCount = new AtomicInteger();
SortedMap<ServiceReference<T>, RefPair<S, T>> refMap = unregisterServiceListener( trackingCount );
if ( trackingCount.get() != -1 )
@@ -1949,29 +1977,34 @@
m_componentManager.log( LogService.LOG_DEBUG, "Setting target property for dependency {0} to {1}", new Object[]
{getName(), target}, null );
BundleContext bundleContext = m_componentManager.getBundleContext();
+ Filter eventFilter = null;
if ( bundleContext != null )
{
- try
+ if ( eventFilterString != null )
{
- m_targetFilter = bundleContext.createFilter( filterString );
- }
- catch ( InvalidSyntaxException ise )
- {
- m_componentManager.log( LogService.LOG_ERROR, "Invalid syntax in target property for dependency {0} to {1}", new Object[]
- {getName(), target}, null );
-
- //create a filter that will never be satisfied
- filterString = "(component.id=-1)";
try
{
- m_targetFilter = bundleContext.createFilter( filterString );
+ eventFilter = bundleContext.createFilter(eventFilterString);
}
- catch ( InvalidSyntaxException e )
+ catch (InvalidSyntaxException ise)
{
- //this should not happen
- return;
- }
+ m_componentManager.log(LogService.LOG_ERROR,
+ "Invalid syntax in target property for dependency {0} to {1}",
+ new Object[] { getName(), target }, null);
+ //create a filter that will never be satisfied
+ eventFilterString = "(component.id=-1)";
+ try
+ {
+ eventFilter = bundleContext.createFilter(eventFilterString);
+ }
+ catch (InvalidSyntaxException e)
+ {
+ //this should not happen
+ return;
+ }
+
+ }
}
}
else
@@ -1983,9 +2016,15 @@
m_customizer.setPreviousRefMap( refMap );
boolean initialActive = oldTracker != null && oldTracker.isActive();
- m_componentManager.log( LogService.LOG_DEBUG, "New service tracker for {0}, initial active: {1}, previous references: {2}", new Object[]
- {getName(), initialActive, refMap}, null );
- ServiceTracker<T, RefPair<S, T>> tracker = new ServiceTracker<T, RefPair<S, T>>( bundleContext, m_targetFilter, m_customizer, initialActive );
+ m_componentManager.log( LogService.LOG_DEBUG, "New service tracker for {0}, initial active: {1}, previous references: {2}, classFilter: {3}, eventFilter {4}, initialReferenceFilter {5}", new Object[]
+ {getName(), initialActive, refMap, classFilterString, eventFilter, initialReferenceFilterString}, null );
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = new ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent>( bundleContext,
+ m_customizer,
+ initialActive,
+ m_componentManager.getActivator(),
+ eventFilter,
+ classFilterString,
+ initialReferenceFilterString);
m_customizer.setTracker( tracker );
//set minimum cardinality
m_minCardinality = minimumCardinality;
@@ -2048,7 +2087,7 @@
SortedMap<ServiceReference<T>, RefPair<S, T>> unregisterServiceListener( AtomicInteger trackingCount )
{
SortedMap<ServiceReference<T>, RefPair<S, T>> refMap;
- ServiceTracker<T, RefPair<S, T>> tracker = m_tracker;
+ ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
if ( tracker != null )
{
refMap = tracker.close( trackingCount );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceEvent.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceEvent.java
new file mode 100644
index 0000000..f06345a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceEvent.java
@@ -0,0 +1,63 @@
+/*
+ * 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.manager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+
+public class ExtendedServiceEvent extends ServiceEvent
+{
+ private List<AbstractComponentManager<?>> managers;
+
+ public ExtendedServiceEvent(ServiceEvent source)
+ {
+ super(source.getType(), source.getServiceReference());
+ }
+
+ public ExtendedServiceEvent(int type, ServiceReference ref)
+ {
+ super(type, ref);
+ }
+
+ public void addComponentManager(AbstractComponentManager<?> manager)
+ {
+ if (managers == null)
+ managers = new ArrayList<AbstractComponentManager<?>>();
+ managers.add(manager);
+ }
+
+ public List<AbstractComponentManager<?>> getManagers()
+ {
+ return managers == null ? Collections.<AbstractComponentManager<?>> emptyList()
+ : managers;
+ }
+
+ public void activateManagers()
+ {
+ for (AbstractComponentManager<?> manager : getManagers())
+ {
+ manager.activateInternal();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListener.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListener.java
new file mode 100644
index 0000000..55b31b3
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListener.java
@@ -0,0 +1,26 @@
+/*
+ * 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.manager;
+
+import org.osgi.framework.ServiceEvent;
+
+public interface ExtendedServiceListener<U extends ServiceEvent>
+{
+ void serviceChanged(U event);
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListenerContext.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListenerContext.java
new file mode 100644
index 0000000..3583ea2
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListenerContext.java
@@ -0,0 +1,32 @@
+/*
+ * 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.manager;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+
+public interface ExtendedServiceListenerContext<U extends ServiceEvent>
+{
+
+ void addServiceListener(String className, Filter filter,
+ ExtendedServiceListener<U> listener);
+
+ void removeServiceListener(String className, Filter filter,
+ ExtendedServiceListener<U> listener);
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
index ab37e62..5a811a4 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
@@ -27,13 +27,11 @@
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
-import org.osgi.framework.AllServiceListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
@@ -72,7 +70,7 @@
* @param <S>
* @param <T>
*/
-public class ServiceTracker<S, T> {
+public class ServiceTracker<S, T, U extends ServiceEvent> {
/* set this to true to compile in debug messages */
static final boolean DEBUG = false;
/**
@@ -85,27 +83,18 @@
*
* @since 1.1
*/
- protected final Filter filter;
+ protected final Filter eventFilter;
/**
* The {@code ServiceTrackerCustomizer} for this tracker.
*/
- final ServiceTrackerCustomizer<S, T> customizer;
+ final ServiceTrackerCustomizer<S, T, U> customizer;
/**
* Filter string for use when adding the ServiceListener. If this field is
* set, then certain optimizations can be taken since we don't have a user
* supplied filter.
*/
- final String listenerFilter;
- /**
- * Class name to be tracked. If this field is set, then we are tracking by
- * class name.
- */
- private final String trackClass;
- /**
- * Reference to be tracked. If this field is set, then we are tracking a
- * single ServiceReference.
- */
- private final ServiceReference<S> trackReference;
+ final String initialReferenceFilterString;
+
/**
* Tracked services: {@code ServiceReference} -> customized Object and
* {@code ServiceListener} object
@@ -129,93 +118,9 @@
return tracked;
}
- /**
- * Cached ServiceReference for getServiceReference.
- *
- * This field is volatile since it is accessed by multiple threads.
- */
- private volatile ServiceReference<S> cachedReference;
- /**
- * Cached service object for getService.
- *
- * This field is volatile since it is accessed by multiple threads.
- */
- private volatile T cachedService;
+ private ExtendedServiceListenerContext<U> extendedServiceListenerContext;
+ private String classFilterString;
- /**
- * Create a {@code ServiceTracker} on the specified {@code ServiceReference}
- * .
- *
- * <p>
- * The service referenced by the specified {@code ServiceReference} will be
- * tracked by this {@code ServiceTracker}.
- *
- * @param context The {@code BundleContext} against which the tracking is
- * done.
- * @param reference The {@code ServiceReference} for the service to be
- * tracked.
- * @param customizer The customizer object to call when services are added,
- * modified, or removed in this {@code ServiceTracker}. If customizer
- * is {@code null}, then this {@code ServiceTracker} will be used as
- * the {@code ServiceTrackerCustomizer} and this
- * {@code ServiceTracker} will call the
- * {@code ServiceTrackerCustomizer} methods on itself.
- */
- public ServiceTracker(final BundleContext context, final ServiceReference<S> reference, final ServiceTrackerCustomizer<S, T> customizer) {
- this.context = context;
- this.trackReference = reference;
- this.trackClass = null;
- this.customizer = customizer;
- this.listenerFilter = "(" + Constants.SERVICE_ID + "=" + reference.getProperty(Constants.SERVICE_ID).toString() + ")";
- try {
- this.filter = context.createFilter(listenerFilter);
- } catch (InvalidSyntaxException e) {
- /*
- * we could only get this exception if the ServiceReference was
- * invalid
- */
- IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
- iae.initCause(e);
- throw iae;
- }
- }
-
- /**
- * Create a {@code ServiceTracker} on the specified class name.
- *
- * <p>
- * Services registered under the specified class name will be tracked by
- * this {@code ServiceTracker}.
- *
- * @param context The {@code BundleContext} against which the tracking is
- * done.
- * @param clazz The class name of the services to be tracked.
- * @param customizer The customizer object to call when services are added,
- * modified, or removed in this {@code ServiceTracker}. If customizer
- * is {@code null}, then this {@code ServiceTracker} will be used as
- * the {@code ServiceTrackerCustomizer} and this
- * {@code ServiceTracker} will call the
- * {@code ServiceTrackerCustomizer} methods on itself.
- */
- public ServiceTracker(final BundleContext context, final String clazz, final ServiceTrackerCustomizer<S, T> customizer) {
- this.context = context;
- this.trackReference = null;
- this.trackClass = clazz;
- this.customizer = customizer;
- // we call clazz.toString to verify clazz is non-null!
- this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz + ")";
- try {
- this.filter = context.createFilter(listenerFilter);
- } catch (InvalidSyntaxException e) {
- /*
- * we could only get this exception if the clazz argument was
- * malformed
- */
- IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
- iae.initCause(e);
- throw iae;
- }
- }
/**
* Create a {@code ServiceTracker} on the specified {@code Filter} object.
@@ -226,51 +131,38 @@
*
* @param context The {@code BundleContext} against which the tracking is
* done.
- * @param filter The {@code Filter} to select the services to be tracked.
* @param customizer The customizer object to call when services are added,
* modified, or removed in this {@code ServiceTracker}. If customizer
* is null, then this {@code ServiceTracker} will be used as the
* {@code ServiceTrackerCustomizer} and this {@code ServiceTracker}
* will call the {@code ServiceTrackerCustomizer} methods on itself.
* @param initialActive Initial active state of the tracker.
+ * @param bundleComponentActivator TODO
+ * @param eventFilter The {@code Filter} to select the services to be tracked.
+ * @param classFilterString TODO
+ * @param initialReferenceFilterString TODO
* @since 1.1
*/
- public ServiceTracker(final BundleContext context, final Filter filter, final ServiceTrackerCustomizer<S, T> customizer, boolean initialActive) {
+ public ServiceTracker(final BundleContext context,
+ final ServiceTrackerCustomizer<S, T, U> customizer,
+ boolean initialActive,
+ ExtendedServiceListenerContext<U> bundleComponentActivator,
+ final Filter eventFilter,
+ final String classFilterString,
+ final String initialReferenceFilterString) {
+ if ((context == null)) {
+ /*
+ * we throw a NPE here to be consistent with the other constructors
+ */
+ throw new NullPointerException( "BundleContext");
+ }
this.context = context;
- this.trackReference = null;
- this.trackClass = null;
- this.listenerFilter = filter.toString();
- this.filter = filter;
+ this.initialReferenceFilterString = initialReferenceFilterString;
+ this.eventFilter = eventFilter;
this.customizer = customizer;
this.active = initialActive;
- if ((context == null)) {
- /*
- * we throw a NPE here to be consistent with the other constructors
- */
- throw new NullPointerException( "BundleContext");
- }
- }
-
- /**
- * Create a {@code ServiceTracker} on the specified class.
- *
- * <p>
- * Services registered under the name of the specified class will be tracked
- * by this {@code ServiceTracker}.
- *
- * @param context The {@code BundleContext} against which the tracking is
- * done.
- * @param clazz The class of the services to be tracked.
- * @param customizer The customizer object to call when services are added,
- * modified, or removed in this {@code ServiceTracker}. If customizer
- * is {@code null}, then this {@code ServiceTracker} will be used as
- * the {@code ServiceTrackerCustomizer} and this
- * {@code ServiceTracker} will call the
- * {@code ServiceTrackerCustomizer} methods on itself.
- * @since 1.5
- */
- public ServiceTracker(final BundleContext context, final Class<S> clazz, final ServiceTrackerCustomizer<S, T> customizer) {
- this(context, clazz.getName(), customizer);
+ this.extendedServiceListenerContext = bundleComponentActivator;
+ this.classFilterString = classFilterString;
}
/**
@@ -315,25 +207,13 @@
return;
}
if (DEBUG) {
- System.out.println("ServiceTracker.open: " + filter);
+ System.out.println("ServiceTracker.open: " + eventFilter);
}
- t = trackAllServices ? new AllTracked( trackingCount ) : new Tracked( trackingCount );
+ t = new Tracked( trackingCount );
synchronized (t) {
try {
- context.addServiceListener(t, listenerFilter);
- ServiceReference<S>[] references = null;
- if (trackClass != null) {
- references = getInitialReferences(trackAllServices, trackClass, null);
- } else {
- if (trackReference != null) {
- if (trackReference.getBundle() != null) {
- ServiceReference<S>[] single = new ServiceReference[] {trackReference};
- references = single;
- }
- } else { /* user supplied filter */
- references = getInitialReferences(trackAllServices, null, listenerFilter);
- }
- }
+ extendedServiceListenerContext.addServiceListener(classFilterString, eventFilter, t);
+ ServiceReference<S>[] references = getInitialReferences(null, initialReferenceFilterString);
/* set tracked with the initial references */
t.setInitial(references);
} catch (InvalidSyntaxException e) {
@@ -349,18 +229,16 @@
/**
* Returns the list of initial {@code ServiceReference}s that will be
* tracked by this {@code ServiceTracker}.
- *
- * @param trackAllServices If {@code true}, use
- * {@code getAllServiceReferences}.
* @param className The class name with which the service was registered, or
* {@code null} for all services.
* @param filterString The filter criteria or {@code null} for all services.
+ *
* @return The list of initial {@code ServiceReference}s.
* @throws InvalidSyntaxException If the specified filterString has an
* invalid syntax.
*/
- private ServiceReference<S>[] getInitialReferences(boolean trackAllServices, String className, String filterString) throws InvalidSyntaxException {
- ServiceReference<S>[] result = (ServiceReference<S>[]) ((trackAllServices) ? context.getAllServiceReferences(className, filterString) : context.getServiceReferences(className, filterString));
+ private ServiceReference<S>[] getInitialReferences(String className, String filterString) throws InvalidSyntaxException {
+ ServiceReference<S>[] result = (ServiceReference<S>[]) context.getServiceReferences(className, filterString);
return result;
}
@@ -386,7 +264,7 @@
return map;
}
if (DEBUG) {
- System.out.println("ServiceTracker.close: " + filter);
+ System.out.println("ServiceTracker.close: " + eventFilter);
}
outgoing.close();
synchronized ( outgoing )
@@ -397,7 +275,7 @@
// references = getServiceReferences();
// tracked = null;
try {
- context.removeServiceListener(outgoing);
+ extendedServiceListenerContext.removeServiceListener(classFilterString, eventFilter, outgoing);
} catch (IllegalStateException e) {
/* In case the context was stopped. */
}
@@ -412,9 +290,7 @@
// }
// }
if (DEBUG) {
- if ((cachedReference == null) && (cachedService == null)) {
- System.out.println("ServiceTracker.close[cached cleared]: " + filter);
- }
+ System.out.println("ServiceTracker.close[cached cleared]: " + eventFilter);
}
return map;
}
@@ -427,7 +303,7 @@
return;
}
if (DEBUG) {
- System.out.println("ServiceTracker.close: " + filter);
+ System.out.println("ServiceTracker.close: " + eventFilter);
}
}
for (ServiceReference<S> ref: toUntrack.keySet()) {
@@ -479,7 +355,7 @@
*
* @param reference The reference to modified service.
* @param service The service object for the modified service.
- * @see ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, Object, int)
+ * @see ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, Object, int, ServiceEvent)
*/
public void modifiedService(ServiceReference<S> reference, T service, int trackingCount) {
/* do nothing */
@@ -504,67 +380,13 @@
*
* @param reference The reference to removed service.
* @param service The service object for the removed service.
- * @see ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, Object, int)
+ * @see ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, Object, int, ServiceEvent)
*/
public void removedService(ServiceReference<S> reference, T service, int trackingCount) {
context.ungetService(reference);
}
/**
- * Wait for at least one service to be tracked by this
- * {@code ServiceTracker}. This method will also return when this
- * {@code ServiceTracker} is closed.
- *
- * <p>
- * It is strongly recommended that {@code waitForService} is not used during
- * the calling of the {@code BundleActivator} methods.
- * {@code BundleActivator} methods are expected to complete in a short
- * period of time.
- *
- * <p>
- * This implementation calls {@link #getService()} to determine if a service
- * is being tracked.
- *
- * @param timeout The time interval in milliseconds to wait. If zero, the
- * method will wait indefinitely.
- * @return Returns the result of {@link #getService()}.
- * @throws InterruptedException If another thread has interrupted the
- * current thread.
- * @throws IllegalArgumentException If the value of timeout is negative.
- */
- public T waitForService(long timeout) throws InterruptedException {
- if (timeout < 0) {
- throw new IllegalArgumentException("timeout value is negative");
- }
-
- T object = getService();
- if (object != null) {
- return object;
- }
-
- final long endTime = (timeout == 0) ? 0 : (System.currentTimeMillis() + timeout);
- do {
- final Tracked t = tracked();
- if (t == null) { /* if ServiceTracker is not open */
- return null;
- }
- synchronized (t) {
- if (t.size() == 0) {
- t.wait(timeout);
- }
- }
- object = getService();
- if (endTime > 0) { // if we have a timeout
- timeout = endTime - System.currentTimeMillis();
- if (timeout <= 0) { // that has expired
- break;
- }
- }
- } while (object == null);
- return object;
- }
-
- /**
* Return an array of {@code ServiceReference}s for all services being
* tracked by this {@code ServiceTracker}.
*
@@ -586,76 +408,6 @@
}
}
- /**
- * Returns a {@code ServiceReference} for one of the services being tracked
- * by this {@code ServiceTracker}.
- *
- * <p>
- * If multiple services are being tracked, the service with the highest
- * ranking (as specified in its {@code service.ranking} property) is
- * returned. If there is a tie in ranking, the service with the lowest
- * service ID (as specified in its {@code service.id} property); that is,
- * the service that was registered first is returned. This is the same
- * algorithm used by {@code BundleContext.getServiceReference}.
- *
- * <p>
- * This implementation calls {@link #getServiceReferences()} to get the list
- * of references for the tracked services.
- *
- * @return A {@code ServiceReference} or {@code null} if no services are
- * being tracked.
- * @since 1.1
- */
- public ServiceReference<S> getServiceReference() {
- ServiceReference<S> reference = cachedReference;
- if (reference != null) {
- if (DEBUG) {
- System.out.println("ServiceTracker.getServiceReference[cached]: " + filter);
- }
- return reference;
- }
- if (DEBUG) {
- System.out.println("ServiceTracker.getServiceReference: " + filter);
- }
- ServiceReference<S>[] references = getServiceReferences();
- int length = (references == null) ? 0 : references.length;
- if (length == 0) { /* if no service is being tracked */
- return null;
- }
- int index = 0;
- if (length > 1) { /* if more than one service, select highest ranking */
- int rankings[] = new int[length];
- int count = 0;
- int maxRanking = Integer.MIN_VALUE;
- for (int i = 0; i < length; i++) {
- Object property = references[i].getProperty(Constants.SERVICE_RANKING);
- int ranking = (property instanceof Integer) ? ((Integer) property).intValue() : 0;
- rankings[i] = ranking;
- if (ranking > maxRanking) {
- index = i;
- maxRanking = ranking;
- count = 1;
- } else {
- if (ranking == maxRanking) {
- count++;
- }
- }
- }
- if (count > 1) { /* if still more than one service, select lowest id */
- long minId = Long.MAX_VALUE;
- for (int i = 0; i < length; i++) {
- if (rankings[i] == maxRanking) {
- long id = ((Long) (references[i].getProperty(Constants.SERVICE_ID))).longValue();
- if (id < minId) {
- index = i;
- minId = id;
- }
- }
- }
- }
- }
- return cachedReference = references[index];
- }
/**
* Returns the service object for the specified {@code ServiceReference} if
@@ -708,34 +460,6 @@
}
}
- /**
- * Returns a service object for one of the services being tracked by this
- * {@code ServiceTracker}.
- *
- * <p>
- * If any services are being tracked, this implementation returns the result
- * of calling {@code getService(getServiceReference())}.
- *
- * @return A service object or {@code null} if no services are being
- * tracked.
- */
- public T getService() {
- T service = cachedService;
- if (service != null) {
- if (DEBUG) {
- System.out.println("ServiceTracker.getService[cached]: " + filter);
- }
- return service;
- }
- if (DEBUG) {
- System.out.println("ServiceTracker.getService: " + filter);
- }
- ServiceReference<S> reference = getServiceReference();
- if (reference == null) {
- return null;
- }
- return cachedService = getService(reference);
- }
/**
* Remove a service from this {@code ServiceTracker}.
@@ -810,10 +534,8 @@
* between the listener thread and the user thread.
*/
void modified() {
- cachedReference = null; /* clear cached value */
- cachedService = null; /* clear cached value */
if (DEBUG) {
- System.out.println("ServiceTracker.modified: " + filter);
+ System.out.println("ServiceTracker.modified: " + eventFilter);
}
}
@@ -1106,11 +828,12 @@
if (DEBUG) {
System.out.println("AbstractTracked.trackInitial: " + item); //$NON-NLS-1$
}
- trackAdding(item, null); /*
- * Begin tracking it. We call trackAdding
- * since we have already put the item in the
- * adding list.
- */
+ /*
+ * Begin tracking it. We call trackAdding
+ * since we have already put the item in the
+ * adding list.
+ */
+ trackAdding(item, null);
}
}
@@ -1410,7 +1133,7 @@
*
* @ThreadSafe
*/
- private class Tracked extends AbstractTracked<ServiceReference<S>, T, ServiceEvent> implements ServiceListener {
+ private class Tracked extends AbstractTracked<ServiceReference<S>, T, U> implements ExtendedServiceListener<U> {
/**
* Tracked constructor.
* @param trackingCount
@@ -1425,7 +1148,7 @@
*
* @param event {@code ServiceEvent} object from the framework.
*/
- final public void serviceChanged(final ServiceEvent event) {
+ final public void serviceChanged(final U event) {
/*
* Check if we had a delayed call (which could happen when we
* close).
@@ -1484,12 +1207,12 @@
* @return Customized object for the tracked item or {@code null} if the
* item is not to be tracked.
*/
- final T customizerAdding( final ServiceReference<S> item, final ServiceEvent related ) {
+ final T customizerAdding( final ServiceReference<S> item, final U related ) {
return customizer.addingService( item );
}
- final void customizerAdded( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount, int serviceCount ) {
- customizer.addedService( item, object, trackingCount, serviceCount );
+ final void customizerAdded( final ServiceReference<S> item, final U related, final T object, int trackingCount, int serviceCount ) {
+ customizer.addedService( item, object, trackingCount, serviceCount, related );
}
/**
@@ -1501,8 +1224,8 @@
* @param object Customized object for the tracked item.
* @param trackingCount
*/
- final void customizerModified( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
- customizer.modifiedService( item, object, trackingCount );
+ final void customizerModified( final ServiceReference<S> item, final U related, final T object, int trackingCount ) {
+ customizer.modifiedService( item, object, trackingCount, related );
}
/**
@@ -1514,8 +1237,8 @@
* @param object Customized object for the tracked item.
* @param trackingCount
*/
- final void customizerRemoved( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
- customizer.removedService(item, object, trackingCount );
+ final void customizerRemoved( final ServiceReference<S> item, final U related, final T object, int trackingCount ) {
+ customizer.removedService(item, object, trackingCount, related );
}
}
@@ -1526,13 +1249,13 @@
* @since 1.3
* @ThreadSafe
*/
- private class AllTracked extends Tracked implements AllServiceListener {
- /**
- * AllTracked constructor.
- * @param trackingCount
- */
- AllTracked( AtomicInteger trackingCount ) {
- super( trackingCount );
- }
- }
+// private class AllTracked extends Tracked<U> implements AllServiceListener {
+// /**
+// * AllTracked constructor.
+// * @param trackingCount
+// */
+// AllTracked( AtomicInteger trackingCount ) {
+// super( trackingCount );
+// }
+// }
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
index 84403ec..6f0c794 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
@@ -16,6 +16,7 @@
package org.apache.felix.scr.impl.manager;
+import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceReference;
/**
@@ -47,7 +48,7 @@
* @ThreadSafe
* @version $Id: c14b8d47026b6bd4ba1f2db7bf7e755d00fc6f6a $
*/
-public interface ServiceTrackerCustomizer<S, T> {
+public interface ServiceTrackerCustomizer<S, T, U extends ServiceEvent> {
/**
* A service is being added to the {@code ServiceTracker}.
*
@@ -69,7 +70,7 @@
*/
public T addingService( ServiceReference<S> reference );
- public void addedService( ServiceReference<S> reference, T service, int trackingCount, int serviceCount );
+ public void addedService( ServiceReference<S> reference, T service, int trackingCount, int serviceCount, U event );
/**
* A service tracked by the {@code ServiceTracker} has been modified.
@@ -79,10 +80,11 @@
* {@code ServiceTracker} has had it properties modified.
*
* @param reference The reference to the service that has been modified.
- * @param service The service object for the specified referenced service.
- * @param trackingCount
+ * @param service The service object for the specified referenced service.
+ * @param trackingCount
+ * @param event TODO
*/
- public void modifiedService( ServiceReference<S> reference, T service, int trackingCount );
+ public void modifiedService( ServiceReference<S> reference, T service, int trackingCount, U event );
/**
* A service tracked by the {@code ServiceTracker} has been removed.
@@ -94,7 +96,8 @@
* @param reference The reference to the service that has been removed.
* @param service The service object for the specified referenced service.
* @param trackingCount
+ * @param event TODO
*/
- public void removedService( ServiceReference<S> reference, T service, int trackingCount );
+ public void removedService( ServiceReference<S> reference, T service, int trackingCount, U event );
}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
index d6f60bf..9854c33 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
@@ -374,7 +374,7 @@
Collection<ServiceReference<S>> srs;
try {
srs = bundleContext.getServiceReferences(clazz, filter);
- Assert.assertEquals(1, srs.size());
+ Assert.assertEquals("Nothing for filter: " + filter, 1, srs.size());
ServiceReference<S> sr = srs.iterator().next();
S s = bundleContext.getService(sr);
Assert.assertNotNull(s);
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java b/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java
index 6674ee4..cd01550 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java
@@ -46,18 +46,20 @@
{
bundleContext.registerService( Object.class, new Object(), null );
- findComponentConfigurationByName( "AsyncLocate", ComponentConfigurationDTO.ACTIVE );
+ findComponentConfigurationByName( "Consumer", ComponentConfigurationDTO.ACTIVE );
- final String pid = "SimpleComponent";
+ final String pid = "TestComponent";
Configuration config = getConfigurationAdmin().getConfiguration( pid, null );
final Hashtable props = new Hashtable();
+ //wrong target property, will not bind
props.put( "target", "bar" );
config.update(props);
delay();
//when deadlock is present the state is actually unsatisfied.
- ComponentConfigurationDTO cc = findComponentConfigurationByName( pid, ComponentConfigurationDTO.ACTIVE );
- delay();
+ ComponentConfigurationDTO cc = findComponentConfigurationByName( pid, ComponentConfigurationDTO.SATISFIED );
+// delay();
+ //correct target property: will bind as new properties are propagated.
props.put( "target", "foo" );
config.update(props);
delay();
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java b/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java
index b99d824..4673cdb 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java
@@ -31,12 +31,12 @@
this.cc = cc;
}
- protected void setSimpleComponent(TestComponent sc)
+ protected void setTestComponent(TestComponent tc)
{
- sc.doIt( );
+ tc.doIt( );
}
- protected void unsetSimpleComponent(ServiceReference<TestComponent> sr)
+ protected void unsetTestComponent(ServiceReference<TestComponent> sr)
{
}
diff --git a/scr/src/test/resources/integration_test_locate.xml b/scr/src/test/resources/integration_test_locate.xml
index 1ca586e..9e285c8 100644
--- a/scr/src/test/resources/integration_test_locate.xml
+++ b/scr/src/test/resources/integration_test_locate.xml
@@ -11,7 +11,7 @@
language governing permissions and limitations under the License. -->
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
- <scr:component name="SimpleComponent"
+ <scr:component name="TestComponent"
configuration-policy="require">
<implementation class="org.apache.felix.scr.integration.components.deadlock.TestComponent" />
<service>
@@ -28,17 +28,17 @@
</scr:component>
- <scr:component name="AsyncLocate"
+ <scr:component name="Consumer"
immediate="true">
<implementation class="org.apache.felix.scr.integration.components.deadlock.Consumer" />
<reference
- name="SimpleComponent"
+ name="TestComponent"
interface="org.apache.felix.scr.integration.components.deadlock.TestComponent"
cardinality="0..1"
policy="dynamic"
- bind="setSimpleComponent"
- unbind="unsetSimpleComponent"
- target='target="foo"'
+ bind="setTestComponent"
+ unbind="unsetTestComponent"
+ target='(target=foo)'
/>
</scr:component>