hi Rodney

sorry to be a PITA but...

we're trying to move the basic reflection code (as opposed to introspection) into lang. there is already a ContructionUtils in there as well as a MethodUtils (which will hopefully in the end replace the one in beanutils).

would it be possible to move this code into lang and work together on an improved version there?

- robert

On Tuesday, November 26, 2002, at 11:25 PM, [EMAIL PROTECTED] wrote:

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].
org>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED].
org>


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

Reply via email to