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 2006/09/01 00:49:00 UTC
svn commit: r439080 - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/ main/java/org/apache/tapestry/annotations/
main/java/org/apache/tapestry/internal/
main/java/org/apache/tapestry/internal/ioc/ main/java/org/apache/tap...
Author: hlship
Date: Thu Aug 31 15:48:58 2006
New Revision: 439080
URL: http://svn.apache.org/viewvc?rev=439080&view=rev
Log:
Incomplete start of component parameter support.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ParameterModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ParameterModel.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/services/ClassFabImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java Thu Aug 31 15:48:58 2006
@@ -48,4 +48,10 @@
* Returns the component this object provides resources for.
*/
ComponentLifecycle getComponent();
+
+ /**
+ * Returns true if the component is currently rendering, false otherwise. This is most often
+ * used to determine if parameter values should be cached.
+ */
+ boolean isRendering();
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java?rev=439080&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java Thu Aug 31 15:48:58 2006
@@ -0,0 +1,44 @@
+package org.apache.tapestry.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation placed on a field to indicate that it is, in fact, an parameter. Parameters may be
+ * optional or required. Required parameters must be bound.
+ * <p>
+ * TODO: Do we want to support a notNull as well as required?
+ *
+ * @author Howard M. Lewis Ship
+ */
+@Target(FIELD)
+@Documented
+@Retention(RUNTIME)
+public @interface Parameter {
+
+ /**
+ * The name of the parameter. If not specified, the name of the parameter is derived from the
+ * name of the field (after stripping off leading punctuation) from the field name.
+ */
+ String name() default "";
+
+ /**
+ * If true, the parameter is required and and must be bound. If false (the default), then the
+ * parameter is optional.
+ */
+ boolean required() default false;
+
+ /**
+ * If true (the default), then the value for the parameter is cached while the component is,
+ * itself, rendering. Values from invariant bindings (such as literal strings) are always
+ * cached, regardless of this setting. Set this attribute to false to force the parameter to be
+ * {@link org.apache.tapestry.Binding#get() re-read} every time the field is accessed, even
+ * while the component is rendering.
+ */
+
+ boolean cache() default true;
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java Thu Aug 31 15:48:58 2006
@@ -25,5 +25,30 @@
*/
public interface InternalComponentResources extends ComponentResources
{
+ /** Returns true if the parameter is bound, false if not. */
+ boolean isBound(String parameterName);
+
+ /**
+ * Reads the value of a parameter, via the parameter's {@link org.apache.tapestry.Binding}.
+ *
+ * @param <T>
+ * @param parameterName
+ * the name of the parameter to read
+ * @param expectedType
+ * the expected type of parameter
+ * @return the value for the parameter, or null if the parameter is not bound.
+ */
+ <T> T readParameter(String parameterName, Class<T> expectedType);
+
+ /**
+ * Returns true if the named parameter's {@link org.apache.tapestry.Binding} is invariant, false
+ * if otherwise, or if the parameter is not bound. Invariant bindings are cached more
+ * aggresively than variant bindings.
+ *
+ * @param parameterName
+ * the name of parameter to check for invariance
+ * @return
+ */
+ boolean isInvariant(String parameterName);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java Thu Aug 31 15:48:58 2006
@@ -107,7 +107,7 @@
}
}
- public RegistryImpl(Collection<ModuleDef> moduleDefs, LogSource logSource)
+ public RegistryImpl(Collection<ModuleDef> moduleDefs, ClassLoader contextClassLoader, LogSource logSource)
{
_logSource = logSource;
@@ -124,7 +124,7 @@
Log log = _logSource.getLog(RegistryImpl.CLASS_FACTORY_SERVICE_ID);
- _classFactory = new ClassFactoryImpl(log);
+ _classFactory = new ClassFactoryImpl(contextClassLoader, log);
addBuiltin(RegistryImpl.CLASS_FACTORY_SERVICE_ID, ClassFactory.class, _classFactory);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java Thu Aug 31 15:48:58 2006
@@ -42,11 +42,11 @@
*/
private Set<ClassLoader> _loaders = newSet();
- ClassFactoryClassPool()
+ ClassFactoryClassPool(ClassLoader contextClassLoader)
{
super(null);
- appendClassLoader(Thread.currentThread().getContextClassLoader());
+ appendClassLoader(contextClassLoader);
}
/**
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java Thu Aug 31 15:48:58 2006
@@ -34,17 +34,30 @@
/**
* ClassPool shared by all modules (all CtClassSource instances).
*/
- private ClassFactoryClassPool _pool = new ClassFactoryClassPool();
+ private final ClassFactoryClassPool _pool;
- private CtClassSource _classSource = new CtClassSource(_pool);
+ private final CtClassSource _classSource;
+
+ private final ClassLoader _loader;
+
+ public ClassFactoryImpl(ClassLoader contextClassLoader)
+ {
+ this(contextClassLoader, LogFactory.getLog(ClassFactoryImpl.class));
+ }
public ClassFactoryImpl()
{
- this(LogFactory.getLog(ClassFactoryImpl.class));
+ this(Thread.currentThread().getContextClassLoader());
}
- public ClassFactoryImpl(Log log)
+ public ClassFactoryImpl(ClassLoader contextClassLoader, Log log)
{
+ _loader = contextClassLoader;
+
+ _pool = new ClassFactoryClassPool(contextClassLoader);
+
+ _classSource = new CtClassSource(_pool);
+
_log = log;
}
@@ -78,11 +91,14 @@
}
}
- /** @since 1.1 */
-
public int getCreatedClassCount()
{
return _classSource.getCreatedClassCount();
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return _loader;
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java Thu Aug 31 15:48:58 2006
@@ -14,9 +14,18 @@
package org.apache.tapestry.internal.model;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
import org.apache.commons.logging.Log;
import org.apache.tapestry.Resource;
import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.model.ParameterModel;
+import org.apache.tapestry.util.Defense;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
/**
* Internal implementation of {@link org.apache.tapestry.model.MutableComponentModel}.
@@ -31,6 +40,8 @@
private final Log _log;
+ private Map<String, ParameterModel> _parameters;
+
public MutableComponentModelImpl(String componentClassName, Log log, Resource baseResource)
{
_componentClassName = componentClassName;
@@ -51,6 +62,47 @@
public String getComponentClassName()
{
return _componentClassName;
+ }
+
+ public void addParameter(String name, boolean required)
+ {
+ // TODO: Check for conflict with base model
+
+ if (_parameters == null)
+ _parameters = newMap();
+ else
+ {
+ if (_parameters.containsKey(name))
+ throw new IllegalArgumentException();
+ }
+
+ Defense.notBlank(name, "name");
+
+ _parameters.put(name, new ParameterModelImpl(name, required));
+ }
+
+ public ParameterModel getParameterModel(String parameterName)
+ {
+ // TODO: Parameters defined in base model
+
+ if (_parameters == null)
+ return null;
+
+ return _parameters.get(parameterName);
+ }
+
+ public List<String> getParameterNames()
+ {
+ // TODO: Parameters from base model
+
+ List<String> names = newList();
+
+ if (_parameters != null)
+ names.addAll(_parameters.keySet());
+
+ Collections.sort(names);
+
+ return names;
}
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ParameterModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ParameterModelImpl.java?rev=439080&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ParameterModelImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/ParameterModelImpl.java Thu Aug 31 15:48:58 2006
@@ -0,0 +1,30 @@
+package org.apache.tapestry.internal.model;
+
+import org.apache.tapestry.model.ParameterModel;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class ParameterModelImpl implements ParameterModel
+{
+ private final String _name;
+
+ private final boolean _required;
+
+ public ParameterModelImpl(String name, boolean required)
+ {
+ _name = name;
+ _required = required;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public boolean isRequired()
+ {
+ return _required;
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java Thu Aug 31 15:48:58 2006
@@ -102,12 +102,12 @@
ctClass)
: new InternalClassTransformationImpl(ctClass, parentTransformation);
- // Not all classes in the packages are components.
+ // Not all classes in the packages are components. That's not just sloppy coding by
+ // application developers, it also represents inner classes (including anonymous classes).
if (transformation.getAnnotation(ComponentClass.class) == null)
return;
- // Eventually these will also be cached or published or something.
// TODO: child class model should start as deep copy of parent model?
// Or have pointer to parent model? Or something.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java Thu Aug 31 15:48:58 2006
@@ -70,11 +70,6 @@
return _loader;
}
- public ComponentInstantiatorSourceImpl(ComponentClassTransformer transformer, Log log)
- {
- this(Thread.currentThread().getContextClassLoader(), transformer, log);
- }
-
public ComponentInstantiatorSourceImpl(ClassLoader parent,
ComponentClassTransformer transformer, Log log)
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java Thu Aug 31 15:48:58 2006
@@ -36,6 +36,7 @@
import org.apache.tapestry.ComponentResources;
import org.apache.tapestry.internal.InternalComponentResources;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.internal.util.InternalUtils;
import org.apache.tapestry.runtime.ComponentLifecycle;
import org.apache.tapestry.services.MethodSignature;
import org.apache.tapestry.util.CollectionFactory;
@@ -76,6 +77,8 @@
private Set<String> _addedFieldNames = newSet();
+ private Set<CtMethod> _addedMethods = newSet();
+
// Cache of class annotations
private List<Annotation> _classAnnotations;
@@ -93,8 +96,6 @@
// All field/method names will have this value as a prefix
- private static final String NAME_PREFIX = "_$";
-
private final String _resourcesFieldName;
private final StringBuilder _description = new StringBuilder();
@@ -297,93 +298,11 @@
{
failIfFrozen();
- String memberName = createMemberName(notBlank(suggested, "suggested"));
+ String memberName = InternalUtils.createMemberName(notBlank(suggested, "suggested"));
return _idAllocator.allocateId(memberName);
}
- /** Strips leading characters defined by {@link #NAME_PREFIX}. */
- private String createMemberName(String memberName)
- {
- failIfFrozen();
-
- StringBuilder builder = new StringBuilder(memberName);
-
- // There may be other prefixes we want to strip off, at some point!
-
- // Strip off leading characters defined by NAME_PREFIX
-
- while (true)
- {
- char ch = builder.charAt(0);
-
- if (NAME_PREFIX.indexOf(ch) < 0)
- break;
-
- builder.deleteCharAt(0);
- }
-
- // Insert the name prefix at the start of the string.
-
- builder.insert(0, NAME_PREFIX);
-
- return builder.toString();
- }
-
- // public void addFieldEncapsulation(CtField field, String readMethodName, String
- // writeMethodName)
- // {
- // failIfFrozen();
- //
- // // TODO: Check if field already encapsulated
- //
- // FieldEncapsulation fe = new FieldEncapsulation(readMethodName, writeMethodName);
- //
- // _encapsulations.put(field, fe);
- // }
- //
- // public void applyFieldEncapsulations()
- // {
- // failIfFrozen();
- //
- // ExprEditor editor = new ExprEditor()
- // {
- //
- // @Override
- // public void edit(FieldAccess f) throws CannotCompileException
- // {
- // // Methods added as part of enhancement are NOT subject
- // // to field encapsulation.
- //
- // if (_addedMethods.contains(f.where()))
- // return;
- //
- // try
- // {
- // CtField field = f.getField();
- // FieldEncapsulation fe = _encapsulations.get(field);
- //
- // if (fe != null)
- // fe.encapsulate(f);
- // }
- // catch (NotFoundException ex)
- // {
- // throw new RuntimeException(ex);
- // }
- // }
- //
- // };
- //
- // try
- // {
- // _ctClass.instrument(editor);
- // }
- // catch (CannotCompileException ex)
- // {
- // throw new RuntimeException(ex);
- // }
- // }
-
public void addImplementedInterface(Class interfaceClass)
{
failIfFrozen();
@@ -515,6 +434,58 @@
_claimedFields.put(fieldName, tag);
}
+ public void addMethod(MethodSignature signature, String methodBody)
+ {
+ failIfFrozen();
+
+ CtClass returnType = findCtClass(signature.getReturnType());
+ CtClass[] parameters = buildCtClassList(signature.getParameterTypes());
+ CtClass[] exceptions = buildCtClassList(signature.getExceptionTypes());
+
+ CtMethod method = new CtMethod(returnType, signature.getMethodName(), parameters, _ctClass);
+
+ // TODO: Check for duplicate method add
+
+ try
+ {
+ method.setModifiers(signature.getModifiers());
+ method.setBody(methodBody);
+ method.setExceptionTypes(exceptions);
+
+ _ctClass.addMethod(method);
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+
+ _addedMethods.add(method);
+
+ addMethodToDescription("add", signature, methodBody);
+ }
+
+ private CtClass[] buildCtClassList(String[] typeNames)
+ {
+ CtClass[] result = new CtClass[typeNames.length];
+
+ for (int i = 0; i < typeNames.length; i++)
+ result[i] = findCtClass(typeNames[i]);
+
+ return result;
+ }
+
+ private CtClass findCtClass(String type)
+ {
+ try
+ {
+ return _classPool.get(type);
+ }
+ catch (NotFoundException ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
public void extendMethod(MethodSignature methodSignature, String methodBody)
{
failIfFrozen();
@@ -530,7 +501,14 @@
throw new RuntimeException(ex);
}
- _formatter.format("extend method: %s %s %s(", Modifier.toString(methodSignature
+ addMethodToDescription("extend", methodSignature, methodBody);
+
+ }
+
+ private void addMethodToDescription(String operation, MethodSignature methodSignature,
+ String methodBody)
+ {
+ _formatter.format("%s method: %s %s %s(", operation, Modifier.toString(methodSignature
.getModifiers()), methodSignature.getReturnType(), methodSignature.getMethodName());
String[] parameterTypes = methodSignature.getParameterTypes();
@@ -556,7 +534,6 @@
}
_formatter.format("\n%s\n\n", methodBody);
-
}
private CtMethod findMethod(MethodSignature methodSignature)
@@ -655,6 +632,9 @@
for (CtField field : _ctClass.getDeclaredFields())
{
+ if (!isInstanceField(field))
+ continue;
+
String fieldName = field.getName();
List<Annotation> annotations = findFieldAnnotations(fieldName);
@@ -672,6 +652,8 @@
}
}
+ Collections.sort(result);
+
return result;
}
@@ -876,6 +858,7 @@
}
_formatter.format("add constructor: %s(", _ctClass.getName());
+
for (int i = 0; i < count; i++)
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java Thu Aug 31 15:48:58 2006
@@ -32,10 +32,12 @@
import org.apache.tapestry.ioc.annotations.Lifecycle;
import org.apache.tapestry.ioc.annotations.Match;
import org.apache.tapestry.ioc.annotations.Order;
+import org.apache.tapestry.ioc.services.ClassFactory;
import org.apache.tapestry.ioc.services.LoggingDecorator;
import org.apache.tapestry.ioc.services.ThreadCleanupHub;
import org.apache.tapestry.services.ApplicationInitializer;
import org.apache.tapestry.services.ApplicationInitializerFilter;
+import org.apache.tapestry.services.BindingSource;
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.ComponentClassTransformWorker;
import org.apache.tapestry.services.MarkupWriterFactory;
@@ -89,11 +91,12 @@
}
public ComponentInstantiatorSource buildComponentInstantiatorSource(
- @InjectService("ComponentClassTransformer")
+ @InjectService("tapestry.ioc.ClassFactory")
+ ClassFactory classFactory, @InjectService("ComponentClassTransformer")
ComponentClassTransformer transformer, Log log)
{
- ComponentInstantiatorSourceImpl source = new ComponentInstantiatorSourceImpl(transformer,
- log);
+ ComponentInstantiatorSourceImpl source = new ComponentInstantiatorSourceImpl(classFactory
+ .getClassLoader(), transformer, log);
_updateListenerHub.addUpdateListener(source);
@@ -122,9 +125,13 @@
}
public PageLoader buildPageLoader(@InjectService("PageElementFactory")
- PageElementFactory pageElementFactory)
+ PageElementFactory pageElementFactory,
+
+ @InjectService("tapestry.BindingSource")
+ BindingSource bindingSource)
{
- PageLoaderImpl service = new PageLoaderImpl(_componentTemplateSource, pageElementFactory);
+ PageLoaderImpl service = new PageLoaderImpl(_componentTemplateSource, pageElementFactory,
+ bindingSource);
_componentInstantiatorSource.addInvalidationListener(service);
@@ -157,11 +164,24 @@
return new UpdateListenerHubImpl();
}
+ /**
+ * Adds a number of standard workers:
+ * <ul>
+ * <li>Retain -- allows fields to retain their values between requests</li>
+ * <li>Parameter</li> -- identifies parameters based on the Parameter annotation</li>
+ * <li>UnclaimedField</li> -- identifies unclaimed fields and resets them to null/0/false at
+ * the end of the request</li>
+ * <li>BeforeRender, RenderTag, etc. -- correspond to component render phases and annotations</li>
+ * </ul>
+ *
+ * @param configuration
+ */
@Contribute("tapestry.ComponentClassTransformWorker")
public void contributeInternalWorkers(
OrderedConfiguration<ComponentClassTransformWorker> configuration)
{
configuration.add("Retain", new RetainWorker());
+ configuration.add("Parameter", new ParameterWorker());
configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
// Workers for the component rendering state machine methods; this is in typical
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java Thu Aug 31 15:48:58 2006
@@ -17,8 +17,10 @@
import java.util.List;
import java.util.Locale;
+import org.apache.tapestry.Binding;
import org.apache.tapestry.events.InvalidationEvent;
import org.apache.tapestry.events.InvalidationListener;
+import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.event.InvalidationEventHubImpl;
import org.apache.tapestry.internal.parser.AttributeToken;
import org.apache.tapestry.internal.parser.ComponentTemplate;
@@ -30,6 +32,7 @@
import org.apache.tapestry.internal.structure.Page;
import org.apache.tapestry.internal.structure.PageElement;
import org.apache.tapestry.internal.structure.PageImpl;
+import org.apache.tapestry.services.BindingSource;
import static org.apache.tapestry.util.CollectionFactory.newList;
@@ -45,15 +48,18 @@
private final PageElementFactory _pageElementFactory;
+ private final BindingSource _bindingSource;
+
private Page _page;
private Locale _locale;
public PageLoaderImpl(ComponentTemplateSource templateSource,
- PageElementFactory pageElementFactory)
+ PageElementFactory pageElementFactory, BindingSource bindingSource)
{
_templateSource = templateSource;
_pageElementFactory = pageElementFactory;
+ _bindingSource = bindingSource;
}
/**
@@ -243,7 +249,9 @@
AttributeToken attribute = (AttributeToken) token;
if (directlyInsideSubcomponent)
- activeComponent.addParameter(attribute);
+ {
+ addBindingToComponent(activeComponent, attribute);
+ }
else
add(loadingComponent, activeComponent, _pageElementFactory
.newAttributeElement(attribute));
@@ -255,6 +263,23 @@
}
+ }
+
+ private void addBindingToComponent(ComponentPageElement component, AttributeToken token)
+ {
+ String name = token.getName();
+ String description = "parameter " + name;
+
+ // Default binding prefix inside templates is literal.
+
+ Binding binding = _bindingSource.newBinding(
+ description,
+ component,
+ InternalConstants.LITERAL_BINDING_PREFIX,
+ token.getValue(),
+ token.getLocation());
+
+ component.addParameter(name, binding);
}
private void addRenderBodyElement(ComponentPageElement loadingComponent)
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java?rev=439080&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java Thu Aug 31 15:48:58 2006
@@ -0,0 +1,131 @@
+package org.apache.tapestry.internal.services;
+
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.internal.ioc.IOCUtilities;
+import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.TransformConstants;
+import org.apache.tapestry.util.BodyBuilder;
+
+/**
+ * Responsible for identifying parameters via the {@link org.apache.tapestry.annotations.Parameter}
+ * annotation on component fields.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public class ParameterWorker implements ComponentClassTransformWorker
+{
+
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ List<String> fieldNames = transformation.findFieldsWithAnnotation(Parameter.class);
+
+ for (String name : fieldNames)
+ {
+ Parameter annotation = transformation.getFieldAnnotation(name, Parameter.class);
+
+ model.addParameter(name, annotation.required());
+
+ String parameterName = getParameterName(name, annotation.name());
+
+ String type = transformation.getFieldType(name);
+
+ String cachedFieldName = transformation.addField(Modifier.PRIVATE, "boolean", name
+ + "_cached");
+
+ String invariantFieldName = addParameterSetup(
+ name,
+ parameterName,
+ cachedFieldName,
+ transformation);
+ }
+ }
+
+ /** Returns the name of a field that stores whether the parameter binding is invariant. */
+
+ private String addParameterSetup(String fieldName, String parameterName,
+ String cachedFieldName, ClassTransformation transformation)
+ {
+ String name = transformation
+ .addField(Modifier.PRIVATE, "boolean", fieldName + "_invariant");
+
+ String resourcesFieldName = transformation.getResourcesFieldName();
+
+ String body = String.format(
+ "%s = %s.isInvariant(\"%s\");",
+ name,
+ resourcesFieldName,
+ parameterName);
+
+ transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE, body);
+
+ // Now, when the page detaches, ensure that any variant parameters are
+ // are returned to default value.
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.addln("if (! %s)", name);
+ builder.begin();
+
+ // TODO: Handle primitives
+
+ builder.addln("%s = null;", fieldName);
+ builder.addln("%s = false;", cachedFieldName);
+ builder.end();
+
+ transformation.extendMethod(
+ TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
+ builder.toString());
+
+ return name;
+ }
+
+ private void addCachedReader(String fieldName, String cachedFieldName,
+ String invariantFieldName, boolean cache, String parameterName, String fieldType,
+ ClassTransformation transformation)
+ {
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ builder.addln("if (%s) return %s;", cachedFieldName, fieldName);
+
+ // TODO: Handle primitive types
+
+ String resourcesFieldName = transformation.getResourcesFieldName();
+
+ builder.addln(
+ "%s result = (%1$s) %s.getParameter(\"%s\", %1$s.class);",
+ fieldType,
+ resourcesFieldName,
+ parameterName);
+
+ // If the binding is invariant, then it's ok to cache. Othewise, its only
+ // ok to cache if a) the @Parameter says to cache and b) the component
+ // is rendering at the point when field is accessed.
+
+ builder.add("if (%s", invariantFieldName);
+
+ if (cache)
+ builder.add(" || %s.isRendering()", resourcesFieldName);
+
+ builder.addln(")");
+ builder.begin();
+ builder.addln("%s = result;", fieldName);
+ builder.addln("%s = true;", cachedFieldName);
+ builder.end();
+
+ builder.addln("return result;");
+ }
+
+ private String getParameterName(String fieldName, String annotatedName)
+ {
+ if (IOCUtilities.isNonBlank(annotatedName))
+ return annotatedName;
+
+ return InternalUtils.stripMemberPrefix(fieldName);
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java Thu Aug 31 15:48:58 2006
@@ -14,8 +14,8 @@
package org.apache.tapestry.internal.structure;
+import org.apache.tapestry.Binding;
import org.apache.tapestry.internal.InternalComponentResources;
-import org.apache.tapestry.internal.parser.AttributeToken;
import org.apache.tapestry.runtime.RenderCommand;
import org.apache.tapestry.runtime.RenderQueue;
@@ -54,11 +54,9 @@
void addToBody(PageElement element);
/**
- * Used during construction of the page to identify a parameter of the component that is bound
- * via a template attribute. An error is logged if there is a conflict, or if the attribute
- * doesn't correspond to a parameter of the component.
+ * Used during construction of the page to identify the binding for a particular parameter.
*/
- void addParameter(AttributeToken attribute);
+ void addParameter(String parameterName, Binding binding);
/** Adds a child component to its container. The child's id must be unique within the container. */
void addChild(ComponentPageElement child);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Thu Aug 31 15:48:58 2006
@@ -18,9 +18,9 @@
import java.util.List;
import java.util.Map;
+import org.apache.tapestry.Binding;
import org.apache.tapestry.MarkupWriter;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
-import org.apache.tapestry.internal.parser.AttributeToken;
import org.apache.tapestry.internal.services.Instantiator;
import org.apache.tapestry.model.ComponentModel;
import org.apache.tapestry.runtime.ComponentLifecycle;
@@ -66,10 +66,7 @@
private Map<String, ComponentPageElement> _children;
- // This is likely to change shortly to something more involved; we need to introduce the concept
- // of parameters as well as a component model for the component.
-
- private final Map<String, AttributeToken> _parameters = newMap();
+ private Map<String, Binding> _bindings;
/** Constructor for the root component of a page. */
public ComponentPageElementImpl(Page page, Instantiator instantiator, ComponentModel model)
@@ -173,11 +170,14 @@
_template.add(element);
}
- public void addParameter(AttributeToken attribute)
+ public void addParameter(String parameterName, Binding binding)
{
// TODO: Check for conflicts, etc.
- _parameters.put(attribute.getName(), attribute);
+ if (_bindings == null)
+ _bindings = newMap();
+
+ _bindings.put(parameterName, binding);
}
public void addChild(ComponentPageElement child)
@@ -372,4 +372,33 @@
{
return _component;
}
+
+ private Binding getBinding(String parameterName)
+ {
+ return _bindings == null ? null : _bindings.get(parameterName);
+ }
+
+ public boolean isBound(String parameterName)
+ {
+ return getBinding(parameterName) != null;
+ }
+
+ public boolean isInvariant(String parameterName)
+ {
+ Binding b = getBinding(parameterName);
+
+ return b != null && b.isInvariant();
+ }
+
+ public <T> T readParameter(String parameterName, Class<T> expectedType)
+ {
+ Binding b = getBinding(parameterName);
+
+ // TODO: If binding is null ...
+
+ // TODO: Type coercion when writing value into binding
+
+ return expectedType.cast(b.get());
+ }
+
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/InternalUtils.java Thu Aug 31 15:48:58 2006
@@ -26,6 +26,12 @@
public class InternalUtils
{
/**
+ * Leading punctiation on member names that is stripped off to form a property name or new
+ * member name.
+ */
+ public static final String NAME_PREFIX = "_$";
+
+ /**
* Converts a method to a user presentable string consisting of the containing class name, the
* method name, and the short form of the parameter list (the class name of each parameter type,
* shorn of the package name portion).
@@ -63,4 +69,38 @@
{
return array == null ? 0 : array.length;
}
+
+ /** Strips leading punctuation ("_" and "$") from the provided name. */
+ public static String stripMemberPrefix(String memberName)
+ {
+ StringBuilder builder = new StringBuilder(memberName);
+
+ // There may be other prefixes we want to strip off, at some point!
+
+ // Strip off leading characters defined by NAME_PREFIX
+
+ // This code is really ugly and needs to be fixed.
+
+ while (true)
+ {
+ char ch = builder.charAt(0);
+
+ if (InternalUtils.NAME_PREFIX.indexOf(ch) < 0)
+ break;
+
+ builder.deleteCharAt(0);
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Strips leading characters defined by {@link InternalUtils#NAME_PREFIX}, then adds the prefix
+ * back in.
+ */
+ public static String createMemberName(String memberName)
+ {
+ return NAME_PREFIX + stripMemberPrefix(memberName);
+ }
+
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java Thu Aug 31 15:48:58 2006
@@ -34,7 +34,7 @@
/**
* Used to construct the IoC {@link org.apache.tapestry.ioc.Registry}. This class is <em>not</em>
- * threadsafe. The registry, once created, <em>is</em> threadsafe.
+ * threadsafe. The Registry, once created, <em>is</em> threadsafe.
*
* @author Howard M. Lewis Ship
*/
@@ -120,7 +120,7 @@
@OneShot.Lockdown
public Registry build()
{
- return new RegistryImpl(_modules.values(), _logSource);
+ return new RegistryImpl(_modules.values(), _classLoader, _logSource);
}
public ClassLoader getClassLoader()
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java Thu Aug 31 15:48:58 2006
@@ -51,4 +51,10 @@
*/
int getCreatedClassCount();
+
+ /**
+ * Returns the class loader used when creating new classes; this is generally the same as the
+ * current thread's context class loader (except perhaps during testing).
+ */
+ ClassLoader getClassLoader();
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java Thu Aug 31 15:48:58 2006
@@ -14,6 +14,8 @@
package org.apache.tapestry.model;
+import java.util.List;
+
import org.apache.commons.logging.Log;
import org.apache.tapestry.Resource;
@@ -40,4 +42,14 @@
/** Returns object that will be used to log warnings and errors related to this component. */
Log getLog();
+
+ /**
+ * Returns an alphabetically sorted list of the names of all formal parameters. This includes
+ * parameters defined by a base class.
+ */
+
+ List<String> getParameterNames();
+
+ /** Return a single parameter model by parameter name, or null if the parameter is not defined. */
+ ParameterModel getParameterModel(String parameterName);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/MutableComponentModel.java Thu Aug 31 15:48:58 2006
@@ -22,5 +22,15 @@
*/
public interface MutableComponentModel extends ComponentModel
{
-
+ /**
+ * Adds a new parameter to the model.
+ *
+ * @param name
+ * new, unique name for the parameter
+ * @param required
+ * if true, the parameter must be bound
+ * @throws IllegalArgumentException
+ * if a parameter with the given name has already been defined for this model
+ */
+ void addParameter(String name, boolean required);
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ParameterModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ParameterModel.java?rev=439080&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ParameterModel.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ParameterModel.java Thu Aug 31 15:48:58 2006
@@ -0,0 +1,15 @@
+package org.apache.tapestry.model;
+
+/**
+ * Model for a parameter of a component.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public interface ParameterModel
+{
+ /** The name of the parameter. */
+ String getName();
+
+ /** If true, the parameter is required. */
+ boolean isRequired();
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/ComponentLifecycle.java Thu Aug 31 15:48:58 2006
@@ -21,7 +21,6 @@
* the component for many different events. This interface is part of the public API for Tapestry,
* but is <em>not</em> expected to be directly implemented by component classes; it should only be
* implemented as part of the component class transformation process.
- *
* <p>
* This interface is likely to change without notice.
*
@@ -30,7 +29,8 @@
public interface ComponentLifecycle extends ResourceAware
{
/**
- * Invoked when the page finishes loading (including the loading of all components).
+ * Invoked when the page finishes loading. This occurs once all components are loaded and all
+ * parameters have been set.
*/
void containingPageDidLoad();
@@ -39,6 +39,14 @@
* client specific state.
*/
void containingPageDidDetach();
+
+ /**
+ * Lifecycle method invoked at the end of the
+ * {@link org.apache.tapestry.annotations.AfterRender} render phase. There is no annotation for
+ * this method, it is part of AfterRender, but is always invoked. It's specific use to to allow
+ * components to clean up cached parameter values.
+ */
+ void cleanupAfterRender();
/**
* Invoked before rendering a component (or its template).
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java Thu Aug 31 15:48:58 2006
@@ -56,6 +56,7 @@
/**
* Generates a list of the names of declared instance fields that have the indicated annotation.
+ * Only the names of private instance fields are returned.
*/
List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass);
@@ -184,8 +185,19 @@
* @param methodBody
* the body of code
* @throws IllegalArgumentException
- * if the method body does not include a call to $proceed, or if the provided
- * Javassist method body can not be compiled
+ * if the provided Javassist method body can not be compiled
*/
void extendMethod(MethodSignature methodSignature, String methodBody);
+
+ /**
+ * Returns the name of a field that provides the {@link org.apache.tapestry.ComponentResources}
+ * for the transformed component. This will be a protected field, accessible to the class and
+ * subclasses.
+ *
+ * @return name of field
+ */
+ String getResourcesFieldName();
+
+ /** Adds a new method to the transformed class. */
+ void addMethod(MethodSignature signature, String methodBody);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java Thu Aug 31 15:48:58 2006
@@ -38,6 +38,10 @@
public static final MethodSignature CONTAINING_PAGE_DID_LOAD_SIGNATURE = new MethodSignature(
"containingPageDidLoad");
+ /** Signature for {@link org.apache.tapestry.runtime.ComponentLifecycle#cleanupAfterRender()}. */
+ public static final MethodSignature CLEANUP_AFTER_RENDER_SIGNATURE = new MethodSignature(
+ "cleanupAfterRender");
+
/**
* Signature for
* {@link org.apache.tapestry.runtime.ComponentLifecycle#containingPageDidDetach()}.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Thu Aug 31 15:48:58 2006
@@ -33,6 +33,7 @@
<package name="org.apache.tapestry.util"/>
<package name="org.apache.tapestry.runtime"/>
<package name="org.apache.tapestry.internal.bindings"/>
+ <package name="org.apache.tapestry.internal.model"/>
</packages>
</test>
</suite>
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/services/ClassFabImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/services/ClassFabImplTest.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/services/ClassFabImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/services/ClassFabImplTest.java Thu Aug 31 15:48:58 2006
@@ -59,7 +59,7 @@
{
ClassLoader threadLoader = Thread.currentThread().getContextClassLoader();
- ClassFactoryClassPool pool = new ClassFactoryClassPool();
+ ClassFactoryClassPool pool = new ClassFactoryClassPool(threadLoader);
pool.appendClassLoader(threadLoader);
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java?rev=439080&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java Thu Aug 31 15:48:58 2006
@@ -0,0 +1,72 @@
+package org.apache.tapestry.internal.model;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.Resource;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.model.ParameterModel;
+import org.testng.annotations.Test;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class MutableComponentModelImplTest extends InternalBaseTestCase
+{
+ private static final String CLASS_NAME = "org.example.components.Foo";
+
+ @Test
+ public void add_new_parameter()
+ {
+ Resource r = newResource();
+ Log log = newLog();
+
+ replay();
+
+ MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+
+ assertTrue(model.getParameterNames().isEmpty());
+
+ String parameterName = "value";
+
+ model.addParameter(parameterName, true);
+
+ ParameterModel pm = model.getParameterModel(parameterName);
+
+ assertEquals(pm.getName(), parameterName);
+ assertEquals(true, pm.isRequired());
+
+ verify();
+ }
+
+ @Test
+ public void get_parameter_by_name_with_no_parameters_defined()
+ {
+ Resource r = newResource();
+ Log log = newLog();
+
+ replay();
+
+ MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+
+ assertNull(model.getParameterModel("foo"));
+
+ verify();
+ }
+
+ @Test
+ public void get_unknown_parameter()
+ {
+
+ Resource r = newResource();
+ Log log = newLog();
+
+ replay();
+
+ MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+ model.addParameter("fred", true);
+
+ assertNull(model.getParameterModel("barney"));
+
+ verify();
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java Thu Aug 31 15:48:58 2006
@@ -30,7 +30,7 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.internal.InternalComponentResources;
-import org.apache.tapestry.internal.ioc.services.PropertyAccessImpl;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
import org.apache.tapestry.internal.transform.pages.BasicComponent;
import org.apache.tapestry.internal.transform.pages.BasicSubComponent;
import org.apache.tapestry.ioc.Registry;
@@ -38,8 +38,6 @@
import org.apache.tapestry.ioc.services.PropertyAccess;
import org.apache.tapestry.runtime.ComponentLifecycle;
import org.apache.tapestry.services.TapestryModule;
-import org.apache.tapestry.test.BaseTestCase;
-import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -51,8 +49,11 @@
*
* @author Howard M. Lewis Ship
*/
-public class ComponentInstantiatorSourceImplTest extends BaseTestCase
+public class ComponentInstantiatorSourceImplTest extends InternalBaseTestCase
{
+ private static final ClassLoader _contextLoader = Thread.currentThread()
+ .getContextClassLoader();
+
private static final String SYNTH_COMPONENT_CLASSNAME = "org.apache.tapestry.internal.transform.pages.SynthComponent";
private File _extraClasspath;
@@ -61,10 +62,9 @@
private Registry _registry;
- private final ClassLoader _originalContextClassLoader = Thread.currentThread()
- .getContextClassLoader();
+ private PropertyAccess _access;
- private final PropertyAccess _access = new PropertyAccessImpl();
+ private ClassLoader _extraLoader;
@Test
public void controlled_packages() throws Exception
@@ -74,7 +74,8 @@
replay();
- ComponentInstantiatorSourceImpl e = new ComponentInstantiatorSourceImpl(transformer, log);
+ ComponentInstantiatorSourceImpl e = new ComponentInstantiatorSourceImpl(_contextLoader,
+ transformer, log);
assertEquals(e.inControlledPackage("foo.bar.Baz"), false);
@@ -106,7 +107,7 @@
ComponentLifecycle target = createComponent(BasicComponent.class);
// Should not be an instance, since it is loaded by a different class loader.
- Assert.assertFalse(BasicComponent.class.isInstance(target));
+ assertFalse(BasicComponent.class.isInstance(target));
_access.set(target, "value", "some default value");
assertEquals(_access.get(target, "value"), "some default value");
@@ -159,7 +160,8 @@
assertEquals(named.getName(), "Original");
// Sometimes this code runs so fast that the updated file has the same timestamp as
- // the original; this little blip seems to help.
+ // the original; this little blip seems to help. Fortunately, we now run tests in
+ // parallel.
Thread.sleep(250);
@@ -186,7 +188,7 @@
ClassPool pool = new ClassPool();
// Inside Maven Surefire, the system classpath is not sufficient to find all
// the necessary files.
- pool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
+ pool.appendClassPath(new LoaderClassPath(_extraLoader));
CtClass ctClass = pool.makeClass(SYNTH_COMPONENT_CLASSNAME);
@@ -243,18 +245,16 @@
URL url = _extraClasspath.toURL();
- ClassLoader extraLoader = new URLClassLoader(new URL[]
- { url }, _originalContextClassLoader);
-
- Thread.currentThread().setContextClassLoader(extraLoader);
-
- RegistryBuilder builder = new RegistryBuilder();
+ _extraLoader = new URLClassLoader(new URL[]
+ { url }, _contextLoader);
+ RegistryBuilder builder = new RegistryBuilder(_extraLoader);
builder.add(TapestryModule.class, InternalModule.class);
_registry = builder.build();
_source = _registry.getService(ComponentInstantiatorSource.class);
+ _access = _registry.getService(PropertyAccess.class);
_source.addPackage("org.apache.tapestry.internal.transform.pages");
}
@@ -262,16 +262,10 @@
@AfterClass
public void shutdownRegistry()
{
- // _registry.shutdown();
+ _registry.shutdown();
_registry = null;
_source = null;
-
- Thread.currentThread().setContextClassLoader(_originalContextClassLoader);
- }
-
- protected final InternalComponentResources newInternalComponentResources()
- {
- return newMock(InternalComponentResources.class);
+ _access = null;
}
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java?rev=439080&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java Thu Aug 31 15:48:58 2006
@@ -0,0 +1,107 @@
+package org.apache.tapestry.internal.structure;
+
+import org.apache.tapestry.Binding;
+import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.services.Instantiator;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.model.ComponentModel;
+import org.apache.tapestry.runtime.ComponentLifecycle;
+import org.easymock.EasyMock;
+import org.testng.annotations.Test;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class ComponentPageElementImplTest extends InternalBaseTestCase
+{
+ @Test
+ public void is_bound()
+ {
+ Page page = newPage();
+ ComponentLifecycle component = newComponentLifecycle();
+ Instantiator ins = newInstantiator(component);
+ ComponentModel model = newComponentModel();
+
+ Binding binding = newBinding();
+
+ replay();
+
+ ComponentPageElement cpe = new ComponentPageElementImpl(page, ins, model);
+
+ assertFalse(cpe.isBound("fred"));
+
+ cpe.addParameter("barney", binding);
+
+ assertFalse(cpe.isBound("fred"));
+ assertTrue(cpe.isBound("barney"));
+
+ verify();
+ }
+
+ @Test
+ public void is_invariant()
+ {
+ Page page = newPage();
+ ComponentLifecycle component = newComponentLifecycle();
+ Instantiator ins = newInstantiator(component);
+ ComponentModel model = newComponentModel();
+
+ Binding binding = newBinding();
+
+ binding.isInvariant();
+ setReturnValue(true);
+
+ replay();
+
+ ComponentPageElement cpe = new ComponentPageElementImpl(page, ins, model);
+
+ assertFalse(cpe.isInvariant("fred"));
+
+ cpe.addParameter("barney", binding);
+
+ assertFalse(cpe.isInvariant("fred"));
+ assertTrue(cpe.isInvariant("barney"));
+
+ verify();
+ }
+
+ @Test
+ public void read_binding()
+ {
+ Page page = newPage();
+ ComponentLifecycle component = newComponentLifecycle();
+ Instantiator ins = newInstantiator(component);
+ ComponentModel model = newComponentModel();
+
+ Binding binding = newBinding();
+
+ binding.get();
+ setReturnValue(new Long(23));
+
+ replay();
+
+ ComponentPageElement cpe = new ComponentPageElementImpl(page, ins, model);
+
+ cpe.addParameter("barney", binding);
+
+ assertEquals(cpe.readParameter("barney", Long.class), new Long(23));
+
+ verify();
+ }
+
+ protected final ComponentModel newComponentModel()
+ {
+ return newMock(ComponentModel.class);
+ }
+
+ private Instantiator newInstantiator(ComponentLifecycle component)
+ {
+ Instantiator ins = newMock(Instantiator.class);
+ ins.newInstance(EasyMock.isA(InternalComponentResources.class));
+
+ setReturnValue(component);
+
+ return ins;
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/ParentClass.java Thu Aug 31 15:48:58 2006
@@ -33,8 +33,14 @@
public String _$conflictField;
@Retain
- public boolean _annotatedField;
+ private boolean _annotatedField;
+ @Retain
+ public String _public_field_annotation_ignored;
+
+ @Retain
+ private static String _static_field_annotation_ignored;
+
public void doNothingParentMethod()
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java?rev=439080&r1=439079&r2=439080&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java Thu Aug 31 15:48:58 2006
@@ -22,6 +22,7 @@
import java.util.Comparator;
import java.util.List;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
@@ -84,4 +85,22 @@
assertEquals(InternalUtils.size(array), 3);
}
+
+ @Test(dataProvider = "memberPrefixData")
+ public void strip_member_prefix(String input, String expected)
+ {
+ assertEquals(InternalUtils.stripMemberPrefix(input), expected);
+ }
+
+ @DataProvider(name = "memberPrefixData")
+ public Object[][] memberPrefixData()
+ {
+ return new Object[][]
+ {
+ { "simple", "simple" },
+ { "_name", "name" },
+ { "$name", "name" },
+ { "$_$__$__$_$___$_$_$_$$name$", "name$" } };
+ }
+
}