rdonkin     2002/09/22 14:45:35

  Modified:    beanutils/src/java/org/apache/commons/beanutils
                        MethodUtils.java
               beanutils/src/test/org/apache/commons/beanutils
                        MethodUtilsTestCase.java
  Added:       beanutils/src/test/org/apache/commons/beanutils/priv
                        PackageBean.java PublicSubBean.java
  Log:
  Added workaround for jvm issue with accessing public methods coded in default access 
superclasses via reflaction from a public access subclass instance. This workaround 
will will most likely fail if the code is run with right security permissions. 
Workaround suggested by Ben Walding.
  
  Revision  Changes    Path
  1.14      +55 -0     
jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/MethodUtils.java
  
  Index: MethodUtils.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/MethodUtils.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- MethodUtils.java  4 Sep 2002 19:23:45 -0000       1.13
  +++ MethodUtils.java  22 Sep 2002 21:45:35 -0000      1.14
  @@ -72,6 +72,18 @@
   /**
    * <p> Utility reflection methods focussed on methods in general rather than 
properties in particular. </p>
    *
  + * <h3>Known Limitations</h3>
  + * <h4>Accessing Public Methods In A Default Access Superclass</h4>
  + * <p>There is an issue when invoking public methods contained in a default access 
superclass.
  + * Reflection locates these methods fine and correctly assigns them as public.
  + * However, an <code>IllegalAccessException</code> is thrown if the method is 
invoked.</p>
  + *
  + * <p><code>MethodUtils</code> contains a workaround for this situation. 
  + * It will attempt to call <code>setAccessible</code> on this method.
  + * If this call succeeds, then the method can be invoked as normal.
  + * This call will only succeed when the application has sufficient security 
privilages. 
  + * If this call fails then a warning will be logged and the method may fail.</p>
  + *
    * @author Craig R. McClanahan
    * @author Ralph Schaer
    * @author Chris Audley
  @@ -541,6 +553,36 @@
           // most of the time this works and it's much faster
           try {
               Method method = clazz.getMethod(methodName, parameterTypes);
  +            if (log.isTraceEnabled()) {
  +                log.trace("Found straight match: " + method);
  +                log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
  +            }
  +            
  +            try {
  +                //
  +                // XXX Default access superclass workaround
  +                //
  +                // When a public class has a default access superclass
  +                // with public methods, these methods are accessible.
  +                // Calling them from compiled code works fine.
  +                //
  +                // Unfortunately, using reflection to invoke these methods
  +                // seems to (wrongly) to prevent access even when the method
  +                // modifer is public.
  +                //
  +                // The following workaround solves the problem but will only
  +                // work from sufficiently privilages code. 
  +                //
  +                // Better workarounds would be greatfully accepted.
  +                //
  +                method.setAccessible(true);
  +                
  +            } catch (SecurityException se) {
  +                // log but continue just in case the method.invoke works anyway
  +                log.warn(
  +                "Cannot setAccessible on method. Therefore cannot use jvm access 
bug workaround.", 
  +                se);
  +            }
               return method;
               
           } catch (NoSuchMethodException e) { /* SWALLOW */ }
  @@ -583,6 +625,19 @@
                               if (log.isTraceEnabled()) {
                                   log.trace(method + " accessible version of " 
                                               + methods[i]);
  +                            }
  +                            try {
  +                                //
  +                                // XXX Default access superclass workaround
  +                                // (See above for more details.)
  +                                //
  +                                method.setAccessible(true);
  +                                
  +                            } catch (SecurityException se) {
  +                                // log but continue just in case the method.invoke 
works anyway
  +                                log.warn(
  +                                "Cannot setAccessible on method. Therefore cannot 
use jvm access bug workaround.", 
  +                                se);
                               }
                               return method;
                           }
  
  
  
  1.10      +18 -1     
jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/MethodUtilsTestCase.java
  
  Index: MethodUtilsTestCase.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/MethodUtilsTestCase.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- MethodUtilsTestCase.java  4 Sep 2002 19:23:45 -0000       1.9
  +++ MethodUtilsTestCase.java  22 Sep 2002 21:45:35 -0000      1.10
  @@ -63,6 +63,7 @@
   import java.lang.reflect.Modifier;
   
   import org.apache.commons.beanutils.priv.PrivateBeanFactory;
  +import org.apache.commons.beanutils.priv.PublicSubBean;
   
   import junit.framework.TestCase;
   import junit.framework.Test;
  @@ -565,5 +566,21 @@
   
       }
   
  -
  +    public void testPublicSub() throws Exception {
  +        // make sure that bean does what it should
  +        PublicSubBean bean = new PublicSubBean();
  +        assertEquals("Start value (foo)", bean.getFoo(), "This is foo");
  +        assertEquals("Start value (bar)", bean.getBar(), "This is bar");
  +        bean.setFoo("new foo");
  +        bean.setBar("new bar");
  +        assertEquals("Set value (foo)", bean.getFoo(), "new foo");
  +        assertEquals("Set value (bar)", bean.getBar(), "new bar");
  +        
  +        // see if we can access public methods in a default access superclass
  +        // from a public access subclass instance
  +        MethodUtils.invokeMethod(bean, "setFoo", "alpha");
  +        assertEquals("Set value (foo:2)", bean.getFoo(), "alpha");
  +        MethodUtils.invokeMethod(bean, "setBar", "beta");
  +        assertEquals("Set value (bar:2)", bean.getFoo(), "alpha");
  +    }
   }
  
  
  
  1.1                  
jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/priv/PackageBean.java
  
  Index: PackageBean.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/priv/PackageBean.java,v
 1.1 2002/09/22 21:45:35 rdonkin Exp $
   * $Revision: 1.1 $
   * $Date: 2002/09/22 21:45:35 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  
  package org.apache.commons.beanutils.priv;
  
  
  /**
   * <p>This class is designed to test the default access jvm problem workaround.
   * The issue is that public methods of a public subclass contained in a default 
access
   * superclass are returned by reflection but an IllegalAccessException is thrown 
   * when they are invoked.</p>
   *
   * <p>This is the default access superclass</p>
   * 
   * @author Robert Burrell Donkin
   * @version $Revision: 1.1 $ $Date: 2002/09/22 21:45:35 $
   */
  
  class PackageBean {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Package private constructor - can only use factory method to create
       * beans.
       */
      PackageBean() {
  
          super();
  
      }
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       */
      private String bar = "This is bar";
  
      public String getBar() {
  
          return (this.bar);
  
      }
      
      public void setBar(String bar) {
  
          this.bar = bar;
  
      }
  
  }
  
  
  
  1.1                  
jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/priv/PublicSubBean.java
  
  Index: PublicSubBean.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/priv/PublicSubBean.java,v
 1.1 2002/09/22 21:45:35 rdonkin Exp $
   * $Revision: 1.1 $
   * $Date: 2002/09/22 21:45:35 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  
  package org.apache.commons.beanutils.priv;
  
  
  /**
   * <p>This class is designed to test the default access jvm problem workaround.
   * The issue is that public methods of a public subclass contained in a default 
access
   * superclass are returned by reflection but an IllegalAccessException is thrown 
   * when they are invoked.</p>
   *
   * <p>This is the default access superclass</p>
   *
   * @author Robert Burrell Donkin
   * @version $Revision: 1.1 $ $Date: 2002/09/22 21:45:35 $
   */
  
  public class PublicSubBean extends PackageBean {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Package private constructor - can only use factory method to create
       * beans.
       */
      public PublicSubBean() {
  
          super();
  
      }
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * A directly implemented property.
       */
      private String foo = "This is foo";
  
      public String getFoo() {
  
          return (this.foo);
  
      }
      
      public void setFoo(String foo) {
  
          this.foo = foo;
  
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to