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/12/30 02:08:41 UTC
svn commit: r491145 - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/ main/java/org/apache/tapestry/annotations/
main/java/org/apache/tapestry/internal/bindings/
main/java/org/apache/tapestry/internal/services/ main/java/...
Author: hlship
Date: Fri Dec 29 17:08:39 2006
New Revision: 491145
URL: http://svn.apache.org/viewvc?view=rev&rev=491145
Log:
Support a value() attribute in the Parameter annotation, the default binding expression for the parameter if otherwise unbound
Added:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html
Removed:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java
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/bindings/PropBindingFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.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/ParameterWorker.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/runtime/PageLifecycleListener.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.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/ValidationTracker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTracker.java Fri Dec 29 17:08:39 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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;
import java.util.List;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImpl.java Fri Dec 29 17:08:39 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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;
import java.io.Serializable;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationTrackerImplTest.java Fri Dec 29 17:08:39 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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;
import java.io.ByteArrayInputStream;
Modified: 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?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Parameter.java Fri Dec 29 17:08:39 2006
@@ -12,47 +12,49 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * 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?
- *
- *
- */
-@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.services.Binding#get() re-read} every time the field is accessed, even
- * while the component is rendering.
- */
-
- boolean cache() default true;
-}
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * 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.
+ */
+@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.services.Binding#get() re-read} every time the field is accessed,
+ * even while the component is rendering.
+ */
+
+ boolean cache() default true;
+
+ /**
+ * The default value for the parameter if not bound (at not the empty string). This is a binding
+ * expression, typically the name of a property of the component to bind.
+ */
+ String value() default "";
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java Fri Dec 29 17:08:39 2006
@@ -133,7 +133,7 @@
private BindingConstructor createConstructor(String key, Class targetClass, String propertyPath)
{
- // Race condition: simulataneous calls to fillCache() for the same targetClass/propertyName
+ // Race condition: simulataneous calls to createConstructor() for the same targetClass/propertyName
// combination may result in duplicate binding classes being created, which causes no great
// harm.
@@ -178,7 +178,7 @@
if (adapter == null)
throw new RuntimeException(BindingsMessages.noSuchProperty(
- targetClass,
+ step,
terminalName,
propertyPath));
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java Fri Dec 29 17:08:39 2006
@@ -12,60 +12,60 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
-import org.apache.tapestry.internal.event.InvalidationEventHub;
-
-/**
- * Creates {@link org.apache.tapestry.internal.services.Instantiator}s for components, based on
- * component class name. This will involve transforming the component's class before it is loaded.
- * <p>
- * In addition, a source acts as an event hub for
- * {@link org.apache.tapestry.events.InvalidationListener}s, so that any information derived from
- * loaded classes can be discarded and rebuilt when classes change.
- * <p>
- * The strategy used is that when <em>any</em> class (in a controlled package) changes, the entire
- * class loader is discarded, along with any instances derived from those classes. A new class
- * loader is created, and then invalidation events are fired to listeners.
- */
-public interface ComponentInstantiatorSource extends InvalidationEventHub
-{
-
- /**
- * Given the name of a component class, provides an instantiator for that component.
- * Instantiators are cached, so repeated calls to this method with the same class name will
- * return the same instance; however, callers should also be aware that the instantiators may
- * lose validity after an invalidation (caused by changes to external Java class files).
- *
- * @param classname
- * FQCN to find (and perhaps transform and load)
- * @return an object which can instantiate an instance of the component
- */
- Instantiator findInstantiator(String classname);
-
- /**
- * Adds a controlled package. Only classes within controlled packages are subject to
- * transformation.
- *
- * @param packageName
- * the package name to add (must not be blank)
- */
- void addPackage(String packageName);
-
- /**
- * Checks to see if a fully qualfied class name exists.
- *
- * @param className
- * name of class to check
- * @return true if the class exists (there's a ".class" file), false otherwise
- */
- boolean exists(String className);
-
- /**
- * Returns a class loader with visibility to the transformed classes. Caution: callers of this
- * should also listen for invalidation events and re-acquire the class loader after an
- * invalidation.
- */
-
- ClassLoader getClassLoader();
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.internal.event.InvalidationEventHub;
+import org.apache.tapestry.ioc.services.ClassFactory;
+
+/**
+ * Creates {@link org.apache.tapestry.internal.services.Instantiator}s for components, based on
+ * component class name. This will involve transforming the component's class before it is loaded.
+ * <p>
+ * In addition, a source acts as an event hub for
+ * {@link org.apache.tapestry.events.InvalidationListener}s, so that any information derived from
+ * loaded classes can be discarded and rebuilt when classes change.
+ * <p>
+ * The strategy used is that when <em>any</em> class (in a controlled package) changes, the entire
+ * class loader is discarded, along with any instances derived from those classes. A new class
+ * loader is created, and then invalidation events are fired to listeners.
+ */
+public interface ComponentInstantiatorSource extends InvalidationEventHub
+{
+
+ /**
+ * Given the name of a component class, provides an instantiator for that component.
+ * Instantiators are cached, so repeated calls to this method with the same class name will
+ * return the same instance; however, callers should also be aware that the instantiators may
+ * lose validity after an invalidation (caused by changes to external Java class files).
+ *
+ * @param classname
+ * FQCN to find (and perhaps transform and load)
+ * @return an object which can instantiate an instance of the component
+ */
+ Instantiator findInstantiator(String classname);
+
+ /**
+ * Adds a controlled package. Only classes within controlled packages are subject to
+ * transformation.
+ *
+ * @param packageName
+ * the package name to add (must not be blank)
+ */
+ void addPackage(String packageName);
+
+ /**
+ * Checks to see if a fully qualfied class name exists.
+ *
+ * @param className
+ * name of class to check
+ * @return true if the class exists (there's a ".class" file), false otherwise
+ */
+ boolean exists(String className);
+
+ /**
+ * Returns a class factory that can be used to generate additional classes around enhanced
+ * classes, or create subclasses of enhanced classes.
+ */
+ ClassFactory getClassFactory();
+
}
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?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- 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 Fri Dec 29 17:08:39 2006
@@ -34,7 +34,10 @@
import org.apache.tapestry.events.UpdateListener;
import org.apache.tapestry.internal.event.InvalidationEventHubImpl;
import org.apache.tapestry.internal.util.URLChangeTracker;
+import org.apache.tapestry.ioc.internal.services.ClassFactoryClassPool;
+import org.apache.tapestry.ioc.internal.services.ClassFactoryImpl;
import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.ClassFactory;
/**
* A wrapper around a Javassist class loader that allows certain classes to be modified as they are
@@ -49,7 +52,7 @@
private final ClassLoader _parent;
- private ClassPool _classPool;
+ private ClassFactoryClassPool _classPool;
private Loader _loader;
@@ -57,6 +60,8 @@
private final Log _log;
+ private ClassFactory _classFactory;
+
/** Map from class name to Instantiator. */
private final Map<String, Instantiator> _instantiatorMap = newMap();
@@ -90,12 +95,6 @@
initializeService();
}
- /** @return the class loader used when loading enhanced/modified classes */
- public ClassLoader getClassLoader()
- {
- return _loader;
- }
-
public synchronized void checkForUpdates()
{
if (!_changeTracker.containsChanges())
@@ -121,13 +120,13 @@
*/
private void initializeService()
{
- _classPool = new ClassPool();
+ _classPool = new ClassFactoryClassPool(_parent);
- ClassPath path = new LoaderClassPath(_parent);
+ _loader = new PackageAwareLoader(_parent, _classPool);
- _classPool.appendClassPath(path);
+ ClassPath path = new LoaderClassPath(_loader);
- _loader = new PackageAwareLoader(_parent, _classPool);
+ _classPool.appendClassPath(path);
try
{
@@ -137,6 +136,8 @@
{
throw new RuntimeException(ex);
}
+
+ _classFactory = new ClassFactoryImpl(_classPool.getLoader(), _classPool, _log);
}
// This is called from well within a synchronized block.
@@ -276,5 +277,10 @@
String path = className.replace(".", "/") + ".class";
return _parent.getResource(path) != null;
+ }
+
+ public ClassFactory getClassFactory()
+ {
+ return _classFactory;
}
}
Modified: 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?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ParameterWorker.java Fri Dec 29 17:08:39 2006
@@ -12,245 +12,275 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
-import java.lang.reflect.Modifier;
-import java.util.List;
-
-import org.apache.tapestry.annotations.Parameter;
+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.InternalConstants;
import org.apache.tapestry.ioc.internal.util.InternalUtils;
import org.apache.tapestry.ioc.util.BodyBuilder;
-import org.apache.tapestry.model.MutableComponentModel;
-import org.apache.tapestry.services.ClassTransformation;
-import org.apache.tapestry.services.ComponentClassTransformWorker;
-import org.apache.tapestry.services.MethodSignature;
-import org.apache.tapestry.services.TransformConstants;
-import org.apache.tapestry.services.TransformUtils;
-
-/**
- * Responsible for identifying parameters via the {@link org.apache.tapestry.annotations.Parameter}
- * annotation on component fields. This is one of the most complex of the transformations.
- *
- *
- */
-public class ParameterWorker implements ComponentClassTransformWorker
-{
- public void transform(ClassTransformation transformation, MutableComponentModel model)
- {
- List<String> fieldNames = transformation.findFieldsWithAnnotation(Parameter.class);
-
- for (String name : fieldNames)
- {
- convertFieldIntoParameter(name, transformation, model);
- }
- }
-
- private void convertFieldIntoParameter(String name, ClassTransformation transformation,
- MutableComponentModel model)
- {
- Parameter annotation = transformation.getFieldAnnotation(name, Parameter.class);
-
- String parameterName = getParameterName(name, annotation.name());
-
- model.addParameter(parameterName, annotation.required());
-
- String type = transformation.getFieldType(name);
-
- boolean cache = annotation.cache();
-
- String cachedFieldName = transformation.addField(Modifier.PRIVATE, "boolean", name
- + "_cached");
-
- String resourcesFieldName = transformation.getResourcesFieldName();
-
- String invariantFieldName = addParameterSetup(
- name,
- parameterName,
- cachedFieldName,
- cache,
- type,
- resourcesFieldName,
- transformation);
-
- addReaderMethod(
- name,
- cachedFieldName,
- invariantFieldName,
- cache,
- parameterName,
- type,
- resourcesFieldName,
- transformation);
-
- addWriterMethod(
- name,
- cachedFieldName,
- cache,
- parameterName,
- type,
- resourcesFieldName,
- transformation);
-
- transformation.claimField(name, annotation);
- }
-
- /** Returns the name of a field that stores whether the parameter binding is invariant. */
-
- private String addParameterSetup(String fieldName, String parameterName,
- String cachedFieldName, boolean cache, String fieldType, String resourcesFieldName,
- ClassTransformation transformation)
- {
- String defaultFieldName = transformation.addField(Modifier.PRIVATE, fieldType, fieldName
- + "_default");
-
- String invariantFieldName = transformation.addField(Modifier.PRIVATE, "boolean", fieldName
- + "_invariant");
-
- BodyBuilder builder = new BodyBuilder();
- builder.begin();
- builder.addln(
- "%s = %s.isInvariant(\"%s\");",
- invariantFieldName,
- resourcesFieldName,
- parameterName);
-
- // Store the current value of the field into the default field. This value will
- // be used to reset the field after rendering.
-
- builder.addln("%s = %s;", defaultFieldName, fieldName);
- builder.end();
-
- transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
- .toString());
-
- // Now, when the component completes rendering, ensure that any variant parameters are
- // are returned to default value. This isn't necessary when the parameter is not cached,
- // because (unless the binding is invariant), there's no value to get rid of (and if it is
- // invariant, there's no need to get rid of it).
-
- if (cache)
- {
- builder.clear();
-
- builder.addln("if (! %s)", invariantFieldName);
- builder.begin();
- builder.addln("%s = %s;", fieldName, defaultFieldName);
- builder.addln("%s = false;", cachedFieldName);
- builder.end();
-
- transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, builder
- .toString());
- }
-
- return invariantFieldName;
- }
-
- private void addWriterMethod(String fieldName, String cachedFieldName, boolean cache,
- String parameterName, String fieldType, String resourcesFieldName,
- ClassTransformation transformation)
- {
- BodyBuilder builder = new BodyBuilder();
- builder.begin();
-
- // Before the component is loaded, updating the property sets the default value
- // for the parameter. The value is stored in the field, but will be
- // rolled into default field inside containingPageDidLoad().
-
- builder.addln("if (! %s.isLoaded())", resourcesFieldName);
- builder.begin();
- builder.addln("%s = $1;", fieldName);
- builder.addln("return;");
- builder.end();
-
- // Always start by updating the parameter; this will implicitly check for
- // read-only or unbound parameters. $1 is the single parameter
- // to the method.
-
- builder.addln("if (%s.isBound(\"%s\"))", resourcesFieldName, parameterName);
- builder.addln(" %s.writeParameter(\"%s\", ($w)$1);", resourcesFieldName, parameterName);
-
- builder.addln("%s = $1;", fieldName);
-
- if (cache)
- builder.addln("%s = %s.isRendering();", cachedFieldName, resourcesFieldName);
-
- builder.end();
-
- String methodName = transformation.newMemberName("_update_parameter_" + parameterName);
-
- MethodSignature signature = new MethodSignature(Modifier.PRIVATE, "void", methodName,
- new String[]
- { fieldType }, null);
-
- transformation.addMethod(signature, builder.toString());
-
- transformation.replaceWriteAccess(fieldName, methodName);
- }
-
- /** Adds a private method that will be the replacement for read-access to the field. */
- private void addReaderMethod(String fieldName, String cachedFieldName,
- String invariantFieldName, boolean cache, String parameterName, String fieldType,
- String resourcesFieldName, ClassTransformation transformation)
- {
- BodyBuilder builder = new BodyBuilder();
- builder.begin();
-
- // While the component is still loading, or when the value for the component is cached,
- // or if the value is not bound, then return the current value of the field.
-
- builder.addln(
- "if (%s || ! %s.isLoaded() || ! %<s.isBound(\"%s\")) return %s;",
- cachedFieldName,
- resourcesFieldName,
- parameterName,
- fieldName);
-
- String cast = TransformUtils.getWrapperTypeName(fieldType);
-
- // The ($r) cast will convert the result to the method return type; generally
- // this does nothing. but for primitive types, it will unwrap
- // the wrapper type back to a primitive.
-
- builder.addln(
- "%s result = ($r) ((%s) %s.readParameter(\"%s\", $type));",
- fieldType,
- cast,
- 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;");
- builder.end();
-
- String methodName = transformation.newMemberName("_read_parameter_" + parameterName);
-
- MethodSignature signature = new MethodSignature(Modifier.PRIVATE, fieldType, methodName,
- null, null);
-
- transformation.addMethod(signature, builder.toString());
-
- transformation.replaceReadAccess(fieldName, methodName);
- }
-
- private String getParameterName(String fieldName, String annotatedName)
- {
- if (InternalUtils.isNonBlank(annotatedName))
- return annotatedName;
-
- return InternalUtils.stripMemberPrefix(fieldName);
- }
-}
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.BindingSource;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.TransformConstants;
+import org.apache.tapestry.services.TransformUtils;
+
+/**
+ * Responsible for identifying parameters via the {@link org.apache.tapestry.annotations.Parameter}
+ * annotation on component fields. This is one of the most complex of the transformations.
+ */
+public class ParameterWorker implements ComponentClassTransformWorker
+{
+ private final BindingSource _bindingSource;
+
+ public ParameterWorker(BindingSource bindingSource)
+ {
+ _bindingSource = bindingSource;
+ }
+
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ List<String> fieldNames = transformation.findFieldsWithAnnotation(Parameter.class);
+
+ for (String name : fieldNames)
+ {
+ convertFieldIntoParameter(name, transformation, model);
+ }
+ }
+
+ private void convertFieldIntoParameter(String name, ClassTransformation transformation,
+ MutableComponentModel model)
+ {
+ Parameter annotation = transformation.getFieldAnnotation(name, Parameter.class);
+
+ String parameterName = getParameterName(name, annotation.name());
+
+ model.addParameter(parameterName, annotation.required());
+
+ String type = transformation.getFieldType(name);
+
+ boolean cache = annotation.cache();
+
+ String cachedFieldName = transformation.addField(Modifier.PRIVATE, "boolean", name
+ + "_cached");
+
+ String resourcesFieldName = transformation.getResourcesFieldName();
+
+ String invariantFieldName = addParameterSetup(
+ name,
+ annotation.value(),
+ parameterName,
+ cachedFieldName,
+ cache,
+ type,
+ resourcesFieldName,
+ transformation);
+
+ addReaderMethod(
+ name,
+ cachedFieldName,
+ invariantFieldName,
+ cache,
+ parameterName,
+ type,
+ resourcesFieldName,
+ transformation);
+
+ addWriterMethod(
+ name,
+ cachedFieldName,
+ cache,
+ parameterName,
+ type,
+ resourcesFieldName,
+ transformation);
+
+ transformation.claimField(name, annotation);
+ }
+
+ /**
+ * Returns the name of a field that stores whether the parameter binding is invariant.
+ */
+ private String addParameterSetup(String fieldName, String defaultBinding, String parameterName,
+ String cachedFieldName, boolean cache, String fieldType, String resourcesFieldName,
+ ClassTransformation transformation)
+ {
+ String defaultFieldName = transformation.addField(Modifier.PRIVATE, fieldType, fieldName
+ + "_default");
+
+ String invariantFieldName = transformation.addField(Modifier.PRIVATE, "boolean", fieldName
+ + "_invariant");
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ if (InternalUtils.isNonBlank(defaultBinding))
+ {
+ builder.addln("if (! %s.isBound(\"%s\"))", resourcesFieldName, parameterName);
+
+ String bindingFactoryFieldName = transformation.addInjectedField(
+ BindingSource.class,
+ "bindingSource",
+ _bindingSource);
+
+ builder
+ .addln(
+ " %s.addParameter(\"%s\", %s.newBinding(\"default %2$s\", %1$s, %1$s, \"%s\", \"%s\", null));",
+ resourcesFieldName,
+ parameterName,
+ bindingFactoryFieldName,
+ InternalConstants.PROP_BINDING_PREFIX,
+ defaultBinding);
+
+ }
+
+ builder.addln(
+ "%s = %s.isInvariant(\"%s\");",
+ invariantFieldName,
+ resourcesFieldName,
+ parameterName);
+
+ // Store the current value of the field into the default field. This value will
+ // be used to reset the field after rendering.
+
+ builder.addln("%s = %s;", defaultFieldName, fieldName);
+ builder.end();
+
+ transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
+ .toString());
+
+ // Now, when the component completes rendering, ensure that any variant parameters are
+ // are returned to default value. This isn't necessary when the parameter is not cached,
+ // because (unless the binding is invariant), there's no value to get rid of (and if it is
+ // invariant, there's no need to get rid of it).
+
+ if (cache)
+ {
+ builder.clear();
+
+ builder.addln("if (! %s)", invariantFieldName);
+ builder.begin();
+ builder.addln("%s = %s;", fieldName, defaultFieldName);
+ builder.addln("%s = false;", cachedFieldName);
+ builder.end();
+
+ transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, builder
+ .toString());
+ }
+
+ return invariantFieldName;
+ }
+
+ private void addWriterMethod(String fieldName, String cachedFieldName, boolean cache,
+ String parameterName, String fieldType, String resourcesFieldName,
+ ClassTransformation transformation)
+ {
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ // Before the component is loaded, updating the property sets the default value
+ // for the parameter. The value is stored in the field, but will be
+ // rolled into default field inside containingPageDidLoad().
+
+ builder.addln("if (! %s.isLoaded())", resourcesFieldName);
+ builder.begin();
+ builder.addln("%s = $1;", fieldName);
+ builder.addln("return;");
+ builder.end();
+
+ // Always start by updating the parameter; this will implicitly check for
+ // read-only or unbound parameters. $1 is the single parameter
+ // to the method.
+
+ builder.addln("if (%s.isBound(\"%s\"))", resourcesFieldName, parameterName);
+ builder.addln(" %s.writeParameter(\"%s\", ($w)$1);", resourcesFieldName, parameterName);
+
+ builder.addln("%s = $1;", fieldName);
+
+ if (cache)
+ builder.addln("%s = %s.isRendering();", cachedFieldName, resourcesFieldName);
+
+ builder.end();
+
+ String methodName = transformation.newMemberName("_update_parameter_" + parameterName);
+
+ MethodSignature signature = new MethodSignature(Modifier.PRIVATE, "void", methodName,
+ new String[]
+ { fieldType }, null);
+
+ transformation.addMethod(signature, builder.toString());
+
+ transformation.replaceWriteAccess(fieldName, methodName);
+ }
+
+ /** Adds a private method that will be the replacement for read-access to the field. */
+ private void addReaderMethod(String fieldName, String cachedFieldName,
+ String invariantFieldName, boolean cache, String parameterName, String fieldType,
+ String resourcesFieldName, ClassTransformation transformation)
+ {
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ // While the component is still loading, or when the value for the component is cached,
+ // or if the value is not bound, then return the current value of the field.
+
+ builder.addln(
+ "if (%s || ! %s.isLoaded() || ! %<s.isBound(\"%s\")) return %s;",
+ cachedFieldName,
+ resourcesFieldName,
+ parameterName,
+ fieldName);
+
+ String cast = TransformUtils.getWrapperTypeName(fieldType);
+
+ // The ($r) cast will convert the result to the method return type; generally
+ // this does nothing. but for primitive types, it will unwrap
+ // the wrapper type back to a primitive.
+
+ builder.addln(
+ "%s result = ($r) ((%s) %s.readParameter(\"%s\", $type));",
+ fieldType,
+ cast,
+ 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;");
+ builder.end();
+
+ String methodName = transformation.newMemberName("_read_parameter_" + parameterName);
+
+ MethodSignature signature = new MethodSignature(Modifier.PRIVATE, fieldType, methodName,
+ null, null);
+
+ transformation.addMethod(signature, builder.toString());
+
+ transformation.replaceReadAccess(fieldName, methodName);
+ }
+
+ private String getParameterName(String fieldName, String annotatedName)
+ {
+ if (InternalUtils.isNonBlank(annotatedName))
+ return annotatedName;
+
+ return InternalUtils.stripMemberPrefix(fieldName);
+ }
+}
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?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- 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 Fri Dec 29 17:08:39 2006
@@ -623,10 +623,6 @@
public void containingPageDidLoad()
{
- verifyRequiredParametersAreBound();
-
- _loaded = true;
-
// If this component has mixins, add the core component to the end of the list, after the
// mixins.
@@ -661,7 +657,14 @@
_components = ordered;
}
+ _loaded = true;
+
+ // For some parameters, bindings (from defaults) are provided inside the callback method, so
+ // that is invoked first, before we check for unbound parameters.
+
invoke(false, CONTAINING_PAGE_DID_LOAD);
+
+ verifyRequiredParametersAreBound();
}
/**
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/runtime/PageLifecycleListener.java Fri Dec 29 17:08:39 2006
@@ -12,29 +12,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.runtime;
-
-/**
- * A set of methods that allow components to know about page-level operations.
- */
-public interface PageLifecycleListener
-{
- /**
- * Invoked when the page finishes loading. This occurs once all components are loaded and all
- * parameters have been set.
- */
- void containingPageDidLoad();
-
- /**
- * Invoked when the page is detached, allowing components a chance to clear out any temporary or
- * client specific state.
- */
- void containingPageDidDetach();
-
- /**
- * Invoked when a page is first attached to the current request, giving components a chance to
- * initialize for the current request.
- */
-
- void containingPageDidAttach();
-}
+package org.apache.tapestry.runtime;
+
+/**
+ * A set of methods that allow components to know about page-level operations.
+ */
+public interface PageLifecycleListener
+{
+ /**
+ * Invoked when the page finishes loading. This occurs once all components are loaded and all
+ * parameters have been set.
+ */
+ void containingPageDidLoad();
+
+ /**
+ * Invoked when the page is detached, allowing components a chance to clear out any temporary or
+ * client specific state.
+ */
+ void containingPageDidDetach();
+
+ /**
+ * Invoked when a page is first attached to the current request, giving components a chance to
+ * initialize for the current request.
+ */
+
+ void containingPageDidAttach();
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BindingSource.java Fri Dec 29 17:08:39 2006
@@ -29,7 +29,7 @@
* factory for the default prefix (often "literal") is used (and passed the full prefix).
* <p>
* The binding represents a connection between the container and the component (the component is
- * usually the child of the component, though in a few cases, it is the component itself). In
+ * usually the child of the container, though in a few cases, it is the component itself). In
* most cases, the expression is evaluated in terms of the resources of the <em>container</em>
* and the component is ignored.
*
@@ -38,7 +38,7 @@
* @param container
* typically, the parent of the component
* @param component
- * the component whose paramter is to be bound
+ * the component whose parameter is to be bound
* @param defaultPrefix
* the default prefix used when the expression itself does not have a prefix
* @param expression
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/MethodSignature.java Fri Dec 29 17:08:39 2006
@@ -12,231 +12,235 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.services;
-
+package org.apache.tapestry.services;
+
import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
-
-import java.lang.reflect.Modifier;
-
-/**
- * A representation of a method signature, which consists of its name, modifiers (primarily,
- * visibility), return type, parameter types, and declared exception types.
- * <p>
- * Types are stored as class names (or primitive names) because the MethodSignature is often used in
- * situations where the actual class has not been loaded yet. When classes are already loaded (such
- * as, for use with {@link org.apache.hivemind.service.ClassFab}), then a different implementation
- * with the same name, {@link org.apache.tapestry.ioc.services.MethodSignature} is used.
- */
-public class MethodSignature implements Comparable<MethodSignature>
-{
- private int _hashCode = -1;
-
- private final int _modifiers;
-
- private final String _returnType;
-
- private final String _methodName;
-
- private final String[] _parameterTypes;
-
- private final String[] _exceptionTypes;
-
- private static final String[] EMPTY_STRINGS = new String[0];
-
- /** Convienience for adding a public void method with no parameters or exception types. */
-
- public MethodSignature(String name)
- {
- this(Modifier.PUBLIC, "void", name, EMPTY_STRINGS, EMPTY_STRINGS);
- }
-
- public MethodSignature(int modifiers, String type, String name, String[] parameterTypes,
- String[] exceptionTypes)
- {
- _modifiers = modifiers;
-
- _returnType = notBlank(type, "type");
- _methodName = notBlank(name, "name");
-
- // TODO: Checks that no element within the two arrays
- // is null or blank.
-
- _parameterTypes = typeNamesOrEmpty(parameterTypes);
- _exceptionTypes = typeNamesOrEmpty(exceptionTypes);
- }
-
- private String[] typeNamesOrEmpty(String[] types)
- {
- return types == null ? EMPTY_STRINGS : types;
- }
-
- /**
- * Returns a non-null array of the names of each declared exception type thrown by the method.
- * Calling code should not modify the array.
- */
- public String[] getExceptionTypes()
- {
- return _exceptionTypes;
- }
-
- /** Returns the name of the method. */
- public String getMethodName()
- {
- return _methodName;
- }
-
- /**
- * Returns the set of modifier flags for this method.
- *
- * @see java.lang.reflect.Modifier
- */
- public int getModifiers()
- {
- return _modifiers;
- }
-
- /**
- * Returns an array of the type name for each parameter. Calling code should not modify the
- * array.
- */
- public String[] getParameterTypes()
- {
- return _parameterTypes;
- }
-
- /** Return the type name of the return type of the method. */
- public String getReturnType()
- {
- return _returnType;
- }
-
- @Override
- public int hashCode()
- {
- if (_hashCode == -1)
- {
- _hashCode = 17 * _modifiers;
- _hashCode += 31 * _returnType.hashCode();
- _hashCode += 31 * _methodName.hashCode();
-
- for (String parameterType : _parameterTypes)
- {
- _hashCode += 31 * parameterType.hashCode();
- }
-
- for (String exceptionType : _exceptionTypes)
- {
- _hashCode += 31 * exceptionType.hashCode();
- }
- }
-
- return _hashCode;
- }
-
- @Override
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof MethodSignature))
- return false;
-
- MethodSignature ms = (MethodSignature) other;
-
- return _modifiers == ms._modifiers && _returnType.equals(ms._returnType)
- && _methodName.equals(ms._methodName)
- && matches(_parameterTypes, ms._parameterTypes)
- && matches(_exceptionTypes, ms._exceptionTypes);
- }
-
- private boolean matches(String[] values, String[] otherValues)
- {
- if (values.length != otherValues.length)
- return false;
-
- for (int i = 0; i < values.length; i++)
- {
- if (!values[i].equals(otherValues[i]))
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns the long form description of the signature. This includes modifiers, return type,
- * method name, parameters and thrown exceptions, formatter approximately as it would appear in
- * Java source (except that parameter names, which are not known, do no appear).
- */
- @Override
- public String toString()
- {
- StringBuilder builder = new StringBuilder();
-
- // Package private is simply omitted.
-
- if (_modifiers != 0)
- {
- builder.append(Modifier.toString(_modifiers));
- builder.append(' ');
- }
-
- builder.append(_returnType);
- builder.append(' ');
-
- addMethodNameAndParameters(builder);
-
- for (int i = 0; i < _exceptionTypes.length; i++)
- {
- if (i == 0)
- builder.append(" throws ");
- else
- builder.append(", ");
-
- builder.append(_exceptionTypes[i]);
- }
-
- return builder.toString();
- }
-
- private void addMethodNameAndParameters(StringBuilder builder)
- {
- builder.append(_methodName);
- builder.append('(');
-
- for (int i = 0; i < _parameterTypes.length; i++)
- {
- if (i > 0)
- builder.append(", ");
-
- builder.append(_parameterTypes[i]);
- }
-
- builder.append(')');
- }
-
- public int compareTo(MethodSignature o)
- {
- int result = _methodName.compareTo(o._methodName);
-
- if (result == 0)
- result = _parameterTypes.length - o._parameterTypes.length;
-
- return result;
- }
-
- /**
- * Returns a shortened form of the string representation of the method. It lists just the name
- * of the method and the types of any parameters, omitting return type, exceptions and
- * modifiers.
- *
- * @return
- */
- public String getMediumDescription()
- {
- StringBuilder builder = new StringBuilder();
-
- addMethodNameAndParameters(builder);
-
- return builder.toString();
- }
-
-}
+
+import java.lang.reflect.Modifier;
+
+/**
+ * A representation of a method signature, which consists of its name, modifiers (primarily,
+ * visibility), return type, parameter types, and declared exception types.
+ * <p>
+ * Types are stored as class names (or primitive names) because the MethodSignature is often used in
+ * situations where the actual class has not been loaded yet. When classes are already loaded (such
+ * as, for use with {@link org.apache.hivemind.service.ClassFab}), then a different implementation
+ * with the same name, {@link org.apache.tapestry.ioc.services.MethodSignature} is used.
+ */
+public class MethodSignature implements Comparable<MethodSignature>
+{
+ private int _hashCode = -1;
+
+ private final int _modifiers;
+
+ private final String _returnType;
+
+ private final String _methodName;
+
+ private final String[] _parameterTypes;
+
+ private final String[] _exceptionTypes;
+
+ private static final String[] EMPTY_STRINGS = new String[0];
+
+ /** Convienience for adding a public void method with no parameters or exception types. */
+
+ public MethodSignature(String name)
+ {
+ this(Modifier.PUBLIC, "void", name, EMPTY_STRINGS, EMPTY_STRINGS);
+ }
+
+ public MethodSignature(int modifiers, String type, String name, String[] parameterTypes,
+ String[] exceptionTypes)
+ {
+ _modifiers = modifiers;
+
+ _returnType = notBlank(type, "type");
+ _methodName = notBlank(name, "name");
+
+ // TODO: Checks that no element within the two arrays
+ // is null or blank.
+
+ _parameterTypes = typeNamesOrEmpty(parameterTypes);
+ _exceptionTypes = typeNamesOrEmpty(exceptionTypes);
+ }
+
+ private String[] typeNamesOrEmpty(String[] types)
+ {
+ return types == null ? EMPTY_STRINGS : types;
+ }
+
+ /**
+ * Returns a non-null array of the names of each declared exception type thrown by the method.
+ * Calling code should not modify the array.
+ */
+ public String[] getExceptionTypes()
+ {
+ return _exceptionTypes;
+ }
+
+ /** Returns the name of the method. */
+ public String getMethodName()
+ {
+ return _methodName;
+ }
+
+ /**
+ * Returns the set of modifier flags for this method.
+ *
+ * @see java.lang.reflect.Modifier
+ */
+ public int getModifiers()
+ {
+ return _modifiers;
+ }
+
+ /**
+ * Returns an array of the type name for each parameter. Calling code should not modify the
+ * array.
+ */
+ public String[] getParameterTypes()
+ {
+ return _parameterTypes;
+ }
+
+ /** Return the type name of the return type of the method. */
+ public String getReturnType()
+ {
+ return _returnType;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ if (_hashCode == -1)
+ {
+ _hashCode = 17 * _modifiers;
+ _hashCode += 31 * _returnType.hashCode();
+ _hashCode += 31 * _methodName.hashCode();
+
+ for (String parameterType : _parameterTypes)
+ {
+ _hashCode += 31 * parameterType.hashCode();
+ }
+
+ for (String exceptionType : _exceptionTypes)
+ {
+ _hashCode += 31 * exceptionType.hashCode();
+ }
+ }
+
+ return _hashCode;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof MethodSignature))
+ return false;
+
+ MethodSignature ms = (MethodSignature) other;
+
+ return _modifiers == ms._modifiers && _returnType.equals(ms._returnType)
+ && _methodName.equals(ms._methodName)
+ && matches(_parameterTypes, ms._parameterTypes)
+ && matches(_exceptionTypes, ms._exceptionTypes);
+ }
+
+ private boolean matches(String[] values, String[] otherValues)
+ {
+ if (values.length != otherValues.length)
+ return false;
+
+ for (int i = 0; i < values.length; i++)
+ {
+ if (!values[i].equals(otherValues[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the long form description of the signature. This includes modifiers, return type,
+ * method name, parameters and thrown exceptions, formatter approximately as it would appear in
+ * Java source (except that parameter names, which are not known, do no appear).
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder();
+
+ // Package private is simply omitted.
+
+ if (_modifiers != 0)
+ {
+ builder.append(Modifier.toString(_modifiers));
+ builder.append(' ');
+ }
+
+ builder.append(_returnType);
+ builder.append(' ');
+
+ addMethodNameAndParameters(builder);
+
+ for (int i = 0; i < _exceptionTypes.length; i++)
+ {
+ if (i == 0)
+ builder.append(" throws ");
+ else
+ builder.append(", ");
+
+ builder.append(_exceptionTypes[i]);
+ }
+
+ return builder.toString();
+ }
+
+ private void addMethodNameAndParameters(StringBuilder builder)
+ {
+ builder.append(_methodName);
+ builder.append('(');
+
+ for (int i = 0; i < _parameterTypes.length; i++)
+ {
+ if (i > 0)
+ builder.append(", ");
+
+ builder.append(_parameterTypes[i]);
+ }
+
+ builder.append(')');
+ }
+
+ /**
+ * Sorting is primarily via method name. For methods with the same name, the second level of
+ * sorting is by parameter count (ascending).
+ */
+ public int compareTo(MethodSignature o)
+ {
+ int result = _methodName.compareTo(o._methodName);
+
+ if (result == 0)
+ result = _parameterTypes.length - o._parameterTypes.length;
+
+ return result;
+ }
+
+ /**
+ * Returns a shortened form of the string representation of the method. It lists just the name
+ * of the method and the types of any parameters, omitting return type, exceptions and
+ * modifiers.
+ *
+ * @return
+ */
+ public String getMediumDescription()
+ {
+ StringBuilder builder = new StringBuilder();
+
+ addMethodNameAndParameters(builder);
+
+ return builder.toString();
+ }
+
+}
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=491145&r1=491144&r2=491145
==============================================================================
--- 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 Dec 29 17:08:39 2006
@@ -53,11 +53,11 @@
import org.apache.tapestry.internal.services.BindingSourceImpl;
import org.apache.tapestry.internal.services.ClasspathAssetAliasManagerImpl;
import org.apache.tapestry.internal.services.CommonResourcesInjectionProvider;
-import org.apache.tapestry.internal.services.ComponentClassFactoryImpl;
import org.apache.tapestry.internal.services.ComponentClassResolverImpl;
import org.apache.tapestry.internal.services.ComponentEventDispatcher;
import org.apache.tapestry.internal.services.ComponentInstanceEventHandler;
import org.apache.tapestry.internal.services.ComponentInstantiatorSource;
+import org.apache.tapestry.internal.services.ComponentInvocationMap;
import org.apache.tapestry.internal.services.ComponentLifecycleMethodWorker;
import org.apache.tapestry.internal.services.ComponentMessagesSourceImpl;
import org.apache.tapestry.internal.services.ComponentResourcesInjectionProvider;
@@ -69,7 +69,6 @@
import org.apache.tapestry.internal.services.EnvironmentalWorker;
import org.apache.tapestry.internal.services.FieldValidatorSourceImpl;
import org.apache.tapestry.internal.services.HeartbeatImpl;
-import org.apache.tapestry.internal.services.ComponentInvocationMap;
import org.apache.tapestry.internal.services.InfrastructureImpl;
import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
import org.apache.tapestry.internal.services.InjectAnonymousWorker;
@@ -538,11 +537,12 @@
* Returns a {@link ClassFactory} that can be used to create extra classes around component
* classes.
*/
- public static ClassFactory buildComponentClassFactory(Log log,
+ public ClassFactory buildComponentClassFactory(
@InjectService("tapestry.internal.ComponentInstantiatorSource")
ComponentInstantiatorSource source)
{
- return new ComponentClassFactoryImpl(log, source);
+
+ return _shadowBuilder.build(source, "classFactory", ClassFactory.class);
}
/**
@@ -603,7 +603,8 @@
Environment environment, @InjectService("tapestry.ComponentClassResolver")
ComponentClassResolver resolver, @InjectService("tapestry.internal.RequestPageCache")
RequestPageCache requestPageCache, @Inject("infrastructure:AssetSource")
- AssetSource assetSource)
+ AssetSource assetSource, @Inject("infrastructure:BindingSource")
+ BindingSource bindingsource)
{
// TODO: Proper scheduling of all of this. Since a given field or method should
// only have a single annotation, the order doesn't matter so much, as long as
@@ -617,7 +618,7 @@
configuration.add("AssetInject", new AssetInjectWorker(assetSource), "before:InjectNamed");
configuration.add("MixinAfter", new MixinAfterWorker());
- configuration.add("Parameter", new ParameterWorker());
+ configuration.add("Parameter", new ParameterWorker(bindingsource));
configuration.add("Component", new ComponentWorker(resolver));
configuration.add("Environment", new EnvironmentalWorker(environment));
configuration.add("Mixin", new MixinWorker(resolver));
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt Fri Dec 29 17:08:39 2006
@@ -225,6 +225,29 @@
the min parameter has a default value of 1. That value is used unless the min parameter is bound,
in which case, the bound value supercedes the default.
+Parameter Binding Defaults
+
+ The Parameter annotation's value() attribute can be used to specify a <binding expression> that will be the
+ default binding for the parameter is otherwise left unbound. Typically, this is the name of a property
+ that that will compute the value on the fly.
+
+ Example:
+
++----+
+ @Parameter("defaultMessage")
+ private String _message;
+
+ @Parameter(required=true)
+ private int _maxLength;
+
+ public String getDefaultMessage()
+ {
+ return String.format("Maximum field length is %d.", _maxLength);
+ }
++---+
+
+ As elsewhere, you may use a prefix on the value. A common prefix to use is the "message:" prefix, to access a localized message.
+
Unbound Parameters
If a parameter is not bound (and is optional), then the value may be read or <updated> at any time.
@@ -232,11 +255,12 @@
Updates to unbound parameters cause no side effects. In the first example, the value parameter of the Count
component is not bound, and this is perfectly valid.
- Note: updates to such fields are temporary; when the component finishes rendering, the field
+ Note: updates to such fields are temporary; when the component <finishes rendering>, the field
will revert to its default value.
<<TODO: This seems contradictory. What does it mean to update an unbound component parameter when the component
- is not rendering?>>
+ is not rendering?>>
+
Parameter Caching
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Fri Dec 29 17:08:39 2006
@@ -57,6 +57,9 @@
<li>
<a href="InjectComponentMismatch.html">InjectComponentMismatch</a> -- check error reporting when @InjectComponent doesn't match the actual field type
</li>
+ <li>
+ <a href="ParameterDefault.html">ParameterDefault</a> -- defaulter methods for component parameters
+ </li>
</ul>
</p>
</body>
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Fri Dec 29 17:08:39 2006
@@ -374,6 +374,15 @@
assertEquals(downloaded, actual);
}
+ @Test
+ public void component_parameter_default_from_method() throws Exception
+ {
+ _selenium.open(BASE_URL);
+ clickAndWait("link=ParameterDefault");
+
+ assertTextPresent("Echo component default: [org.apache.tapestry.integration.app1.pages.ParameterDefault:echo]");
+ }
+
/**
* {@link InjectComponentWorker} is largely tested by the forms tests ({@link RenderDisabled}
* is built on it). This test is for the failure case, where a mixin class is used with the
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Echo.java Fri Dec 29 17:08:39 2006
@@ -12,26 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.integration.app1.components;
-
-import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.annotations.BeginRender;
-import org.apache.tapestry.annotations.ComponentClass;
-import org.apache.tapestry.annotations.Parameter;
-
-/**
- * Echos out its value parameter (used to test parameter overrides between component annoation and
- * template).
- */
-@ComponentClass
-public class Echo
-{
- @Parameter(required = true)
- private String _value;
-
- @BeginRender
- void render(MarkupWriter writer)
- {
- writer.write(_value);
- }
-}
+package org.apache.tapestry.integration.app1.components;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
+/**
+ * Echos out its value parameter. Uused to test parameter overrides between component annoation and
+ * template. Also, used to test parameter defaulter methods.
+ */
+@ComponentClass
+public class Echo
+{
+ @Parameter("componentResources.completeId")
+ private String _value;
+
+ @BeginRender
+ void render(MarkupWriter writer)
+ {
+ writer.write(_value);
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java?view=auto&rev=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ParameterDefault.java Fri Dec 29 17:08:39 2006
@@ -0,0 +1,23 @@
+// Copyright 2006 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.integration.app1.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+
+@ComponentClass
+public class ParameterDefault
+{
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponent.java Fri Dec 29 17:08:39 2006
@@ -74,18 +74,13 @@
public void afterRenderBody(MarkupWriter writer, LifecycleEvent<Boolean> event)
{
- // TODO Auto-generated method stub
-
}
public void afterRenderTemplate(MarkupWriter writer, LifecycleEvent<Boolean> event)
{
- // TODO Auto-generated method stub
-
}
public void beforeRenderTemplate(MarkupWriter writer, LifecycleEvent<Boolean> event)
{
- // TODO Auto-generated method stub
}
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java?view=auto&rev=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/DefaultParameterComponent.java Fri Dec 29 17:08:39 2006
@@ -0,0 +1,34 @@
+// Copyright 2006 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.services;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
+/**
+ * Used by {@link org.apache.tapestry.internal.services.ParameterWorkerTest}.
+ */
+@ComponentClass
+public class DefaultParameterComponent
+{
+ @Parameter("literal:greeting")
+ private String _value;
+
+ public String getValue()
+ {
+ return _value;
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLocatorTest.java Fri Dec 29 17:08:39 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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.services;
import java.util.Locale;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java Fri Dec 29 17:08:39 2006
@@ -21,11 +21,14 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.test.InternalBaseTestCase;
import org.apache.tapestry.ioc.internal.services.PropertyAccessImpl;
import org.apache.tapestry.ioc.services.PropertyAccess;
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.Binding;
+import org.apache.tapestry.services.BindingSource;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
@@ -450,6 +453,59 @@
verify();
}
+ @Test
+ public void parameter_with_default() throws Exception
+ {
+ final BindingSource source = newBindingSource();
+ final InternalComponentResources resources = newInternalComponentResources();
+ final Binding binding = newBinding();
+ String boundValue = "howdy!";
+
+ MutableComponentModel model = newMutableComponentModel();
+
+ model.addParameter("value", false);
+
+ Runnable phaseTwoTraining = new Runnable()
+ {
+ public void run()
+ {
+ train_isBound(resources, "value", false);
+
+ expect(
+ source.newBinding(
+ "default value",
+ resources,
+ resources,
+ InternalConstants.PROP_BINDING_PREFIX,
+ "literal:greeting",
+ null)).andReturn(binding);
+
+ resources.addParameter("value", binding);
+
+ train_isInvariant(resources, "value", true);
+
+ };
+ };
+
+ Component component = setupForIntegrationTest(
+ resources,
+ newLog(),
+ DefaultParameterComponent.class.getName(),
+ model,
+ source,
+ phaseTwoTraining);
+
+ train_isLoaded(resources, true);
+ train_isBound(resources, "value", true);
+ train_readParameter(resources, "value", String.class, boundValue);
+
+ replay();
+
+ assertEquals(_access.get(component, "value"), boundValue);
+
+ verify();
+ }
+
protected final void train_isRendering(InternalComponentResources resources, boolean rendering)
{
expect(resources.isRendering()).andReturn(rendering);
@@ -461,10 +517,40 @@
expect(resources.readParameter(parameterName, expectedType)).andReturn(value);
}
- private Component setupForIntegrationTest(InternalComponentResources resources)
+ /** This is for the majority of tests. */
+ private Component setupForIntegrationTest(final InternalComponentResources resources)
throws Exception
{
- Log log = newLog();
+ MutableComponentModel model = newMutableComponentModel();
+
+ model.addParameter("invariantObject", false);
+ model.addParameter("invariantPrimitive", false);
+ model.addParameter("object", false);
+ model.addParameter("primitive", true);
+ model.addParameter("uncached", false);
+
+ Runnable phaseTwoTraining = new Runnable()
+ {
+ public void run()
+ {
+ trainForPageDidLoad(resources);
+
+ }
+ };
+
+ return setupForIntegrationTest(
+ resources,
+ newLog(),
+ ParameterComponent.class.getName(),
+ model,
+ newBindingSource(),
+ phaseTwoTraining);
+ }
+
+ private Component setupForIntegrationTest(InternalComponentResources resources, Log log,
+ String componentClassName, MutableComponentModel model, BindingSource source,
+ Runnable phaseTwoTraining) throws Exception
+ {
ClassPool pool = new ClassPool();
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
pool.appendClassPath(new LoaderClassPath(contextLoader));
@@ -473,21 +559,13 @@
loader.delegateLoadingOf("org.apache.tapestry.");
- CtClass ctClass = pool.get(ParameterComponent.class.getName());
+ CtClass ctClass = pool.get(componentClassName);
InternalClassTransformation transformation = new InternalClassTransformationImpl(ctClass,
_contextClassLoader, log, null);
- MutableComponentModel model = newMutableComponentModel();
-
- model.addParameter("invariantObject", false);
- model.addParameter("invariantPrimitive", false);
- model.addParameter("object", false);
- model.addParameter("primitive", true);
- model.addParameter("uncached", false);
-
replay();
- new ParameterWorker().transform(transformation, model);
+ new ParameterWorker(source).transform(transformation, model);
verify();
@@ -499,7 +577,7 @@
Instantiator instantiator = transformation.createInstantiator(transformedClass);
- trainForPageDidLoad(resources);
+ phaseTwoTraining.run();
replay();
Modified: 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?view=diff&rev=491145&r1=491144&r2=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java Fri Dec 29 17:08:39 2006
@@ -150,6 +150,10 @@
train_getParameterModel(model, "fred", pmodel);
train_isRequired(pmodel, true);
+ // Now called *before* the check for unbound parametesr
+
+ component.containingPageDidLoad();
+
train_getComponentClassName(model, "foo.components.MyComponent");
replay();
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html?view=auto&rev=491145
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterDefault.html Fri Dec 29 17:08:39 2006
@@ -0,0 +1,6 @@
+<t:comp type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+
+ Echo component default: [<t:comp type="Echo" id="echo"/>]
+
+</t:comp>