You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/02/10 01:55:24 UTC

svn commit: r505594 - in /tapestry/tapestry5: tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ tapes...

Author: hlship
Date: Fri Feb  9 16:55:22 2007
New Revision: 505594

URL: http://svn.apache.org/viewvc?view=rev&rev=505594
Log:
Make some changes to ClassFactory to gain access to the line number of a particular method (a capability that depends on Javassist).
Change BeanEditorModelSource and GridDataModelSource to use the position of the getter method as the default order for properties, unless overridden with the @Order annotation.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBean.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBeanSubclass.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/PropertyOrderBean.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/AnnotatedBean.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/BeanWithIndexedProperty.java
      - copied unchanged from r499156, tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BeanWithIndexedProperty.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/LineNumberBean.java
Removed:
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BeanWithIndexedProperty.java
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/GridDataModelSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/RegistrationData.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/Track.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/GridDataModelSourceImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SimpleBean.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StoogeBean.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WriteOnlyBean.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/IOCUtilities.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassPropertyAdapterImpl.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImpl.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAdapterImpl.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFabUtils.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassPropertyAdapter.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImplTest.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImplTest.java
    tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/services/ClassFabUtilsTest.java

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java Fri Feb  9 16:55:22 2007
@@ -18,6 +18,8 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -29,6 +31,9 @@
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
+import org.apache.tapestry.ioc.services.PropertyAdapter;
 
 /** Shared utility methods used by various implementation classes. */
 public class TapestryUtils
@@ -232,5 +237,91 @@
 
         return toUserPresentable(extractIdFromPropertyExpression(IOCUtilities
                 .toSimpleId(propertyExpression)));
+    }
+
+    private static class PropertyOrder implements Comparable<PropertyOrder>
+    {
+        final String _propertyName;
+
+        final int _classDepth;
+
+        final int _sortKey;
+
+        public PropertyOrder(final String propertyName, int classDepth, int sortKey)
+        {
+            _propertyName = propertyName;
+            _classDepth = classDepth;
+            _sortKey = sortKey;
+        }
+
+        public int compareTo(PropertyOrder o)
+        {
+            int result = _classDepth - o._classDepth;
+
+            if (result == 0)
+                result = _sortKey - o._sortKey;
+
+            if (result == 0)
+                result = _propertyName.compareTo(o._propertyName);
+
+            return result;
+        }
+    }
+
+    /**
+     * Sorts the property names into presentation order. Filters out any properties that have an
+     * explicit {@link Order}, leaving the remainder. Estimates each properties position based on
+     * the relative position of the propertie's getter or setter. The code assumes that all methods
+     * are readable (have a getter method).
+     * 
+     * @param classAdapter
+     *            defines the bean that contains the properties
+     * @param classFactory
+     *            used to access method line number information
+     * @param propertyNames
+     *            the initial set of property names
+     * @return propertyNames filtered and sorted
+     */
+    public static List<String> orderProperties(ClassPropertyAdapter classAdapter,
+            ClassFactory classFactory, List<String> propertyNames)
+    {
+        List<PropertyOrder> properties = newList();
+
+        for (String name : propertyNames)
+        {
+            PropertyAdapter pa = classAdapter.getPropertyAdapter(name);
+
+            if (pa.getAnnotation(Order.class) != null)
+                continue;
+
+            Method readMethod = pa.getReadMethod();
+
+            // Kind of assuming that line number information will be availble here.
+
+            properties.add(new PropertyOrder(name, computeDepth(readMethod), classFactory
+                    .getMethodLineNumber(readMethod)));
+        }
+
+        Collections.sort(properties);
+
+        List<String> result = newList();
+
+        for (PropertyOrder po : properties)
+            result.add(po._propertyName);
+
+        return result;
+    }
+
+    private static int computeDepth(Method method)
+    {
+        int depth = 0;
+        Class c = method.getDeclaringClass();
+        while (c != Object.class)
+        {
+            depth++;
+            c = c.getSuperclass();
+        }
+
+        return depth;
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java Fri Feb  9 16:55:22 2007
@@ -14,14 +14,19 @@
 
 package org.apache.tapestry.internal.services;
 
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
+import java.util.List;
 import java.util.Map;
 
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.beaneditor.BeanEditorModel;
 import org.apache.tapestry.events.InvalidationListener;
+import org.apache.tapestry.internal.TapestryUtils;
 import org.apache.tapestry.internal.beaneditor.BeanEditorModelImpl;
 import org.apache.tapestry.ioc.Messages;
-import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
 import org.apache.tapestry.ioc.services.PropertyAccess;
 import org.apache.tapestry.ioc.services.PropertyAdapter;
@@ -38,15 +43,18 @@
 
     private final PropertyConduitSource _propertyConduitSource;
 
+    private final ClassFactory _classFactory;
+
     private final StrategyRegistry<String> _registry;
 
     public BeanEditorModelSourceImpl(final TypeCoercer typeCoercer,
             final PropertyAccess propertyAccess, final PropertyConduitSource propertyConduitSource,
-            Map<Class, String> configuration)
+            ClassFactory classFactory, Map<Class, String> configuration)
     {
         _typeCoercer = typeCoercer;
         _propertyAccess = propertyAccess;
         _propertyConduitSource = propertyConduitSource;
+        _classFactory = classFactory;
 
         _registry = StrategyRegistry.newInstance(String.class, configuration);
     }
