You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2013/02/02 19:07:23 UTC
svn commit: r1441781 - in /commons/sandbox/beanutils2/trunk/src: changes/
main/java/org/apache/commons/beanutils2/
test/java/org/apache/commons/beanutils2/
test/java/org/apache/commons/beanutils2/testbeans/
Author: britter
Date: Sat Feb 2 18:07:23 2013
New Revision: 1441781
URL: http://svn.apache.org/viewvc?rev=1441781&view=rev
Log:
[SANDBOX-436] - Implement BeanAccessor.getMapped
Added:
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultMappedPropertyGetterAccessor.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MethodUtil.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetMappedPropertyTestCase.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MethodUtilTest.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildBean.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildInterface.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestBean.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestInterface.java (with props)
Modified:
commons/sandbox/beanutils2/trunk/src/changes/changes.xml
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/PropertyDescriptorsRegistry.java
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/ThrowingExceptionBean.java
Modified: commons/sandbox/beanutils2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/changes/changes.xml?rev=1441781&r1=1441780&r2=1441781&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/changes/changes.xml (original)
+++ commons/sandbox/beanutils2/trunk/src/changes/changes.xml Sat Feb 2 18:07:23 2013
@@ -23,6 +23,9 @@
</properties>
<body>
<release version="0.1" date="201?-??-??" description="First release.">
+ <action dev="britter" type="add" issue="SANDBOX-436" due-to="Benedikt Ritter">
+ Implement BeanAccessor.getMapped
+ </action>
<action dev="britter" type="update" issue="SANDBOX-433" due-to="Benedikt Ritter">
Setting properties or calling methods very often results in a NullPointerException
</action>
Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java?rev=1441781&r1=1441780&r2=1441781&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java Sat Feb 2 18:07:23 2013
@@ -121,6 +121,12 @@ public interface BeanProperties<B>
Method getIndexedWriteMethod( String propertyName )
throws IntrospectionException;
+ MappedPropertyDescriptor getMappedPropertyDescriptor( String propertyName )
+ throws IntrospectionException;
+
+ Method getMappedReadMethod( String propertyName )
+ throws IntrospectionException;
+
/**
*
* @return
@@ -128,5 +134,4 @@ public interface BeanProperties<B>
*/
Map<String, PropertyDescriptor> getPropertiesIndex()
throws IntrospectionException;
-
}
Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java?rev=1441781&r1=1441780&r2=1441781&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java Sat Feb 2 18:07:23 2013
@@ -103,8 +103,17 @@ final class DefaultBeanAccessor<B>
*/
public MappedPropertyGetterAccessor getMapped( String propertyName )
{
- // TODO
- return null;
+ checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
+ Method mappedReadMethod;
+ try
+ {
+ mappedReadMethod = properties.getMappedReadMethod( propertyName );
+ }
+ catch ( IntrospectionException e )
+ {
+ throw new NoSuchPropertyException( propertyName, getBeanClass(), e );
+ }
+ return new DefaultMappedPropertyGetterAccessor<B>( bean, propertyName, mappedReadMethod );
}
/**
Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java?rev=1441781&r1=1441780&r2=1441781&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java Sat Feb 2 18:07:23 2013
@@ -189,6 +189,29 @@ final class DefaultBeanProperties<B>
/**
* {@inheritDoc}
*/
+ public MappedPropertyDescriptor getMappedPropertyDescriptor( String propertyName )
+ throws IntrospectionException
+ {
+ PropertyDescriptor propertyDescriptor = getPropertyDescriptor( propertyName );
+ checkArgument( propertyDescriptor instanceof MappedPropertyDescriptor,
+ "Property '%s' in bean of type %s is not a mapped property", propertyName, beanClass.getName() );
+ return (MappedPropertyDescriptor) propertyDescriptor;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Method getMappedReadMethod( String propertyName )
+ throws IntrospectionException
+ {
+ MappedPropertyDescriptor mappedPropertyDescriptor = getMappedPropertyDescriptor( propertyName );
+
+ return checkGetterMethod( mappedPropertyDescriptor.getMappedReadMethod(), propertyName );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public Map<String, PropertyDescriptor> getPropertiesIndex()
throws IntrospectionException
{
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultMappedPropertyGetterAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultMappedPropertyGetterAccessor.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultMappedPropertyGetterAccessor.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultMappedPropertyGetterAccessor.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,86 @@
+package org.apache.commons.beanutils2;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.Assertions.checkNotNull;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+class DefaultMappedPropertyGetterAccessor<B>
+ implements MappedPropertyGetterAccessor
+{
+
+ private final B bean;
+ private final String propertyName;
+ private final Method mappedReadMethod;
+
+ /**
+ * Constructs a new instance of DefaultMappedPropertyGetterAccessor.
+ *
+ * @param bean
+ * @param propertyName
+ * @param mappedReadMethod
+ */
+ public DefaultMappedPropertyGetterAccessor( B bean, String propertyName, Method mappedReadMethod )
+ {
+ this.bean = bean;
+ this.propertyName = propertyName;
+ this.mappedReadMethod = mappedReadMethod;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public BeanAccessor<?> of( String key )
+ {
+ checkNotNull( key, "Can not get mapped property '%s' in bean of type '%s' for null!", propertyName,
+ bean.getClass().getName() );
+ Object mappedValue = invokeGetter( key );
+ return wrapInAccessor( mappedValue );
+ }
+
+ private BeanAccessor<?> wrapInAccessor( Object mappedValue )
+ {
+ if ( mappedValue != null )
+ {
+ return new DefaultBeanAccessor<Object>( mappedValue );
+ }
+ else
+ {
+ return new NullBeanAccessor<Object>( bean.getClass().getName(), mappedReadMethod.getName() );
+ }
+ }
+
+ private Object invokeGetter( String key )
+ {
+ try
+ {
+ return mappedReadMethod.invoke( bean, key );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new PropertyGetterNotAccessibleException( propertyName, mappedReadMethod.getName(), bean.getClass(), e );
+ }
+ catch ( InvocationTargetException e )
+ {
+ throw new PropertyGetterInvocationException( propertyName, mappedReadMethod.getName(), bean.getClass(), e );
+ }
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultMappedPropertyGetterAccessor.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,578 @@
+/*
+ * 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.commons.beanutils2;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * EXTRACTED FROM BeanUtils1
+ *
+ * A MappedPropertyDescriptor describes one mapped property. Mapped properties are multivalued properties like indexed
+ * properties but that are accessed with a String key instead of an index. Such property values are typically stored in
+ * a Map collection. For this class to work properly, a mapped value must have getter and setter methods of the form
+ * <p>
+ * <code>get<strong>Property</strong>(String key)<code> and
+ * <p><code>set<strong>Property</strong>(String key, Object value)<code>,
+ * <p>where <code><strong>Property</strong></code> must be replaced by the name of the property.
+ *
+ * @see java.beans.PropertyDescriptor
+ * @author Rey Francois
+ * @author Gregor Rayman
+ * @version $Revision: 806915 $ $Date: 2009-08-23 02:50:23 +0200 (Sun, 23 Aug 2009) $
+ */
+
+public class MappedPropertyDescriptor
+ extends PropertyDescriptor
+{
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The underlying data type of the property we are describing.
+ */
+ private Reference<Class<?>> mappedPropertyTypeRef;
+
+ /**
+ * The reader method for this property (if any).
+ */
+ private MappedMethodReference mappedReadMethodRef;
+
+ /**
+ * The writer method for this property (if any).
+ */
+ private MappedMethodReference mappedWriteMethodRef;
+
+ /**
+ * The parameter types array for the reader method signature.
+ */
+ @SuppressWarnings( "unchecked" )
+ // we can not create a generic array
+ private static final Class<String>[] STRING_CLASS_PARAMETER = new Class[] { String.class };
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Constructs a MappedPropertyDescriptor for a property that follows the standard Java convention by having getFoo
+ * and setFoo accessor methods, with the addition of a String parameter (the key). Thus if the argument name is
+ * "fred", it will assume that the writer method is "setFred" and the reader method is "getFred". Note that the
+ * property name should start with a lower case character, which will be capitalized in the method names.
+ *
+ * @param propertyName The programmatic name of the property.
+ * @param beanClass The Class object for the target bean. For example sun.beans.OurButton.class.
+ * @exception IntrospectionException if an exception occurs during introspection.
+ */
+ public MappedPropertyDescriptor( String propertyName, Class<?> beanClass )
+ throws IntrospectionException
+ {
+
+ super( propertyName, null, null );
+
+ if ( propertyName == null || propertyName.length() == 0 )
+ {
+ throw new IntrospectionException( "bad property name: " + propertyName + " on class: "
+ + beanClass.getClass().getName() );
+ }
+
+ setName( propertyName );
+ String base = capitalizePropertyName( propertyName );
+
+ // Look for mapped read method and matching write method
+ Method mappedReadMethod = null;
+ Method mappedWriteMethod = null;
+ try
+ {
+ try
+ {
+ mappedReadMethod = getMethod( beanClass, "get" + base, STRING_CLASS_PARAMETER );
+ }
+ catch ( IntrospectionException e )
+ {
+ mappedReadMethod = getMethod( beanClass, "is" + base, STRING_CLASS_PARAMETER );
+ }
+ Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };
+ mappedWriteMethod = getMethod( beanClass, "set" + base, params );
+ }
+ catch ( IntrospectionException e )
+ {
+ /*
+ * Swallow IntrospectionException TODO: Why?
+ */
+ }
+
+ // If there's no read method, then look for just a write method
+ if ( mappedReadMethod == null )
+ {
+ mappedWriteMethod = getMethod( beanClass, "set" + base, 2 );
+ }
+
+ if ( ( mappedReadMethod == null ) && ( mappedWriteMethod == null ) )
+ {
+ throw new IntrospectionException( "Property '" + propertyName + "' not found on " + beanClass.getName() );
+ }
+ mappedReadMethodRef = new MappedMethodReference( mappedReadMethod );
+ mappedWriteMethodRef = new MappedMethodReference( mappedWriteMethod );
+
+ findMappedPropertyType();
+ }
+
+ /**
+ * This constructor takes the name of a mapped property, and method names for reading and writing the property.
+ *
+ * @param propertyName The programmatic name of the property.
+ * @param beanClass The Class object for the target bean. For example sun.beans.OurButton.class.
+ * @param mappedGetterName The name of the method used for reading one of the property values. May be null if the
+ * property is write-only.
+ * @param mappedSetterName The name of the method used for writing one of the property values. May be null if the
+ * property is read-only.
+ * @exception IntrospectionException if an exception occurs during introspection.
+ */
+ public MappedPropertyDescriptor( String propertyName, Class<?> beanClass, String mappedGetterName,
+ String mappedSetterName )
+ throws IntrospectionException
+ {
+
+ super( propertyName, null, null );
+
+ if ( propertyName == null || propertyName.length() == 0 )
+ {
+ throw new IntrospectionException( "bad property name: " + propertyName );
+ }
+ setName( propertyName );
+
+ // search the mapped get and set methods
+ Method mappedReadMethod = null;
+ Method mappedWriteMethod = null;
+ mappedReadMethod = getMethod( beanClass, mappedGetterName, STRING_CLASS_PARAMETER );
+
+ if ( mappedReadMethod != null )
+ {
+ Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };
+ mappedWriteMethod = getMethod( beanClass, mappedSetterName, params );
+ }
+ else
+ {
+ mappedWriteMethod = getMethod( beanClass, mappedSetterName, 2 );
+ }
+ mappedReadMethodRef = new MappedMethodReference( mappedReadMethod );
+ mappedWriteMethodRef = new MappedMethodReference( mappedWriteMethod );
+
+ findMappedPropertyType();
+ }
+
+ /**
+ * This constructor takes the name of a mapped property, and Method objects for reading and writing the property.
+ *
+ * @param propertyName The programmatic name of the property.
+ * @param mappedGetter The method used for reading one of the property values. May be be null if the property is
+ * write-only.
+ * @param mappedSetter The method used for writing one the property values. May be null if the property is
+ * read-only.
+ * @exception IntrospectionException if an exception occurs during introspection.
+ */
+ public MappedPropertyDescriptor( String propertyName, Method mappedGetter, Method mappedSetter )
+ throws IntrospectionException
+ {
+
+ super( propertyName, mappedGetter, mappedSetter );
+
+ if ( propertyName == null || propertyName.length() == 0 )
+ {
+ throw new IntrospectionException( "bad property name: " + propertyName );
+ }
+
+ setName( propertyName );
+ mappedReadMethodRef = new MappedMethodReference( mappedGetter );
+ mappedWriteMethodRef = new MappedMethodReference( mappedSetter );
+ findMappedPropertyType();
+ }
+
+ // -------------------------------------------------------- Public Methods
+
+ /**
+ * Gets the Class object for the property values.
+ *
+ * @return The Java type info for the property values. Note that the "Class" object may describe a built-in Java
+ * type such as "int". The result may be "null" if this is a mapped property that does not support non-keyed
+ * access.
+ * <p>
+ * This is the type that will be returned by the mappedReadMethod.
+ */
+ public Class<?> getMappedPropertyType()
+ {
+ return mappedPropertyTypeRef.get();
+ }
+
+ /**
+ * Gets the method that should be used to read one of the property value.
+ *
+ * @return The method that should be used to read the property value. May return null if the property can't be read.
+ */
+ public Method getMappedReadMethod()
+ {
+ return mappedReadMethodRef.get();
+ }
+
+ /**
+ * Sets the method that should be used to read one of the property value.
+ *
+ * @param mappedGetter The mapped getter method.
+ * @throws IntrospectionException If an error occurs finding the mapped property
+ */
+ public void setMappedReadMethod( Method mappedGetter )
+ throws IntrospectionException
+ {
+ mappedReadMethodRef = new MappedMethodReference( mappedGetter );
+ findMappedPropertyType();
+ }
+
+ /**
+ * Gets the method that should be used to write one of the property value.
+ *
+ * @return The method that should be used to write one of the property value. May return null if the property can't
+ * be written.
+ */
+ public Method getMappedWriteMethod()
+ {
+ return mappedWriteMethodRef.get();
+ }
+
+ /**
+ * Sets the method that should be used to write the property value.
+ *
+ * @param mappedSetter The mapped setter method.
+ * @throws IntrospectionException If an error occurs finding the mapped property
+ */
+ public void setMappedWriteMethod( Method mappedSetter )
+ throws IntrospectionException
+ {
+ mappedWriteMethodRef = new MappedMethodReference( mappedSetter );
+ findMappedPropertyType();
+ }
+
+ // ------------------------------------------------------- Private Methods
+
+ /**
+ * Introspect our bean class to identify the corresponding getter and setter methods.
+ */
+ private void findMappedPropertyType()
+ throws IntrospectionException
+ {
+ try
+ {
+ Method mappedReadMethod = getMappedReadMethod();
+ Method mappedWriteMethod = getMappedWriteMethod();
+ Class<?> mappedPropertyType = null;
+ if ( mappedReadMethod != null )
+ {
+ if ( mappedReadMethod.getParameterTypes().length != 1 )
+ {
+ throw new IntrospectionException( "bad mapped read method arg count" );
+ }
+ mappedPropertyType = mappedReadMethod.getReturnType();
+ if ( mappedPropertyType == Void.TYPE )
+ {
+ throw new IntrospectionException( "mapped read method " + mappedReadMethod.getName()
+ + " returns void" );
+ }
+ }
+
+ if ( mappedWriteMethod != null )
+ {
+ Class<?>[] params = mappedWriteMethod.getParameterTypes();
+ if ( params.length != 2 )
+ {
+ throw new IntrospectionException( "bad mapped write method arg count" );
+ }
+ if ( mappedPropertyType != null && mappedPropertyType != params[1] )
+ {
+ throw new IntrospectionException( "type mismatch between mapped read and write methods" );
+ }
+ mappedPropertyType = params[1];
+ }
+ mappedPropertyTypeRef = new SoftReference<Class<?>>( mappedPropertyType );
+ }
+ catch ( IntrospectionException ex )
+ {
+ throw ex;
+ }
+ }
+
+ /**
+ * Return a capitalized version of the specified property name.
+ *
+ * @param s The property name
+ */
+ private static String capitalizePropertyName( String s )
+ {
+ if ( s.length() == 0 )
+ {
+ return s;
+ }
+
+ char[] chars = s.toCharArray();
+ chars[0] = Character.toUpperCase( chars[0] );
+ return new String( chars );
+ }
+
+ /**
+ * Find a method on a class with a specified number of parameters.
+ */
+ private static Method internalGetMethod( Class<?> initial, String methodName, int parameterCount )
+ {
+ // For overridden methods we need to find the most derived version.
+ // So we start with the given class and walk up the superclass chain.
+ for ( Class<?> clazz = initial; clazz != null; clazz = clazz.getSuperclass() )
+ {
+ Method[] methods = clazz.getDeclaredMethods();
+ for ( int i = 0; i < methods.length; i++ )
+ {
+ Method method = methods[i];
+ if ( method == null )
+ {
+ continue;
+ }
+ // skip static methods.
+ int mods = method.getModifiers();
+ if ( !Modifier.isPublic( mods ) || Modifier.isStatic( mods ) )
+ {
+ continue;
+ }
+ if ( method.getName().equals( methodName ) && method.getParameterTypes().length == parameterCount )
+ {
+ return method;
+ }
+ }
+ }
+
+ // Now check any inherited interfaces. This is necessary both when
+ // the argument class is itself an interface, and when the argument
+ // class is an abstract class.
+ Class<?>[] interfaces = initial.getInterfaces();
+ for ( int i = 0; i < interfaces.length; i++ )
+ {
+ Method method = internalGetMethod( interfaces[i], methodName, parameterCount );
+ if ( method != null )
+ {
+ return method;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Find a method on a class with a specified number of parameters.
+ */
+ private static Method getMethod( Class<?> clazz, String methodName, int parameterCount )
+ throws IntrospectionException
+ {
+ if ( methodName == null )
+ {
+ return null;
+ }
+
+ Method method = internalGetMethod( clazz, methodName, parameterCount );
+ if ( method != null )
+ {
+ return method;
+ }
+
+ // No Method found
+ throw new IntrospectionException( "No method \"" + methodName + "\" with " + parameterCount + " parameter(s)" );
+ }
+
+ /**
+ * Find a method on a class with a specified parameter list.
+ */
+ private static Method getMethod( Class<?> clazz, String methodName, Class<?>[] parameterTypes )
+ throws IntrospectionException
+ {
+ if ( methodName == null )
+ {
+ return null;
+ }
+
+ Method method = AccessibleObjectsRegistry.getMethodsRegistry().get( true, clazz, methodName, parameterTypes );
+ if ( method != null )
+ {
+ return method;
+ }
+
+ int parameterCount = ( parameterTypes == null ) ? 0 : parameterTypes.length;
+
+ // No Method found
+ throw new IntrospectionException( "No method \"" + methodName + "\" with " + parameterCount
+ + " parameter(s) of matching types." );
+ }
+
+ /**
+ * Holds a {@link Method} in a {@link SoftReference} so that it it doesn't prevent any ClassLoader being garbage
+ * collected, but tries to re-create the method if the method reference has been released. See
+ * http://issues.apache.org/jira/browse/BEANUTILS-291
+ */
+ private static class MappedMethodReference
+ {
+ private String className;
+
+ private String methodName;
+
+ private Reference<Method> methodRef;
+
+ private Reference<Class<?>> classRef;
+
+ private Reference<Class<?>> writeParamTypeRef0;
+
+ private Reference<Class<?>> writeParamTypeRef1;
+
+ private String[] writeParamClassNames;
+
+ MappedMethodReference( Method m )
+ {
+ if ( m != null )
+ {
+ className = m.getDeclaringClass().getName();
+ methodName = m.getName();
+ methodRef = new SoftReference<Method>( m );
+ classRef = new WeakReference<Class<?>>( m.getDeclaringClass() );
+ Class<?>[] types = m.getParameterTypes();
+ if ( types.length == 2 )
+ {
+ writeParamTypeRef0 = new WeakReference<Class<?>>( types[0] );
+ writeParamTypeRef1 = new WeakReference<Class<?>>( types[1] );
+ writeParamClassNames = new String[2];
+ writeParamClassNames[0] = types[0].getName();
+ writeParamClassNames[1] = types[1].getName();
+ }
+ }
+ }
+
+ private Method get()
+ {
+ if ( methodRef == null )
+ {
+ return null;
+ }
+ Method m = methodRef.get();
+ if ( m == null )
+ {
+ Class<?> clazz = classRef.get();
+ if ( clazz == null )
+ {
+ clazz = reLoadClass();
+ if ( clazz != null )
+ {
+ classRef = new WeakReference<Class<?>>( clazz );
+ }
+ }
+ if ( clazz == null )
+ {
+ throw new RuntimeException( "Method " + methodName + " for " + className
+ + " could not be reconstructed - class reference has gone" );
+ }
+ Class<?>[] paramTypes = null;
+ if ( writeParamClassNames != null )
+ {
+ paramTypes = new Class[2];
+ paramTypes[0] = writeParamTypeRef0.get();
+ if ( paramTypes[0] == null )
+ {
+ paramTypes[0] = reLoadClass( writeParamClassNames[0] );
+ if ( paramTypes[0] != null )
+ {
+ writeParamTypeRef0 = new WeakReference<Class<?>>( paramTypes[0] );
+ }
+ }
+ paramTypes[1] = writeParamTypeRef1.get();
+ if ( paramTypes[1] == null )
+ {
+ paramTypes[1] = reLoadClass( writeParamClassNames[1] );
+ if ( paramTypes[1] != null )
+ {
+ writeParamTypeRef1 = new WeakReference<Class<?>>( paramTypes[1] );
+ }
+ }
+ }
+ else
+ {
+ paramTypes = STRING_CLASS_PARAMETER;
+ }
+ try
+ {
+ m = clazz.getMethod( methodName, paramTypes );
+ // Un-comment following line for testing
+ // System.out.println("Recreated Method " + methodName + " for " + className);
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new RuntimeException( "Method " + methodName + " for " + className
+ + " could not be reconstructed - method not found" );
+ }
+ methodRef = new SoftReference<Method>( m );
+ }
+ return m;
+ }
+
+ /**
+ * Try to re-load the class
+ */
+ private Class<?> reLoadClass()
+ {
+ return reLoadClass( className );
+ }
+
+ /**
+ * Try to re-load the class
+ */
+ private Class<?> reLoadClass( String name )
+ {
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ // Try the context class loader
+ if ( classLoader != null )
+ {
+ try
+ {
+ return classLoader.loadClass( name );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ // ignore
+ }
+ }
+
+ // Try this class's class loader
+ classLoader = MappedPropertyDescriptor.class.getClassLoader();
+ try
+ {
+ return classLoader.loadClass( name );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ return null;
+ }
+ }
+ }
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MethodUtil.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MethodUtil.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MethodUtil.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MethodUtil.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,58 @@
+package org.apache.commons.beanutils2;
+
+/*
+ * 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.
+ */
+
+import java.lang.reflect.Method;
+
+/**
+ * Utility for handling {@link Method Methods}
+ */
+final class MethodUtil
+{
+
+ private MethodUtil()
+ {
+ // this class cannot be instantiated
+ }
+
+ public static boolean isMappedSetter( Method method )
+ {
+ boolean startsWithSet = method.getName().startsWith( "set" );
+ boolean twoParameters = method.getParameterTypes().length == 2;
+ if ( startsWithSet && twoParameters )
+ {
+ return method.getParameterTypes()[0].equals( String.class );
+ }
+ return false;
+ }
+
+ public static boolean isMappedGetter( Method method )
+ {
+ boolean startsWithGet = method.getName().startsWith( "get" );
+ boolean onlyOneParameter = method.getParameterTypes().length == 1;
+ boolean returnsSomething = !method.getReturnType().equals( Void.TYPE );
+ if ( startsWithGet && onlyOneParameter && returnsSomething )
+ {
+ return method.getParameterTypes()[0].equals( String.class );
+ }
+ return false;
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/MethodUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/PropertyDescriptorsRegistry.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/PropertyDescriptorsRegistry.java?rev=1441781&r1=1441780&r2=1441781&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/PropertyDescriptorsRegistry.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/PropertyDescriptorsRegistry.java Sat Feb 2 18:07:23 2013
@@ -26,7 +26,11 @@ import java.beans.IndexedPropertyDescrip
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.locks.Lock;
@@ -74,7 +78,10 @@ final class PropertyDescriptorsRegistry
propertiesIndex = new HashMap<String, PropertyDescriptor>();
BeanInfo beanInfo = getBeanInfo( beanType );
- for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() )
+ List<PropertyDescriptor> propertyDescriptors =
+ new ArrayList<PropertyDescriptor>( Arrays.asList( beanInfo.getPropertyDescriptors() ) );
+ propertyDescriptors.addAll( getMappedPropertyDescriptors( beanType ) );
+ for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
{
makeMethodsAccessible( beanType, propertyDescriptor );
propertiesIndex.put( propertyDescriptor.getName(), propertyDescriptor );
@@ -90,6 +97,24 @@ final class PropertyDescriptorsRegistry
}
}
+ private Collection<PropertyDescriptor> getMappedPropertyDescriptors( Class<?> beanType ) throws IntrospectionException
+ {
+ Map<String, PropertyDescriptor> mappedPropertyDescirptors = new HashMap<String, PropertyDescriptor>();
+ for ( Method method : beanType.getMethods() )
+ {
+ if ( MethodUtil.isMappedGetter( method ) || MethodUtil.isMappedSetter( method ) )
+ {
+ String propertyName = method.getName().substring( 3 );
+ propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1);
+ if ( !mappedPropertyDescirptors.containsKey( propertyName ) )
+ {
+ mappedPropertyDescirptors.put( propertyName, new MappedPropertyDescriptor( propertyName , beanType ));
+ }
+ }
+ }
+ return mappedPropertyDescirptors.values();
+ }
+
private void makeMethodsAccessible( Class<?> beanType, PropertyDescriptor propertyDescriptor )
throws IntrospectionException
{
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetMappedPropertyTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetMappedPropertyTestCase.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetMappedPropertyTestCase.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetMappedPropertyTestCase.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,124 @@
+package org.apache.commons.beanutils2;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.BeanUtils.on;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.apache.commons.beanutils2.testbeans.ThrowingExceptionBean;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GetMappedPropertyTestCase
+{
+
+ private TestBean testBean;
+ private ThrowingExceptionBean exceptionBean;
+
+ @Before
+ public void setUp()
+ {
+ testBean = new TestBean();
+ exceptionBean = new ThrowingExceptionBean();
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void getMappedNull()
+ throws Exception
+ {
+ on( testBean ).getMapped( null );
+ }
+
+ @Test( expected = NoSuchPropertyException.class )
+ public void getMappedUnknownProperty()
+ throws Exception
+ {
+ on( testBean ).getMapped( "unknown" );
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void getMappedNotMappedProperty()
+ throws Exception
+ {
+ on( testBean ).getMapped( "intProperty" );
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void getMappedIntNullKey()
+ throws Exception
+ {
+ on( testBean ).getMapped( "mappedIntProperty" ).of( null );
+ }
+
+ @Test
+ public void getMappedUnknownKey()
+ throws Exception
+ {
+ BeanAccessor<?> result = on( testBean ).getMapped( "mappedProperty" ).of( "unknownKey" );
+ assertNull( result.get() );
+ }
+
+ @Test
+ public void getMappedMappedProperty()
+ throws Exception
+ {
+ BeanAccessor<?> result = on( testBean ).getMapped( "mappedProperty" ).of( "First Key" );
+ assertEquals( "First Value", result.get() );
+ }
+
+ @Test
+ public void getMappedMappedIntProperty()
+ throws Exception
+ {
+ BeanAccessor<?> result = on( testBean ).getMapped( "mappedIntProperty" ).of( "One" );
+ assertEquals( Integer.valueOf( 1 ), result.get() );
+ }
+
+ @Test
+ public void getMappedMappedObjects()
+ throws Exception
+ {
+ BeanAccessor<?> result = on( testBean ).getMapped( "mappedObjects" ).of( "First Key" );
+ assertEquals( "First Value", result.get() );
+ }
+
+ @Test( expected = PropertyGetterInvocationException.class )
+ public void getExceptionMapped()
+ {
+ on( exceptionBean ).getMapped( "exceptionMapped" ).of( "A Key" );
+ }
+
+ @Test( expected = NoSuchPropertyException.class )
+ public void getPrivateMapped()
+ {
+ on( exceptionBean ).getMapped( "privateMapped" );
+ }
+
+ @Test( expected = NoSuchPropertyException.class )
+ public void getProtectedMapped()
+ {
+ on( exceptionBean ).getMapped( "protecedMapped" );
+ }
+
+ @Test( expected = NoSuchPropertyException.class )
+ public void getDefaultMapped()
+ {
+ on( exceptionBean ).getMapped( "defaultMapped" );
+ }
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetMappedPropertyTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,392 @@
+package org.apache.commons.beanutils2;
+
+/*
+ * 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.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.beans.IntrospectionException;
+
+import org.apache.commons.beanutils2.testbeans.MappedPropertyChildBean;
+import org.apache.commons.beanutils2.testbeans.MappedPropertyChildInterface;
+import org.apache.commons.beanutils2.testbeans.MappedPropertyTestBean;
+import org.apache.commons.beanutils2.testbeans.MappedPropertyTestInterface;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * <p>
+ * Test Case for the <code>MappedPropertyDescriptor</code>.
+ * </p>
+ * Extracted from BeanUtils1
+ */
+public class MappedPropertyTestCase
+{
+
+ @Test( expected = IntrospectionException.class )
+ public void testConstructorNullClass()
+ throws Exception
+ {
+ new MappedPropertyDescriptor( null, MappedPropertyTestBean.class );
+ }
+
+ @Test( expected = IntrospectionException.class )
+ public void testConstructorEmptyStringClass()
+ throws Exception
+ {
+ new MappedPropertyDescriptor( "", MappedPropertyTestBean.class );
+ }
+
+ @Test( expected = IntrospectionException.class )
+ public void testConstructorNullNullNull()
+ throws Exception
+ {
+ new MappedPropertyDescriptor( null, null, null );
+ }
+
+ @Test( expected = IntrospectionException.class )
+ public void testConstructorEmptyStringNullNull()
+ throws Exception
+ {
+ new MappedPropertyDescriptor( "", null, null );
+ }
+
+ /**
+ * Test valid method name
+ */
+ @Test
+ public void testFound()
+ {
+ String property = "mapproperty";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test boolean "is" method name
+ */
+ @Test
+ public void testBooleanMapped()
+ {
+ String property = "mappedBoolean";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test invalid method name
+ */
+ @Test
+ public void testNotFound()
+ {
+ String property = "xxxxxxx";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ new MappedPropertyDescriptor( property, clazz );
+ fail( "Property '" + property + "' found in " + clazz.getName() );
+ }
+ catch ( Exception ex )
+ {
+ // expected result
+ }
+ }
+
+ /**
+ * Test Mapped Property - Getter only
+ */
+ @Test
+ public void testMappedGetterOnly()
+ {
+ String property = "mappedGetterOnly";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNull( "Setter is found", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test Mapped Property - Setter Only
+ */
+ @Test
+ public void testMappedSetterOnly()
+ {
+ String property = "mappedSetterOnly";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNull( "Getter is found", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test Mapped Property - Invalid Setter
+ */
+ @Test
+ public void testInvalidSetter()
+ {
+ String property = "invalidSetter";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNull( "Setter is found", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test Mapped Property - Invalid Getter
+ */
+ @Test
+ public void testInvalidGetter()
+ {
+ String property = "invalidGetter";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNull( "Getter is found", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test Mapped Property - Different Types Expect to find the getDifferentTypes() method, but not the
+ * setDifferentTypes() method because setDifferentTypes() sets and Integer, while getDifferentTypes() returns a
+ * Long.
+ */
+ @Test
+ public void testDifferentTypes()
+ {
+ String property = "differentTypes";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNull( "Setter is found", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test Mpa getter
+ */
+ @Test
+ @Ignore // TODO review this test
+ public void testMapGetter()
+ {
+ MappedPropertyTestBean bean = new MappedPropertyTestBean();
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ String property = "myMap";
+ try
+ {
+ String testValue = "test value";
+ String testKey = "testKey";
+ // BeanUtils.setProperty( bean, "myMap(" + testKey + ")", "test value" );
+ assertEquals( "Map getter", testValue, bean.getMyMap().get( testKey ) );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Test set mapped property failed: " + ex );
+ }
+ }
+
+ /**
+ * Test property with any two args
+ */
+ @Test
+ public void testAnyArgsProperty()
+ {
+ String property = "anyMapped";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNull( "Getter is found", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test property with two primitve args
+ */
+ @Test
+ public void testPrimitiveArgsProperty()
+ {
+ String property = "mappedPrimitive";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNull( "Getter is found", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test 'protected' mapped property
+ */
+ @Test( expected = IntrospectionException.class )
+ public void testProtected()
+ throws IntrospectionException
+ {
+ String property = "protectedProperty";
+ Class<MappedPropertyTestBean> clazz = MappedPropertyTestBean.class;
+ new MappedPropertyDescriptor( property, clazz );
+ }
+
+ /**
+ * Test 'public' method in parent
+ */
+ @Test
+ public void testPublicParentMethod()
+ {
+ String property = "mapproperty";
+ Class<MappedPropertyChildBean> clazz = MappedPropertyChildBean.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test 'protected' method in parent
+ */
+ @Test( expected = IntrospectionException.class )
+ public void testProtectedParentMethod()
+ throws IntrospectionException
+ {
+ String property = "protectedMapped";
+ Class<MappedPropertyChildBean> clazz = MappedPropertyChildBean.class;
+ new MappedPropertyDescriptor( property, clazz );
+ }
+
+ /**
+ * Test Interface with mapped property
+ */
+ @Test
+ public void testInterfaceMapped()
+ {
+ String property = "mapproperty";
+ Class<MappedPropertyTestInterface> clazz = MappedPropertyTestInterface.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+
+ /**
+ * Test property not found in interface
+ */
+ @Test( expected = IntrospectionException.class )
+ public void testInterfaceNotFound()
+ throws IntrospectionException
+ {
+ String property = "XXXXXX";
+ Class<MappedPropertyTestInterface> clazz = MappedPropertyTestInterface.class;
+ new MappedPropertyDescriptor( property, clazz );
+ }
+
+ /**
+ * Test Interface Inherited mapped property
+ */
+ @Test
+ public void testChildInterfaceMapped()
+ {
+ String property = "mapproperty";
+ Class<MappedPropertyChildInterface> clazz = MappedPropertyChildInterface.class;
+ try
+ {
+ MappedPropertyDescriptor desc = new MappedPropertyDescriptor( property, clazz );
+ assertNotNull( "Getter is missing", desc.getMappedReadMethod() );
+ assertNotNull( "Setter is missing", desc.getMappedWriteMethod() );
+ }
+ catch ( Exception ex )
+ {
+ fail( "Property '" + property + "' Not Found in " + clazz.getName() + ": " + ex );
+ }
+ }
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MethodUtilTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MethodUtilTest.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MethodUtilTest.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MethodUtilTest.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,84 @@
+package org.apache.commons.beanutils2;
+
+/*
+ * 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.
+ */
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+public class MethodUtilTest
+{
+
+ @Test
+ public void isMappedSetterWithMappedPropertySetter()
+ throws Exception
+ {
+ Method mappedPropertySetter =
+ TestBean.class.getMethod( "setMappedProperty", new Class<?>[] { String.class, String.class } );
+ assertTrue( MethodUtil.isMappedSetter( mappedPropertySetter ) );
+ }
+
+ @Test
+ public void isMappedSetterWithIndexedPropertySetter()
+ throws Exception
+ {
+ Method indexedPropertySetter =
+ TestBean.class.getMethod( "setIntIndexed", new Class<?>[] { int.class, int.class } );
+ assertFalse( MethodUtil.isMappedSetter( indexedPropertySetter ) );
+ }
+
+ @Test
+ public void isMappedSetterWithStringPropertySetter()
+ throws Exception
+ {
+
+ Method stringPropertySetter = TestBean.class.getMethod( "setStringProperty", new Class<?>[] { String.class } );
+ assertFalse( MethodUtil.isMappedSetter( stringPropertySetter ) );
+ }
+
+ @Test
+ public void isMappedGetterWithMappedPropertyGetter()
+ throws Exception
+ {
+ Method mappedPropertyGetter = TestBean.class.getMethod( "getMappedProperty", new Class<?>[] { String.class } );
+ assertTrue( MethodUtil.isMappedGetter( mappedPropertyGetter ) );
+ }
+
+ @Test
+ public void isMappedGetterWithIndexedPropertyGetter()
+ throws Exception
+ {
+ Method indexedPropertyGetter = TestBean.class.getMethod( "getIntIndexed", new Class<?>[] { int.class } );
+ assertFalse( MethodUtil.isMappedGetter( indexedPropertyGetter ) );
+ }
+
+ @Test
+ public void isMappedGetterWithStringPropertyGetter()
+ throws Exception
+ {
+
+ Method stringPropertyGetter = TestBean.class.getMethod( "getStringProperty", new Class<?>[] {} );
+ assertFalse( MethodUtil.isMappedGetter( stringPropertyGetter ) );
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/MethodUtilTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildBean.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildBean.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildBean.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildBean.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,30 @@
+package org.apache.commons.beanutils2.testbeans;
+
+/*
+ * 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.
+ */
+
+/**
+ * Inherited Mapped property test bean.
+ * Extracted from BeanUtils1
+ *
+ * @version $Revision: 1088801 $ $Date: 2011-04-05 00:06:02 +0200 (Tue, 05 Apr 2011) $
+ */
+public class MappedPropertyChildBean
+ extends MappedPropertyTestBean
+{
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildInterface.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildInterface.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildInterface.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildInterface.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,30 @@
+package org.apache.commons.beanutils2.testbeans;
+
+/*
+ * 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.
+ */
+
+/**
+ * Test Child Interface
+ * Extracted from BeanUtils1
+ *
+ * @version $Revision: 1088801 $ $Date: 2011-04-05 00:06:02 +0200 (Tue, 05 Apr 2011) $
+ */
+public interface MappedPropertyChildInterface
+ extends MappedPropertyTestInterface
+{
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyChildInterface.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestBean.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestBean.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestBean.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestBean.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,124 @@
+package org.apache.commons.beanutils2.testbeans;
+
+/*
+ * 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.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Just a java bean (JAJB) to try to replicate a reported bug
+ * Extracted from BeanUtils1
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 658830 $ $Date: 2008-05-21 21:56:21 +0200 (Wed, 21 May 2008) $
+ */
+public class MappedPropertyTestBean
+{
+
+ // TODO generics
+ private final Map map = new HashMap();
+
+ private final Map myMap = new HashMap();
+
+ // -------------------------------------------------------------- Properties
+
+ public String getMapproperty( String key )
+ {
+ return (String) map.get( key );
+ }
+
+ public void setMapproperty( String key, String value )
+ {
+ map.put( key, value );
+ }
+
+ public boolean isMappedBoolean( String key )
+ {
+ return ( (Boolean) map.get( key ) ).booleanValue();
+ }
+
+ public void setMappedBoolean( String key, boolean value )
+ {
+ map.put( key, ( value ? Boolean.TRUE : Boolean.FALSE ) );
+ }
+
+ protected String getProtectedMapped( String key )
+ {
+ return (String) map.get( key );
+ }
+
+ protected void setProtectedMapped( String key, String value )
+ {
+ map.put( key, value );
+ }
+
+ public void setMappedPrimitive( int key, int value )
+ {
+ map.put( new Integer( key ), new Integer( value ) );
+ }
+
+ public void setAnyMapped( MappedPropertyTestBean key, MappedPropertyTestBean value )
+ {
+ map.put( key, value );
+ }
+
+ public void setMappedSetterOnly( String key, String value )
+ {
+ map.put( key, value );
+ }
+
+ public String getMappedGetterOnly( String key )
+ {
+ return (String) map.get( key );
+ }
+
+ public String getInvalidGetter( String key, String other )
+ {
+ return (String) map.get( key );
+ }
+
+ public Map getMyMap()
+ {
+ return myMap;
+ }
+
+ public void setInvalidGetter( String key, String value )
+ {
+ map.put( key, value );
+ }
+
+ public String getInvalidSetter( String key )
+ {
+ return (String) map.get( key );
+ }
+
+ public void setInvalidSetter( String key, String value, String other )
+ {
+ }
+
+ public Long getDifferentTypes( String key )
+ {
+ return new Long( ( (Number) map.get( key ) ).longValue() );
+ }
+
+ public void setDifferentTypes( String key, Integer value )
+ {
+ map.put( key, value );
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestInterface.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestInterface.java?rev=1441781&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestInterface.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestInterface.java Sat Feb 2 18:07:23 2013
@@ -0,0 +1,33 @@
+package org.apache.commons.beanutils2.testbeans;
+
+/*
+ * 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.
+ */
+
+/**
+ * Test Interface
+ * Extracted from BeanUtils1
+ *
+ * @version $Revision: 1088801 $ $Date: 2011-04-05 00:06:02 +0200 (Tue, 05 Apr 2011) $
+ */
+public interface MappedPropertyTestInterface
+{
+
+ public String getMapproperty( String key );
+
+ public void setMapproperty( String key, String value );
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/MappedPropertyTestInterface.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/ThrowingExceptionBean.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/ThrowingExceptionBean.java?rev=1441781&r1=1441780&r2=1441781&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/ThrowingExceptionBean.java (original)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/testbeans/ThrowingExceptionBean.java Sat Feb 2 18:07:23 2013
@@ -140,6 +140,48 @@ public class ThrowingExceptionBean
// do nothing
}
+ public int getExceptionMapped( String key)
+ {
+ throw new RuntimeException( "Get indexed always throws an exception!" );
+ }
+
+ public void setExceptionMapped( String key, RuntimeException e )
+ {
+ throw e;
+ }
+
+ @SuppressWarnings( "unused" ) // used in IllegalAccessException test cases
+ private String getPrivateMapped( String key )
+ {
+ return "A Value";
+ }
+
+ @SuppressWarnings( "unused" ) // used in IllegalAccessException test cases
+ private void setPrivateMapped( String key, Object value )
+ {
+ // do nothing
+ }
+
+ protected String getProtectedMapped( String key )
+ {
+ return "A Value";
+ }
+
+ protected void setProtectedMapped( String key, String value)
+ {
+ // do nothing
+ }
+
+ String getDefaultMapped( String key )
+ {
+ return "A Value";
+ }
+
+ void setDefaultMapped( String key, String value )
+ {
+ // do nothing
+ }
+
public static void staticException( String message )
{
throw new RuntimeException( message );