You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ui...@apache.org on 2014/05/19 08:47:08 UTC
svn commit: r1595756 [2/2] - in
/felix/sandbox/pderop/dependencymanager-prototype: dm.it/src/dm/it/
dm/src/dm/ dm/src/dm/impl/ dm/src/dm/impl/index/
dm/src/dm/impl/index/multiproperty/ dm/src/dm/impl/metatype/ dm/src/tracker/
Added: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AspectServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AspectServiceImpl.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AspectServiceImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AspectServiceImpl.java Mon May 19 06:47:07 2014
@@ -0,0 +1,242 @@
+/*
+ * 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 dm.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import dm.Component;
+import dm.ComponentStateListener;
+import dm.Dependency;
+import dm.DependencyManager;
+import dm.ServiceDependency;
+import dm.context.DependencyContext;
+
+public class AspectServiceImpl extends FilterComponent {
+
+ private final String m_add;
+ private final String m_change;
+ private final String m_remove;
+ private final String m_swap;
+ private int m_ranking;
+
+ public AspectServiceImpl(DependencyManager dm, Class<?> aspectInterface, String aspectFilter, int ranking, String autoConfig, String add, String change, String remove, String swap) {
+ super(dm.createComponent());
+ this.m_ranking = ranking;
+ this.m_add = add;
+ this.m_change = change;
+ this.m_remove = remove;
+ this.m_swap = swap;
+
+ m_component.setImplementation(new AspectImpl(aspectInterface, autoConfig))
+ .add(dm.createServiceDependency()
+ .setService(aspectInterface, createDependencyFilterForAspect(aspectFilter))
+ .setAutoConfig(false)
+ .setCallbacks("added", "removed"))
+ .setCallbacks("init", null, "stop", null);
+
+// m_component.setDebug("aspectfactory-" + m_ranking);
+ }
+
+ private String createDependencyFilterForAspect(String aspectFilter) {
+ // we only want to match services which are not themselves aspects
+ if (aspectFilter == null || aspectFilter.length() == 0) {
+ return "(!(" + DependencyManager.ASPECT + "=*))";
+ }
+ else {
+ return "(&(!(" + DependencyManager.ASPECT + "=*))" + aspectFilter + ")";
+ }
+ }
+
+ private Properties getServiceProperties(ServiceReference ref) {
+ Properties props = new Properties();
+ String[] keys = ref.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ String key = keys[i];
+ if (key.equals(Constants.SERVICE_ID) || key.equals(Constants.SERVICE_RANKING) || key.equals(DependencyManager.ASPECT) || key.equals(Constants.OBJECTCLASS)) {
+ // do not copy these
+ }
+ else {
+ props.put(key, ref.getProperty(key));
+ }
+ }
+ if (m_serviceProperties != null) {
+ Enumeration<?> e = m_serviceProperties.keys();
+ while (e.hasMoreElements()) {
+ Object key = e.nextElement();
+ props.put(key, m_serviceProperties.get(key));
+ }
+ }
+ // finally add our aspect property
+ props.put(DependencyManager.ASPECT, ref.getProperty(Constants.SERVICE_ID));
+ // and the ranking
+ props.put(Constants.SERVICE_RANKING, Integer.valueOf(m_ranking));
+ return props;
+ }
+
+ class AspectImpl extends AbstractDecorator {
+
+ private final Class<?> m_aspectInterface;
+ private final String m_autoConfig;
+
+ public AspectImpl(Class<?> aspectInterface, String autoConfig) {
+ this.m_aspectInterface = aspectInterface;
+ this.m_autoConfig = autoConfig;
+ }
+
+ /**
+ * Creates an aspect implementation component for a new original service.
+ * @param param First entry contains the ref to the original service
+ */
+ @Override
+ public Component createService(Object[] params) {
+ // Get the new original service reference.
+ ServiceReference ref = (ServiceReference) params[0];
+ List<DependencyContext> dependencies = m_component.getDependencies();
+ // remove our internal dependency, replace it with one that points to the specific service that just was passed in.
+ dependencies.remove(0);
+ Properties serviceProperties = getServiceProperties(ref);
+ String[] serviceInterfaces = getServiceInterfaces();
+
+ ServiceDependency aspectDependency = (ServiceDependencyImpl)
+ m_manager.createServiceDependency().setService(m_aspectInterface, createAspectFilter(ref)).setRequired(true);
+ aspectDependency.setDebug("aspect " + m_ranking);
+
+ aspectDependency.setCallbacks(new CallbackProxy(aspectDependency, ref),
+ m_add != null ? "addAspect" : null,
+ "changeAspect", // We have to propagate in case aspect does not have a change callback
+ m_remove != null ? "removeAspect" : null,
+ m_swap != null ? "swapAspect" : null);
+
+ if (m_autoConfig != null) {
+ aspectDependency.setAutoConfig(m_autoConfig);
+ } else if (m_add == null && m_change == null && m_remove == null && m_swap == null) {
+ // Since we have set callbacks, we must reactivate setAutoConfig because user has not specified any callbacks.
+ aspectDependency.setAutoConfig(true);
+ }
+
+ Component service = m_manager.createComponent()
+ .setInterface(serviceInterfaces, serviceProperties)
+ .setImplementation(m_serviceImpl)
+ .setFactory(m_factory, m_factoryCreateMethod) // if not set, no effect
+ .setComposition(m_compositionInstance, m_compositionMethod) // if not set, no effect
+ .setCallbacks(m_callbackObject, m_init, m_start, m_stop, m_destroy) // if not set, no effect
+ .add(aspectDependency);
+
+ service.setDebug("aspectimpl-" + m_ranking);
+
+ configureAutoConfigState(service, m_component);
+
+ for (DependencyContext dc : dependencies) {
+ service.add((Dependency) dc.createCopy());
+ }
+
+ for (int i = 0; i < m_stateListeners.size(); i++) {
+ service.add((ComponentStateListener) m_stateListeners.get(i));
+ }
+ return service;
+ }
+
+ private String[] getServiceInterfaces() {
+ List<String> serviceNames = new ArrayList<>();
+ // Of course, we provide the aspect interface.
+ serviceNames.add(m_aspectInterface.getName());
+ // But also append additional aspect implementation interfaces.
+ if (m_serviceInterfaces != null) {
+ for (int i = 0; i < m_serviceInterfaces.length; i ++) {
+ if (!m_serviceInterfaces[i].equals(m_aspectInterface.getName())) {
+ serviceNames.add(m_serviceInterfaces[i]);
+ }
+ }
+ }
+ return (String[]) serviceNames.toArray(new String[serviceNames.size()]);
+ }
+
+ private String createAspectFilter(ServiceReference ref) {
+ Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
+ return "(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))(|(" + Constants.SERVICE_ID + "=" + sid + ")(" + DependencyManager.ASPECT + "=" + sid + ")))";
+ }
+
+ }
+
+ class CallbackProxy {
+ private final ServiceDependencyImpl m_aspectDependency;
+ private final ServiceReference m_originalServiceRef;
+
+ CallbackProxy(ServiceDependency aspectDependency, ServiceReference originalServiceRef) {
+ m_aspectDependency = (ServiceDependencyImpl) aspectDependency;
+ m_originalServiceRef = originalServiceRef;
+ }
+
+ @SuppressWarnings("unused")
+ private void addAspect(Component c, ServiceReference ref, Object service) {
+ // Just forward "add" service dependency callback.
+
+ // Invoke is done on dependency.getInstances() which unfortunately returns this callback instance...
+ ServiceEventImpl event = new ServiceEventImpl(ref, service);
+ m_aspectDependency.invoke(m_add, event, m_aspectDependency.getComponentContext().getInstances());
+ }
+
+ @SuppressWarnings("unused")
+ private void changeAspect(Component c, ServiceReference ref, Object service) {
+ // Invoke "change" service dependency callback
+ if (m_change != null) {
+ ServiceEventImpl event = new ServiceEventImpl(ref, service);
+ m_aspectDependency.invoke(m_change, event, m_aspectDependency.getComponentContext().getInstances());
+ }
+ // Propagate change to immediate higher aspect, or to client using our aspect.
+ // We always propagate our own properties, and the ones from the original service, but we don't inherit
+ // from lower ranked aspect service properties.
+ Dictionary<?,?> props = getServiceProperties(m_originalServiceRef);
+ c.setServiceProperties(props);
+ }
+
+ @SuppressWarnings("unused")
+ private void removeAspect(Component c, ServiceReference ref, Object service) {
+ // Just forward "remove" service dependency callback.
+ ServiceEventImpl event = new ServiceEventImpl(ref, service);
+ m_aspectDependency.invoke(m_remove, event, m_aspectDependency.getComponentContext().getInstances());
+ }
+
+ @SuppressWarnings("unused")
+ private void swapAspect(Component c, ServiceReference prevRef, Object prev, ServiceReference currRef,
+ Object curr) {
+ Object[] instances = m_aspectDependency.getComponentContext().getInstances();
+
+ // TODO ASPECTS: It sometimes appears (mostly on component/dependency remove) the size of the instances array is 0, meaning the component
+ // is no longer registered. This should not happen! Figure out why it happens anyway.
+// System.out.println("[proxy] swapAspect..." + instances.length);
+
+ // Just forward "swap" service dependency callback.
+ m_aspectDependency.invokeSwap(m_swap, prevRef, prev, currRef, curr, m_aspectDependency.getComponentContext().getInstances());
+ }
+
+ @Override
+ public String toString() {
+ return "CallbackProxy";
+ }
+ }
+
+}
Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AspectServiceImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java Mon May 19 06:47:07 2014
@@ -64,6 +64,15 @@ public class ComponentImpl implements Co
private final long m_id;
private static AtomicLong m_idGenerator = new AtomicLong();
private final Map<DependencyContext, ConcurrentSkipListSet<Event>> m_dependencyEvents = new HashMap<>();
+
+ private boolean debug = false;
+ private String debugKey;
+
+ public void setDebug(String debugKey) {
+ System.out.println("*" + debugKey + " set debug");
+ this.debugKey = debugKey;
+ this.debug = true;
+ }
// configuration (static)
private volatile String m_callbackInit;
@@ -80,6 +89,8 @@ public class ComponentImpl implements Co
private volatile Object m_compositionManager;
private volatile String m_compositionManagerGetMethod;
private volatile Object m_compositionManagerInstance;
+
+ private boolean m_handlingChange;
static class SCDImpl implements ComponentDependencyDeclaration {
private final String m_name;
@@ -217,6 +228,10 @@ public class ComponentImpl implements Co
@Override
public void handleAdded(DependencyContext dc, Event e) {
+ if (debug) {
+ System.out.println("*" + debugKey + " T" + Thread.currentThread().getId() + " handleAdded " + e);
+ }
+
Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
dependencyEvents.add(e);
dc.setAvailable(true);
@@ -327,14 +342,37 @@ public class ComponentImpl implements Co
}
private void handleChange() {
- ComponentState oldState;
- ComponentState newState;
- do {
- oldState = m_state;
- newState = calculateNewState(oldState);
- m_state = newState;
- }
- while (performTransition(oldState, newState));
+ // At this point, our component is starting, or a dependency is being added/changed/removed.
+ // So, we have to calculate a new state change for this component.
+ // Now, if we decide to call the component's init method, then at this point, if the component adds
+ // some additional instance-bound (and *available*) dependencies, then this will trigger a recursive call to
+ // our handleChange method, which we are currently executing. Since this would mess around with the execution of
+ // our current handleChange method execution, we are using a special "m_handlingChange" flag, which avoids this
+ // kind of problem.
+ if (! m_handlingChange) {
+ if (debug) {
+ System.out.println("*" + debugKey + " T" + Thread.currentThread().getId() + " handleChange");
+ }
+ try {
+ m_handlingChange = true;
+ ComponentState oldState;
+ ComponentState newState;
+ do {
+ oldState = m_state;
+ newState = calculateNewState(oldState);
+ if (debug) {
+ System.out.println("*" + debugKey + " T" + Thread.currentThread().getId() + " " + oldState + " -> " + newState);
+ }
+ m_state = newState;
+ }
+ while (performTransition(oldState, newState));
+ } finally {
+ m_handlingChange = false;
+ if (debug) {
+ System.out.println("*" + debugKey + " T" + Thread.currentThread().getId() + " end handling change.");
+ }
+ }
+ }
}
/** Based on the current state, calculate the new state. */
@@ -379,6 +417,9 @@ public class ComponentImpl implements Co
return true;
}
if (oldState == ComponentState.WAITING_FOR_REQUIRED && newState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
+ if (debug) {
+ System.out.println("*" + debugKey + " T" + Thread.currentThread().getId() + " instantiate!");
+ }
instantiateComponent();
invokeAddRequiredDependencies();
invokeAutoConfigDependencies();
@@ -470,6 +511,9 @@ public class ComponentImpl implements Co
private void startDependencies(List<DependencyContext> dependencies) {
// Start first optional dependencies first.
+ if (debug) {
+ System.out.println("*" + debugKey + " T" + Thread.currentThread().getId() + " startDependencies.");
+ }
List<DependencyContext> requiredDeps = new ArrayList();
for (DependencyContext d : dependencies) {
if (d.isRequired()) {
@@ -1104,4 +1148,12 @@ public class ComponentImpl implements Co
public ComponentDeclaration getComponentDeclaration() {
return this;
}
+
+ @Override
+ public String toString() {
+ if (debug) {
+ System.out.println(debugKey);
+ }
+ return super.toString();
+ }
}
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/DependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/DependencyImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/DependencyImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/DependencyImpl.java Mon May 19 06:47:07 2014
@@ -203,9 +203,13 @@ public class DependencyImpl<T extends De
}
}
- public void invoke(String method, Event e) {
+ public void invoke(String method, Event e, Object[] instances) {
// specific for this type of dependency
- m_component.invokeCallbackMethod(getInstances(), method, new Class[][] {{}}, new Object[][] {{}});
+ m_component.invokeCallbackMethod(instances, method, new Class[][] {{}}, new Object[][] {{}});
+ }
+
+ public void invoke(String method, Event e) {
+ invoke(method, e, getInstances());
}
public T setRequired(boolean required) {
@@ -285,6 +289,10 @@ public class DependencyImpl<T extends De
return null;
}
+ public ComponentContext getComponentContext() {
+ return m_component;
+ }
+
protected void ensureNotActive() {
if (isStarted()) {
throw new IllegalStateException("Cannot modify state while active.");
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FactoryConfigurationAdapterImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FactoryConfigurationAdapterImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FactoryConfigurationAdapterImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FactoryConfigurationAdapterImpl.java Mon May 19 06:47:07 2014
@@ -5,7 +5,6 @@ import java.lang.reflect.InvocationTarge
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
-import java.util.List;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -14,7 +13,6 @@ import org.osgi.service.metatype.MetaTyp
import org.osgi.service.metatype.ObjectClassDefinition;
import dm.Component;
-import dm.ComponentStateListener;
import dm.Dependency;
import dm.DependencyManager;
import dm.PropertyMetaData;
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FilterComponent.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FilterComponent.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FilterComponent.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FilterComponent.java Mon May 19 06:47:07 2014
@@ -29,7 +29,6 @@ import org.osgi.framework.ServiceRegistr
import dm.Component;
import dm.ComponentDeclaration;
import dm.ComponentDependencyDeclaration;
-import dm.ComponentState;
import dm.ComponentStateListener;
import dm.Dependency;
import dm.DependencyManager;
@@ -311,4 +310,11 @@ public class FilterComponent implements
public ComponentDeclaration getComponentDeclaration() {
return this;
}
+
+ // TODO: Remove..
+ @Override
+ public void setDebug(String string) {
+ // TODO Auto-generated method stub
+
+ }
}
\ No newline at end of file
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/Logger.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/Logger.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/Logger.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/Logger.java Mon May 19 06:47:07 2014
@@ -23,7 +23,6 @@ import java.lang.reflect.Method;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
-import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/SerialExecutor.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/SerialExecutor.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/SerialExecutor.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/SerialExecutor.java Mon May 19 06:47:07 2014
@@ -90,7 +90,52 @@ public class SerialExecutor implements E
command.run();
}
catch (Throwable t) {
- m_logger.log(LogService.LOG_ERROR, "Error processing tasks", t);
+ if (m_logger != null) {
+ m_logger.log(LogService.LOG_ERROR, "Error processing tasks", t);
+ }
}
}
+
+ // TODO ASPECTS: Review. Added methods for separately scheduling and executing tasks
+ // on the SerialExecutor. This is used in the ServiceTracker which must ensure
+ // customizer callback methods are executed in the correct order.
+
+
+ public void schedule(Runnable runnable) {
+ synchronized (this) {
+ m_queue.add(runnable);
+ }
+ }
+
+ public void execute() {
+ Runnable next = null;
+ synchronized (this) {
+ if (m_runningThread == null || m_runningThread == Thread.currentThread()) {
+ // It's our turn
+ if (!m_queue.isEmpty()) {
+ next = m_queue.get(0);
+ m_runningThread = Thread.currentThread();
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+ while (next != null) {
+ runTask(next);
+ synchronized (this) {
+ m_queue.remove(0); // The first element is the one we have just executed
+ next = m_queue.isEmpty() ? null : (Runnable) m_queue.get(0);
+ if (next == null) {
+ m_runningThread = null;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[Executor: queue size: " + m_queue.size() + "]";
+ }
}
\ No newline at end of file
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ServiceDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ServiceDependencyImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ServiceDependencyImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ServiceDependencyImpl.java Mon May 19 06:47:07 2014
@@ -3,6 +3,7 @@ package dm.impl;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.AbstractMap;
+import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Map;
@@ -18,6 +19,7 @@ import org.osgi.service.log.LogService;
import tracker.ServiceTracker;
import tracker.ServiceTrackerCustomizer;
import dm.Component;
+import dm.ComponentDeclaration;
import dm.ServiceDependency;
import dm.context.DependencyContext;
import dm.context.Event;
@@ -33,6 +35,13 @@ public class ServiceDependencyImpl exten
private volatile Object m_defaultImplementation;
private volatile Object m_defaultImplementationInstance;
private volatile Object m_nullObject;
+ private boolean debug = false;
+ private String debugKey;
+
+ public void setDebug(String debugKey) {
+ this.debugKey = debugKey;
+ this.debug = true;
+ }
/**
* Entry to wrap service properties behind a Map.
@@ -193,6 +202,9 @@ public class ServiceDependencyImpl exten
} else {
throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
}
+ if (debug) {
+ m_tracker.setDebug(debugKey);
+ }
m_tracker.open();
}
}
@@ -214,6 +226,9 @@ public class ServiceDependencyImpl exten
@Override
public void addedService(ServiceReference reference, Object service) {
+ if (debug) {
+ System.out.println(debugKey + " addedService");
+ }
add(new ServiceEventImpl(reference, service));
}
@@ -228,9 +243,9 @@ public class ServiceDependencyImpl exten
}
@Override
- public void invoke(String method, Event e) {
+ public void invoke(String method, Event e, Object[] instances) {
ServiceEventImpl se = (ServiceEventImpl) e;
- m_component.invokeCallbackMethod(getInstances(), method,
+ m_component.invokeCallbackMethod(instances, method,
new Class[][]{
{Component.class, ServiceReference.class, m_trackedServiceName},
{Component.class, ServiceReference.class, Object.class},
@@ -265,6 +280,10 @@ public class ServiceDependencyImpl exten
);
}
+ public void invoke(String method, Event e) {
+ invoke(method, e, getInstances());
+ }
+
@Override
public Class<?> getAutoConfigType() {
return m_trackedServiceName;
@@ -425,15 +444,63 @@ public class ServiceDependencyImpl exten
return m_defaultImplementationInstance;
}
+ public void invokeSwap(String swapMethod, ServiceReference previousReference, Object previous,
+ ServiceReference currentReference, Object current) {
+ try {
+ invokeSwap(swapMethod, previousReference, previous, currentReference, current, getInstances());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void invokeSwap(String swapMethod, ServiceReference previousReference, Object previous,
+ ServiceReference currentReference, Object current, Object[] instances) {
+ if (debug) {
+ System.out.println("invoke swap: " + swapMethod + " on component " + m_component + ", instances: " + Arrays.toString(instances) + " - " + ((ComponentDeclaration)m_component).getState());
+ }
+ try {
+ m_component.invokeCallbackMethod(instances, swapMethod,
+ new Class[][]{
+ {m_trackedServiceName, m_trackedServiceName},
+ {Object.class, Object.class},
+ {ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName},
+ {ServiceReference.class, Object.class, ServiceReference.class, Object.class},
+ {Component.class, m_trackedServiceName, m_trackedServiceName},
+ {Component.class, Object.class, Object.class},
+ {Component.class, ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName},
+ {Component.class, ServiceReference.class, Object.class, ServiceReference.class, Object.class}},
+
+ new Object[][]{
+ {previous, current},
+ {previous, current},
+ {previousReference, previous, currentReference, current},
+ {previousReference, previous, currentReference, current}, {m_component, previous, current},
+ {m_component, previous, current}, {m_component, previousReference, previous, currentReference, current},
+ {m_component, previousReference, previous, currentReference, current}}
+ );
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
@Override
- public void swappedService(ServiceReference reference, Object service,
- ServiceReference newReference, Object newService) {
- System.out.println("### SWAPPED");
+ public void swappedService(final ServiceReference reference, final Object service,
+ final ServiceReference newReference, final Object newService) {
if (m_swap != null) {
- // TODO: invoke swap callback
+ // it's will not trigger a state change, but the actual swap should be scheduled to prevent things
+ // getting out of order.
+ // TODO ASPECTS: Check the relation with the component lifecycle. When not adding the 'false' to the execute,
+ // the swap is sometimes performed before the actual initial component.added has been completed. This
+ // is due to prevention of re-entrant execution issues as described in ComponentImpl.handleChange()
+ ((SerialExecutor)m_component.getExecutor()).execute(new Runnable() {
+ @Override
+ public void run() {
+ invokeSwap(m_swap, reference, service, newReference, newService);
+ }
+ }, false);
} else {
addedService(newReference, newService);
- removedService(newReference, newService);
+ removedService(reference, service);
}
}
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/TemporalServiceDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/TemporalServiceDependencyImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/TemporalServiceDependencyImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/TemporalServiceDependencyImpl.java Mon May 19 06:47:07 2014
@@ -8,6 +8,7 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import dm.DependencyActivatorBase;
import dm.ServiceDependency;
/**
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/AspectFilterIndex.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/AspectFilterIndex.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/AspectFilterIndex.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/AspectFilterIndex.java Mon May 19 06:47:07 2014
@@ -29,10 +29,6 @@ import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
-import dm.*;
-import dm.impl.ServiceUtil;
-import tracker.*;
-
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
@@ -40,6 +36,12 @@ import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
+import tracker.ServiceTracker;
+import tracker.ServiceTrackerCustomizer;
+import dm.DependencyManager;
+import dm.FilterIndex;
+import dm.impl.ServiceUtil;
+
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/ServiceRegistryCache.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/ServiceRegistryCache.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/ServiceRegistryCache.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/ServiceRegistryCache.java Mon May 19 06:47:07 2014
@@ -18,7 +18,6 @@
*/
package dm.impl.index;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/multiproperty/Property.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/multiproperty/Property.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/multiproperty/Property.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/multiproperty/Property.java Mon May 19 06:47:07 2014
@@ -20,12 +20,9 @@ package dm.impl.index.multiproperty;
import java.util.Set;
import java.util.TreeSet;
-
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-import java.util.Set;
-import java.util.TreeSet;
public class Property {
boolean m_negate;
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/MetaTypeProviderImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/MetaTypeProviderImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/MetaTypeProviderImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/MetaTypeProviderImpl.java Mon May 19 06:47:07 2014
@@ -32,8 +32,6 @@ import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TreeSet;
-import dm.PropertyMetaData;
-import dm.impl.Logger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.service.cm.ConfigurationException;
@@ -43,6 +41,9 @@ import org.osgi.service.log.LogService;
import org.osgi.service.metatype.MetaTypeProvider;
import org.osgi.service.metatype.ObjectClassDefinition;
+import dm.PropertyMetaData;
+import dm.impl.Logger;
+
/**
* When a ConfigurationDepdendency is configured with properties metadata, we provide
* a specific ManagedService which also implements the MetaTypeProvider interface. This interface
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/PropertyMetaDataImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/PropertyMetaDataImpl.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/PropertyMetaDataImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/PropertyMetaDataImpl.java Mon May 19 06:47:07 2014
@@ -23,9 +23,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import dm.PropertyMetaData;
import org.osgi.service.metatype.AttributeDefinition;
+import dm.PropertyMetaData;
+
/**
* DependencyManager PropertyMetaData Implementation. This class describes meta informations regarding
* one given configuration property.
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/AbstractTracked.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/AbstractTracked.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/AbstractTracked.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/AbstractTracked.java Mon May 19 06:47:07 2014
@@ -21,6 +21,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import dm.impl.SerialExecutor;
+
/**
* Abstract class to track items. If a Tracker is reused (closed then reopened),
* then a new AbstractTracked object is used. This class acts a map of tracked
@@ -94,6 +96,8 @@ abstract class AbstractTracked {
* @GuardedBy this
*/
private final LinkedList initial;
+
+ private SerialExecutor m_executor = new SerialExecutor(null);
/**
* AbstractTracked constructor.
@@ -180,15 +184,20 @@ abstract class AbstractTracked {
continue; /* skip this item */
}
adding.add(item);
+ final AbstractCustomizerActionSet actionSet = trackAdding(item, null);
+ m_executor.schedule(new Runnable() {
+
+ @Override
+ public void run() {
+ actionSet.execute();
+
+ }
+
+ });
}
if (DEBUG) {
System.out.println("AbstractTracked.trackInitial: " + item); //$NON-NLS-1$
}
- trackAdding(item, null).execute(); /*
- * Begin tracking it. We call trackAdding
- * since we have already put the item in the
- * adding list.
- */
}
}
@@ -429,6 +438,14 @@ abstract class AbstractTracked {
int getTrackingCount() {
return trackingCount;
}
+
+ /**
+ * Returns the serial executor used by this tracked.
+ * @return
+ */
+ SerialExecutor getExecutor() {
+ return m_executor;
+ }
/**
* Call the specific customizer adding method. This method must not be
Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/ServiceTracker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/ServiceTracker.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/ServiceTracker.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/ServiceTracker.java Mon May 19 06:47:07 2014
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicInteger;
import org.osgi.framework.AllServiceListener;
import org.osgi.framework.BundleContext;
@@ -140,6 +141,14 @@ public class ServiceTracker implements S
* track all aspects or just the highest ranked ones.
*/
public boolean m_trackAllAspects;
+
+ private boolean debug = false;
+ private String debugKey;
+
+ public void setDebug(String debugKey) {
+ this.debug = true;
+ this.debugKey = debugKey;
+ }
/**
* Create a <code>ServiceTracker</code> on the specified
@@ -338,6 +347,9 @@ public class ServiceTracker implements S
* longer valid.
*/
public void open(boolean trackAllServices, boolean trackAllAspects) {
+ if (debug) {
+ System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " open");
+ }
final Tracked t;
synchronized (this) {
if (tracked != null) {
@@ -370,7 +382,12 @@ public class ServiceTracker implements S
}
}
/* set tracked with the initial references */
- t.setInitial(references);
+ t.setInitial(references);
+
+ // only actually schedules the actions for execution within this synchronized block,
+ // but do the actual execution afterwards.
+ t.trackInitial();
+
}
catch (InvalidSyntaxException e) {
throw new RuntimeException(
@@ -381,7 +398,8 @@ public class ServiceTracker implements S
tracked = t;
}
/* Call tracked outside of synchronized region */
- t.trackInitial(); /* process the initial references */
+ // just trigger the executor
+ t.getExecutor().execute();
}
/**
@@ -1101,12 +1119,12 @@ public class ServiceTracker implements S
* @param event <code>ServiceEvent</code> object from the framework.
*/
public void serviceChanged(final ServiceEvent event) {
- if (m_trackAllAspects) {
- serviceChangedIncludeAspects(event);
- }
- else {
- serviceChangedHideAspects(event);
- }
+ if (m_trackAllAspects) {
+ serviceChangedIncludeAspects(event);
+ }
+ else {
+ serviceChangedHideAspects(event);
+ }
}
public void serviceChangedIncludeAspects(final ServiceEvent event) {
@@ -1118,6 +1136,9 @@ public class ServiceTracker implements S
return;
}
final ServiceReference reference = event.getServiceReference();
+ if (debug) {
+ System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " [serviceChangedIncludeAspects] " + reference.getProperty("service.ranking"));
+ }
if (DEBUG) {
System.out
.println("ServiceTracker.Tracked.serviceChanged["
@@ -1166,8 +1187,11 @@ public class ServiceTracker implements S
private boolean isModifiedEndmatchSupported() {
return listenerFilter != null;
}
+
+ private AtomicInteger step = new AtomicInteger();
public void serviceChangedHideAspects(final ServiceEvent event) {
+ int n = step.getAndIncrement();
/*
* Check if we had a delayed call (which could happen when we
* close).
@@ -1178,85 +1202,107 @@ public class ServiceTracker implements S
final ServiceReference reference = event.getServiceReference();
if (DEBUG) {
System.out
- .println("ServiceTracker.Tracked.serviceChanged["
+ .println(n + " ServiceTracker.Tracked.serviceChanged["
+ event.getType() + "]: " + reference);
}
long sid = ServiceUtil.getServiceId(reference);
- switch (event.getType()) {
- case ServiceEvent.REGISTERED :
- case ServiceEvent.MODIFIED :
- ServiceReference higherRankedReference = null;
- ServiceReference lowerRankedReference = null;
- ServiceReference highestTrackedReference = highestTrackedCache(sid);
- if (highestTrackedReference != null) {
- int ranking = ServiceUtil.getRanking(reference);
- int highestTrackedRanking = ServiceUtil.getRanking(highestTrackedReference);
- if (ranking > highestTrackedRanking) {
- // found a higher ranked one!
- if (DEBUG) {
- System.out.println("ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: Found a higher ranked aspect: " + ServiceUtil.toString(reference) + " vs " + ServiceUtil.toString(highestTrackedReference));
- }
- higherRankedReference = highestTrackedReference;
- }
- else if (ranking < highestTrackedRanking) {
- // found lower ranked one!
- if (DEBUG) {
- System.out.println("ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: Found a lower ranked aspect: " + ServiceUtil.toString(reference) + " vs " + ServiceUtil.toString(highestTrackedReference));
- }
- lowerRankedReference = highestTrackedReference;
- }
- }
-
- if (isModifiedEndmatchSupported()) { // either registered or modified
- registerOrUpdate(event, reference, higherRankedReference, lowerRankedReference);
- }
- else { // service listener added without filter
- if (filter.match(reference)) {
- registerOrUpdate(event, reference, higherRankedReference, lowerRankedReference);
+ AbstractCustomizerActionSet actionSet = null;
+ synchronized(this) {
+ switch (event.getType()) {
+ case ServiceEvent.REGISTERED :
+ case ServiceEvent.MODIFIED :
+ ServiceReference higherRankedReference = null;
+ ServiceReference lowerRankedReference = null;
+ ServiceReference highestTrackedReference = highestTrackedCache(sid);
+ if (highestTrackedReference != null) {
+ int ranking = ServiceUtil.getRanking(reference);
+ int highestTrackedRanking = ServiceUtil.getRanking(highestTrackedReference);
+ if (ranking > highestTrackedRanking) {
+ // found a higher ranked one!
+ if (DEBUG) {
+ System.out.println("ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: Found a higher ranked aspect: " + ServiceUtil.toString(reference) + " vs " + ServiceUtil.toString(highestTrackedReference));
+ }
+ higherRankedReference = highestTrackedReference;
+ }
+ else if (ranking < highestTrackedRanking) {
+ // found lower ranked one!
+ if (DEBUG) {
+ System.out.println("ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: Found a lower ranked aspect: " + ServiceUtil.toString(reference) + " vs " + ServiceUtil.toString(highestTrackedReference));
+ }
+ lowerRankedReference = highestTrackedReference;
+ }
+ }
+ if (isModifiedEndmatchSupported()) { // either registered or modified
+ actionSet = registerOrUpdate(event, reference, higherRankedReference, lowerRankedReference);
}
- else {
- unregister(event, reference, sid);
+ else { // service listener added without filter
+ if (filter.match(reference)) {
+ actionSet = registerOrUpdate(event, reference, higherRankedReference, lowerRankedReference);
+ }
+ else {
+ actionSet = unregister(event, reference, sid);
+ }
}
+ break;
+ case 8 /* ServiceEvent.MODIFIED_ENDMATCH */ : // handle as unregister
+ case ServiceEvent.UNREGISTERING :
+ actionSet = unregister(event, reference, sid);
+ /*
+ * If the customizer throws an unchecked exception, it is
+ * safe to let it propagate
+ */
+ break;
+ }
+ // schedule the actionset for execution. We'll use a serial executor to prevent the actions to
+ // be performed out of order.
+ final AbstractCustomizerActionSet commandActionSet = actionSet;
+ getExecutor().schedule(new Runnable() {
+
+ @Override
+ public void run() {
+ commandActionSet.execute();
}
- break;
- case 8 /* ServiceEvent.MODIFIED_ENDMATCH */ : // handle as unregister
- case ServiceEvent.UNREGISTERING :
- unregister(event, reference, sid);
- /*
- * If the customizer throws an unchecked exception, it is
- * safe to let it propagate
- */
- break;
+
+ });
}
+ getExecutor().execute();
}
-
- private void registerOrUpdate(final ServiceEvent event,
+
+ private AbstractCustomizerActionSet registerOrUpdate(final ServiceEvent event,
final ServiceReference reference, ServiceReference higher,
ServiceReference lower) {
+ if (debug) {
+// System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " [registerOrUpdate] lower: " + lower + ", higher: " + higher);
+ }
+ AbstractCustomizerActionSet actionSet = null;
if (lower != null) {
hide(reference);
}
else {
- AbstractCustomizerActionSet actionSet = track(reference, event);
+ actionSet = track(reference, event);
if (higher != null) {
actionSet.appendActionSet(untrack(higher, null));
hide(higher);
}
- actionSet.execute();
}
/*
* If the customizer throws an unchecked exception, it
* is safe to let it propagate
*/
+ return actionSet;
}
- private void unregister(final ServiceEvent event,
+ private AbstractCustomizerActionSet unregister(final ServiceEvent event,
final ServiceReference reference, long sid) {
+ if (debug) {
+ System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " [unregister] " + reference.getProperty("service.ranking"));
+ }
+ AbstractCustomizerActionSet actionSet = null;
ServiceReference ht = highestTrackedCache(sid);
if (reference.equals(ht)) {
ServiceReference hh = highestHiddenCache(sid);
- AbstractCustomizerActionSet actionSet = null;
+
if (hh != null) {
unhide(hh);
actionSet = track(hh, null);
@@ -1266,11 +1312,11 @@ public class ServiceTracker implements S
} else {
actionSet.appendActionSet(untrack(reference, event));
}
- actionSet.execute();
}
else {
unhide(reference);
}
+ return actionSet;
}
@@ -1360,14 +1406,49 @@ public class ServiceTracker implements S
// This actions set deliberately postpones invocation of the customizer methods to be able to combine added and removed
// into a single swap call.
return new AbstractCustomizerActionSet() {
+
+ @Override
+ public void addCustomizerAdded(Object item, Object related,
+ Object object) {
+ if (debug) {
+// System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " addCustomizerAdded " + object);
+ }
+ super.addCustomizerAdded(item, related, object);
+ }
+
+ @Override
+ public void addCustomizerModified(Object item, Object related,
+ Object object) {
+ if (debug) {
+// System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " addCustomizerModified " + object);
+ }
+ super.addCustomizerModified(item, related, object);
+ }
+
+ @Override
+ public void addCustomizerRemoved(Object item, Object related,
+ Object object) {
+ if (debug) {
+// System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " addCustomizerRemoved " + object);
+ }
+ super.addCustomizerRemoved(item, related, object);
+ }
+
@Override
void execute() {
// inspect the actions and check whether we should perform a swap
List<CustomizerAction> actions = getActions();
+ if (actions.size() > 2) {
+ throw new IllegalStateException("Unexpected action count: " + actions.size());
+ }
if (actions.size() == 2 && actions.get(0).getType() == Type.ADDED && actions.get(1).getType() == Type.REMOVED) {
// ignore related
// item = ServiceReference
// object = service
+ debug("swapped");
+ if (debug) {
+ System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " swapping " + actions.get(1).getObject() + " with " + actions.get(0).getObject());
+ }
customizer.swappedService((ServiceReference)actions.get(1).getItem(), actions.get(1).getObject(), (ServiceReference)actions.get(0).getItem(), actions.get(0).getObject());
} else {
// just sequentially call the customizer methods
@@ -1375,12 +1456,21 @@ public class ServiceTracker implements S
try {
switch (action.getType()) {
case ADDED:
+ debug(Thread.currentThread().getId() + " added");
+ if (debug) {
+ System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " adding " + action.getObject());
+ }
customizerAdded(action.getItem(), action.getRelated(), action.getObject());
break;
case MODIFIED:
+ debug("modified");
customizerModified(action.getItem(), action.getRelated(), action.getObject());
break;
case REMOVED:
+ debug("removed");
+ if (debug) {
+ System.out.println("[ServiceTracker] " + debugKey + " T" + Thread.currentThread().getId() + " removing " + action.getObject());
+ }
customizerRemoved(action.getItem(), action.getRelated(), action.getObject());
}
} catch (Exception e) {
@@ -1393,6 +1483,12 @@ public class ServiceTracker implements S
}
}
+
+ private void debug(String message) {
+ if (customizer.toString().equals("ServiceDependency[interface dm.it.AspectRaceTest$S (&(!(org.apache.felix.dependencymanager.aspect=*))(id=1))]")) {
+// System.out.println(message);
+ }
+ }
/**
* Subclass of Tracked which implements the AllServiceListener interface.