You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2009/08/03 11:07:24 UTC

svn commit: r800267 - in /felix/trunk/scr/src: main/java/org/apache/felix/scr/impl/helper/ main/java/org/apache/felix/scr/impl/manager/ test/java/org/apache/felix/scr/impl/helper/ test/java/org/apache/felix/scr/impl/metadata/instances/ test/java/org/ap...

Author: fmeschbe
Date: Mon Aug  3 09:07:23 2009
New Revision: 800267

URL: http://svn.apache.org/viewvc?rev=800267&view=rev
Log:
FELIX-1440 Add support for method lookup termination on suitable
non-accessible methods for activate/deactivate methods plus the
respective test case

Added:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java   (with props)
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java?rev=800267&r1=800266&r2=800267&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java Mon Aug  3 09:07:23 2009
@@ -114,13 +114,19 @@
         final String packageName = getPackageName( objectClass );
         final Class[] parameterTypesList = tester.getParameterLists();
 
-        for ( Class clazz = objectClass; clazz != null; clazz = clazz.getSuperclass() )
+        // flag indicating a suitable but inaccessible method has been found
+        boolean suitableMethodNotAccessible = false;
+
+        // lookup methods until there is no more super class or a class would
+        // have at least one suitable method but none is accessible
+        for ( Class clazz = objectClass; clazz != null && !suitableMethodNotAccessible; clazz = clazz.getSuperclass() )
         {
             // turns false on first package not equal to the package of objectClass (or different class loader)
             acceptPackage &= packageName.equals( getPackageName( clazz ) )
                 && clazz.getClassLoader() == objectClass.getClassLoader();
             final boolean acceptPrivate = tester.acceptPrivate() && clazz == objectClass;
 
+
             // check parameter types first
             for ( int i = 0; i < parameterTypesList.length; i++ )
             {
@@ -136,6 +142,10 @@
                 {
                     // ignore for now
                 }
+                catch ( SuitableMethodNotAccessibleException smnae )
+                {
+                    suitableMethodNotAccessible = true;
+                }
                 catch ( Throwable throwable )
                 {
                     // unexpected problem accessing the method, don't let everything
@@ -148,11 +158,16 @@
             Method[] methods = clazz.getDeclaredMethods();
             for ( int i = 0; i < methods.length; i++ )
             {
-                if ( methods[i].getName().equals( name ) && tester.isSuitable( methods[i] )
-                    && accept( methods[i], acceptPrivate, acceptPackage ) )
+                if ( methods[i].getName().equals( name ) && tester.isSuitable( methods[i] ) )
                 {
-                    // check modifiers etc.
-                    return methods[i];
+                    if ( accept( methods[i], acceptPrivate, acceptPackage ) )
+                    {
+                        // check modifiers etc.
+                        return methods[i];
+                    }
+
+                    // method is suitable but not accessible, flag it
+                    suitableMethodNotAccessible = true;
                 }
             }
 
@@ -168,6 +183,10 @@
                 {
                     // ignore for now
                 }
+                catch ( SuitableMethodNotAccessibleException smnae )
+                {
+                    suitableMethodNotAccessible = true;
+                }
                 catch ( Throwable throwable )
                 {
                     // unexpected problem accessing the method, don't let everything
@@ -199,11 +218,15 @@
      *
      * @throws NoSuchMethodException If no public or protected method with
      *      the given name can be found in the class or any of its super classes.
+     * @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 ) throws NoSuchMethodException, InvocationTargetException
+        boolean acceptPackage ) throws NoSuchMethodException, SuitableMethodNotAccessibleException,
+        InvocationTargetException
     {
         try
         {
@@ -228,9 +251,8 @@
             throw new InvocationTargetException( throwable, "Unexpected problem trying to get method " + name );
         }
 
-        // walked up the complete super class hierarchy and still not found
-        // anything, sigh ...
-        throw new NoSuchMethodException( name );
+        // suitable method found which is not accessible
+        throw new SuitableMethodNotAccessibleException();
     }
 
 

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java?rev=800267&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java Mon Aug  3 09:07:23 2009
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+
+public class SuitableMethodNotAccessibleException extends Exception
+{
+}
\ No newline at end of file

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/SuitableMethodNotAccessibleException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java?rev=800267&r1=800266&r2=800267&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java Mon Aug  3 09:07:23 2009
@@ -23,6 +23,7 @@
 import java.lang.reflect.Method;
 import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
 import org.apache.felix.scr.impl.helper.ReflectionHelper;
+import org.apache.felix.scr.impl.helper.SuitableMethodNotAccessibleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
@@ -80,24 +81,33 @@
      *      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.
-     * @throws SuitableMethodNotAccessibleException If a suitable method was
-     *      found which is not accessible
      */
     private Method findMethod( final Class targetClass, final boolean acceptPrivate, final boolean acceptPackage )
-        throws InvocationTargetException//, SuitableMethodNotAccessibleException
+        throws InvocationTargetException
     {
         // 112.3.1 The method is searched for using the following priority
-        // 1. The method's parameter type is org.osgi.framework.ServiceReference
-        // 2. The method's parameter type is the type specified by the
-        // reference's interface attribute
-        // 3. The method's parameter type is assignable from the type specified
-        // by the reference's interface attribute
+        // 1 - Service reference parameter
+        // 2 - Service object parameter
+        // 3 - Service interface assignement compatible methods
+        // 4 - same as 2, but with Map param (DS 1.1 only)
+        // 5 - same as 3, but with Map param (DS 1.1 only)
+
+        // flag indicating a suitable but inaccessible method has been found
+        boolean suitableMethodNotAccessible = false;
 
         // Case 1 - Service reference parameter
-        Method method = getServiceReferenceMethod( targetClass, acceptPrivate, acceptPackage );
-        if ( method != null )
+        Method method;
+        try
+        {
+            method = getServiceReferenceMethod( targetClass, acceptPrivate, acceptPackage );
+            if ( method != null )
+            {
+                return method;
+            }
+        }
+        catch ( SuitableMethodNotAccessibleException ex )
         {
-            return method;
+            suitableMethodNotAccessible = true;
         }
 
         // for further methods we need the class of the service object
@@ -105,15 +115,21 @@
         if ( parameterClass != null )
         {
 
-            // Case2 - Service object parameter
-            method = getServiceObjectMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
-            if ( method != null )
+            // Case 2 - Service object parameter
+            try
             {
-                return method;
+                method = getServiceObjectMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
+                if ( method != null )
+                {
+                    return method;
+                }
+            }
+            catch ( SuitableMethodNotAccessibleException ex )
+            {
+                suitableMethodNotAccessible = true;
             }
 
             // Case 3 - Service interface assignement compatible methods
-            SuitableMethodNotAccessibleException methodAccessibleEx = null;
             try
             {
                 method = getServiceObjectAssignableMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
@@ -124,21 +140,28 @@
             }
             catch ( SuitableMethodNotAccessibleException ex )
             {
-                methodAccessibleEx = ex;
+                suitableMethodNotAccessible = true;
             }
 
             // signatures taking a map are only supported starting with DS 1.1
             if ( m_isDS11 )
             {
 
-                // Case 4: same as case 2, but + Map param (DS 1.1 only)
-                method = getServiceObjectWithMapMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
-                if ( method != null )
+                // Case 4 - same as case 2, but + Map param (DS 1.1 only)
+                try
                 {
-                    return method;
+                    method = getServiceObjectWithMapMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
+                    if ( method != null )
+                    {
+                        return method;
+                    }
+                }
+                catch ( SuitableMethodNotAccessibleException ex )
+                {
+                    suitableMethodNotAccessible = true;
                 }
 
-                // Case 5: same as case 3, but + Map param (DS 1.1 only)
+                // Case 5 - same as case 3, but + Map param (DS 1.1 only)
                 try
                 {
                     method = getServiceObjectAssignableWithMapMethod( targetClass, parameterClass, acceptPrivate,
@@ -150,20 +173,20 @@
                 }
                 catch ( SuitableMethodNotAccessibleException ex )
                 {
-                    methodAccessibleEx = ex;
+                    suitableMethodNotAccessible = true;
                 }
 
             }
 
-            // if at least one suitable method could be found but none of
-            // the suitable methods are accessible, we have to terminate
-            if ( methodAccessibleEx != null )
-            {
-                m_logger.log( LogService.LOG_ERROR,
-                    "DependencyManager : Suitable but non-accessible method found in class " + targetClass.getName() );
-                return null;
-            }
+        }
 
+        // if at least one suitable method could be found but none of
+        // the suitable methods are accessible, we have to terminate
+        if (suitableMethodNotAccessible )
+        {
+            m_logger.log( LogService.LOG_ERROR,
+                "DependencyManager : Suitable but non-accessible method found in class " + targetClass.getName() );
+            return null;
         }
 
         // if we get here, we have no method, so check the super class
@@ -231,11 +254,13 @@
      *      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
      * @throws InvocationTargetException If an unexpected Throwable is caught
      *      trying to find the requested method.
      */
     private Method getServiceReferenceMethod( final Class targetClass, boolean acceptPrivate, boolean acceptPackage )
-        throws InvocationTargetException
+        throws SuitableMethodNotAccessibleException, InvocationTargetException
     {
         try
         {
@@ -264,11 +289,13 @@
      *      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
      * @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 ) throws InvocationTargetException
+        boolean acceptPackage ) throws SuitableMethodNotAccessibleException, InvocationTargetException
     {
         try
         {
@@ -366,11 +393,14 @@
      *      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
      * @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 ) throws InvocationTargetException
+        boolean acceptPrivate, boolean acceptPackage ) throws SuitableMethodNotAccessibleException,
+        InvocationTargetException
     {
         try
         {
@@ -603,10 +633,4 @@
 
     }
 
-    //---------- Logger ------------------------------------
-
-    static class SuitableMethodNotAccessibleException extends Exception
-    {
-    }
-
 }

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java?rev=800267&r1=800266&r2=800267&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java Mon Aug  3 09:07:23 2009
@@ -184,6 +184,27 @@
     }
 
 
+    public void test_suitable_method_selection() throws Exception
+    {
+        // this would be the protected BaseObject.activate_suitable
+        checkMethod( base, "activate_suitable" );
+        checkMethod( level1, "activate_suitable" );
+
+        // this would be the private Level2Object.activate_suitable
+        checkMethod( level2, "activate_suitable" );
+
+        // this must fail to find a method, since Level2Object's activate_suitable
+        // is private and terminates the search for Level3Object
+        try {
+            checkMethod( level3, "activate_suitable" );
+            fail("Level3Object must not find activate_suitable method");
+        } catch (NoSuchMethodException nsme) {
+            // expecting method lookup abort on suitable private
+            // method in Level2Object class
+        }
+    }
+
+
     //---------- internal
 
     /**

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java?rev=800267&r1=800266&r2=800267&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java Mon Aug  3 09:07:23 2009
@@ -47,4 +47,10 @@
     {
         throw new MethodNameException( "activate_comp_bundle" );
     }
+
+
+    protected void activate_suitable( ComponentContext ctx )
+    {
+        throw new MethodNameException( "activate_suitable" );
+    }
 }

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java?rev=800267&r1=800266&r2=800267&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java Mon Aug  3 09:07:23 2009
@@ -31,7 +31,7 @@
 
     private void activate_comp_map( ComponentContext ctx, Map map )
     {
-        throw new MethodNameException("activate_comp_map");
+        throw new MethodNameException( "activate_comp_map" );
     }
 
 
@@ -39,12 +39,18 @@
     // Map has higher precedence
     public void activate_collision()
     {
-        throw new MethodNameException("not_expected_to_be_found");
+        throw new MethodNameException( "not_expected_to_be_found" );
     }
 
 
     public void activate_collision( Map map )
     {
-        throw new MethodNameException("activate_collision");
+        throw new MethodNameException( "activate_collision" );
+    }
+
+
+    private void activate_suitable( Map map )
+    {
+        throw new MethodNameException( "activate_suitable" );
     }
 }