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()
{