@@ -58,15 +66,17 @@
 
     public BeanEditorModel create(Class beanClass, ComponentResources resources)
     {
-        Defense.notNull(beanClass, "beanClass");
-        Defense.notNull(resources, "resources");
+        notNull(beanClass, "beanClass");
+        notNull(resources, "resources");
 
         Messages messages = resources.getMessages();
 
         ClassPropertyAdapter adapter = _propertyAccess.getAdapter(beanClass);
 
-        BeanEditorModel model = new BeanEditorModelImpl(beanClass, _propertyConduitSource, _typeCoercer,
-                messages);
+        BeanEditorModel model = new BeanEditorModelImpl(beanClass, _propertyConduitSource,
+                _typeCoercer, messages);
+
+        List<String> propertyNames = newList();
 
         for (String propertyName : adapter.getPropertyNames())
         {
@@ -82,7 +92,23 @@
                     continue;
 
                 model.add(propertyName).editorType(editorType);
+
+                propertyNames.add(propertyName);
             }
+        }
+
+        // Set default property order for properties that are not explicit.
+
+        List<String> orderedNames = TapestryUtils.orderProperties(
+                adapter,
+                _classFactory,
+                propertyNames);
+
+        for (int i = 0; i < orderedNames.size(); i++)
+        {
+            String propertyName = orderedNames.get(i);
+
+            model.get(propertyName).order(i);
         }
 
         return model;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/GridDataModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/GridDataModelSourceImpl.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/GridDataModelSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/GridDataModelSourceImpl.java Fri Feb  9 16:55:22 2007
@@ -14,11 +14,17 @@
 
 package org.apache.tapestry.internal.services;
 
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
+import java.util.List;
+
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.grid.GridDataModel;
+import org.apache.tapestry.internal.TapestryUtils;
 import org.apache.tapestry.internal.grid.GridDataModelImpl;
 import org.apache.tapestry.ioc.Messages;
-import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
 import org.apache.tapestry.ioc.services.PropertyAccess;
 import org.apache.tapestry.services.GridDataModelSource;
@@ -28,18 +34,22 @@
 {
     private final PropertyAccess _access;
 
+    private final ClassFactory _classFactory;
+
     private final PropertyConduitSource _source;
 
-    public GridDataModelSourceImpl(PropertyAccess access, PropertyConduitSource source)
+    public GridDataModelSourceImpl(PropertyAccess access, ClassFactory classFactory,
+            PropertyConduitSource source)
     {
         _access = access;
+        _classFactory = classFactory;
         _source = source;
     }
 
     public GridDataModel create(Class rowType, ComponentResources resources)
     {
-        Defense.notNull(rowType, "rowType");
-        Defense.notNull(resources, "resources");
+        notNull(rowType, "rowType");
+        notNull(resources, "resources");
 
         Messages messages = resources.getMessages();
 
@@ -47,13 +57,31 @@
 
         ClassPropertyAdapter adapter = _access.getAdapter(rowType);
 
+        List<String> propertyNames = newList();
+
         for (String name : adapter.getPropertyNames())
         {
             if (name.equals("class"))
                 continue;
 
             if (adapter.getPropertyAdapter(name).isRead())
+            {
                 model.add(name);
+                propertyNames.add(name);
+            }
+        }
+
+        // Set default property order for properties that are not explicit.
+
+        List<String> orderedNames = TapestryUtils.orderProperties(
+                adapter,
+                _classFactory,
+                propertyNames);
+
+        for (int i = 0; i < orderedNames.size(); i++)
+        {
+            String name = orderedNames.get(i);
+            model.get(name).order(i);
         }
 
         return model;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Fri Feb  9 16:55:22 2007
@@ -217,6 +217,8 @@
 
     private final PropertyConduitSource _propertyConduitSource;
 
+    private final ClassFactory _componentClassFactory;
+
     // Yes, you can inject services defined by this module into this module. The service proxy is
     // created without instantiating the module itself. We're careful about making as many
     // service builder and contributor methods static as possible to avoid recursive build
@@ -262,7 +264,10 @@
     PropertyConduitSource propertyConduitSource,
 
     @Inject("infrastructure:PropertyAccess")
-    PropertyAccess propertyAccess)
+    PropertyAccess propertyAccess,
+
+    @InjectService("ComponentClassFactory")
+    ClassFactory componentClassFactory)
     {
         _pipelineBuilder = pipelineBuilder;
         _shadowBuilder = shadowBuilder;
@@ -278,6 +283,7 @@
         _linkFactory = linkFactory;
         _propertyAccess = propertyAccess;
         _propertyConduitSource = propertyConduitSource;
+        _componentClassFactory = componentClassFactory;
     }
 
     /**
@@ -678,7 +684,11 @@
 
     /**
      * Returns a {@link ClassFactory} that can be used to create extra classes around component
-     * classes.
+     * classes. This ClassFactory will be cleared whenever an underlying component class is
+     * discovered to have changed. Use of this class factory implies that your code will become
+     * aware of this (if necessary) to discard any cached object (alas, this currently involves
+     * dipping into the internals side to register for the correct notifications). Failure to
+     * properly clean up can result in really nasty PermGen space memory leaks.
      */
     public ClassFactory buildComponentClassFactory()
     {
@@ -1312,7 +1322,7 @@
     Map<Class, String> configuration)
     {
         BeanEditorModelSourceImpl service = new BeanEditorModelSourceImpl(typeCoercer,
-                _propertyAccess, _propertyConduitSource, configuration);
+                _propertyAccess, _propertyConduitSource, _componentClassFactory, configuration);
 
         _componentInstantiatorSource.addInvalidationListener(service);
 
@@ -1369,13 +1379,10 @@
                 fieldValidatorSource);
     }
 
-    public PropertyConduitSource buildPropertyConduitSource(
-
-    @InjectService("ComponentClassFactory")
-    ClassFactory componentClassFactory)
+    public PropertyConduitSource buildPropertyConduitSource()
     {
         PropertyConduitSourceImpl service = new PropertyConduitSourceImpl(_propertyAccess,
-                componentClassFactory);
+                _componentClassFactory);
 
         _componentInstantiatorSource.addInvalidationListener(service);
 
