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 2015/07/09 00:10:16 UTC

svn commit: r1689973 [13/25] - in /felix/sandbox/pderop/dependencymanager.ds: cnf/ext/ cnf/localrepo/ cnf/localrepo/org.apache.felix.framework/ cnf/releaserepo/ org.apache.felix.dependencymanager.ds.itest/ org.apache.felix.dependencymanager.ds.itest/.s...

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BaseMethod.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BaseMethod.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BaseMethod.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BaseMethod.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,624 @@
+/*
+ * 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.helper;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.metadata.DSVersion;
+import org.osgi.service.log.LogService;
+
+
+/**
+ * Component method to be invoked on service (un)binding.
+ */
+public abstract class BaseMethod<P>
+{
+
+    private final DSVersion dsVersion;
+    private final boolean configurableServiceProperties;
+
+    private final String m_methodName;
+    private final Class<?> m_componentClass;
+
+    private volatile Method m_method;
+
+    private final boolean m_methodRequired;
+
+    private volatile State m_state;
+
+    protected BaseMethod( final String methodName,
+            final Class<?> componentClass, final DSVersion dsVersion, final boolean configurableServiceProperties )
+    {
+        this( methodName, methodName != null, componentClass, dsVersion, configurableServiceProperties );
+    }
+
+
+    protected BaseMethod( final String methodName,
+            final boolean methodRequired, final Class<?> componentClass, final DSVersion dsVersion, final boolean configurableServiceProperties )
+    {
+        m_methodName = methodName;
+        m_methodRequired = methodRequired;
+        m_componentClass = componentClass;
+        this.dsVersion = dsVersion;
+        this.configurableServiceProperties = configurableServiceProperties;
+        if ( m_methodName == null )
+        {
+            m_state = NotApplicable.INSTANCE;
+        }
+        else
+        {
+            m_state = NotResolved.INSTANCE;
+        }
+    }
+
+    protected final DSVersion getDSVersion()
+    {
+        return dsVersion;
+    }
+
+
+    protected final boolean isDS12Felix()
+    {
+        return configurableServiceProperties;
+    }
+
+
+    protected final String getMethodName()
+    {
+        return m_methodName;
+    }
+
+    final Method getMethod()
+    {
+        return m_method;
+    }
+
+    protected final Class<?> getComponentClass()
+    {
+        return m_componentClass;
+    }
+
+
+    void setMethod( Method method, SimpleLogger logger )
+    {
+        this.m_method = method;
+
+        if ( method != null )
+        {
+            m_state = Resolved.INSTANCE;
+            logger.log( LogService.LOG_DEBUG, "Found {0} method: {1}", new Object[]
+                { getMethodNamePrefix(), method }, null );
+        }
+        else if ( m_methodRequired )
+        {
+            m_state = NotFound.INSTANCE;
+            logger.log(LogService.LOG_ERROR, "{0} method [{1}] not found; Component will fail",
+                new Object[]
+                    { getMethodNamePrefix(), getMethodName() }, null);
+        }
+        else
+        {
+            // optional method not found, log as DEBUG and ignore
+            logger.log( LogService.LOG_DEBUG, "{0} method [{1}] not found, ignoring", new Object[]
+                { getMethodNamePrefix(), getMethodName() }, null );
+            m_state = NotApplicable.INSTANCE;
+        }
+    }
+
+
+    State getState()
+    {
+        return m_state;
+    }
+
+
+    /**
+     * Finds the method named in the {@link #m_methodName} field in the given
+     * <code>targetClass</code>. If the target class has no acceptable method
+     * the class hierarchy is traversed until a method is found or the root
+     * of the class hierarchy is reached without finding a method.
+     *
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class or any super class.
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested method.
+     * @param logger
+     */
+    private Method findMethod( SimpleLogger logger ) throws InvocationTargetException
+    {
+        boolean acceptPrivate = getDSVersion().isDS11();
+        boolean acceptPackage = getDSVersion().isDS11();
+
+        final Class<?> targetClass = getComponentClass();
+        final ClassLoader targetClasslLoader = targetClass.getClassLoader();
+        final String targetPackage = getPackageName( targetClass );
+        Class<?> theClass = targetClass;
+
+        while (true)
+        {
+
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "Locating method " + getMethodName() + " in class " + theClass.getName(), null );
+            }
+
+            try
+            {
+                Method method = doFindMethod( theClass, acceptPrivate, acceptPackage, logger );
+                if ( method != null )
+                {
+                    return method;
+                }
+            }
+            catch ( SuitableMethodNotAccessibleException ex )
+            {
+                // log and return null
+                logger.log( LogService.LOG_ERROR,
+                    "findMethod: Suitable but non-accessible method {0} found in class {1}, subclass of {2}", new Object[]
+                        { getMethodName(), theClass.getName(), targetClass.getName() }, null );
+                break;
+            }
+
+            // if we get here, we have no method, so check the super class
+            theClass = theClass.getSuperclass();
+            if ( theClass == null )
+            {
+                break;
+            }
+
+            // super class method check ignores private methods and accepts
+            // package methods only if in the same package and package
+            // methods are (still) allowed
+            acceptPackage &= targetClasslLoader == theClass.getClassLoader()
+                && targetPackage.equals( getPackageName( theClass ) );
+
+            // private methods will not be accepted any more in super classes
+            acceptPrivate = false;
+        }
+
+        // nothing found after all these years ...
+        return null;
+    }
+
+
+    protected abstract Method doFindMethod( final Class<?> targetClass, final boolean acceptPrivate,
+            final boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException, InvocationTargetException;
+
+
+    private MethodResult invokeMethod( final Object componentInstance, final P rawParameter, SimpleLogger logger )
+        throws InvocationTargetException
+    {
+        try
+        {
+            if ( componentInstance != null )
+            {
+                final Object[] params = getParameters(m_method, rawParameter);
+                logger.log( LogService.LOG_DEBUG, "invoking {0}: {1}: parameters {2}", new Object[]
+                        { getMethodNamePrefix(), getMethodName(), Arrays.asList( params ) }, null );
+                Object result = m_method.invoke(componentInstance, params);
+                logger.log( LogService.LOG_DEBUG, "invoked {0}: {1}", new Object[]
+                    { getMethodNamePrefix(), getMethodName() }, null );
+                return new MethodResult((m_method.getReturnType() != Void.TYPE), (Map<String, Object>) result);
+            }
+            else
+            {
+                logger.log( LogService.LOG_WARNING, "Method {0}: {1} cannot be called on null object",
+                    new Object[]
+                        { getMethodNamePrefix(), getMethodName() }, null );
+            }
+        }
+        catch ( IllegalStateException ise )
+        {
+            logger.log( LogService.LOG_DEBUG, ise.getMessage(), null );
+            return null;
+        }
+        catch ( IllegalAccessException ex )
+        {
+            // 112.3.1 If the method is not is not declared protected or
+            // public, SCR must log an error message with the log service,
+            // if present, and ignore the method
+            logger.log( LogService.LOG_DEBUG, "Method {0} cannot be called", new Object[]
+                { getMethodName() }, ex );
+        }
+        catch ( InvocationTargetException ex )
+        {
+            throw ex;
+        }
+        catch ( Throwable t )
+        {
+            throw new InvocationTargetException( t );
+        }
+
+        // assume success (also if the method is not available or accessible)
+        return MethodResult.VOID; // TODO: or null ??
+    }
+
+    protected boolean returnValue()
+    {
+        // allow returning Map if declared as DS 1.2-Felix or newer
+        return isDS12Felix();
+    }
+
+    /**
+     * Returns the parameter array created from the <code>rawParameter</code>
+     * using the actual parameter type list of the <code>method</code>.
+     * @param method
+     * @param rawParameter
+     * @return
+     * @throws IllegalStateException If the required parameters cannot be
+     *      extracted from the <code>rawParameter</code>
+     */
+    protected abstract Object[] getParameters( Method method, P rawParameter );
+
+
+    protected String getMethodNamePrefix()
+    {
+        return "";
+    }
+
+
+    //---------- Helpers
+
+    /**
+     * Finds the named public or protected method in the given class or any
+     * super class. If such a method is found, its accessibility is enfored by
+     * calling the <code>Method.setAccessible</code> method if required and
+     * the method is returned. Enforcing accessibility is required to support
+     * invocation of protected methods.
+     *
+     *
+     * @param clazz The <code>Class</code> which provides the method.
+     * @param name The name of the method.
+     * @param parameterTypes The parameters to the method. Passing
+     *      <code>null</code> is equivalent to using an empty array.
+     *
+     * @param logger
+     * @return The named method with enforced accessibility or <code>null</code>
+     *      if no such method exists in the class.
+     *
+     * @throws SuitableMethodNotAccessibleException If method with the given
+     *      name taking the parameters is found in the class but the method
+     *      is not accessible.
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to access the desired method.
+     */
+    public /* static */ Method getMethod( Class<?> clazz, String name, Class[] parameterTypes, boolean acceptPrivate,
+            boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException,
+        InvocationTargetException
+    {
+        try
+        {
+            // find the declared method in this class
+            Method method = clazz.getDeclaredMethod( name, parameterTypes );
+
+            // accept public and protected methods only and ensure accessibility
+            if ( accept( method, acceptPrivate, acceptPackage, returnValue() ) )
+            {
+                return method;
+            }
+
+            // the method would fit the requirements but is not acceptable
+            throw new SuitableMethodNotAccessibleException();
+        }
+        catch ( NoSuchMethodException nsme )
+        {
+            // thrown if no method is declared with the given name and
+            // parameters
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                String argList = ( parameterTypes != null ) ? Arrays.asList( parameterTypes ).toString() : "";
+                logger.log( LogService.LOG_DEBUG, "Declared Method {0}.{1}({2}) not found", new Object[]
+                    { clazz.getName(), name, argList }, null );
+            }
+        }
+        catch ( NoClassDefFoundError cdfe )
+        {
+            // may be thrown if a method would be found but the signature
+            // contains throws declaration for an exception which cannot
+            // be loaded
+            if ( logger.isLogEnabled( LogService.LOG_WARNING ) )
+            {
+                StringBuffer buf = new StringBuffer();
+                buf.append( "Failure loooking up method " ).append( name ).append( '(' );
+                for ( int i = 0; parameterTypes != null && i < parameterTypes.length; i++ )
+                {
+                    buf.append( parameterTypes[i].getName() );
+                    if ( i > 0 )
+                    {
+                        buf.append( ", " );
+                    }
+                }
+                buf.append( ") in class class " ).append( clazz.getName() ).append( ". Assuming no such method." );
+                logger.log( LogService.LOG_WARNING, buf.toString(), cdfe );
+            }
+        }
+        catch ( SuitableMethodNotAccessibleException e)
+        {
+            throw e;
+        }
+        catch ( Throwable throwable )
+        {
+            // unexpected problem accessing the method, don't let everything
+            // blow up in this situation, just throw a declared exception
+            throw new InvocationTargetException( throwable, "Unexpected problem trying to get method " + name );
+        }
+
+        // caught and ignored exception, assume no method and continue search
+        return null;
+    }
+
+
+    /**
+     * Returns <code>true</code> if the method is acceptable to be returned from the
+     * {@link #getMethod(Class, String, Class[], boolean, boolean, SimpleLogger)} and also
+     * makes the method accessible.
+     * <p>
+     * This method returns <code>true</code> iff:
+     * <ul>
+     * <li>The method has <code>void</code> return type</li>
+     * <li>Is not static</li>
+     * <li>Is public or protected</li>
+     * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li>
+     * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li>
+     * </ul>
+     * <p>
+     * This method is package private for unit testing purposes. It is not
+     * meant to be called from client code.
+     *
+     *
+     * @param method The method to check
+     * @param acceptPrivate Whether a private method is acceptable
+     * @param acceptPackage Whether a package private method is acceptable
+     * @param allowReturnValue whether the method can return a value (to update service registration properties)
+     * @return whether the method is acceptable
+     */
+    protected static boolean accept( final Method method, boolean acceptPrivate, boolean acceptPackage, boolean allowReturnValue )
+    {
+        if (!(Void.TYPE == method.getReturnType() || (ClassUtils.MAP_CLASS == method.getReturnType() && allowReturnValue)))
+        {
+            return false;
+        }
+
+        // check modifiers now
+        int mod = method.getModifiers();
+
+        // no static method
+        if ( Modifier.isStatic( mod ) )
+        {
+            return false;
+        }
+
+        // accept public and protected methods
+        if ( Modifier.isPublic( mod ) || Modifier.isProtected( mod ) )
+        {
+            setAccessible( method );
+            return true;
+        }
+
+        // accept private if accepted
+        if ( Modifier.isPrivate( mod ) )
+        {
+            if ( acceptPrivate )
+            {
+                setAccessible( method );
+                return true;
+            }
+
+            return false;
+        }
+
+        // accept default (package)
+        if ( acceptPackage )
+        {
+            setAccessible( method );
+            return true;
+        }
+
+        // else don't accept
+        return false;
+    }
+
+
+    private static void setAccessible(final Method method)
+    {
+        AccessController.doPrivileged( new PrivilegedAction<Object>()
+        {
+            public Object run()
+            {
+                method.setAccessible( true );
+                return null;
+            }
+        } );
+    }
+
+
+    /**
+     * Returns the name of the package to which the class belongs or an
+     * empty string if the class is in the default package.
+     */
+    public static String getPackageName( Class<?> clazz )
+    {
+        String name = clazz.getName();
+        int dot = name.lastIndexOf( '.' );
+        return ( dot > 0 ) ? name.substring( 0, dot ) : "";
+    }
+
+
+    //---------- State management  ------------------------------------
+
+    /**
+     * Calls the declared method on the given component with the provided
+     * method call arguments.
+     *
+     *
+     *
+     *
+     * @param componentInstance The component instance on which to call the
+     *      method
+     * @param rawParameter The parameter container providing the actual
+     *      parameters to provide to the called method
+     * @param methodCallFailureResult The result to return from this method if
+     *      calling the method resulted in an exception.
+     *
+     * @param logger
+     * @return <code>true</code> if the method was called successfully or the
+     *      method was not found and was not required. <code>false</code> if
+     *      the method was not found but required.
+     *      <code>methodCallFailureResult</code> is returned if the method was
+     *      found and called, but the method threw an exception.
+     */
+    public MethodResult invoke( final Object componentInstance, final P rawParameter,
+            final MethodResult methodCallFailureResult, SimpleLogger logger )
+    {
+        try
+        {
+            return m_state.invoke( this, componentInstance, rawParameter, logger );
+        }
+        catch ( InvocationTargetException ite )
+        {
+            logger.log( LogService.LOG_ERROR, "The {0} method has thrown an exception", new Object[]
+                { getMethodName() }, ite.getCause() );
+        }
+
+        return methodCallFailureResult;
+    }
+
+
+    public boolean methodExists( SimpleLogger logger )
+    {
+        return m_state.methodExists( this, logger );
+    }
+
+    private static interface State
+    {
+
+        <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
+            throws InvocationTargetException;
+
+
+        <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger );
+    }
+
+    private static class NotApplicable implements State
+    {
+
+        private static final State INSTANCE = new NotApplicable();
+
+
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
+        {
+            return MethodResult.VOID;
+        }
+
+
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
+        {
+            return true;
+        }
+    }
+
+    private static class NotResolved implements State
+    {
+        private static final State INSTANCE = new NotResolved();
+
+
+        private synchronized <P> void resolve( final BaseMethod<P> baseMethod, SimpleLogger logger )
+        {
+            logger.log( LogService.LOG_DEBUG, "getting {0}: {1}", new Object[]
+                    {baseMethod.getMethodNamePrefix(), baseMethod.getMethodName()}, null );
+
+            // resolve the method
+            Method method = null;
+            try
+            {
+                method = baseMethod.findMethod( logger );
+            }
+            catch ( InvocationTargetException ex )
+            {
+                logger.log( LogService.LOG_WARNING, "{0} cannot be found", new Object[]
+                        {baseMethod.getMethodName()}, ex.getTargetException() );
+            }
+
+            baseMethod.setMethod( method, logger );
+        }
+
+
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
+            throws InvocationTargetException
+        {
+            resolve( baseMethod, logger );
+            return baseMethod.getState().invoke( baseMethod, componentInstance, rawParameter, logger );
+        }
+
+
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
+        {
+            resolve( baseMethod, logger );
+            return baseMethod.getState().methodExists( baseMethod, logger );
+        }
+    }
+
+    private static class NotFound implements State
+    {
+        private static final State INSTANCE = new NotFound();
+
+
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
+        {
+            // 112.3.1 If the method is not found , SCR must log an error
+            // message with the log service, if present, and ignore the
+            // method
+            logger.log( LogService.LOG_ERROR, "{0} method [{1}] not found", new Object[]
+                { baseMethod.getMethodNamePrefix(), baseMethod.getMethodName() }, null );
+            return null;
+        }
+
+
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
+        {
+            return false;
+        }
+    }
+
+    private static class Resolved implements State
+    {
+        private static final State INSTANCE = new Resolved();
+
+
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
+            throws InvocationTargetException
+        {
+            return baseMethod.invokeMethod( componentInstance, rawParameter, logger );
+        }
+
+
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
+        {
+            return true;
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethod.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethod.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethod.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethod.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,694 @@
+/*
+ * 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.helper;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
+import org.apache.felix.scr.impl.manager.RefPair;
+import org.apache.felix.scr.impl.metadata.DSVersion;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata.ReferenceScope;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+
+/**
+ * Component method to be invoked on service (un)binding.
+ */
+public class BindMethod extends BaseMethod<BindParameters>
+implements org.apache.felix.scr.impl.helper.ReferenceMethod
+{
+    private final String m_referenceClassName;
+
+    private final ReferenceMetadata.ReferenceScope m_referenceScope;
+
+    private enum ParamType {
+        serviceReference,
+        serviceObjects,
+        serviceType,
+        map
+    }
+
+    //initialized for cases where there is no method.
+    private volatile List<ParamType> m_paramTypes = Collections.emptyList();
+
+
+    public BindMethod( final String methodName,
+            final Class<?> componentClass, final String referenceClassName, final DSVersion dsVersion, final boolean configurableServiceProperties, ReferenceScope referenceScope )
+    {
+        super( methodName, componentClass, dsVersion, configurableServiceProperties );
+        m_referenceClassName = referenceClassName;
+        m_referenceScope = referenceScope;
+    }
+
+
+    /**
+     * Finds the method named in the {@link #m_methodName} field in the given
+     * <code>targetClass</code>. If the target class has no acceptable method
+     * the class hierarchy is traversed until a method is found or the root
+     * of the class hierarchy is reached without finding a method.
+     *
+     *
+     * @param targetClass The class in which to look for the method
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @param logger
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class or any super class.
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested method.
+     */
+    @Override
+    protected Method doFindMethod( final Class<?> targetClass, 
+    		final boolean acceptPrivate, 
+    		final boolean acceptPackage, 
+    		final SimpleLogger logger )
+        throws SuitableMethodNotAccessibleException, InvocationTargetException
+    {
+        // 112.3.1 The method is searched for using the following priority
+        //  1 - ServiceReference single parameter
+        //  2 - DS 1.3+ : ComponentServiceObjects single parameter
+        //  3 - Service object single parameter
+        //  4 - Service interface assignment compatible single parameter
+        //  5 - DS 1.3+ : Single argument with Map
+        //  6 - DS 1.1/DS 1.2 : two parameters, first the type of or assignment compatible with the service, the second Map
+        //  7 - DS 1.3+ : one or more parameters of types ServiceReference, ServiceObjects, interface type, 
+    	//                or assignment compatible to interface type, in any order.
+
+    	// flag indicating a suitable but inaccessible method has been found
+        boolean suitableMethodNotAccessible = false;
+
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "doFindMethod: Looking for method " + targetClass.getName() + "." + getMethodName(), null );
+        }
+
+        // Case 1 - Service reference parameter
+        Method method;
+        try
+        {
+            method = getServiceReferenceMethod( targetClass, acceptPrivate, acceptPackage, logger );
+            if ( method != null )
+            {
+                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                {
+                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+                }
+                m_paramTypes = Collections.singletonList(ParamType.serviceReference);
+                return method;
+            }
+        }
+        catch ( SuitableMethodNotAccessibleException ex )
+        {
+            suitableMethodNotAccessible = true;
+        }
+
+        // Case 2 - ComponentServiceObjects parameter
+        if ( getDSVersion().isDS13() )
+        {
+	        try
+	        {
+	            method = getComponentObjectsMethod( targetClass, acceptPrivate, acceptPackage, logger );
+	            if ( method != null )
+	            {
+	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+	                {
+	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+	                }
+	                m_paramTypes = Collections.singletonList(ParamType.serviceObjects);
+	                return method;
+	            }
+	        }
+	        catch ( SuitableMethodNotAccessibleException ex )
+	        {
+	            suitableMethodNotAccessible = true;
+	        }
+        }
+        
+        // for further methods we need the class of the service object
+        final Class<?> parameterClass = ClassUtils.getClassFromComponentClassLoader( targetClass, m_referenceClassName, logger );
+        if ( parameterClass != null )
+        {
+
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log(
+                    LogService.LOG_DEBUG,
+                    "doFindMethod: No method taking ServiceReference found, checking method taking "
+                        + parameterClass.getName(), null );
+            }
+
+            // Case 3 - Service object parameter
+            try
+            {
+                method = getServiceObjectMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
+                if ( method != null )
+                {
+	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+	                {
+	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+	                }
+	                m_paramTypes = Collections.singletonList(ParamType.serviceType);
+                    return method;
+                }
+            }
+            catch ( SuitableMethodNotAccessibleException ex )
+            {
+                suitableMethodNotAccessible = true;
+            }
+
+            // Case 4 - Service interface assignment compatible methods
+            try
+            {
+                method = getServiceObjectAssignableMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
+                if ( method != null )
+                {
+	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+	                {
+	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+	                }
+                    m_paramTypes = Collections.singletonList(ParamType.serviceType);
+                    return method;
+                }
+            }
+            catch ( SuitableMethodNotAccessibleException ex )
+            {
+                suitableMethodNotAccessible = true;
+            }
+
+            // Case 5 - DS 1.3+ : Single argument with Map
+            if ( getDSVersion().isDS13() )
+            {
+                try
+                {
+                    method = getMapMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
+                    if ( method != null )
+                    {
+    	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+    	                {
+    	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+    	                }
+                        m_paramTypes = Collections.singletonList(ParamType.map);
+                        return method;
+                    }
+                }
+                catch ( SuitableMethodNotAccessibleException ex )
+                {
+                    suitableMethodNotAccessible = true;
+                }            	
+            }
+            
+            // signatures taking a map are only supported starting with DS 1.1
+            if ( getDSVersion().isDS11() && !getDSVersion().isDS13() )
+            {
+
+                // Case 6 - same as case 3, but + Map param (DS 1.1 only)
+                try
+                {
+                    method = getServiceObjectWithMapMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
+                    if ( method != null )
+                    {
+    	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+    	                {
+    	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+    	                }
+                        List<ParamType> paramTypes = new ArrayList<ParamType>(2);
+                        paramTypes.add(ParamType.serviceType);
+                        paramTypes.add(ParamType.map);
+                        m_paramTypes = paramTypes;
+                        return method;
+                    }
+                }
+                catch ( SuitableMethodNotAccessibleException ex )
+                {
+                    suitableMethodNotAccessible = true;
+                }
+
+                // Case 6 - same as case 4, but + Map param (DS 1.1 only)
+                try
+                {
+                    method = getServiceObjectAssignableWithMapMethod( targetClass, parameterClass, acceptPrivate,
+                        acceptPackage );
+                    if ( method != null )
+                    {
+    	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+    	                {
+    	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
+    	                }
+                        List<ParamType> paramTypes = new ArrayList<ParamType>(2);
+                        paramTypes.add(ParamType.serviceType);
+                        paramTypes.add(ParamType.map);
+                        m_paramTypes = paramTypes;
+                        return method;
+                    }
+                }
+                catch ( SuitableMethodNotAccessibleException ex )
+                {
+                    suitableMethodNotAccessible = true;
+                }
+
+            }
+            // Case 7 - Multiple parameters
+            if ( getDSVersion().isDS13() )
+            {
+                for (Method m: targetClass.getDeclaredMethods())
+                {
+                    if (getMethodName().equals(m.getName())) {
+                        Class<?>[] parameterTypes = m.getParameterTypes();
+                        boolean matches = true;
+                        boolean specialMatch = true;
+                        List<ParamType> paramTypes = new ArrayList<ParamType>(parameterTypes.length);
+                        for (Class<?> paramType: parameterTypes) {
+                            if (paramType == ClassUtils.SERVICE_REFERENCE_CLASS)
+                            {
+                                if (specialMatch && parameterClass == ClassUtils.SERVICE_REFERENCE_CLASS)
+                                {
+                                    specialMatch = false;
+                                    paramTypes.add(ParamType.serviceType);
+                                }
+                                else
+                                {
+                                    paramTypes.add(ParamType.serviceReference);
+                                }
+                            }
+                            else if (paramType == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS)
+                            {
+                                if (specialMatch && parameterClass == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS)
+                                {
+                                    specialMatch = false;
+                                    paramTypes.add(ParamType.serviceType);
+                                }
+                                else
+                                {
+                                    paramTypes.add(ParamType.serviceObjects);
+                                }
+                            }
+                            else if (paramType == Map.class)
+                            {
+                                if (specialMatch && parameterClass == Map.class)
+                                {
+                                    specialMatch = false;
+                                    paramTypes.add(ParamType.serviceType);
+                                }
+                                else
+                                {
+                                    paramTypes.add(ParamType.map);
+                                }
+                            }
+                            else if (paramType.isAssignableFrom( parameterClass ) )
+                            {
+                                paramTypes.add(ParamType.serviceType);
+                            }
+                            else
+                            {
+                                matches = false;
+                                break;
+                            }
+                        }
+                        if (matches)
+                        {
+                            if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+                            {
+            	                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            	                {
+            	                    logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + m, null );
+            	                }
+                                m_paramTypes = paramTypes;
+                                return m;
+                            }
+                            suitableMethodNotAccessible = true;
+                        }
+                    }
+                }
+            }
+        }
+        else if ( logger.isLogEnabled( LogService.LOG_WARNING ) )
+        {
+            logger.log(
+                LogService.LOG_WARNING,
+                "doFindMethod: Cannot check for methods taking parameter class " + m_referenceClassName + ": "
+                    + targetClass.getName() + " does not see it", null );
+        }
+
+        // if at least one suitable method could be found but none of
+        // the suitable methods are accessible, we have to terminate
+        if ( suitableMethodNotAccessible )
+        {
+            logger.log( LogService.LOG_ERROR,
+                "doFindMethod: Suitable but non-accessible method found in class {0}", new Object[]
+                    { targetClass.getName() }, null );
+            throw new SuitableMethodNotAccessibleException();
+        }
+
+        // no method found
+        return null;
+    }
+
+    /**
+     * Returns a method taking a single <code>ServiceReference</code> object
+     * as a parameter or <code>null</code> if no such method exists.
+     *
+     *
+     * @param targetClass The class in which to look for the method. Only this
+     *      class is searched for the method.
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @param logger
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class.
+     * @throws SuitableMethodNotAccessibleException If a suitable method was
+     *      found which is not accessible
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested method.
+     */
+    private Method getServiceReferenceMethod( final Class<?> targetClass, boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger )
+        throws SuitableMethodNotAccessibleException, InvocationTargetException
+    {
+        return getMethod( targetClass, getMethodName(), new Class[]
+            { ClassUtils.SERVICE_REFERENCE_CLASS }, acceptPrivate, acceptPackage, logger );
+    }
+
+    private Method getComponentObjectsMethod( final Class<?> targetClass, boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger )
+        throws SuitableMethodNotAccessibleException, InvocationTargetException
+    {
+        return getMethod(targetClass, getMethodName(),
+            new Class[] { ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS }, acceptPrivate, acceptPackage,
+            logger);
+    }
+
+
+    /**
+     * Returns a method taking a single parameter of the exact type declared
+     * for the service reference or <code>null</code> if no such method exists.
+     *
+     *
+     * @param targetClass The class in which to look for the method. Only this
+     *      class is searched for the method.
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @param logger
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class.
+     * @throws SuitableMethodNotAccessibleException If a suitable method was
+     *      found which is not accessible
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested method.
+     */
+    private Method getServiceObjectMethod( final Class<?> targetClass, final Class<?> parameterClass, boolean acceptPrivate,
+            boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException, InvocationTargetException
+    {
+        return getMethod( targetClass, getMethodName(), new Class[]
+            { parameterClass }, acceptPrivate, acceptPackage, logger );
+    }
+
+
+    /**
+     * Returns a method taking a single object whose type is assignment
+     * compatible with the declared service type or <code>null</code> if no
+     * such method exists.
+     *
+     *
+     * @param targetClass The class in which to look for the method. Only this
+     *      class is searched for the method.
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @param logger
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class.
+     * @throws SuitableMethodNotAccessibleException If a suitable method was
+     *      found which is not accessible
+     */
+    private Method getServiceObjectAssignableMethod( final Class<?> targetClass, final Class<?> parameterClass,
+            boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException
+    {
+        // Get all potential bind methods
+        Method candidateBindMethods[] = targetClass.getDeclaredMethods();
+        boolean suitableNotAccessible = false;
+
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log(
+                LogService.LOG_DEBUG,
+                "getServiceObjectAssignableMethod: Checking " + candidateBindMethods.length
+                    + " declared method in class " + targetClass.getName(), null );
+        }
+
+        // Iterate over them
+        for ( int i = 0; i < candidateBindMethods.length; i++ )
+        {
+            Method method = candidateBindMethods[i];
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG, "getServiceObjectAssignableMethod: Checking " + method, null );
+            }
+
+            // Get the parameters for the current method
+            Class[] parameters = method.getParameterTypes();
+
+            // Select only the methods that receive a single
+            // parameter
+            // and a matching name
+            if ( parameters.length == 1 && method.getName().equals( getMethodName() ) )
+            {
+
+                if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                {
+                    logger.log( LogService.LOG_DEBUG, "getServiceObjectAssignableMethod: Considering " + method, null );
+                }
+
+                // Get the parameter type
+                final Class<?> theParameter = parameters[0];
+
+                // Check if the parameter type is ServiceReference
+                // or is assignable from the type specified by the
+                // reference's interface attribute
+                if ( theParameter.isAssignableFrom( parameterClass ) )
+                {
+                    if ( accept( method, acceptPrivate, acceptPackage, false ) )
+                    {
+                        return method;
+                    }
+
+                    // suitable method is not accessible, flag for exception
+                    suitableNotAccessible = true;
+                }
+                else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                {
+                    logger.log(
+                        LogService.LOG_DEBUG,
+                        "getServiceObjectAssignableMethod: Parameter failure: Required " + theParameter + "; actual "
+                            + parameterClass.getName(), null );
+                }
+
+            }
+        }
+
+        // if one or more suitable methods which are not accessible is/are
+        // found an exception is thrown
+        if ( suitableNotAccessible )
+        {
+            throw new SuitableMethodNotAccessibleException();
+        }
+
+        // no method with assignment compatible argument found
+        return null;
+    }
+
+
+    /**
+     * Returns a method taking two parameters, the first being of the exact
+     * type declared for the service reference and the second being a
+     * <code>Map</code> or <code>null</code> if no such method exists.
+     *
+     *
+     * @param targetClass The class in which to look for the method. Only this
+     *      class is searched for the method.
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @param logger
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class.
+     * @throws SuitableMethodNotAccessibleException If a suitable method was
+     *      found which is not accessible
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested method.
+     */
+    private Method getServiceObjectWithMapMethod( final Class<?> targetClass, final Class<?> parameterClass,
+            boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException,
+        InvocationTargetException
+    {
+        return getMethod( targetClass, getMethodName(), new Class[]
+            { parameterClass, ClassUtils.MAP_CLASS }, acceptPrivate, acceptPackage, logger );
+    }
+
+
+    /**
+     * Returns a method taking two parameters, the first being an object
+     * whose type is assignment compatible with the declared service type and
+     * the second being a <code>Map</code> or <code>null</code> if no such
+     * method exists.
+     *
+     * @param targetClass The class in which to look for the method. Only this
+     *      class is searched for the method.
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class.
+     * @throws SuitableMethodNotAccessibleException If a suitable method was
+     *      found which is not accessible
+     */
+    private Method getServiceObjectAssignableWithMapMethod( final Class<?> targetClass, final Class<?> parameterClass,
+        boolean acceptPrivate, boolean acceptPackage ) throws SuitableMethodNotAccessibleException
+    {
+        // Get all potential bind methods
+        Method candidateBindMethods[] = targetClass.getDeclaredMethods();
+        boolean suitableNotAccessible = false;
+
+        // Iterate over them
+        for ( int i = 0; i < candidateBindMethods.length; i++ )
+        {
+            final Method method = candidateBindMethods[i];
+            final Class[] parameters = method.getParameterTypes();
+            if ( parameters.length == 2 && method.getName().equals( getMethodName() ) )
+            {
+
+                // parameters must be refclass,map
+                if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == ClassUtils.MAP_CLASS )
+                {
+                    if ( accept( method, acceptPrivate, acceptPackage, false ) )
+                    {
+                        return method;
+                    }
+
+                    // suitable method is not accessible, flag for exception
+                    suitableNotAccessible = true;
+                }
+            }
+        }
+
+        // if one or more suitable methods which are not accessible is/are
+        // found an exception is thrown
+        if ( suitableNotAccessible )
+        {
+            throw new SuitableMethodNotAccessibleException();
+        }
+
+        // no method with assignment compatible argument found
+        return null;
+    }
+
+    /**
+     * Returns a method taking a single map parameter
+     * or <code>null</code> if no such method exists.
+     *
+     *
+     * @param targetClass The class in which to look for the method. Only this
+     *      class is searched for the method.
+     * @param acceptPrivate <code>true</code> if private methods should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private methods should
+     *      be considered.
+     * @param logger
+     * @return The requested method or <code>null</code> if no acceptable method
+     *      can be found in the target class.
+     * @throws SuitableMethodNotAccessibleException If a suitable method was
+     *      found which is not accessible
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested method.
+     */
+    private Method getMapMethod( final Class<?> targetClass, final Class<?> parameterClass,
+            boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException,
+        InvocationTargetException
+    {
+        return getMethod( targetClass, getMethodName(), new Class[]
+            { ClassUtils.MAP_CLASS }, acceptPrivate, acceptPackage, logger );
+    }
+
+    public <S, T> boolean getServiceObject( ComponentContextImpl<S> key, RefPair<S, T> refPair, BundleContext context, SimpleLogger logger )
+    {
+        //??? this resolves which we need.... better way?
+        if ( refPair.getServiceObject(key) == null && methodExists( logger ) )
+        {
+            if ( m_paramTypes.contains(ParamType.serviceType) ) {
+                return refPair.getServiceObject(key, context, logger);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    protected Object[] getParameters( Method method, BindParameters bp )
+    {
+        ComponentContextImpl key = bp.getComponentContext();
+        Object[] result = new Object[ m_paramTypes.size()];
+        RefPair<?, ?> refPair = bp.getRefPair();
+        int i = 0;
+        for ( ParamType pt: m_paramTypes ) {
+            switch (pt) {
+                case serviceReference:
+                    result[i++] = refPair.getRef();
+                    break;
+
+                case serviceObjects:
+                    result[i++] = ((ComponentServiceObjectsHelper)bp.getComponentContext().getComponentServiceObjectsHelper()).getServiceObjects(refPair.getRef());
+                    break;
+
+                case map:
+                    result[i++] = new ReadOnlyDictionary<String, Object>( refPair.getRef() );
+                    break;
+
+                case serviceType:
+                    result[i++] = refPair.getServiceObject(key);
+                    break;
+
+                default: throw new IllegalStateException("unexpected ParamType: " + pt);
+
+            }
+        }
+        return result;
+    }
+
+
+    @Override
+    protected String getMethodNamePrefix()
+    {
+        return "bind";
+    }
+
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethods.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethods.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethods.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindMethods.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,79 @@
+/*
+ * 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.helper;
+
+
+import org.apache.felix.scr.impl.metadata.DSVersion;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+
+/**
+ * @version $Rev: 1637793 $ $Date: 2014-11-10 06:51:04 +0100 (Mon, 10 Nov 2014) $
+ */
+public class BindMethods implements ReferenceMethods
+{
+    private final ReferenceMethod m_bind;
+    private final ReferenceMethod m_updated;
+    private final ReferenceMethod m_unbind;
+
+    public BindMethods( ReferenceMetadata m_dependencyMetadata, Class<?> instanceClass,
+            final DSVersion dsVersion, final boolean configurableServiceProperties )
+    {
+        ReferenceMetadata.ReferenceScope referenceScope = m_dependencyMetadata.getScope();
+        m_bind = new org.apache.felix.scr.impl.helper.BindMethod(
+                m_dependencyMetadata.getBind(),
+                instanceClass,
+                m_dependencyMetadata.getInterface(),
+                dsVersion, configurableServiceProperties, referenceScope
+        );
+        m_updated = new org.apache.felix.scr.impl.helper.UpdatedMethod(
+                m_dependencyMetadata.getUpdated(),
+                instanceClass,
+                m_dependencyMetadata.getInterface(),
+                dsVersion, configurableServiceProperties, referenceScope
+        );
+        m_unbind = new org.apache.felix.scr.impl.helper.UnbindMethod(
+                m_dependencyMetadata.getUnbind(),
+                instanceClass,
+                m_dependencyMetadata.getInterface(),
+                dsVersion, configurableServiceProperties, referenceScope
+        );
+    }
+
+    public ReferenceMethod getBind()
+    {
+        return m_bind;
+    }
+
+    public ReferenceMethod getUnbind()
+    {
+        return m_unbind;
+    }
+
+    public ReferenceMethod getUpdated()
+    {
+        return m_updated;
+    }
+
+    public InitReferenceMethod getInit()
+    {
+        return null;
+    }
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindParameters.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindParameters.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindParameters.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/BindParameters.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,45 @@
+/*
+ * 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.helper;
+
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
+import org.apache.felix.scr.impl.manager.RefPair;
+
+public class BindParameters
+{
+    
+    private final ComponentContextImpl<?> componentContext;
+    private final RefPair<?, ?> refPair;
+    public BindParameters(ComponentContextImpl<?> componentContext, RefPair<?, ?> refPair)
+    {
+        this.componentContext = componentContext;
+        this.refPair = refPair;
+    }
+    
+    public ComponentContextImpl<?> getComponentContext()
+    {
+        return componentContext;
+    }
+    
+    public RefPair<?, ?> getRefPair()
+    {
+        return refPair;
+    }
+    
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ClassUtils.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ClassUtils.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ClassUtils.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ClassUtils.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,163 @@
+/*
+ * 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.helper;
+
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.Activator;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentServiceObjects;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+
+/**
+ * Utility methods for class handling used by method and field references.
+ */
+public class ClassUtils
+{
+
+    private static final Class<?> OBJECT_CLASS = Object.class;
+
+    public static final Class<?> SERVICE_REFERENCE_CLASS = ServiceReference.class;
+
+    public static final Class<?> COMPONENTS_SERVICE_OBJECTS_CLASS = ComponentServiceObjects.class;
+
+    public static final Class<?> MAP_CLASS = Map.class;
+    public static final Class<?> MAP_ENTRY_CLASS = Map.Entry.class;
+
+    public static final Class<?> COLLECTION_CLASS = Collection.class;
+    public static final Class<?> LIST_CLASS = List.class;
+
+    /**
+     * Returns the class object representing the class of the field reference
+     * The class loader of the component class is used to load the service class.
+     * <p>
+     * It may well be possible, that the class loader of the target class cannot
+     * see the service object class, for example if the service reference is
+     * inherited from a component class of another bundle.
+     *
+     * @return The class object for the referred to service or <code>null</code>
+     *      if the class loader of the <code>targetClass</code> cannot see that
+     *      class.
+     */
+    public static Class<?> getClassFromComponentClassLoader(
+            final Class<?> componentClass,
+            final String className,
+            final SimpleLogger logger )
+    {
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log(
+                LogService.LOG_DEBUG,
+                "getReferenceClass: Looking for interface class {0} through loader of {1}",
+                    new Object[] {className, componentClass.getName()}, null );
+        }
+
+        try
+        {
+            // need the class loader of the target class, which may be the
+            // system classloader, which case getClassLoader may retur null
+            ClassLoader loader = componentClass.getClassLoader();
+            if ( loader == null )
+            {
+                loader = ClassLoader.getSystemClassLoader();
+            }
+
+            final Class<?> referenceClass = loader.loadClass( className );
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "getParameterClass: Found class {0}", new Object[] {referenceClass.getName()}, null );
+            }
+            return referenceClass;
+        }
+        catch ( final ClassNotFoundException cnfe )
+        {
+            // if we can't load the class, perhaps the method is declared in a
+            // super class so we try this class next
+        }
+
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: Not found through component class, using PackageAdmin service", null );
+        }
+
+        // try to load the class with the help of the PackageAdmin service
+        PackageAdmin pa = ( PackageAdmin ) Activator.getPackageAdmin();
+        if ( pa != null )
+        {
+            final String referenceClassPackage = className.substring( 0, className
+                .lastIndexOf( '.' ) );
+            ExportedPackage[] pkg = pa.getExportedPackages( referenceClassPackage );
+            if ( pkg != null )
+            {
+                for ( int i = 0; i < pkg.length; i++ )
+                {
+                    try
+                    {
+                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                        {
+                            logger.log(
+                                LogService.LOG_DEBUG,
+                                "getParameterClass: Checking Bundle {0}/{1}",
+                                    new Object[] {pkg[i].getExportingBundle().getSymbolicName(), pkg[i].getExportingBundle().getBundleId()}, null );
+                        }
+
+                        Class<?> referenceClass = pkg[i].getExportingBundle().loadClass( className );
+                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                        {
+                            logger.log( LogService.LOG_DEBUG,
+                                    "getParameterClass: Found class {0}", new Object[] {referenceClass.getName()}, null );
+                        }
+                        return referenceClass;
+                    }
+                    catch ( ClassNotFoundException cnfe )
+                    {
+                        // exported package does not provide the interface !!!!
+                    }
+                }
+            }
+            else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "getParameterClass: No bundles exporting package {0} found", new Object[] {referenceClassPackage}, null );
+            }
+        }
+        else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: PackageAdmin service not available, cannot find class", null );
+        }
+
+        // class cannot be found, neither through the component nor from an
+        // export, so we fall back to assuming Object
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: No class found, falling back to class Object", null );
+        }
+        return OBJECT_CLASS;
+    }
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Coercions.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Coercions.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Coercions.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/Coercions.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,442 @@
+/*
+ * 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.helper;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentException;
+
+/**
+ * This implements the coercion table in RFC 190 5.6.3 
+ *
+ */
+public class Coercions
+{
+// Numbers are   AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short
+//annotation fields can be primitives, String, Class, enums, annotations, and arrays of the preceding types 
+//    input scalars
+//    String | Integer | Long | Float
+//    | Double | Byte | Short
+//| Character | Boolean
+    private static final byte byte0 = 0;
+    private static final double double0 = 0;
+    private static final float float0 = 0;
+    private static final int int0 = 0;
+    private static final long long0 = 0;
+    private static final short short0 = 0;
+    
+    public static Object coerce(Class<?> type, Object raw, Bundle bundle )
+    {
+        if (type == Byte.class || type == byte.class)
+        {
+            return coerceToByte(raw);
+        }
+        if (type == Boolean.class || type == boolean.class)
+        {
+            return coerceToBoolean(raw);
+        }
+        if (type == Class.class)
+        {
+            return coerceToClass(raw, bundle);
+        }
+        if (type == Double.class || type == double.class)
+        {
+            return coerceToDouble(raw);
+        }
+        if (type.isEnum())
+        {
+            Class clazz = type; //TODO is there a better way to do ? enum creation?
+            return coerceToEnum(raw, clazz);
+        }
+        if (type == Float.class || type == float.class)
+        {
+            return coerceToFloat(raw);
+        }
+        if (type == Integer.class || type == int.class)
+        {
+            return coerceToInteger(raw);
+        }
+        if (type == Long.class || type == long.class)
+        {
+            return coerceToLong(raw);
+        }
+        if (type == Short.class || type == short.class)
+        {
+            return coerceToShort(raw);
+        }
+        if (type == String.class)
+        {
+            return coerceToString(raw);
+        }
+        throw new ComponentException ("unexpected output type " + type);
+    }
+    
+    public static byte coerceToByte(Object o)
+    {
+        o = multipleToSingle( o, byte0 );
+        if (o instanceof Byte)
+        {
+            return (Byte)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Byte.parseByte( (String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o? 1: byte0;
+        }
+        if (o instanceof Character)
+        {
+            return ( byte ) ((Character)o).charValue();
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).byteValue();
+        }
+        if (o == null) 
+        {
+            return 0;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static double coerceToDouble(Object o)
+    {
+        o = multipleToSingle( o, double0 );
+        if (o instanceof Double)
+        {
+            return (Double)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Double.parseDouble((String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o? 1: 0;
+        }
+        if (o instanceof Character)
+        {
+            return ( double ) ((Character)o).charValue();
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).doubleValue();
+        }
+        if (o == null) 
+        {
+            return 0;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static float coerceToFloat(Object o)
+    {
+        o = multipleToSingle( o, float0 );
+        if (o instanceof Float)
+        {
+            return (Float)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Float.parseFloat((String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o? 1: 0;
+        }
+        if (o instanceof Character)
+        {
+            return ( float ) ((Character)o).charValue();
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).floatValue();
+        }
+        if (o == null) 
+        {
+            return 0;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static int coerceToInteger(Object o)
+    {
+        o = multipleToSingle( o, int0 );
+        if (o instanceof Integer)
+        {
+            return (Integer)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Integer.parseInt( (String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o? 1: 0;
+        }
+        if (o instanceof Character)
+        {
+            return ( int ) ((Character)o).charValue();
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).intValue();
+        }
+        if (o == null) 
+        {
+            return 0;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static long coerceToLong(Object o)
+    {
+        o = multipleToSingle( o, long0 );
+        if (o instanceof Long)
+        {
+            return (Long)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Long.parseLong( (String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o? 1: 0;
+        }
+        if (o instanceof Character)
+        {
+            return ( long ) ((Character)o).charValue();
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).longValue();
+        }
+        if (o == null) 
+        {
+            return 0;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static short coerceToShort(Object o)
+    {
+        o = multipleToSingle( o, short0 );
+        if (o instanceof Short)
+        {
+            return (Short)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Short.parseShort( (String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o? 1: short0;
+        }
+        if (o instanceof Character)
+        {
+            return ( short ) ((Character)o).charValue();
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).shortValue();
+        }
+        if (o == null) 
+        {
+            return 0;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static String coerceToString(Object o)
+    {
+        o = multipleToSingle( o, null );
+        if (o instanceof String)
+        {
+            return (String)o;
+        }
+        if (o == null)
+        {
+            return null;
+        }
+        
+        return o.toString();
+    }
+    
+    public static boolean coerceToBoolean(Object o)
+    {
+        o = multipleToSingle( o, false );
+        if (o instanceof Boolean)
+        {
+            return (Boolean)o;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return Boolean.parseBoolean( (String)o );
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o instanceof Character)
+        {
+            return ((Character)o).charValue() != 0;
+        }
+        if (o instanceof Number)
+        {
+            return ((Number)o).intValue() != 0;
+        }
+        if (o == null) 
+        {
+            return false;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static Class<?> coerceToClass(Object o, Bundle b)
+    {
+        o = multipleToSingle( o, null );
+        if (o == null)
+        {
+            return null;
+        }
+        if (o instanceof String)
+        {
+            try
+            {
+                return b.loadClass( (String)o );
+            }
+            catch ( ClassNotFoundException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    public static <T extends Enum<T>> T coerceToEnum(Object o, Class<T> clazz)
+    {
+        o = multipleToSingle( o, null );
+        if (o instanceof String)
+        {
+            try
+            {
+            return Enum.valueOf( clazz, (String)o );
+            }
+            catch ( IllegalArgumentException e )
+            {
+                throw new ComponentException(e);
+            }
+        }
+        if (o == null) 
+        {
+            return null;
+        }
+        throw new ComponentException( "Unrecognized input type: " + o);
+    }
+    
+    private static Object multipleToSingle(Object o, Object defaultValue)
+    {
+        if (o instanceof Collection)
+        {
+            return firstCollectionElement( o, defaultValue );
+        }
+        if (o != null && o.getClass().isArray()) {
+            return firstArrayElement( o, defaultValue);
+        }
+        return o;
+    }
+    
+    private static Object firstCollectionElement( Object raw, Object defaultValue )
+    {
+        if (!(raw instanceof Collection)) 
+        {
+            throw new ComponentException("Not a collection: " + raw);
+        }
+        Collection<?> c = ( Collection<?> ) raw;
+        if (c.isEmpty())
+        {
+            return defaultValue;
+        }
+        return c.iterator().next();
+    }
+
+    private static Object firstArrayElement(Object o, Object defaultValue)
+    {
+        if (o == null || !o.getClass().isArray()) {
+            throw new ComponentException("Not an array: " + o);
+        }
+        if (Array.getLength( o ) == 0)
+        {
+            return defaultValue;
+        }
+        return Array.get( o, 0 );
+    }
+
+}

Added: felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentMethods.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentMethods.java?rev=1689973&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentMethods.java (added)
+++ felix/sandbox/pderop/dependencymanager.ds/org.apache.felix.dependencymanager.ds/src/org/apache/felix/scr/impl/helper/ComponentMethods.java Wed Jul  8 22:10:14 2015
@@ -0,0 +1,99 @@
+/*
+ * 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.helper;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+import org.apache.felix.scr.impl.metadata.DSVersion;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+
+/**
+ * @version $Rev: 1653352 $ $Date: 2015-01-20 20:58:11 +0100 (Tue, 20 Jan 2015) $
+ */
+public class ComponentMethods
+{
+    private ActivateMethod m_activateMethod;
+    private ModifiedMethod m_modifiedMethod;
+    private DeactivateMethod m_deactivateMethod;
+
+    private final Map<String, ReferenceMethods> bindMethodMap = new HashMap<String, ReferenceMethods>();
+
+    public synchronized void initComponentMethods( ComponentMetadata componentMetadata, Class<?> implementationObjectClass )
+    {
+        if (m_activateMethod != null)
+        {
+            return;
+        }
+        DSVersion dsVersion = componentMetadata.getDSVersion();
+        boolean configurableServiceProperties = componentMetadata.isConfigurableServiceProperties();
+        boolean supportsInterfaces = componentMetadata.isConfigureWithInterfaces();
+        m_activateMethod = new ActivateMethod( componentMetadata.getActivate(), componentMetadata
+                .isActivateDeclared(), implementationObjectClass, dsVersion, configurableServiceProperties, supportsInterfaces );
+        m_deactivateMethod = new DeactivateMethod( componentMetadata.getDeactivate(),
+                componentMetadata.isDeactivateDeclared(), implementationObjectClass, dsVersion, configurableServiceProperties, supportsInterfaces );
+
+        m_modifiedMethod = new ModifiedMethod( componentMetadata.getModified(), implementationObjectClass, dsVersion, configurableServiceProperties, supportsInterfaces );
+
+        for ( ReferenceMetadata referenceMetadata: componentMetadata.getDependencies() )
+        {
+            final String refName = referenceMetadata.getName();
+            final ReferenceMethods methods;
+            if ( referenceMetadata.getField() != null && referenceMetadata.getBind() != null)
+            {
+                methods = new DuplexReferenceMethods(
+                        new FieldMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties),
+                        new BindMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties));
+            }
+            else if ( referenceMetadata.getField() != null )
+            {
+                methods = new FieldMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties);
+            }
+            else
+            {
+                methods = new BindMethods( referenceMetadata, implementationObjectClass, dsVersion, configurableServiceProperties);
+            }
+            bindMethodMap.put( refName, methods );
+        }
+    }
+
+    public ActivateMethod getActivateMethod()
+    {
+        return m_activateMethod;
+    }
+
+    public DeactivateMethod getDeactivateMethod()
+    {
+        return m_deactivateMethod;
+    }
+
+    public ModifiedMethod getModifiedMethod()
+    {
+        return m_modifiedMethod;
+    }
+
+    public ReferenceMethods getBindMethods(String refName )
+    {
+        return bindMethodMap.get( refName );
+    }
+
+}