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 );
+ }
+
+}