@@ -1384,6 +1391,7 @@
 
     public GridDataModelSource buildGridDataModelSource()
     {
-        return new GridDataModelSourceImpl(_propertyAccess, _propertyConduitSource);
+        return new GridDataModelSourceImpl(_propertyAccess, _componentClassFactory,
+                _propertyConduitSource);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Fri Feb  9 16:55:22 2007
@@ -18,7 +18,6 @@
 import static org.apache.tapestry.internal.test.CodeEq.codeEq;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.isA;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -771,15 +770,6 @@
         expect(source.get(strategyName)).andReturn(strategy).atLeastOnce();
     }
 
-    protected final void train_get(Messages messages, String key, String message)
-    {
-        expect(messages.get(key)).andReturn(message).atLeastOnce();
-    }
-
-    protected final void stub_contains(Messages messages, boolean contained)
-    {
-        expect(messages.contains(isA(String.class))).andStubReturn(contained);
-    }
 
     protected final <T extends Annotation> void train_getAnnotation(AnnotationProvider provider,
             Class<T> annotationClass, T annotation)

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/RegistrationData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/RegistrationData.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/RegistrationData.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/RegistrationData.java Fri Feb  9 16:55:22 2007
@@ -14,7 +14,6 @@
 
 package org.apache.tapestry.integration.app1.data;
 
-import org.apache.tapestry.beaneditor.Order;
 import org.apache.tapestry.beaneditor.Validate;
 
 public class RegistrationData
@@ -29,59 +28,54 @@
 
     private boolean _citizen;
 
-    @Order(300)
+    public String getFirstName()
+    {
+        return _firstName;
+    }
+
+    @Validate("required,minlength=5")
+    public String getLastName()
+    {
+        return _lastName;
+    }
+
     @Validate("min=1900,max=2007")
     public int getBirthYear()
     {
         return _birthYear;
     }
 
-    public void setBirthYear(int birthYear)
+    public Sex getSex()
     {
-        _birthYear = birthYear;
+        return _sex;
     }
 
-    public String getFirstName()
+    public boolean isCitizen()
     {
-        return _firstName;
+        return _citizen;
     }
 
-    @Order(100)
-    @Validate("required,minlength=3")
-    public void setFirstName(String firstName)
+    public void setBirthYear(int birthYear)
     {
-        _firstName = firstName;
+        _birthYear = birthYear;
     }
 
-    @Validate("required,minlength=5")
-    public String getLastName()
+    @Validate("required,minlength=3")
+    public void setFirstName(String firstName)
     {
-        return _lastName;
+        _firstName = firstName;
     }
 
-    @Order(200)
     public void setLastName(String lastName)
     {
         _lastName = lastName;
     }
 
-    public Sex getSex()
-    {
-        return _sex;
-    }
-
-    @Order(400)
     public void setSex(Sex sex)
     {
         _sex = sex;
     }
 
