You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2012/06/08 17:44:47 UTC

svn commit: r1348122 - in /commons/sandbox/beanutils2/trunk/src: changes/ main/java/org/apache/commons/beanutils2/ test/java/org/apache/commons/beanutils2/

Author: simonetripodi
Date: Fri Jun  8 15:44:47 2012
New Revision: 1348122

URL: http://svn.apache.org/viewvc?rev=1348122&view=rev
Log:
[SANDBOX-397] Replace NullPointerExceptions been thrown in DefaultBeanAccessor with NoSuchMethodEceptions - partially contains code provided by Benedikt Ritter

Added:
    commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java   (with props)
    commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java   (with props)
Modified:
    commons/sandbox/beanutils2/trunk/src/changes/changes.xml
    commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java
    commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/ClassAccessor.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/DefaultClassAccessor.java
    commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetPropertyTestCase.java
    commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsReadableTestCase.java
    commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsWritableTestCase.java
    commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/SetPropertyTestCase.java
    commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/VoidMethodsTestCase.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=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/changes/changes.xml (original)
+++ commons/sandbox/beanutils2/trunk/src/changes/changes.xml Fri Jun  8 15:44:47 2012
@@ -38,6 +38,9 @@
     <action dev="simonetripodi" type="add" issue="SANDBOX-398" due-to="Benedikt Ritter">
       Implement unit tests for BeanUtils.onClassName()
     </action>
+    <action dev="simonetripodi" type="add" issue="SANDBOX-397" due-to="Benedikt Ritter">
+      Replace NullPointerExceptions been thrown in DefaultBeanAccessor with NoSuchMethodEceptions
+    </action>
     <action dev="simonetripodi" type="add" issue="SANDBOX-396" due-to="Benedikt Ritter">
       Implement clone() on DefaultBeanAccessor
     </action>

Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java Fri Jun  8 15:44:47 2012
@@ -52,28 +52,6 @@ public interface BeanAccessor<B>
     IndexedPropertySetterAccessor<B> setMapped( String propertyName )
         throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException;
 
