You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2014/10/18 01:00:55 UTC
svn commit: r1632688 - in /felix/sandbox/pderop/dependencymanager-prototype:
org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/
org.apache.felix.dependencymanager/src/org/apache/felix/dm/
org.apache.felix.dependencymanager/src/org/...
Author: pderop
Date: Fri Oct 17 23:00:55 2014
New Revision: 1632688
URL: http://svn.apache.org/r1632688
Log:
FELIX-4672: Allow callbacks to third party instance for adapters.
Added:
felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AdapterWithCallbackInstanceTest.java
Modified:
felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java
felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java
felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java
felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java
Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AdapterWithCallbackInstanceTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AdapterWithCallbackInstanceTest.java?rev=1632688&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AdapterWithCallbackInstanceTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AdapterWithCallbackInstanceTest.java Fri Oct 17 23:00:55 2014
@@ -0,0 +1,142 @@
+/*
+ * 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.dm.itest;
+
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+public class AdapterWithCallbackInstanceTest extends TestBase {
+
+ public void testServiceWithAdapterAndConsumer() {
+ DependencyManager m = getDM();
+ // helper class that ensures certain steps get executed in sequence
+ Ensure e = new Ensure();
+
+ Component provider = m.createComponent()
+ .setInterface(OriginalService.class.getName(), null)
+ .setImplementation(new ServiceProvider(e));
+
+ Component consumer = m.createComponent()
+ .setImplementation(new ServiceConsumer(e))
+ .add(m.createServiceDependency()
+ .setService(AdaptedService.class)
+ .setRequired(true)
+ );
+
+ ServiceAdapterCallbackInstance callbackInstance = new ServiceAdapterCallbackInstance(e);
+ Component adapter = m.createAdapterService(OriginalService.class, null, "m_originalService", callbackInstance, "set", "changed","unset", null)
+ .setInterface(AdaptedService.class.getName(), null)
+ .setImplementation(new ServiceAdapter(e));
+
+ // add the provider and the adapter
+ m.add(provider);
+ m.add(adapter);
+ // Checks if the callbackInstances is called, and if the adapter start method is called
+ e.waitForStep(2, 5000);
+
+ // add a consumer that will invoke the adapter
+ // which will in turn invoke the original provider
+ m.add(consumer);
+ // now validate that both have been invoked in the right order
+ e.waitForStep(4, 5000);
+ // remove the provider again
+ m.remove(provider);
+ // ensure that the consumer is stopped
+ e.waitForStep(5, 5000);
+ // remove adapter and consumer
+ m.remove(adapter);
+ m.remove(consumer);
+ }
+
+ static interface OriginalService {
+ public void invoke();
+ }
+
+ static interface AdaptedService {
+ public void invoke();
+ }
+
+ static class ServiceProvider implements OriginalService {
+ private final Ensure m_ensure;
+ public ServiceProvider(Ensure e) {
+ m_ensure = e;
+ }
+ public void invoke() {
+ m_ensure.step(4);
+ }
+ }
+
+ public static class ServiceAdapter implements AdaptedService {
+ private volatile OriginalService m_originalService;
+ private final Ensure m_ensure;
+
+ public String toString() {
+ return "XX: ServiceAdapter";
+ }
+
+ public ServiceAdapter(Ensure e) {
+ m_ensure = e;
+ }
+
+ public void start() { System.out.println("start"); m_ensure.step(2); }
+ public void stop() { System.out.println("stop"); }
+ public void invoke() {
+ m_originalService.invoke();
+ }
+ }
+
+ public static class ServiceAdapterCallbackInstance {
+ private final Ensure m_ensure;
+ public ServiceAdapterCallbackInstance(Ensure e) {
+ m_ensure = e;
+ }
+
+ public void set(OriginalService m_originalService) {
+ m_ensure.step(1);
+ }
+
+ public void changed(Map<String, String> props, OriginalService m_originalService) {
+ m_ensure.step();
+ }
+
+ public void unset(Map<String, String> props, OriginalService m_originalService) {
+ m_ensure.step();
+ }
+ }
+
+ static class ServiceConsumer {
+ private volatile AdaptedService m_service;
+ private final Ensure m_ensure;
+
+ public ServiceConsumer(Ensure e) {
+ m_ensure = e;
+ }
+ public void start() {
+ m_ensure.step(3);
+ m_service.invoke();
+ }
+ public void stop() {
+ m_ensure.step(5);
+ }
+ }
+}
+
+
Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java?rev=1632688&r1=1632687&r2=1632688&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java Fri Oct 17 23:00:55 2014
@@ -18,6 +18,7 @@
*/
package org.apache.felix.dm;
+import org.apache.felix.dm.impl.AdapterServiceImpl;
import org.apache.felix.dm.impl.Logger;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -262,6 +263,16 @@ public abstract class DependencyActivato
}
/**
+ * Creates a new adapter service.
+ * @return the adapter service
+ * @see DependencyManager#createAdapterService(Class, String, String, Object, String, String, String, String)
+ */
+ public Component createAdapterService(Class<?> serviceInterface, String serviceFilter,
+ String autoConfig, Object callbackInstance, String add, String change, String remove, String swap) {
+ return m_manager.createAdapterService(serviceInterface, serviceFilter, autoConfig, callbackInstance, add, change, remove, swap);
+ }
+
+ /**
* Creates a new resource adapter service.
*
* @return the resource adapter service
Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java?rev=1632688&r1=1632687&r2=1632688&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java Fri Oct 17 23:00:55 2014
@@ -258,6 +258,31 @@ public class DependencyManager {
* <h3>Usage Example</h3>
*
* <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class<?> serviceInterface, String serviceFilter) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null, null, null);
+ }
+
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
* manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
* .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
* .setImplementation(AdapterImpl.class);
@@ -269,7 +294,7 @@ public class DependencyManager {
* @return a service that acts as a factory for generating adapters
*/
public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String autoConfig) {
- return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null, null, null);
}
/**
@@ -284,17 +309,23 @@ public class DependencyManager {
* <h3>Usage Example</h3>
*
* <blockquote><pre>
- * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
* .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
* .setImplementation(AdapterImpl.class);
* </pre></blockquote>
*
* @param serviceInterface the service interface to apply the adapter to
* @param serviceFilter the filter condition to use with the service interface
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @param swap name of the callback method to invoke on swap
* @return a service that acts as a factory for generating adapters
*/
- public Component createAdapterService(Class<?> serviceInterface, String serviceFilter) {
- return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
+ public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
+ String remove)
+ {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, add, change, remove, null);
}
/**
@@ -325,7 +356,7 @@ public class DependencyManager {
public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
String remove, String swap)
{
- return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, add, change, remove, swap);
}
/**
@@ -340,23 +371,25 @@ public class DependencyManager {
* <h3>Usage Example</h3>
*
* <blockquote><pre>
- * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove", "swap")
* .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
* .setImplementation(AdapterImpl.class);
* </pre></blockquote>
*
* @param serviceInterface the service interface to apply the adapter to
* @param serviceFilter the filter condition to use with the service interface
+ * @param autoConfig the name of the member to inject the service into, or null.
+ * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the adapter itself
* @param add name of the callback method to invoke on add
* @param change name of the callback method to invoke on change
* @param remove name of the callback method to invoke on remove
* @param swap name of the callback method to invoke on swap
* @return a service that acts as a factory for generating adapters
*/
- public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
- String remove)
+ public Component createAdapterService(Class<?> serviceInterface, String serviceFilter,
+ String autoConfig, Object callbackInstance, String add, String change, String remove, String swap)
{
- return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, callbackInstance, add, change, remove, swap);
}
/**
Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java?rev=1632688&r1=1632687&r2=1632688&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java Fri Oct 17 23:00:55 2014
@@ -45,43 +45,40 @@ public class AdapterServiceImpl extends
* @param dm the dependency manager used to create our internal adapter service
* @param adapteeInterface the service interface to apply the adapter to
* @param adapteeFilter the filter condition to use with the service interface
- * @param add
- * @param change
- * @param remove
+ * @param autoConfig the name of the member to inject the service into
+ * @param callbackInstance the instance to invoke the callback on, or null
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @param swap name of the callback method to invoke on swap
*/
- public AdapterServiceImpl(DependencyManager dm, Class<?> adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove, String swap) {
+ public AdapterServiceImpl(DependencyManager dm, Class<?> adapteeInterface, String adapteeFilter, String autoConfig,
+ Object callbackInstance, String add, String change, String remove, String swap)
+ {
super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
- m_component.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, add, change, remove, swap))
+ m_component.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, callbackInstance, add, change, remove, swap))
.add(dm.createServiceDependency()
.setService(adapteeInterface, adapteeFilter)
.setAutoConfig(false)
.setCallbacks("added", null, "removed", "swapped"))
.setCallbacks("init", null, "stop", null);
}
-
- public AdapterServiceImpl(DependencyManager dm, Class<?> adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove) {
- super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
- m_component.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, add, change, remove, null))
- .add(dm.createServiceDependency()
- .setService(adapteeInterface, adapteeFilter)
- .setAutoConfig(false)
- .setCallbacks("added", null, "removed", "swapped"))
- .setCallbacks("init", null, "stop", null);
- }
-
+
public class AdapterImpl extends AbstractDecorator {
private final Class<?> m_adapteeInterface;
private final String m_adapteeFilter;
+ private final Object m_dependencyCallbackInstance;
private final String m_add;
private final String m_change;
private final String m_remove;
private final String m_swap;
private final String m_autoConfig;
- public AdapterImpl(Class<?> adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove, String swap) {
+ public AdapterImpl(Class<?> adapteeInterface, String adapteeFilter, String autoConfig, Object callbackInstance, String add, String change, String remove, String swap) {
m_adapteeInterface = adapteeInterface;
m_adapteeFilter = adapteeFilter;
m_autoConfig = autoConfig;
+ m_dependencyCallbackInstance = callbackInstance;
m_add = add;
m_change = change;
m_swap = swap;
@@ -99,11 +96,14 @@ public class AdapterServiceImpl extends
.setService(m_adapteeInterface, "(|(" + Constants.SERVICE_ID + "=" + serviceIdToTrack
+ ")(" + DependencyManager.ASPECT + "=" + serviceIdToTrack + "))")
.setRequired(true);
+ if (m_add != null || m_change != null || m_remove != null || m_swap != null) {
+ dependency.setCallbacks(m_dependencyCallbackInstance, m_add, m_change, m_remove, m_swap);
+ }
if (m_autoConfig != null) {
dependency.setAutoConfig(m_autoConfig);
- }
- if (m_add != null || m_change != null || m_remove != null || m_swap != null) {
- dependency.setCallbacks(m_add, m_change, m_remove, m_swap);
+ } else {
+ // enable auto configuration if there is no add callback or if there is one on a callbackInstance
+ dependency.setAutoConfig(m_add == null || (m_add != null && m_dependencyCallbackInstance != null));
}
dependency.setPropagate(this, "propagateAdapteeProperties");
Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java?rev=1632688&r1=1632687&r2=1632688&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java Fri Oct 17 23:00:55 2014
@@ -275,10 +275,18 @@ public class FieldUtil {
private static boolean mayInjectToMap(Class<?> clazz, Field field, boolean strictClassEquality) {
Class<?> fieldType = field.getType();
if (Map.class.isAssignableFrom(fieldType)) {
+ if (! (field.getGenericType() instanceof ParameterizedType)) {
+ return false;
+ }
ParameterizedType parameterType = (ParameterizedType) field.getGenericType();
if (parameterType == null) {
return false;
}
+
+ if (! (parameterType.getActualTypeArguments()[0] instanceof Class<?>) ||
+ ! (parameterType.getActualTypeArguments()[1] instanceof Class<?>)) {
+ return false;
+ }
Class<?> K = (Class<?>) parameterType.getActualTypeArguments()[0];
Class<?> V = (Class<?>) parameterType.getActualTypeArguments()[1];