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]>