-    // checks
-
-    /**
-     * Checks if the specified property name identifies a readable property.
-     *
-     * @param propertyName the name of the property to be checked.
-     * @return {@code true}, if the property is readable.
-     * @throws IntrospectionException TODO
-     */
-    boolean isReadable( String propertyName )
-        throws IntrospectionException;
-
-    /**
-     * Checks if the specified property name identifies a writable property.
-     *
-     * @param propertyName the name of the property to be checked.
-     * @return {@code true}, if the property is writable.
-     * @throws IntrospectionException TODO
-     */
-    boolean isWritable( String propertyName )
-        throws IntrospectionException;
-
     // clone
 
     /**

Added: 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=1348122&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java Fri Jun  8 15:44:47 2012
@@ -0,0 +1,110 @@
+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.beans.IndexedPropertyDescriptor;
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+public interface BeanProperties<B>
+{
+
+    /**
+     * Checks if the specified property name identifies a readable property.
+     *
+     * @param propertyName the name of the property to be checked.
+     * @return {@code true}, if the property is readable.
+     * @throws IntrospectionException TODO
+     * @throws NoSuchMethodException TODO
+     */
+    boolean isReadable( String propertyName )
+        throws IntrospectionException, NoSuchMethodException;
+
+    /**
+     * Checks if the specified property name identifies a writable property.
+     *
+     * @param propertyName the name of the property to be checked.
+     * @return {@code true}, if the property is writable.
+     * @throws IntrospectionException TODO
+     * @throws NoSuchMethodException TODO
+     */
+    boolean isWritable( String propertyName )
+        throws IntrospectionException, NoSuchMethodException;
+
+    /**
+     *
+     * @param propertyName
+     * @return
+     * @throws IntrospectionException
+     * @throws NoSuchMethodException
+     */
+    public abstract PropertyDescriptor getPropertyDescriptor( String propertyName )
+        throws IntrospectionException, NoSuchMethodException;
+
+    /**
+     *
+     * @param propertyName
+     * @return
+     * @throws IntrospectionException
+     * @throws NoSuchMethodException
+     */
+    public abstract PropertyDescriptor getReadPropertyDescriptor( String propertyName )
+        throws IntrospectionException, NoSuchMethodException;
+
+    /**
+     *
+     * @param propertyName
+     * @return
+     * @throws NoSuchMethodException
+     * @throws IntrospectionException
+     */
+    public abstract IndexedPropertyDescriptor getIndexedPropertyDescriptor( String propertyName )
+        throws NoSuchMethodException, IntrospectionException;
+
+    /**
+     *
+     * @param propertyName
+     * @return
+     * @throws NoSuchMethodException
+     * @throws IntrospectionException
+     */
+    public abstract IndexedPropertyDescriptor getIndexedReadPropertyDescriptor( String propertyName )
+        throws NoSuchMethodException, IntrospectionException;
+
+    /**
+     *
+     * @param name
+     * @return
+     * @throws NoSuchMethodException
+     * @throws IntrospectionException
+     */
+    public abstract PropertyDescriptor getWritePropertyDescriptor( String name )
+        throws NoSuchMethodException, IntrospectionException;
+
+    /**
+     *
+     * @return
+     * @throws IntrospectionException
+     */
+    public abstract Map<String, PropertyDescriptor> getPropertiesIndex()
+        throws IntrospectionException;
+
+}

Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanProperties.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/ClassAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/ClassAccessor.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/ClassAccessor.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/ClassAccessor.java Fri Jun  8 15:44:47 2012
@@ -37,6 +37,10 @@ public interface ClassAccessor<B>
         throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException,
         NoSuchMethodException;
 
+    // bean properties
+
+    BeanProperties<B> getProperties();
+
     // static methods invocation
 
     ArgumentsAccessor invokeStatic( String methodName );

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=1348122&r1=1348121&r2=1348122&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 Fri Jun  8 15:44:47 2012
@@ -19,9 +19,7 @@ package org.apache.commons.beanutils2;
  * under the License.
  */
 
-import static java.lang.String.format;
 import static org.apache.commons.beanutils2.BeanUtils.on;
-import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
 import static org.apache.commons.beanutils2.internal.Assertions.checkNotNull;
 
 import java.beans.IndexedPropertyDescriptor;