-    public boolean isCitizen()
-    {
-        return _citizen;
-    }
-
-    @Order(500)
     public void setCitizen(boolean citizen)
     {
         _citizen = citizen;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/Track.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/Track.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/Track.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/Track.java Fri Feb  9 16:55:22 2007
@@ -14,8 +14,6 @@
 
 package org.apache.tapestry.integration.app1.data;
 
-import org.apache.tapestry.beaneditor.Order;
-
 /** One track from a music library. */
 public class Track
 {
@@ -30,67 +28,61 @@
     private String _title;
 
     private int _rating;
-   
-    @Order(200)
-    public String getAlbum()
+
+    public String getTitle()
     {
-        return _album;
+        return _title;
     }
 
-    public void setAlbum(String album)
+    public String getAlbum()
     {
-        _album = album;
+        return _album;
     }
 
-    @Order(300)
     public String getArtist()
     {
         return _artist;
     }
 
-    public void setArtist(String artist)
+    public String getGenre()
     {
-        _artist = artist;
+        return _genre;
     }
 
-    @Order(400)
-    public String getGenre()
+    public int getPlayCount()
     {
-        return _genre;
+        return _playCount;
     }
 
-    public void setGenre(String genre)
+    /** Rating as a value between 0 and 100. */
+    public int getRating()
     {
-        _genre = genre;
+        return _rating;
     }
 
-    public int getPlayCount()
+    public void setAlbum(String album)
     {
-        return _playCount;
+        _album = album;
     }
 
-    @Order(500)
-    public void setPlayCount(int playCount)
+    public void setArtist(String artist)
     {
-        _playCount = playCount;
+        _artist = artist;
     }
 
-    /** Rating as a value between 0 and 100. */
-    @Order(600)
-    public int getRating()
+    public void setGenre(String genre)
     {
-        return _rating;
+        _genre = genre;
     }
 
-    public void setRating(int rating)
+    public void setPlayCount(int playCount)
     {
-        _rating = rating;
+        _playCount = playCount;
     }
 
-    @Order(100)
-    public String getTitle()
+    public void setRating(int rating)
     {
-        return _title;
+        _rating = rating;
     }
 
     public void setTitle(String title)

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBean.java?view=auto&rev=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBean.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBean.java Fri Feb  9 16:55:22 2007
@@ -0,0 +1,60 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.tapestry.internal;
+
+import org.apache.tapestry.ioc.services.ClassFactory;
+
+/**
+ * Used as test when setting the order of properties via
+ * {@link TapestryUtils#orderProperties(org.apache.tapestry.ioc.services.ClassPropertyAdapter, ClassFactory, java.util.List)}.
+ */
+public class DataBean
+{
+    private String _firstName;
+
+    private String _lastName;
+
+    private int _age;
+
+    public String getFirstName()
+    {
+        return _firstName;
+    }
+
+    public String getLastName()
+    {
+        return _lastName;
+    }
+
+    public int getAge()
+    {
+        return _age;
+    }
+
+    public void setAge(int age)
+    {
+        _age = age;
+    }
+
+    public void setFirstName(String firstName)
+    {
+        _firstName = firstName;
+    }
+
+    public void setLastName(String lastName)
+    {
+        _lastName = lastName;
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBeanSubclass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBeanSubclass.java?view=auto&rev=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBeanSubclass.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBeanSubclass.java Fri Feb  9 16:55:22 2007
@@ -0,0 +1,67 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.tapestry.internal;
+
+public class DataBeanSubclass extends DataBean
+{
+    private String _street;
+
+    private String _city;
+
+    private String _state;
+
+    private String _zip;
+
+    public String getStreet()
+    {
+        return _street;
+    }
+
+    public String getCity()
+    {
+        return _city;
+    }
+
+    public String getState()
+    {
+        return _state;
+    }
+
+    public String getZip()
+    {
+        return _zip;
+    }
+
+    public void setCity(String city)
+    {
+        _city = city;
+    }
+
+    public void setStreet(String street)
+    {
+        _street = street;
+    }
+
+    public void setState(String state)
+    {
+        _state = state;
+    }
+
+    public void setZip(String zip)
+    {
+        _zip = zip;
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/PropertyOrderBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/PropertyOrderBean.java?view=auto&rev=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/PropertyOrderBean.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/PropertyOrderBean.java Fri Feb  9 16:55:22 2007
@@ -0,0 +1,57 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.tapestry.internal;
+
+import org.apache.tapestry.beaneditor.Order;
+
+public class PropertyOrderBean
+{
+    private String _first;
+
+    private String _second;
+
+    private String _third;
+
+    public String getFirst()
+    {
+        return _first;
+    }
+
+    public String getSecond()
+    {
+        return _second;
+    }
+
+    @Order(-1)
+    public String getThird()
+    {
+        return _third;
+    }
+
+    public void setFirst(String first)
+    {
+        _first = first;
+    }
+
+    public void setSecond(String second)
+    {
+        _second = second;
+    }
+
+    public void setThird(String third)
+    {
+        _third = third;
+    }
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java Fri Feb  9 16:55:22 2007
@@ -16,6 +16,7 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -25,12 +26,35 @@
 import org.apache.tapestry.beaneditor.Order;
 import org.apache.tapestry.internal.test.InternalBaseTestCase;
 import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
+import org.apache.tapestry.ioc.services.PropertyAccess;
 import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 public class TapestryUtilsTest extends InternalBaseTestCase
 {
+    private ClassFactory _classFactory;
+
+    private PropertyAccess _access;
+
+    @BeforeClass
+    public void setup()
+    {
+        _classFactory = getObject("service:tapestry.ioc.ClassFactory", ClassFactory.class);
+        _access = getObject("service:tapestry.ioc.PropertyAccess", PropertyAccess.class);
+    }
+
+    @AfterClass
+    public void cleanup()
+    {
+        _access = null;
+        _classFactory = null;
+    }
+
     @Test
     public void close_null_is_noop()
     {
@@ -285,5 +309,58 @@
                 "Biff");
 
         verify();
+    }
+
+    @Test
+    public void property_order_basic()
+    {
+        ClassPropertyAdapter adapter = _access.getAdapter(DataBean.class);
+
+        List<String> names = adapter.getPropertyNames();
+
+        names.remove("class");
+
+        List<String> sorted = TapestryUtils.orderProperties(adapter, _classFactory, names);
+
+        assertEquals(sorted, Arrays.asList("firstName", "lastName", "age"));
+    }
+
+    @Test
+    public void property_order_on_subclass()
+    {
+        ClassPropertyAdapter adapter = _access.getAdapter(DataBeanSubclass.class);
+
+        List<String> names = adapter.getPropertyNames();
+
+        names.remove("class");
+
+        List<String> sorted = TapestryUtils.orderProperties(adapter, _classFactory, names);
+
+        // Subclass properties listed after superclass properties, as desired.
+
+        assertEquals(sorted, Arrays.asList(
+                "firstName",
+                "lastName",
+                "age",
+                "street",
+                "city",
+                "state",
+                "zip"));
+    }
+
+    @Test
+    public void properties_with_order_annotation_filtered()
+    {
+        ClassPropertyAdapter adapter = _access.getAdapter(PropertyOrderBean.class);
+
+        List<String> names = adapter.getPropertyNames();
+
+        names.remove("class");
+
+        List<String> sorted = TapestryUtils.orderProperties(adapter, _classFactory, names);
+
+        // Property third has an explicit @Order
+
+        assertEquals(sorted, Arrays.asList("first", "second"));
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImplTest.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImplTest.java Fri Feb  9 16:55:22 2007
@@ -59,7 +59,9 @@
 
         BeanEditorModel model = _source.create(SimpleBean.class, resources);
 
-        assertEquals(model.getPropertyNames(), Arrays.asList("age", "firstName", "lastName"));
+        // Based on order of the getter methods (no longer alphabetical)
+
+        assertEquals(model.getPropertyNames(), Arrays.asList("firstName", "lastName", "age"));
 
         PropertyEditModel age = model.get("age");
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/GridDataModelSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/GridDataModelSourceImplTest.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/GridDataModelSourceImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/GridDataModelSourceImplTest.java Fri Feb  9 16:55:22 2007
@@ -60,7 +60,7 @@
 
         // class is not in the list
 
-        assertEquals(model.getPropertyNames(), Arrays.asList("age", "firstName", "lastName"));
+        assertEquals(model.getPropertyNames(), Arrays.asList("firstName", "lastName", "age"));
 
         ColumnModel age = model.get("age");
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SimpleBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SimpleBean.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SimpleBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SimpleBean.java Fri Feb  9 16:55:22 2007
@@ -22,29 +22,29 @@
 
     private int _age;
 
-    public int getAge()
+    public String getFirstName()
     {
-        return _age;
+        return _firstName;
     }
 
-    public void setAge(int age)
+    public String getLastName()
     {
-        _age = age;
+        return _lastName;
     }
 
-    public String getFirstName()
+    public int getAge()
     {
-        return _firstName;
+        return _age;
     }
 
-    public void setFirstName(String firstName)
+    public void setAge(int age)
     {
-        _firstName = firstName;
+        _age = age;
     }
 
-    public String getLastName()
+    public void setFirstName(String firstName)
     {
-        return _lastName;
+        _firstName = firstName;
     }
 
     public void setLastName(String lastName)

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StoogeBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StoogeBean.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StoogeBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StoogeBean.java Fri Feb  9 16:55:22 2007
@@ -20,15 +20,15 @@
 {
     private int _moe, _larry, _curly, _shemp;
 
-    @Order(100)
-    public int getCurly()
+    public int getMoe()
     {
-        return _curly;
+        return _moe;
     }
 
-    public void setCurly(int curly)
+    @Order(100)
+    public int getCurly()
     {
-        _curly = curly;
+        return _curly;
     }
 
     public int getLarry()
@@ -36,25 +36,25 @@
         return _larry;
     }
 
-    @Order(-1)
-    public void setLarry(int larry)
+    public int getShemp()
     {
-        _larry = larry;
+        return _shemp;
     }
 
-    public int getMoe()
+    public void setCurly(int curly)
     {
-        return _moe;
+        _curly = curly;
     }
 
-    public void setMoe(int moe)
+    @Order(-1)
+    public void setLarry(int larry)
     {
-        _moe = moe;
+        _larry = larry;
     }
 
-    public int getShemp()
+    public void setMoe(int moe)
     {
-        return _shemp;
+        _moe = moe;
     }
 
     public void setShemp(int shemp)

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WriteOnlyBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WriteOnlyBean.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WriteOnlyBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WriteOnlyBean.java Fri Feb  9 16:55:22 2007
@@ -16,18 +16,18 @@
 
 public class WriteOnlyBean
 {
-    public String getReadWrite()
+    public String getReadOnly()
     {
         return null;
     }
 
-    public void setReadWrite(String value)
+    public String getReadWrite()
     {
+        return null;
     }
 
-    public String getReadOnly()
+    public void setReadWrite(String value)
     {
-        return null;
     }
 
     public void setWriteOnly(String value)

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/IOCUtilities.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/IOCUtilities.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/IOCUtilities.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/IOCUtilities.java Fri Feb  9 16:55:22 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java Fri Feb  9 16:55:22 2007
@@ -14,7 +14,10 @@
 
 package org.apache.tapestry.ioc.internal.services;
 
+import java.lang.reflect.Method;
+
 import javassist.CtClass;
+import javassist.CtMethod;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -106,6 +109,32 @@
     public ClassLoader getClassLoader()
     {
         return _loader;
+    }
+
+    public int getMethodLineNumber(Method method)
+    {
+        CtClass ctClass = _classSource.getCtClass(method.getDeclaringClass());
+
+        StringBuilder builder = new StringBuilder("(");
+
+        for (Class parameterType : method.getParameterTypes())
+        {
+            builder.append(ClassFabUtils.getTypeCode(parameterType));
+        }
+
+        builder.append(")");
+        builder.append(ClassFabUtils.getTypeCode(method.getReturnType()));
+
+        try
+        {
+            CtMethod ctMethod = ctClass.getMethod(method.getName(), builder.toString());
+
+            return ctMethod.getMethodInfo().getLineNumber(0);
+        }
+        catch (Exception ex)
+        {
+            return -1;
+        }
     }
 
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassPropertyAdapterImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassPropertyAdapterImpl.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassPropertyAdapterImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassPropertyAdapterImpl.java Fri Feb  9 16:55:22 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -28,11 +28,11 @@
 {
     private final Map<String, PropertyAdapter> _adapters = newMap();
 
-    private final Class _targetClass;
+    private final Class _beanType;
 
-    public ClassPropertyAdapterImpl(Class targetClass, List<PropertyDescriptor> descriptors)
+    public ClassPropertyAdapterImpl(Class beanType, List<PropertyDescriptor> descriptors)
     {
-        _targetClass = targetClass;
+        _beanType = beanType;
 
         for (PropertyDescriptor pd : descriptors)
         {
@@ -47,12 +47,17 @@
         }
     }
 
+    public Class getBeanType()
+    {
+        return _beanType;
+    }
+
     @Override
     public String toString()
     {
         String names = InternalUtils.joinSorted(_adapters.keySet());
 
-        return String.format("<ClassPropertyAdaptor %s : %s>", _targetClass.getName(), names);
+        return String.format("<ClassPropertyAdaptor %s : %s>", _beanType.getName(), names);
     }
 
     public List<String> getPropertyNames()
@@ -80,7 +85,7 @@
         PropertyAdapter pa = _adapters.get(name);
 
         if (pa == null)
-            throw new IllegalArgumentException(ServiceMessages.noSuchProperty(_targetClass, name));
+            throw new IllegalArgumentException(ServiceMessages.noSuchProperty(_beanType, name));
 
         return pa;
     }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImpl.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImpl.java Fri Feb  9 16:55:22 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAdapterImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAdapterImpl.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAdapterImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyAdapterImpl.java Fri Feb  9 16:55:22 2007
@@ -12,119 +12,132 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.ioc.internal.services;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import org.apache.tapestry.ioc.internal.util.Defense;
-import org.apache.tapestry.ioc.services.PropertyAdapter;
-
-public class PropertyAdapterImpl implements PropertyAdapter
-{
-    private final String _name;
-
-    private final Method _readMethod;
-
-    private final Method _writeMethod;
-
-    private final Class _type;
-
-    public PropertyAdapterImpl(String name, Class type, Method readMethod, Method writeMethod)
-    {
-        _name = Defense.notBlank(name, "name");
-        _type = Defense.notNull(type, "type");
-        _readMethod = readMethod;
-        _writeMethod = writeMethod;
-    }
-
-    public PropertyAdapterImpl(PropertyDescriptor descriptor)
-    {
-        this(descriptor.getName(), descriptor.getPropertyType(), descriptor.getReadMethod(),
-                descriptor.getWriteMethod());
-    }
-
-    public String getName()
-    {
-        return _name;
-    }
-
-    public Method getReadMethod()
-    {
-        return _readMethod;
-    }
-
-    public Class getType()
-    {
-        return _type;
-    }
-
-    public Method getWriteMethod()
-    {
-        return _writeMethod;
-    }
-
-    public boolean isRead()
-    {
-        return _readMethod != null;
-    }
-
-    public boolean isUpdate()
-    {
-        return _writeMethod != null;
-    }
-
-    public Object get(Object instance)
-    {
-        if (_readMethod == null)
-            throw new UnsupportedOperationException(ServiceMessages.readNotSupported(
-                    instance,
-                    _name));
-
-        Throwable fail = null;
-
-        try
-        {
-            return _readMethod.invoke(instance);
-        }
-        catch (InvocationTargetException ex)
-        {
-            fail = ex.getTargetException();
-        }
-        catch (Exception ex)
-        {
-            fail = ex;
-        }
-
-        throw new RuntimeException(ServiceMessages.readFailure(_name, instance, fail), fail);
-    }
-
-    public void set(Object instance, Object value)
-    {
-        if (_writeMethod == null)
-            throw new UnsupportedOperationException(ServiceMessages.writeNotSupported(
-                    instance,
-                    _name));
-
-        Throwable fail = null;
-
-        try
-        {
-            _writeMethod.invoke(instance, value);
-
-            return;
-        }
-        catch (InvocationTargetException ex)
-        {
-            fail = ex.getTargetException();
-        }
-        catch (Exception ex)
-        {
-            fail = ex;
-        }
-
-        throw new RuntimeException(ServiceMessages.writeFailure(_name, instance, fail), fail);
-    }
-
-}
+package org.apache.tapestry.ioc.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tapestry.ioc.services.PropertyAdapter;
+
+public class PropertyAdapterImpl implements PropertyAdapter
+{
+    private final String _name;
+
+    private final Method _readMethod;
+
+    private final Method _writeMethod;
+
+    private final Class _type;
+
+    public PropertyAdapterImpl(String name, Class type, Method readMethod, Method writeMethod)
+    {
+        _name = notBlank(name, "name");
+        _type = notNull(type, "type");
+
+        _readMethod = readMethod;
+        _writeMethod = writeMethod;
+    }
+
+    public PropertyAdapterImpl(PropertyDescriptor descriptor)
+    {
+        this(descriptor.getName(), descriptor.getPropertyType(), descriptor.getReadMethod(),
+                descriptor.getWriteMethod());
+    }
+
+    public String getName()
+    {
+        return _name;
+    }
+
+    public Method getReadMethod()
+    {
+        return _readMethod;
+    }
+
+    public Class getType()
+    {
+        return _type;
+    }
+
+    public Method getWriteMethod()
+    {
+        return _writeMethod;
+    }
+
+    public boolean isRead()
+    {
+        return _readMethod != null;
+    }
+
+    public boolean isUpdate()
+    {
+        return _writeMethod != null;
+    }
+
+    public Object get(Object instance)
+    {
+        if (_readMethod == null)
+            throw new UnsupportedOperationException(ServiceMessages.readNotSupported(
+                    instance,
+                    _name));
+
+        Throwable fail = null;
+
+        try
+        {
+            return _readMethod.invoke(instance);
+        }
+        catch (InvocationTargetException ex)
+        {
+            fail = ex.getTargetException();
+        }
+        catch (Exception ex)
+        {
+            fail = ex;
+        }
+
+        throw new RuntimeException(ServiceMessages.readFailure(_name, instance, fail), fail);
+    }
+
+    public void set(Object instance, Object value)
+    {
+        if (_writeMethod == null)
+            throw new UnsupportedOperationException(ServiceMessages.writeNotSupported(
+                    instance,
+                    _name));
+
+        Throwable fail = null;
+
+        try
+        {
+            _writeMethod.invoke(instance, value);
+
+            return;
+        }
+        catch (InvocationTargetException ex)
+        {
+            fail = ex.getTargetException();
+        }
+        catch (Exception ex)
+        {
+            fail = ex;
+        }
+
+        throw new RuntimeException(ServiceMessages.writeFailure(_name, instance, fail), fail);
+    }
+
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+    {
+        T result = _readMethod != null ? _readMethod.getAnnotation(annotationClass) : null;
+
+        if (result == null && _writeMethod != null)
+            result = _writeMethod.getAnnotation(annotationClass);
+
+        return result;
+    }
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFabUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFabUtils.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFabUtils.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFabUtils.java Fri Feb  9 16:55:22 2007
@@ -190,4 +190,15 @@
 
         return primitiveType; // Not a primitive!
     }
+
+    public static String getTypeCode(Class type)
+    {
+        if (type.equals(void.class)) return "V";
+
+        if (type.isPrimitive()) return PRIMITIVE_INFO.get(type.getName()).getTypeCode();
+
+        if (type.isArray()) return "[" + getTypeCode(type.getComponentType());
+
+        return "L" + type.getName().replace('.', '/') + ";";
+    }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java Fri Feb  9 16:55:22 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.ioc.services;
 
+import java.lang.reflect.Method;
+
 /**
  * Service used when dynamically creating new classes.
  * 
@@ -46,8 +48,6 @@
 
     /**
      * Returns the number of classes (and interfaces) actually created.
-     * 
-     * @since 1.2
      */
 
     int getCreatedClassCount();
@@ -57,4 +57,6 @@
      * current thread's context class loader (except perhaps during testing).
      */
     ClassLoader getClassLoader();
+
+    int getMethodLineNumber(Method method);
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassPropertyAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassPropertyAdapter.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassPropertyAdapter.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassPropertyAdapter.java Fri Feb  9 16:55:22 2007
@@ -26,6 +26,9 @@
     /** Returns the names of all properties, sorted into alphabetic order. */
     List<String> getPropertyNames();
 
+    /** Returns the type of bean this adapter provides properties for. */
+    Class getBeanType();
+
     /**
      * Returns the property adapter with the given name, or null if no such adapter exists.
      */

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java Fri Feb  9 16:55:22 2007
@@ -12,68 +12,79 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.ioc.services;
-
-import java.lang.reflect.Method;
-
-/**
- * Provides access to a single property within a class.
- * 
- * 
- * @see org.apache.tapestry.ioc.services.ClassPropertyAdapter
- */
-public interface PropertyAdapter
-{
-    /**
-     * Returns the name of the property.
-     */
-    String getName();
-
-    /**
-     * Returns true if the property is readable (i.e., has a getter method).
-     */
-    boolean isRead();
-
-    /**
-     * Returns the method used to read the property, or null if the property is not readable.
-     */
-    public Method getReadMethod();
-
-    /**
-     * Returns true if the property is writeable (i.e., has a setter method).
-     */
-    boolean isUpdate();
-
-    /**
-     * Returns the method used to update the property, or null if the property is not writeable.
-     */
-    public Method getWriteMethod();
-
-    /**
-     * Reads the property value.
-     * 
-     * @param instance
-     *            to read from
-     * @throws UnsupportedOperationException
-     *             if the property is write only
-     */
-    Object get(Object instance);
-
-    /**
-     * Updates the property value. The provided value must not be null if the property type is
-     * primitive, and must otherwise be of the proper type.
-     * 
-     * @param instance
-     *            to update
-     * @param value
-     *            new value for the property
-     * @throws UnsupportedOperationException
-     *             if the property is read only
-     */
-    void set(Object instance, Object value);
-
-    /**
-     * Returns the type of the property.
-     */
-    Class getType();
-}
+package org.apache.tapestry.ioc.services;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * Provides access to a single property within a class.
+ * 
+ * @see org.apache.tapestry.ioc.services.ClassPropertyAdapter
+ */
+public interface PropertyAdapter
+{
+    /**
+     * Returns the name of the property.
+     */
+    String getName();
+
+    /**
+     * Returns true if the property is readable (i.e., has a getter method).
+     */
+    boolean isRead();
+
+    /**
+     * Returns the method used to read the property, or null if the property is not readable.
+     */
+    public Method getReadMethod();
+
+    /**
+     * Returns true if the property is writeable (i.e., has a setter method).
+     */
+    boolean isUpdate();
+
+    /**
+     * Returns the method used to update the property, or null if the property is not writeable.
+     */
+    public Method getWriteMethod();
+
+    /**
+     * Reads the property value.
+     * 
+     * @param instance
+     *            to read from
+     * @throws UnsupportedOperationException
+     *             if the property is write only
+     */
+    Object get(Object instance);
+
+    /**
+     * Updates the property value. The provided value must not be null if the property type is
+     * primitive, and must otherwise be of the proper type.
+     * 
+     * @param instance
+     *            to update
+     * @param value
+     *            new value for the property
+     * @throws UnsupportedOperationException
+     *             if the property is read only
+     */
+    void set(Object instance, Object value);
+
+    /**
+     * Returns the type of the property.
+     */
+    Class getType();
+
+    /**
+     * Returns an annotation on the property. The read method (if present) is checked first,
+     * followed by the write method.
+     * 
+     * @param <T>
+     * @param annotationClass
+     *            the annotation to retrieve
+     * @return the annotation on the read or write method, or null if not present on either method
+     */
+    <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java Fri Feb  9 16:55:22 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.ioc.test;
 
+import static org.easymock.EasyMock.isA;
+
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.Locale;
@@ -331,5 +333,15 @@
     protected void train_format(MessageFormatter formatter, String result, Object... arguments)
     {
         expect(formatter.format(arguments)).andReturn(result);
+    }
+
+    protected final void train_get(Messages messages, String key, String message)
+    {
+        expect(messages.get(key)).andReturn(message).atLeastOnce();
+    }
+
+    protected final void stub_contains(Messages messages, boolean contained)
+    {
+        expect(messages.contains(isA(String.class))).andStubReturn(contained);
     }
 }

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/AnnotatedBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/AnnotatedBean.java?view=auto&rev=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/AnnotatedBean.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/AnnotatedBean.java Fri Feb  9 16:55:22 2007
@@ -0,0 +1,55 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.tapestry.ioc.internal.services;
+
+import org.apache.tapestry.ioc.annotations.Lifecycle;
+
+public class AnnotatedBean
+{
+    public String getReadWrite()
+    {
+        return null;
+    }
+
+    public void setReadWrite(String value)
+    {
+    }
+
+    public String getAnnotationOnWrite()
+    {
+        return null;
+    }
+
+    @Lifecycle("onwrite")
+    public void setAnnotationOnWrite(String value)
+    {
+    }
+
+    @Lifecycle("onread")
+    public String getAnnotationOnRead()
+    {
+        return null;
+    }
+
+    @Lifecycle("onwrite")
+    public void setAnnotationOnRead(String value)
+    {
+    }
+
+    public String getReadOnly()
+    {
+        return null;
+    }
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImplTest.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImplTest.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImplTest.java Fri Feb  9 16:55:22 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry.ioc.internal.services;
 
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
 import org.apache.tapestry.ioc.services.ClassFab;
@@ -80,6 +81,30 @@
         Runnable instance = (Runnable) newClass.newInstance();
 
         instance.run();
+    }
+
+    @Test
+    public void get_method_line_number() throws Exception
+    {
+        ClassFactory factory = new ClassFactoryImpl();
+
+        Class target = LineNumberBean.class;
+
+        Method m = target.getMethod("fred");
+
+        // 21 is the line containing the close brace
+
+        assertEquals(factory.getMethodLineNumber(m), 21);
+
+        m = target.getMethod("betty", String.class, int.class);
+
+        // 25 is the line of the return statement
+
+        assertEquals(factory.getMethodLineNumber(m), 25);
+
+        m = target.getDeclaredMethod("wilma", int[].class, Double[][][].class);
+
+        assertEquals(factory.getMethodLineNumber(m), 30);
     }
 
     private void addRunMethod(ClassFab cf)

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/LineNumberBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/LineNumberBean.java?view=auto&rev=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/LineNumberBean.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/LineNumberBean.java Fri Feb  9 16:55:22 2007
@@ -0,0 +1,32 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.tapestry.ioc.internal.services;
+
+public class LineNumberBean
+{
+    public void fred()
+    {
+    }
+
+    public int betty(String foo, int bar)
+    {
+        return bar;
+    }
+
+    protected String wilma(int[] first, Double[][][] threed)
+    {
+        return null;
+    }
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImplTest.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImplTest.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/PropertyAccessImplTest.java Fri Feb  9 16:55:22 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 import java.util.Random;
 
 import org.apache.tapestry.ioc.Registry;
+import org.apache.tapestry.ioc.annotations.Lifecycle;
 import org.apache.tapestry.ioc.internal.IOCInternalTestCase;
 import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
 import org.apache.tapestry.ioc.services.PropertyAccess;
@@ -286,6 +287,9 @@
     public void clear_wipes_internal_cache()
     {
         ClassPropertyAdapter cpa1 = _access.getAdapter(Bean.class);
+
+        assertSame(cpa1.getBeanType(), Bean.class);
+
         ClassPropertyAdapter cpa2 = _access.getAdapter(Bean.class);
 
         assertSame(cpa2, cpa1);
@@ -396,5 +400,46 @@
         ClassPropertyAdapter cpa = _access.getAdapter(BeanWithIndexedProperty.class);
 
         assertEquals(cpa.getPropertyNames(), Arrays.asList("class", "primitiveProperty"));
+    }
+
+    @Test
+    public void get_annotation_when_annotation_not_present()
+    {
+        PropertyAdapter pa = _access.getAdapter(AnnotatedBean.class)
+                .getPropertyAdapter("readWrite");
+
+        assertNull(pa.getAnnotation(Lifecycle.class));
+    }
+
+    @Test
+    public void get_annotation_with_annotation_on_write_method()
+    {
+        PropertyAdapter pa = _access.getAdapter(AnnotatedBean.class).getPropertyAdapter(
+                "annotationOnWrite");
+
+        Lifecycle annotation = pa.getAnnotation(Lifecycle.class);
+        assertNotNull(annotation);
+
+        assertEquals(annotation.value(), "onwrite");
+    }
+
+    @Test
+    public void read_method_annotation_overrides_write_method_annotation()
+    {
+        PropertyAdapter pa = _access.getAdapter(AnnotatedBean.class).getPropertyAdapter(
+                "annotationOnRead");
+
+        Lifecycle annotation = pa.getAnnotation(Lifecycle.class);
+        assertNotNull(annotation);
+
+        assertEquals(annotation.value(), "onread");
+    }
+
+    @Test
+    public void no_write_method_reading_missing_annotation()
+    {
+        PropertyAdapter pa = _access.getAdapter(AnnotatedBean.class).getPropertyAdapter("readOnly");
+
+        assertNull(pa.getAnnotation(Lifecycle.class));
     }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/services/ClassFabUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/services/ClassFabUtilsTest.java?view=diff&rev=505594&r1=505593&r2=505594
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/services/ClassFabUtilsTest.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/services/ClassFabUtilsTest.java Fri Feb  9 16:55:22 2007
@@ -42,6 +42,27 @@
         { "java.lang.Runnable[][]", "[[Ljava.lang.Runnable;" } };
     }
 
+    @Test(dataProvider = "typeCodeProvider")
+    public void get_type_code(Class input, String expected)
+    {
+        assertEquals(ClassFabUtils.getTypeCode(input), expected);
+    }
+
+    @DataProvider(name = "typeCodeProvider")
+    public Object[][] get_type_code_provider()
+    {
+        return new Object[][]
+        {
+        { int.class, "I" },
+        { int[].class, "[I" },
+        { Thread.class, "Ljava/lang/Thread;" },
+        { Thread[].class, "[Ljava/lang/Thread;" },
+        { Double[][].class, "[[Ljava/lang/Double;" },
+        { void.class, "V" },
+
+        };
+    }
+
     @Test
     public void unwrap_method()
     {