rwaldhoff 2002/11/26 15:25:57 Modified: beanutils project.xml beanutils/src/java/org/apache/commons/beanutils MethodUtils.java beanutils/src/test/org/apache/commons/beanutils TestBean.java Added: beanutils/src/java/org/apache/commons/beanutils ConstructorUtils.java beanutils/src/test/org/apache/commons/beanutils ConstructorUtilsTestCase.java Log: add ConstructorUtils, parallel to MethodUtils Revision Changes Path 1.7 +6 -0 jakarta-commons/beanutils/project.xml Index: project.xml =================================================================== RCS file: /home/cvs/jakarta-commons/beanutils/project.xml,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- project.xml 30 Oct 2002 17:08:59 -0000 1.6 +++ project.xml 26 Nov 2002 23:25:57 -0000 1.7 @@ -40,6 +40,12 @@ <email>[EMAIL PROTECTED]</email> <organization>Apache Software Foundation</organization> </developer> + <developer> + <name>Rodney Waldhoff</name> + <id>rwaldhoff</id> + <email>[EMAIL PROTECTED]</email> + <organization>Apache Software Foundation</organization> + </developer> </developers> <dependencies> 1.17 +1 -1 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.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- MethodUtils.java 19 Nov 2002 21:51:06 -0000 1.16 +++ MethodUtils.java 26 Nov 2002 23:25:57 -0000 1.17 @@ -680,7 +680,7 @@ * * @return true if the assignement is compatible. */ - private static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) { + protected static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) { // try plain assignment if (parameterType.isAssignableFrom(parameterization)) { return true; 1.1 jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/ConstructorUtils.java Index: ConstructorUtils.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 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; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; /** * @version $Revision: 1.1 $ $Date: 2002/11/26 23:25:57 $ * @author Craig R. McClanahan * @author Ralph Schaer * @author Chris Audley * @author Rey François * @author Gregor Raıman * @author Jan Sorensen * @author Robert Burrell Donkin * @author Rodney Waldhoff */ public class ConstructorUtils { // --------------------------------------------------------- Private Members /** An empty class array */ private static final Class[] emptyClassArray = new Class[0]; /** An empty object array */ private static final Object[] emptyObjectArray = new Object[0]; // --------------------------------------------------------- Public Methods public static Object invokeConstructor(Class klass, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Object[] args = { arg }; return invokeConstructor(klass, args); } public static Object invokeConstructor(Class klass, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (null == args) { args = emptyObjectArray; } int arguments = args.length; Class parameterTypes[] = new Class[arguments]; for (int i = 0; i < arguments; i++) { parameterTypes[i] = args[i].getClass(); } return invokeConstructor(klass, args, parameterTypes); } public static Object invokeConstructor( Class klass, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (parameterTypes == null) { parameterTypes = emptyClassArray; } if (args == null) { args = emptyObjectArray; } Constructor ctor = getMatchingAccessibleConstructor(klass, parameterTypes); if (null == ctor) { throw new NoSuchMethodException( "No such accessible constructor on object: " + klass.getName()); } return ctor.newInstance(args); } public static Object invokeExactConstructor(Class klass, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Object[] args = { arg }; return invokeExactConstructor(klass, args); } public static Object invokeExactConstructor(Class klass, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (null == args) { args = emptyObjectArray; } int arguments = args.length; Class parameterTypes[] = new Class[arguments]; for (int i = 0; i < arguments; i++) { parameterTypes[i] = args[i].getClass(); } return invokeExactConstructor(klass, args, parameterTypes); } public static Object invokeExactConstructor( Class klass, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (args == null) { args = emptyObjectArray; } if (parameterTypes == null) { parameterTypes = emptyClassArray; } Constructor ctor = getAccessibleConstructor(klass, parameterTypes); if (null == ctor) { throw new NoSuchMethodException( "No such accessible constructor on object: " + klass.getName()); } return ctor.newInstance(args); } public static Constructor getAccessibleConstructor( Class klass, Class parameterType) { Class[] parameterTypes = { parameterType }; return getAccessibleConstructor(klass, parameterTypes); } public static Constructor getAccessibleConstructor( Class klass, Class[] parameterTypes) { try { return getAccessibleConstructor( klass.getConstructor(parameterTypes)); } catch (NoSuchMethodException e) { return (null); } } public static Constructor getAccessibleConstructor(Constructor ctor) { // Make sure we have a method to check if (ctor == null) { return (null); } // If the requested method is not public we cannot call it if (!Modifier.isPublic(ctor.getModifiers())) { return (null); } // If the declaring class is public, we are done Class clazz = ctor.getDeclaringClass(); if (Modifier.isPublic(clazz.getModifiers())) { return (ctor); } // what else can we do? return null; } // -------------------------------------------------------- Private Methods private static Constructor getMatchingAccessibleConstructor( Class clazz, Class[] parameterTypes) { // see if we can find the method directly // most of the time this works and it's much faster try { Constructor ctor = clazz.getConstructor(parameterTypes); 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. // ctor.setAccessible(true); } catch (SecurityException se) {} return ctor; } catch (NoSuchMethodException e) { /* SWALLOW */ } // search through all methods int paramSize = parameterTypes.length; Constructor[] ctors = clazz.getConstructors(); for (int i = 0, size = ctors.length; i < size; i++) { // compare parameters Class[] ctorParams = ctors[i].getParameterTypes(); int ctorParamSize = ctorParams.length; if (ctorParamSize == paramSize) { boolean match = true; for (int n = 0; n < ctorParamSize; n++) { if (!MethodUtils .isAssignmentCompatible( ctorParams[n], parameterTypes[n])) { match = false; break; } } if (match) { // get accessible version of method Constructor ctor = getAccessibleConstructor(ctors[i]); if (ctor != null) { try { ctor.setAccessible(true); } catch (SecurityException se) {} return ctor; } } } } return null; } } 1.14 +54 -4 jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/TestBean.java Index: TestBean.java =================================================================== RCS file: /home/cvs/jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/TestBean.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- TestBean.java 24 Sep 2002 18:45:54 -0000 1.13 +++ TestBean.java 26 Nov 2002 23:25:57 -0000 1.14 @@ -73,12 +73,62 @@ * General purpose test bean for JUnit tests for the "beanutils" component. * * @author Craig R. McClanahan + * @author Rodney Waldhoff * @version $Revision$ $Date$ */ public class TestBean { + // ----------------------------------------------------------- Constructors + public TestBean() { + } + + public TestBean(String stringProperty) { + setStringProperty(stringProperty); + } + + public TestBean(float floatProperty) { + setFloatProperty(floatProperty); + } + + public TestBean(boolean booleanProperty) { + setBooleanProperty(booleanProperty); + } + + public TestBean(Boolean booleanSecond) { + setBooleanSecond(booleanSecond.booleanValue()); + } + + public TestBean(float floatProperty, String stringProperty) { + setFloatProperty(floatProperty); + setStringProperty(stringProperty); + } + + public TestBean(boolean booleanProperty, String stringProperty) { + setBooleanProperty(booleanProperty); + setStringProperty(stringProperty); + } + + public TestBean(Boolean booleanSecond, String stringProperty) { + setBooleanSecond(booleanSecond.booleanValue()); + setStringProperty(stringProperty); + } + + public TestBean(Integer intProperty) { + setIntProperty(intProperty.intValue()); + } + + TestBean(int intProperty) { + setIntProperty(intProperty); + } + + protected TestBean(boolean booleanProperty, boolean booleanSecond, String stringProperty) { + setBooleanProperty(booleanProperty); + setBooleanSecond(booleanSecond); + setStringProperty(stringProperty); + } + // ------------------------------------------------------------- Properties 1.1 jakarta-commons/beanutils/src/test/org/apache/commons/beanutils/ConstructorUtilsTestCase.java Index: ConstructorUtilsTestCase.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 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; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * <p> Test case for <code>ConstructorUtils</code> </p> * */ public class ConstructorUtilsTestCase extends TestCase { // ---------------------------------------------------------- Constructors /** * Construct a new instance of this test case. * * @param name Name of the test case */ public ConstructorUtilsTestCase(String name) { super(name); } // -------------------------------------------------- Overall Test Methods /** * Set up instance variables required by this test case. */ public void setUp() throws Exception { super.setUp(); } /** * Return the tests included in this test suite. */ public static Test suite() { return (new TestSuite(ConstructorUtilsTestCase.class)); } /** * Tear down instance variables required by this test case. */ public void tearDown() throws Exception { super.tearDown(); } // ------------------------------------------------ Individual Test Methods public void testInvokeConstructor() throws Exception { { Object obj = ConstructorUtils.invokeConstructor(TestBean.class,"TEST"); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals("TEST",((TestBean)obj).getStringProperty()); } { Object obj = ConstructorUtils.invokeConstructor(TestBean.class,new Float(17.3f)); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(17.3f,((TestBean)obj).getFloatProperty(),0.0f); } } public void testInvokeConstructorWithArgArray() throws Exception { Object[] args = { new Float(17.3f), "TEST" }; Object obj = ConstructorUtils.invokeConstructor(TestBean.class,args); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(17.3f,((TestBean)obj).getFloatProperty(),0.0f); assertEquals("TEST",((TestBean)obj).getStringProperty()); } public void testInvokeConstructorWithTypeArray() throws Exception { { Object[] args = { Boolean.TRUE, "TEST" }; Class[] types = { Boolean.TYPE, String.class }; Object obj = ConstructorUtils.invokeConstructor(TestBean.class,args,types); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(true,((TestBean)obj).getBooleanProperty()); assertEquals("TEST",((TestBean)obj).getStringProperty()); } { Object[] args = { Boolean.TRUE, "TEST" }; Class[] types = { Boolean.class, String.class }; Object obj = ConstructorUtils.invokeConstructor(TestBean.class,args,types); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(true,((TestBean)obj).isBooleanSecond()); assertEquals("TEST",((TestBean)obj).getStringProperty()); } } public void testInvokeExactConstructor() throws Exception { { Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,"TEST"); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals("TEST",((TestBean)obj).getStringProperty()); } { try { Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,new Float(17.3f)); fail("Expected NoSuchMethodException"); } catch(NoSuchMethodException e) { // expected } } { Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,Boolean.TRUE); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(true,((TestBean)obj).isBooleanSecond()); } } public void testInvokeExactConstructorWithArgArray() throws Exception { { Object[] args = { new Float(17.3f), "TEST" }; try { Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args); fail("Expected NoSuchMethodException"); } catch(NoSuchMethodException e) { // expected } } { Object[] args = { Boolean.TRUE, "TEST" }; Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(true,((TestBean)obj).isBooleanSecond()); assertEquals("TEST",((TestBean)obj).getStringProperty()); } } public void testInvokeExactConstructorWithTypeArray() throws Exception { { Object[] args = { Boolean.TRUE, "TEST" }; Class[] types = { Boolean.TYPE, String.class }; Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(true,((TestBean)obj).getBooleanProperty()); assertEquals("TEST",((TestBean)obj).getStringProperty()); } { Object[] args = { Boolean.TRUE, "TEST" }; Class[] types = { Boolean.class, String.class }; Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(true,((TestBean)obj).isBooleanSecond()); assertEquals("TEST",((TestBean)obj).getStringProperty()); } { Object[] args = { new Float(17.3f), "TEST" }; Class[] types = { Float.TYPE, String.class }; Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types); assertNotNull(obj); assertTrue(obj instanceof TestBean); assertEquals(17.3f,((TestBean)obj).getFloatProperty(),0.0f); assertEquals("TEST",((TestBean)obj).getStringProperty()); } { Object[] args = { new Float(17.3f), "TEST" }; Class[] types = { Float.class, String.class }; try { Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types); fail("Expected NoSuchMethodException"); } catch(NoSuchMethodException e) { // expected } } } public void testGetAccessibleConstructor() throws Exception { { Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,String.class); assertNotNull(ctor); assertTrue(Modifier.isPublic(ctor.getModifiers())); } { Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,Integer.class); assertNotNull(ctor); assertTrue(Modifier.isPublic(ctor.getModifiers())); } { Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,Integer.TYPE); assertNull(ctor); } } public void testGetAccessibleConstructorWithTypeArray() throws Exception { { Class[] types = { Boolean.TYPE, String.class }; Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,types); assertNotNull(ctor); assertTrue(Modifier.isPublic(ctor.getModifiers())); } { Class[] types = { Boolean.TYPE, Boolean.TYPE, String.class }; Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,types); assertNull(ctor); } } public void testGetAccessibleConstructorWithConstructorArg() throws Exception { { Class[] types = { Integer.class }; Constructor c1 = TestBean.class.getConstructor(types); Constructor ctor = ConstructorUtils.getAccessibleConstructor(c1); assertNotNull(ctor); assertTrue(Modifier.isPublic(ctor.getModifiers())); } { Class[] types = { Integer.class }; Constructor c1 = TestBean.class.getDeclaredConstructor(types); Constructor ctor = ConstructorUtils.getAccessibleConstructor(c1); assertNotNull(ctor); assertTrue(Modifier.isPublic(ctor.getModifiers())); } { Class[] types = { Integer.TYPE }; Constructor c1 = TestBean.class.getDeclaredConstructor(types); Constructor ctor = ConstructorUtils.getAccessibleConstructor(c1); assertNull(ctor); } } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>