@@ -36,13 +34,16 @@ final class DefaultBeanAccessor<B>
     implements BeanAccessor<B>
 {
 
-    private final PropertyDescriptorsRegistry registry = PropertyDescriptorsRegistry.getInstance();
-
     private final B bean;
 
+    private final BeanProperties<B> properties;
+
     public DefaultBeanAccessor( B bean )
     {
         this.bean = bean;
+        @SuppressWarnings( "unchecked" ) // we can be sure, that bean is of Class<B>
+        Class<B> beanClass = (Class<B>) bean.getClass();
+        properties = on( beanClass ).getProperties();
     }
 
     // get
@@ -50,19 +51,11 @@ final class DefaultBeanAccessor<B>
     /**
      * {@inheritDoc}
      */
-    public BeanAccessor<?> get( String name )
+    public BeanAccessor<?> get( String propertyName )
         throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException
     {
-        PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( bean.getClass(), name );
-        propertyDescriptor = checkNotNull( propertyDescriptor, "Property '%s' does not exist in bean of type %s",
-                                           name, bean.getClass().getName() );
-
-        if ( propertyDescriptor.getReadMethod() == null )
-        {
-            throw new NoSuchMethodException( format( "Bean of type %s does not provide a getter for property '%s'!",
-                                                     bean.getClass().getName(), name ) );
-        }
-
+        checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
+        PropertyDescriptor propertyDescriptor = properties.getReadPropertyDescriptor( propertyName );
         Object newBean = propertyDescriptor.getReadMethod().invoke( bean );
         return new DefaultBeanAccessor<Object>( newBean );
     }
@@ -73,22 +66,10 @@ final class DefaultBeanAccessor<B>
     public IndexedPropertyGetterAccessor getIndexed( String propertyName )
         throws IntrospectionException, NoSuchMethodException
     {
-        PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( bean.getClass(), propertyName );
-        propertyDescriptor = checkNotNull( propertyDescriptor, "Property '%s' does not exist in bean of type %s",
-                                           propertyName, bean.getClass().getName() );
-        checkArgument( IndexedPropertyDescriptor.class.isInstance( propertyDescriptor ),
-                       "Property '%s' in bean of type %s is not an indexed property",
-                       propertyName, bean.getClass().getName() );
-
-        IndexedPropertyDescriptor indexedPropertyDescriptor = (IndexedPropertyDescriptor) propertyDescriptor;
-
-        if ( indexedPropertyDescriptor.getIndexedReadMethod() == null )
-        {
-            throw new NoSuchMethodException( format( "Bean of type %s does not provide a getter for indexed property '%s'!",
-                                                     bean.getClass().getName(), propertyName ) );
-        }
-
-        return new DefaultIndexedPropertyGetterAccessor( bean, propertyName, indexedPropertyDescriptor.getIndexedReadMethod() );
+        checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
+        IndexedPropertyDescriptor indexedPropertyDescriptor = properties.getIndexedReadPropertyDescriptor( propertyName );
+        return new DefaultIndexedPropertyGetterAccessor( bean, propertyName,
+                                                         indexedPropertyDescriptor.getIndexedReadMethod() );
     }
 
     /**
@@ -127,15 +108,8 @@ final class DefaultBeanAccessor<B>
     public BeanPropertySetter<B> set( String propertyName )
         throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException
     {
-        PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( bean.getClass(), propertyName );
-        propertyDescriptor = checkNotNull( propertyDescriptor, "Property '%s' does not exist in bean of type %s",
-                                           propertyName, bean.getClass().getName() );
-
-        if ( propertyDescriptor.getWriteMethod() == null )
-        {
-            throw new NoSuchMethodException( String.format( "Bean of type %s does not provide a setter for property '%s'!",
-                                                            bean.getClass().getName(), propertyName ) );
-        }
+        checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
+        PropertyDescriptor propertyDescriptor = properties.getWritePropertyDescriptor( propertyName );
         return new DefaultBeanPropertySetter<B>( bean, propertyDescriptor.getWriteMethod() );
     }
 
@@ -159,52 +133,6 @@ final class DefaultBeanAccessor<B>
         return null;
     }
 
-    // checks
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isReadable( String propertyName )
-        throws IntrospectionException
-    {
-        PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( bean.getClass(), propertyName );
-        propertyDescriptor = checkNotNull( propertyDescriptor, "Property '%s' does not exist in bean of type %s",
-                                           propertyName,
-                                           bean.getClass().getName() );
-
-        if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
-        {
-            IndexedPropertyDescriptor indexed = (IndexedPropertyDescriptor) propertyDescriptor;
-            return indexed.getIndexedReadMethod() != null ? true : false;
-        }
-        else // TODO what about mapped properties?
-        {
-            return propertyDescriptor.getReadMethod() != null ? true : false;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isWritable( String propertyName )
-        throws IntrospectionException
-    {
-        PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( bean.getClass(), propertyName );
-        propertyDescriptor = checkNotNull( propertyDescriptor, "Property '%s' does not exist in bean of type %s",
-                                           propertyName,
-                                           bean.getClass().getName() );
-
-        if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
-        {
-            IndexedPropertyDescriptor indexed = (IndexedPropertyDescriptor) propertyDescriptor;
-            return indexed.getIndexedWriteMethod() != null ? true : false;
-        }
-        else // TODO what about mapped properties?
-        {
-            return propertyDescriptor.getWriteMethod() != null ? true : false;
-        }
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -240,7 +168,7 @@ final class DefaultBeanAccessor<B>
     public Map<String, Object> describe()
         throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException
     {
-        final Map<String, PropertyDescriptor> propertiesIndex = registry.getPropertiesIndex( bean.getClass() );
+        final Map<String, PropertyDescriptor> propertiesIndex = properties.getPropertiesIndex();
         final Map<String, Object> result = new HashMap<String, Object>( propertiesIndex.size() );
 
         for ( Entry<String, PropertyDescriptor> key : propertiesIndex.entrySet() )
@@ -267,15 +195,27 @@ final class DefaultBeanAccessor<B>
         {
             if ( entry.getKey() != null )
             {
-                PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( bean.getClass(), entry.getKey() );
-                if ( propertyDescriptor != null && propertyDescriptor.getWriteMethod() != null )
-                {
-                    set( entry.getKey() ).with( entry.getValue() );
-                }
+                setIfWritable( entry.getKey(), entry.getValue() );
             }
         }
     }
 
+    private void setIfWritable( String propertyName, Object propertyValue )
+        throws IntrospectionException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
+    {
+        try
+        {
+            properties.getWritePropertyDescriptor( propertyName );
+        }
+        catch ( NoSuchMethodException e )
+        {
+            // either the property there is no property with the given name or it is not writable so we skip it.
+            return;
+        }
+
+        set( propertyName ).with( propertyValue );
+    }
+
     /**
      * {@inheritDoc}
      */

Added: 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=1348122&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java Fri Jun  8 15:44:47 2012
@@ -0,0 +1,171 @@
+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 java.lang.String.format;
+import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
+import static org.apache.commons.beanutils2.internal.Assertions.checkNotNull;
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+final class DefaultBeanProperties<B>
+    implements BeanProperties<B>
+{
+
+    private final PropertyDescriptorsRegistry registry = PropertyDescriptorsRegistry.getInstance();
+
+    private final Class<B> beanClass;
+
+    DefaultBeanProperties( Class<B> beanClass )
+    {
+        this.beanClass = beanClass;
+    }
+
+    // checks
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isReadable( String propertyName )
+        throws IntrospectionException, NoSuchMethodException
+    {
+        checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
+        PropertyDescriptor propertyDescriptor = getPropertyDescriptor( propertyName );
+
+        if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
+        {
+            IndexedPropertyDescriptor indexed = (IndexedPropertyDescriptor) propertyDescriptor;
+            return indexed.getIndexedReadMethod() != null ? true : false;
+        }
+
+        // TODO what about mapped properties?
+        return propertyDescriptor.getReadMethod() != null ? true : false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isWritable( String propertyName )
+        throws IntrospectionException, NoSuchMethodException
+    {
+        checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
+        PropertyDescriptor propertyDescriptor = getPropertyDescriptor( propertyName );
+
+        if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
+        {
+            IndexedPropertyDescriptor indexed = (IndexedPropertyDescriptor) propertyDescriptor;
+            return indexed.getIndexedWriteMethod() != null ? true : false;
+        }
+
+        // TODO what about mapped properties?
+        return propertyDescriptor.getWriteMethod() != null ? true : false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PropertyDescriptor getPropertyDescriptor( String propertyName )
+        throws IntrospectionException, NoSuchMethodException
+    {
+        PropertyDescriptor propertyDescriptor = registry.getPropertyDescriptor( beanClass, propertyName );
+
+        checkMethod( propertyDescriptor, "Property '%s' does not exist in bean of type %s",
+                     propertyName, beanClass.getName() );
+
+        return propertyDescriptor;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PropertyDescriptor getReadPropertyDescriptor( String propertyName )
+        throws IntrospectionException, NoSuchMethodException
+    {
+        PropertyDescriptor propertyDescriptor = getPropertyDescriptor( propertyName );
+
+        checkMethod( propertyDescriptor.getReadMethod(),
+                     "Bean of type %s does not provide a getter for property '%s'!",
+                     beanClass.getName(), propertyName );
+
+        return propertyDescriptor;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public IndexedPropertyDescriptor getIndexedPropertyDescriptor( String propertyName )
+        throws NoSuchMethodException, IntrospectionException
+    {
+        PropertyDescriptor propertyDescriptor = getPropertyDescriptor( propertyName );
+        checkArgument( propertyDescriptor instanceof IndexedPropertyDescriptor,
+                       "Property '%s' in bean of type %s is not an indexed property", propertyName, beanClass.getName() );
+        return (IndexedPropertyDescriptor) propertyDescriptor;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public IndexedPropertyDescriptor getIndexedReadPropertyDescriptor( String propertyName )
+        throws NoSuchMethodException, IntrospectionException
+    {
+        IndexedPropertyDescriptor indexedPropertyDescriptor = getIndexedPropertyDescriptor( propertyName );
+
+        checkMethod( indexedPropertyDescriptor.getIndexedReadMethod(),
+                     "Bean of type %s does not provide a getter for indexed property '%s'!",
+                     beanClass.getName(), propertyName );
+
+        return indexedPropertyDescriptor;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PropertyDescriptor getWritePropertyDescriptor( String name )
+        throws NoSuchMethodException, IntrospectionException
+    {
+        PropertyDescriptor propertyDescriptor = getPropertyDescriptor( name );
+
+        checkMethod( propertyDescriptor.getWriteMethod(),
+                     "Bean of type %s does not provide a setter for property '%s'!",
+                     beanClass.getName(), name );
+
+        return propertyDescriptor;
+    }
+
+    private static <T> void checkMethod( T method, String errorMessageTemplate, Object...arsg )
+        throws NoSuchMethodException
+    {
+        if ( method == null )
+        {
+            throw new NoSuchMethodException( format( errorMessageTemplate, arsg ) );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Map<String, PropertyDescriptor> getPropertiesIndex()
+        throws IntrospectionException
+    {
+        return registry.getPropertiesIndex( beanClass );
+    }
+
+}

Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanProperties.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultClassAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultClassAccessor.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultClassAccessor.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultClassAccessor.java Fri Jun  8 15:44:47 2012
@@ -33,11 +33,14 @@ final class DefaultClassAccessor<B>
     private final AccessibleObjectsRegistry<Constructor<?>> constructorRegistry =
                     AccessibleObjectsRegistry.getConstructorsRegistry();
 
+    private final BeanProperties<B> beanProperties;
+
     private final Class<B> beanClass;
 
     public DefaultClassAccessor( Class<B> beanClass )
     {
         this.beanClass = beanClass;
+        beanProperties = new DefaultBeanProperties<B>( beanClass );
     }
 
     // pure new class instantiation
@@ -118,6 +121,13 @@ final class DefaultClassAccessor<B>
         return new DefaultBeanAccessor<B>( bean );
     }
 
+    // bean properties
+
+    public BeanProperties<B> getProperties()
+    {
+        return beanProperties;
+    }
+
     // static methods
 
     /**

Modified: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetPropertyTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetPropertyTestCase.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetPropertyTestCase.java (original)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/GetPropertyTestCase.java Fri Jun  8 15:44:47 2012
@@ -64,4 +64,18 @@ public final class GetPropertyTestCase
         on( bean ).get( "writeOnlyProperty" ).get();
     }
 
+    @Test( expected = NoSuchMethodException.class )
+    public void getUnknownProperty()
+        throws Exception
+    {
+        on( bean ).get( "unknown" );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void getNull()
+        throws Exception
+    {
+        on( bean ).get( null );
+    }
+
 }

Modified: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsReadableTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsReadableTestCase.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsReadableTestCase.java (original)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsReadableTestCase.java Fri Jun  8 15:44:47 2012
@@ -21,39 +21,23 @@ import static org.apache.commons.beanuti
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 
 public class IsReadableTestCase
 {
 
-    private TestBean testBean;
-
-    @Before
-    public void setUp()
-    {
-        testBean = new TestBean();
-    }
-
-    @After
-    public void tearDown()
-    {
-        testBean = null;
-    }
-
     @Test( expected = NullPointerException.class )
     public void isReadableNull()
         throws Exception
     {
-        on( testBean ).isReadable( null );
+        on( TestBean.class ).getProperties().isReadable( null );
     }
 
-    @Test( expected = NullPointerException.class )
+    @Test( expected = NoSuchMethodException.class )
     public void isReadbleUnknown()
         throws Exception
     {
-        on( testBean ).isReadable( "unknown" );
+        on( TestBean.class ).getProperties().isReadable( "unknown" );
     }
 
     @Test
@@ -61,7 +45,7 @@ public class IsReadableTestCase
         throws Exception
     {
         assertTrue( "isReadable returned false for a read/write int property!",
-                    on( testBean ).isReadable( "intProperty" ) );
+                    on( TestBean.class ).getProperties().isReadable( "intProperty" ) );
     }
 
     @Test
@@ -69,7 +53,7 @@ public class IsReadableTestCase
         throws Exception
     {
         assertTrue( "isReadable returned false for a read/write array property!",
-                    on( testBean ).isReadable( "intArray" ) );
+                    on( TestBean.class ).getProperties().isReadable( "intArray" ) );
     }
 
     @Test
@@ -77,7 +61,7 @@ public class IsReadableTestCase
         throws Exception
     {
         assertTrue( "isReadable returned false for a read/write indexed property!",
-                    on( testBean ).isReadable( "intIndexed" ) );
+                    on( TestBean.class ).getProperties().isReadable( "intIndexed" ) );
     }
 
     @Test
@@ -85,7 +69,7 @@ public class IsReadableTestCase
         throws Exception
     {
         assertTrue( "isReadable returned false for a read/write map property!",
-                    on( testBean ).isReadable( "mapProperty" ) );
+                    on( TestBean.class ).getProperties().isReadable( "mapProperty" ) );
     }
 
     @Test
@@ -93,7 +77,7 @@ public class IsReadableTestCase
         throws Exception
     {
         assertTrue( "isReadble returned false for a read only property!",
-                    on( testBean ).isReadable( "readOnlyProperty" ) );
+                    on( TestBean.class ).getProperties().isReadable( "readOnlyProperty" ) );
     }
 
     @Test
@@ -101,7 +85,7 @@ public class IsReadableTestCase
         throws Exception
     {
         assertFalse( "isReadable returned true for a write only property!",
-                     on( testBean ).isReadable( "writeOnlyProperty" ) );
+                     on( TestBean.class ).getProperties().isReadable( "writeOnlyProperty" ) );
     }
 
 }

Modified: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsWritableTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsWritableTestCase.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsWritableTestCase.java (original)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/IsWritableTestCase.java Fri Jun  8 15:44:47 2012
@@ -21,39 +21,23 @@ import static org.apache.commons.beanuti
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 
 public class IsWritableTestCase
 {
 
-    private TestBean testBean;
-
-    @Before
-    public void setUp()
-    {
-        testBean = new TestBean();
-    }
-
-    @After
-    public void tearDown()
-    {
-        testBean = null;
-    }
-
     @Test( expected = NullPointerException.class )
     public void isWritableNull()
         throws Exception
     {
-        on( testBean ).isWritable( null );
+        on( TestBean.class ).getProperties().isWritable( null );
     }
 
-    @Test( expected = NullPointerException.class )
+    @Test( expected = NoSuchMethodException.class )
     public void isWritbleUnknown()
         throws Exception
     {
-        on( testBean ).isWritable( "unknown" );
+        on( TestBean.class ).getProperties().isWritable( "unknown" );
     }
 
     @Test
@@ -61,7 +45,7 @@ public class IsWritableTestCase
         throws Exception
     {
         assertTrue( "isWritable returned false for a read/write int property!",
-                    on( testBean ).isWritable( "intProperty" ) );
+                    on( TestBean.class ).getProperties().isWritable( "intProperty" ) );
     }
 
     @Test
@@ -69,7 +53,7 @@ public class IsWritableTestCase
         throws Exception
     {
         assertTrue( "isWritable returned false for a read/write array property!",
-                    on( testBean ).isWritable( "intArray" ) );
+                    on( TestBean.class ).getProperties().isWritable( "intArray" ) );
     }
 
     @Test
@@ -77,7 +61,7 @@ public class IsWritableTestCase
         throws Exception
     {
         assertTrue( "isWritable returned false for a read/write indexed property!",
-                    on( testBean ).isWritable( "intIndexed" ) );
+                    on( TestBean.class ).getProperties().isWritable( "intIndexed" ) );
     }
 
     @Test
@@ -85,7 +69,7 @@ public class IsWritableTestCase
         throws Exception
     {
         assertTrue( "isWritable returned false for a read/write map property!",
-                    on( testBean ).isWritable( "mapProperty" ) );
+                    on( TestBean.class ).getProperties().isWritable( "mapProperty" ) );
     }
 
     @Test
@@ -93,7 +77,7 @@ public class IsWritableTestCase
         throws Exception
     {
         assertFalse( "isWriteable returned true for a read only property!",
-                     on( testBean ).isWritable( "readOnlyProperty" ) );
+                     on( TestBean.class ).getProperties().isWritable( "readOnlyProperty" ) );
     }
 
     @Test
@@ -101,7 +85,7 @@ public class IsWritableTestCase
         throws Exception
     {
         assertTrue( "isWritable returned false for a write only property!",
-                    on( testBean ).isWritable( "writeOnlyProperty" ) );
+                    on( TestBean.class ).getProperties().isWritable( "writeOnlyProperty" ) );
     }
 
 }

Modified: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/SetPropertyTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/SetPropertyTestCase.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/SetPropertyTestCase.java (original)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/SetPropertyTestCase.java Fri Jun  8 15:44:47 2012
@@ -77,7 +77,7 @@ public class SetPropertyTestCase
     /**
      * Tests if trying to set a nonexistent property causes an NPE.
      */
-    @Test( expected = NullPointerException.class )
+    @Test( expected = NoSuchMethodException.class )
     public void setNonExistentProperty()
         throws Exception
     {
@@ -114,4 +114,13 @@ public class SetPropertyTestCase
         on( testBean ).set( "readOnlyProperty" ).with( 15 );
     }
 
+    /**
+     * Test if passing null to set causes an NPE
+     */
+    @Test( expected = NullPointerException.class )
+    public void setNull()
+        throws Exception
+    {
+        on( testBean ).set( null );
+    }
 }

Modified: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/VoidMethodsTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/VoidMethodsTestCase.java?rev=1348122&r1=1348121&r2=1348122&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/VoidMethodsTestCase.java (original)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/VoidMethodsTestCase.java Fri Jun  8 15:44:47 2012
@@ -96,20 +96,6 @@ public class VoidMethodsTestCase
         voidAccessor.setMapped( "propertyName" );
     }
 
-    @Test( expected = NullPointerException.class )
-    public void isReadable()
-        throws Exception
-    {
-        voidAccessor.isReadable( "propertyName" );
-    }
-
-    @Test( expected = NullPointerException.class )
-    public void isWritable()
-        throws Exception
-    {
-        voidAccessor.isWritable( "propertyName" );
-    }
-
     @Test
     public void cast()
     {