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/05 20:14:55 UTC
svn commit: r440425 - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/annotations/
main/java/org/apache/tapestry/internal/bindings/
main/java/org/apache/tapestry/internal/ioc/services/
main/java/org/apache/tapestry/interna...
Author: hlship
Date: Tue Sep 5 11:14:53 2006
New Revision: 440425
URL: http://svn.apache.org/viewvc?view=rev&rev=440425
Log:
Add initial support for the @Inject annotation.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.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/ioc/services/ClassFactoryClassPool.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.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/InternalClassTransformation.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/ServicesMessages.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/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
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/Loop.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.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/services/ReadOnlyBean.java
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java Tue Sep 5 11:14:53 2006
@@ -0,0 +1,40 @@
+// 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.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;
+
+/**
+ * Allows injection of various objects into a component class.
+ *
+ * @author Howard M. Lewis Ship
+ * @see org.apache.tapestry.internal.services.InjectionProvider
+ */
+@Target(FIELD)
+@Documented
+@Retention(RUNTIME)
+public @interface Inject {
+
+ /**
+ * Identifies the value to be injected, when the type by itself is insufficient. Omitted in many
+ * cases.
+ */
+ String value() default "";
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java Tue Sep 5 11:14:53 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.bindings;
import org.apache.tapestry.Location;
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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 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.bindings;
import java.lang.reflect.Constructor;
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?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -56,9 +56,9 @@
/**
* Convienience method for adding to the ClassPath for a particular class loader.
* <p>
- * TODO: This code assumes that ClassLoaders are structured as a "line" not a proper "tree". That
- * is, if the ClassLoader hiearchy actually does have branches, rather than a straight line from
- * root to leaf, it may not work.
+ * TODO: This code assumes that ClassLoaders are structured as a "line" not a proper "tree".
+ * That is, if the ClassLoader hiearchy actually does have branches, rather than a straight line
+ * from root to leaf, it may not work.
*
* @param loader
* the class loader to add (derived from a loaded class, and may be null for some
@@ -87,6 +87,11 @@
}
_loader = loader;
+ }
+
+ public ClassLoader getLoader()
+ {
+ return _loader;
}
/**
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java Tue Sep 5 11:14:53 2006
@@ -29,8 +29,14 @@
{
/**
* Performs a transformation on the class, accessing the class from the class pool.
+ *
+ * @param ctClass
+ * compile time class to be transformed
+ * @param classLoader
+ * class loader used to resolve references to other classes (both transformed and
+ * not)
*/
- void transformComponentClass(CtClass ctClass);
+ void transformComponentClass(CtClass ctClass, ClassLoader classLoader);
/** Creates a new instantiator instance. */
Instantiator createInstantiator(Class componentClass);
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?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -75,7 +75,7 @@
}
@Concurrent.Write
- public void transformComponentClass(CtClass ctClass)
+ public void transformComponentClass(CtClass ctClass, ClassLoader classLoader)
{
String classname = ctClass.getName();
@@ -99,8 +99,8 @@
// TODO: Check that the name is not already in the map.
InternalClassTransformation transformation = parentTransformation == null ? new InternalClassTransformationImpl(
- ctClass)
- : new InternalClassTransformationImpl(ctClass, parentTransformation);
+ ctClass, classLoader)
+ : new InternalClassTransformationImpl(ctClass, parentTransformation, classLoader);
// 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).
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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -160,7 +160,7 @@
// Do the transformations here
- _transformer.transformComponentClass(ctClass);
+ _transformer.transformComponentClass(ctClass, _loader);
diag = "END";
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java Tue Sep 5 11:14:53 2006
@@ -0,0 +1,95 @@
+// 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.Inject;
+import org.apache.tapestry.internal.ioc.IOCUtilities;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+
+/**
+ * Worker for the {@link org.apache.tapestry.annotations.Inject} annotation.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public class InjectWorker implements ComponentClassTransformWorker
+{
+ private final ObjectProvider _objectProvider;
+
+ private final ServiceLocator _locator;
+
+ // Really, a chain of command
+
+ private final InjectionProvider _injectionProvider;
+
+ public InjectWorker(ObjectProvider objectProvider, ServiceLocator locator,
+ InjectionProvider injectionProvider)
+ {
+ _objectProvider = objectProvider;
+ _locator = locator;
+ _injectionProvider = injectionProvider;
+ }
+
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ for (String fieldName : transformation.findFieldsWithAnnotation(Inject.class))
+ {
+ Inject annotation = transformation.getFieldAnnotation(fieldName, Inject.class);
+
+ String value = annotation.value();
+
+ if (IOCUtilities.isBlank(value))
+ injectAnnonymous(fieldName, transformation, model);
+ else
+ injectNamed(fieldName, value, transformation, model);
+
+ transformation.claimField(fieldName, annotation);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ private void injectNamed(String fieldName, String value, ClassTransformation transformation,
+ MutableComponentModel model)
+ {
+ String fieldType = transformation.getFieldType(fieldName);
+
+ Class type = transformation.toClass(fieldType);
+
+ Object inject = _objectProvider.provide(value, type, _locator);
+
+ transformation.injectField(fieldName, inject);
+ }
+
+ private void injectAnnonymous(String fieldName, ClassTransformation transformation,
+ MutableComponentModel model)
+ {
+ String fieldType = transformation.getFieldType(fieldName);
+
+ boolean result = _injectionProvider.provideInjection(
+ fieldName,
+ fieldType,
+ _locator,
+ transformation,
+ model);
+
+ if (!result)
+ throw new RuntimeException(ServicesMessages.noInjectionFound(transformation
+ .getClassName(), fieldName, fieldType));
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java Tue Sep 5 11:14:53 2006
@@ -0,0 +1,53 @@
+// 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.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+
+/**
+ * Provides some form of injection when the value for an
+ * {@link org.apache.tapestry.annotations.Inject} annotation is blank. In this case, the provider is
+ * responsible for determining the value to be injected from the field name and field type.
+ * <p>
+ * This interface will be used as part of a
+ * {@link org.apache.tapestry.ioc.services.ChainBuilder chain of command}.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public interface InjectionProvider
+{
+ /**
+ * Peform the injection, if possible. Most often, this will result in a call to
+ * {@link ClassTransformation#injectField(String, Object)}. The caller is responsible for
+ * invoking {@link ClassTransformation#claimField(String, Object)}.
+ *
+ * @param fieldName
+ * the name of the field requesting injection
+ * @param fieldType
+ * the type of the field (as a string)
+ * @param locator
+ * allows services to be located
+ * @param transformation
+ * allows the code for the class to be transformed
+ * @param componentModel
+ * defines the relevant aspects of the component
+ * @return true if an injection has been made (terminates the command chain), false to continue
+ * down the chain
+ */
+ boolean provideInjection(String fieldName, String fieldType, ServiceLocator locator,
+ ClassTransformation transformation, MutableComponentModel componentModel);
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java Tue Sep 5 11:14:53 2006
@@ -21,8 +21,8 @@
import org.apache.tapestry.util.IdAllocator;
/**
- * Extends {@link org.apache.tapestry.services.ClassTransformation} with additional methods that
- * may only be used internally by Tapestry.
+ * Extends {@link org.apache.tapestry.services.ClassTransformation} with additional methods that may
+ * only be used internally by Tapestry.
*
* @author Howard M. Lewis Ship
*/
@@ -35,9 +35,9 @@
String getResourcesFieldName();
/**
- * Invoked after all {@link ComponentClassTransformWorker}s have had their chance to work over the
- * class. This performs any final operations for the class transformation, which includes coming
- * up with the final constructor method for the class.
+ * Invoked after all {@link ComponentClassTransformWorker}s have had their chance to work over
+ * the class. This performs any final operations for the class transformation, which includes
+ * coming up with the final constructor method for the class.
*/
void finish();
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?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -42,6 +42,7 @@
import org.apache.tapestry.internal.util.InternalUtils;
import org.apache.tapestry.runtime.ComponentLifecycle;
import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.TransformUtils;
import org.apache.tapestry.util.CollectionFactory;
import org.apache.tapestry.util.IdAllocator;
@@ -64,7 +65,7 @@
private final CtClass _ctClass;
- private final ClassPool _classPool;
+ private ClassPool _classPool;
private final IdAllocator _idAllocator;
@@ -106,14 +107,17 @@
private Formatter _formatter = new Formatter(_description);
+ private ClassLoader _loader;
+
/**
* This is a constructor for the root class, the class that directly contains the ComponentClass
* annotation.
*/
- public InternalClassTransformationImpl(CtClass ctClass)
+ public InternalClassTransformationImpl(CtClass ctClass, ClassLoader loader)
{
_ctClass = ctClass;
_classPool = _ctClass.getClassPool();
+ _loader = loader;
_idAllocator = new IdAllocator();
@@ -135,10 +139,12 @@
}
public InternalClassTransformationImpl(CtClass ctClass,
- InternalClassTransformation parentTransformation)
+ InternalClassTransformation parentTransformation, ClassLoader loader)
{
_ctClass = ctClass;
_classPool = _ctClass.getClassPool();
+ _loader = loader;
+
_resourcesFieldName = parentTransformation.getResourcesFieldName();
_idAllocator = parentTransformation.getIdAllocator();
@@ -186,6 +192,9 @@
_fieldWriteTransforms = null;
_constructor = null;
_formatter = null;
+ _loader = null;
+ // _ctClass = null; -- needed by toString()
+ _classPool = null;
}
public String getResourcesFieldName()
@@ -661,6 +670,8 @@
public List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass)
{
+ failIfFrozen();
+
List<String> result = newList();
for (CtField field : _ctClass.getDeclaredFields())
@@ -693,6 +704,8 @@
public List<MethodSignature> findMethodsWithAnnotation(
Class<? extends Annotation> annotationClass)
{
+ failIfFrozen();
+
List<MethodSignature> result = newList();
for (CtMethod method : _ctClass.getDeclaredMethods())
@@ -781,13 +794,20 @@
public String getFieldType(String fieldName)
{
+ failIfFrozen();
+
+ CtClass type = getFieldCtType(fieldName);
+
+ return type.getName();
+ }
+
+ private CtClass getFieldCtType(String fieldName)
+ {
try
{
CtField field = _ctClass.getDeclaredField(fieldName);
- CtClass type = field.getType();
-
- return type.getName();
+ return field.getType();
}
catch (NotFoundException ex)
{
@@ -849,11 +869,41 @@
String fieldName = addField(Modifier.PROTECTED, type.getName(), suggestedName);
- _constructorArgs.add(new ConstructorArg(ctType, value));
+ addInjectToConstructor(fieldName, ctType, value);
+
+ return fieldName;
+ }
+
+ /**
+ * Adds a parameter to the constructor for the class; the parameter is used to initialize the
+ * value for a field.
+ *
+ * @param fieldName
+ * name of field to inject
+ * @param fieldType
+ * Javassist type of the field (and corresponding parameter)
+ * @param value
+ * the value to be injected (which will in unusual cases be null)
+ */
+ private void addInjectToConstructor(String fieldName, CtClass fieldType, Object value)
+ {
+ _constructorArgs.add(new ConstructorArg(fieldType, value));
_constructor.append(format(" %s = $%d;\n", fieldName, _constructorArgs.size()));
+ }
- return fieldName;
+ @SuppressNullCheck
+ public void injectField(String fieldName, Object value)
+ {
+ notNull(fieldName, "fieldName");
+
+ failIfFrozen();
+
+ CtClass type = getFieldCtType(fieldName);
+
+ addInjectToConstructor(fieldName, type, value);
+
+ makeReadOnly(fieldName);
}
private CtClass convertNameToCtType(String type) throws NotFoundException
@@ -1128,4 +1178,28 @@
throw new RuntimeException(ex);
}
}
+
+ public Class toClass(String type)
+ {
+ failIfFrozen();
+
+ // No reason why this can't be allowed to work after freezing.
+
+ String finalType = TransformUtils.getWrapperType(type);
+
+ try
+ {
+ return Class.forName(finalType, true, _loader);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public String getClassName()
+ {
+ return _ctClass.getName();
+ }
+
}
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?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -14,19 +14,11 @@
package org.apache.tapestry.internal.services;
-import java.lang.annotation.Annotation;
-
import org.apache.commons.logging.Log;
-import org.apache.tapestry.annotations.BeforeRenderBody;
-import org.apache.tapestry.annotations.BeginRender;
-import org.apache.tapestry.annotations.CleanupRender;
-import org.apache.tapestry.annotations.AfterRender;
-import org.apache.tapestry.annotations.SetupRender;
import org.apache.tapestry.events.InvalidationEvent;
import org.apache.tapestry.events.InvalidationListener;
import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.bindings.PropBindingFactory;
-import org.apache.tapestry.ioc.IOCUtilities;
import org.apache.tapestry.ioc.LogSource;
import org.apache.tapestry.ioc.OrderedConfiguration;
import org.apache.tapestry.ioc.annotations.Contribute;
@@ -46,8 +38,6 @@
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.ComponentClassTransformWorker;
import org.apache.tapestry.services.MarkupWriterFactory;
-import org.apache.tapestry.services.MethodSignature;
-import org.apache.tapestry.services.TransformConstants;
import org.apache.tapestry.services.WebContext;
import org.apache.tapestry.services.WebRequestFilter;
@@ -167,49 +157,6 @@
public UpdateListenerHub buildUpdateListenerHub()
{
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>SetupRender, BeginRender, etc. -- correspond to component render phases and annotations</li>
- * </ul>
- *
- * @param configuration
- */
- @Contribute("tapestry.ComponentClassTransformWorker")
- public void contributeInternalWorkers(
- OrderedConfiguration<ComponentClassTransformWorker> configuration)
- {
- // TODO: Proper scheduling of all of this.
-
- configuration.add("Parameter", new ParameterWorker());
-
- // Workers for the component rendering state machine methods; this is in typical
- // execution order.
-
- add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
- add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, BeginRender.class);
- add(configuration, TransformConstants.BEFORE_RENDER_BODY_SIGNATURE, BeforeRenderBody.class);
- add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, AfterRender.class);
- add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class);
-
- configuration.add("Retain", new RetainWorker());
- configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
- }
-
- private void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
- MethodSignature signature, Class<? extends Annotation> annotationClass)
- {
- // make the name match the annotation class name.
-
- String name = IOCUtilities.toSimpleId(annotationClass.getName());
-
- configuration.add(name, new ComponentLifecycleMethodWorker(signature, annotationClass));
}
/**
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Tue Sep 5 11:14:53 2006
@@ -138,4 +138,9 @@
{
return MESSAGES.format("read-only-field", className, fieldName);
}
+
+ static String noInjectionFound(String className, String fieldName, String fieldType)
+ {
+ return MESSAGES.format("no-injection-found", className, fieldName, fieldType);
+ }
}
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?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -42,6 +42,12 @@
{
/**
+ * Returns the name of the class being transformed.
+ */
+
+ String getClassName();
+
+ /**
* Returns the name of a new member (field or method). Ensures that the resulting name does not
* conflict with any existing member (declared by the underlying class, or inherited from a base
* class).
@@ -167,6 +173,16 @@
String addInjectedField(Class type, String suggestedName, Object value);
/**
+ * Converts the field into a read only field whose value is the provided value.
+ *
+ * @param fieldName
+ * name of field to convert
+ * @param value
+ * the value provided by the field
+ */
+ void injectField(String fieldName, Object value);
+
+ /**
* Transforms the class to implement the indicated interface. If the class (or its super class)
* does not already implement the interface, then the interface is added, and default
* implementations of any methods of the interface are added.
@@ -224,4 +240,11 @@
* {@link #extendMethod(MethodSignature, String)}.
*/
void replaceWriteAccess(String fieldName, String methodName);
+
+ /**
+ * Converts a type name into a corresponding class (possibly, a transformed class). Primitive
+ * type names are returned as wrapper types.
+ */
+
+ Class toClass(String type);
}
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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -15,6 +15,7 @@
package org.apache.tapestry.services;
import java.io.IOException;
+import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -25,6 +26,11 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.AfterRender;
+import org.apache.tapestry.annotations.BeforeRenderBody;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.CleanupRender;
+import org.apache.tapestry.annotations.SetupRender;
import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
@@ -33,19 +39,26 @@
import org.apache.tapestry.internal.services.ComponentClassFactoryImpl;
import org.apache.tapestry.internal.services.ComponentClassResolverImpl;
import org.apache.tapestry.internal.services.ComponentInstantiatorSource;
+import org.apache.tapestry.internal.services.ComponentLifecycleMethodWorker;
import org.apache.tapestry.internal.services.HTMLDispatcher;
import org.apache.tapestry.internal.services.InfrastructureImpl;
import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
+import org.apache.tapestry.internal.services.InjectWorker;
+import org.apache.tapestry.internal.services.InjectionProvider;
import org.apache.tapestry.internal.services.InternalModule;
import org.apache.tapestry.internal.services.MarkupWriterImpl;
import org.apache.tapestry.internal.services.PageResponseRenderer;
+import org.apache.tapestry.internal.services.ParameterWorker;
import org.apache.tapestry.internal.services.RequestGlobalsImpl;
import org.apache.tapestry.internal.services.RequestPageCache;
+import org.apache.tapestry.internal.services.RetainWorker;
import org.apache.tapestry.internal.services.StaticFilesFilter;
+import org.apache.tapestry.internal.services.UnclaimedFieldWorker;
import org.apache.tapestry.internal.services.WebContextImpl;
import org.apache.tapestry.internal.services.WebRequestImpl;
import org.apache.tapestry.internal.services.WebResponseImpl;
import org.apache.tapestry.ioc.Configuration;
+import org.apache.tapestry.ioc.IOCUtilities;
import org.apache.tapestry.ioc.MappedConfiguration;
import org.apache.tapestry.ioc.ObjectProvider;
import org.apache.tapestry.ioc.OrderedConfiguration;
@@ -340,7 +353,7 @@
@InjectService("Infrastructure")
Infrastructure infrastructure)
{
- configuration.add("service", infrastructure.getObjectProvider());
+ configuration.add("infrastructure", infrastructure.getObjectProvider());
}
public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
@@ -380,5 +393,63 @@
ComponentInstantiatorSource source)
{
return new ComponentClassFactoryImpl(log, source);
+ }
+
+ /**
+ * A chain of command for providing values for {@link org.apache.tapestry.annotations.Inject}-ed
+ * fields in component classes. The service's configuration can be extended to allow for
+ * different automatic injections (based on some combination of field type and field name).
+ */
+
+ public InjectionProvider buildInjectionProvider(List<InjectionProvider> configuration)
+ {
+ return _chainBuilder.build(InjectionProvider.class, configuration);
+ }
+
+ /**
+ * 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>SetupRender, BeginRender, etc. -- correspond to component render phases and annotations</li>
+ * </ul>
+ *
+ * @param configuration
+ */
+ @Contribute("tapestry.ComponentClassTransformWorker")
+ public void contributeTransformWorkers(
+ OrderedConfiguration<ComponentClassTransformWorker> configuration,
+ ServiceLocator locator, @InjectService("tapestry.ioc.MasterObjectProvider")
+ ObjectProvider objectProvider, @InjectService("InjectionProvider")
+ InjectionProvider injectionProvider)
+ {
+ // TODO: Proper scheduling of all of this.
+
+ configuration.add("Inject", new InjectWorker(objectProvider, locator, injectionProvider));
+ configuration.add("Parameter", new ParameterWorker());
+
+ // Workers for the component rendering state machine methods; this is in typical
+ // execution order.
+
+ add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+ add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, BeginRender.class);
+ add(configuration, TransformConstants.BEFORE_RENDER_BODY_SIGNATURE, BeforeRenderBody.class);
+ add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, AfterRender.class);
+ add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class);
+
+ configuration.add("Retain", new RetainWorker());
+ configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
+ }
+
+ private void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
+ MethodSignature signature, Class<? extends Annotation> annotationClass)
+ {
+ // make the name match the annotation class name.
+
+ String name = IOCUtilities.toSimpleId(annotationClass.getName());
+
+ configuration.add(name, new ComponentLifecycleMethodWorker(signature, annotationClass));
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java Tue Sep 5 11:14:53 2006
@@ -34,6 +34,7 @@
import org.apache.tapestry.annotations.SetupRender;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.internal.services.InjectionProvider;
import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.LogSource;
import org.apache.tapestry.ioc.MappedConfiguration;
@@ -53,6 +54,7 @@
import org.apache.tapestry.services.ClassTransformation;
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.WebRequest;
import static java.lang.Thread.sleep;
import static org.apache.tapestry.internal.test.CodeEq.codeEq;
@@ -441,5 +443,22 @@
{
tf.findMethodsWithAnnotation(SetupRender.class);
setReturnValue(sigs);
+ }
+
+ protected final WebRequest newWebRequest()
+ {
+ return newMock(WebRequest.class);
+ }
+
+ protected final void train_provideInjection(InjectionProvider provider, String fieldName, String fieldType, ServiceLocator locator, ClassTransformation transformation, MutableComponentModel model, boolean result)
+ {
+ provider.provideInjection(fieldName, fieldType, locator, transformation, model);
+ setReturnValue(result);
+ }
+
+ protected final void train_toClass(ClassTransformation transformation, String type, Class classForType)
+ {
+ transformation.toClass(type);
+ setReturnValue(classForType);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Tue Sep 5 11:14:53 2006
@@ -34,4 +34,6 @@
may-not-nest-elements-inside-body=Element '%s' is nested within a Tapestry body element, which is not allowed.
method-compile-error=Error compiling method %s (%s): %s
render-queue-error=Render queue error in %s: %s
-read-only-field=Field %s.%s is read-only.
\ No newline at end of file
+read-only-field=Field %s.%s is read-only.
+no-injection-found=Could not find a suitable object to inject into %s.%s (type %s). \
+ Use the value attribute of the @Inject annotation to identify exactly what should be injected into this field.
\ No newline at end of file
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=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Tue Sep 5 11:14:53 2006
@@ -2,26 +2,23 @@
<head>
<title>Tapestry 5 Integration Application 1</title>
</head>
-
<body>
-
<p>
<em>This page is static.</em>
</p>
- <p>
- Tapestry 5 Integration Application 1:
-
- <ul>
- <a href="Start.html">Start Page</a>
- <a href="MerryChristmas.html">Loop Page</a>
+ <p> Tapestry 5 Integration Application 1: <ul>
+ <li>
+ <a href="Start.html">Start Page</a>
+ </li>
+ <li>
+ <a href="MerryChristmas.html">Loop Page</a>
+ </li>
+ <li>
+ <a href="InjectPage.html">Inject Page</a>
+ </li>
</ul>
</p>
-
-
- <p>
- Feast your eyes:
- </p>
-
+ <p> Feast your eyes: </p>
<img src="render-states1_1.png" alt="Component Render States"/>
</body>
-</html>
\ No newline at end of file
+</html>
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?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Tue Sep 5 11:14:53 2006
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<suite name="Tapestry" parallel="true" thread-count="10" annotations="1.5" verbose="2">
<test name="Tapestry Core">
<packages>
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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -116,6 +116,19 @@
// Selenium is nice enough to remove the elements and excess whitespace.
assertTrue(body.contains("Ho! Ho! Ho!"));
+
+ _selenium.open(BASE_URL);
+
+ _selenium.click("link=Inject Page");
+ _selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
+
+ body = _selenium.getBodyText();
+
+ // This is the output from the proxy for the WebRequest service, which is what's injected
+ // into and output by, the component.
+
+ assertTrue(body
+ .contains("<Proxy for tapestry.WebRequest(org.apache.tapestry.services.WebRequest)>"));
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java Tue Sep 5 11:14:53 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.integration.app1.components;
import org.apache.tapestry.annotations.ComponentClass;
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java Tue Sep 5 11:14:53 2006
@@ -0,0 +1,39 @@
+// 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.components;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.services.WebRequest;
+
+/**
+ * This will go away once we implement output expressions in templates.
+ *
+ * @author Howard M. Lewis Ship
+ */
+@ComponentClass
+public class WriteWebRequest
+{
+ @Inject("infrastructure:request")
+ private WebRequest _request;
+
+ @BeginRender
+ void writeRequest(MarkupWriter writer)
+ {
+ writer.write(_request.toString());
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java Tue Sep 5 11:14:53 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 InjectPage
+{
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java Tue Sep 5 11:14:53 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.integration.app1.pages;
import org.apache.tapestry.annotations.ComponentClass;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java Tue Sep 5 11:14:53 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.bindings;
import org.apache.tapestry.ComponentResources;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java Tue Sep 5 11:14:53 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.bindings;
import org.apache.tapestry.Binding;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java Tue Sep 5 11:14:53 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.bindings;
public class TargetBean extends DefaultComponentLifecyle
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java Tue Sep 5 11:14:53 2006
@@ -0,0 +1,150 @@
+// 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.Inject;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.WebRequest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class InjectWorkerTest extends InternalBaseTestCase
+{
+
+ private static final String WEBREQUEST_CLASS_NAME = WebRequest.class.getName();
+
+ @Test
+ public void annotation_has_value()
+ {
+ ObjectProvider provider = newObjectProvider();
+ ServiceLocator locator = newServiceLocator();
+ InjectionProvider ip = newMock(InjectionProvider.class);
+ Inject annotation = newMock(Inject.class);
+ ClassTransformation ct = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+ WebRequest injected = newWebRequest();
+
+ train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+ train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+ train_value(annotation, "foo:Bar");
+
+ train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+ train_toClass(ct, WEBREQUEST_CLASS_NAME, WebRequest.class);
+
+ train_provide(provider, "foo:Bar", WebRequest.class, locator, injected);
+
+ ct.injectField("myfield", injected);
+
+ ct.claimField("myfield", annotation);
+
+ replay();
+
+ InjectWorker worker = new InjectWorker(provider, locator, ip);
+
+ worker.transform(ct, model);
+
+ verify();
+ }
+
+ @Test
+ public void no_value_for_annotation()
+ {
+ ObjectProvider provider = newObjectProvider();
+ ServiceLocator locator = newServiceLocator();
+ InjectionProvider ip = newMock(InjectionProvider.class);
+ Inject annotation = newMock(Inject.class);
+ ClassTransformation ct = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+
+ train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+ train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+ train_value(annotation, "");
+
+ train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+
+ train_provideInjection(ip, "myfield", WEBREQUEST_CLASS_NAME, locator, ct, model, true);
+
+ ct.claimField("myfield", annotation);
+
+ replay();
+
+ InjectWorker worker = new InjectWorker(provider, locator, ip);
+
+ worker.transform(ct, model);
+
+ verify();
+ }
+
+ @Test
+ public void anonymous_injection_not_provided()
+ {
+ ObjectProvider provider = newObjectProvider();
+ ServiceLocator locator = newServiceLocator();
+ InjectionProvider ip = newMock(InjectionProvider.class);
+ Inject annotation = newMock(Inject.class);
+ ClassTransformation ct = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+
+ train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+ train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+ train_value(annotation, "");
+
+ train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+
+ train_provideInjection(ip, "myfield", WEBREQUEST_CLASS_NAME, locator, ct, model, false);
+
+ train_getClassName(ct, "foo.Baz");
+
+ replay();
+
+ InjectWorker worker = new InjectWorker(provider, locator, ip);
+
+ try
+ {
+ worker.transform(ct, model);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(ex.getMessage(), ServicesMessages.noInjectionFound(
+ "foo.Baz",
+ "myfield",
+ WEBREQUEST_CLASS_NAME));
+ }
+
+ verify();
+ }
+
+ protected void train_getClassName(ClassTransformation transformation, String className)
+ {
+ transformation.getClassName();
+ setReturnValue(className);
+ }
+
+ private void train_value(Inject annotation, String value)
+ {
+ annotation.value();
+ setReturnValue(value);
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java Tue Sep 5 11:14:53 2006
@@ -19,6 +19,7 @@
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import javassist.ClassPool;
import javassist.CtClass;
@@ -111,7 +112,7 @@
throws NotFoundException
{
CtClass ctClass = findCtClass(targetClass);
- return new InternalClassTransformationImpl(ctClass);
+ return new InternalClassTransformationImpl(ctClass, _contextClassLoader);
}
@Test
@@ -316,7 +317,7 @@
}
@Test
- public void inject_field() throws Exception
+ public void add_injected_field() throws Exception
{
InternalComponentResources resources = newInternalComponentResources();
@@ -324,7 +325,11 @@
CtClass targetObjectCtClass = findCtClass(TargetObject.class);
- InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+ InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+ _contextClassLoader);
+
+ // Default behavior is to add an injected field for the InternalComponentResources object,
+ // so we'll just check that.
ct.finish();
@@ -344,7 +349,8 @@
CtClass ctClass = findCtClass(BasicComponent.class);
- InternalClassTransformation ct = new InternalClassTransformationImpl(ctClass);
+ InternalClassTransformation ct = new InternalClassTransformationImpl(ctClass,
+ _contextClassLoader);
_classPool.toClass(ctClass, childLoader);
@@ -383,7 +389,8 @@
CtClass targetObjectCtClass = findCtClass(TargetObject.class);
- InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+ InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+ _contextClassLoader);
ct.addImplementedInterface(FooInterface.class);
ct.addImplementedInterface(GetterMethodsInterface.class);
@@ -428,7 +435,8 @@
CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
- InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+ InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+ _contextClassLoader);
ct.makeReadOnly("_value");
@@ -457,6 +465,49 @@
verify();
}
+ @Test
+ public void inject_field() throws Exception
+ {
+ InternalComponentResources resources = newInternalComponentResources();
+
+ replay();
+
+ ClassLoader childLoader = newLoader();
+
+ CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
+
+ InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+ _contextClassLoader);
+
+ ct.injectField("_value", "Tapestry");
+
+ ct.finish();
+
+ Class transformed = _classPool.toClass(targetObjectCtClass, childLoader);
+
+ Object target = ct.createInstantiator(transformed).newInstance(resources);
+
+ PropertyAccess access = new PropertyAccessImpl();
+
+ assertEquals(access.get(target, "value"), "Tapestry");
+
+ try
+ {
+ access.set(target, "value", "anything");
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ // The PropertyAccess layer adds a wrapper exception around the real one.
+
+ assertEquals(
+ ex.getCause().getMessage(),
+ "Field org.apache.tapestry.internal.services.ReadOnlyBean._value is read-only.");
+ }
+
+ verify();
+ }
+
/**
* Tests the basic functionality of overriding read and write; also tests the case for multiple
* field read/field write substitions.
@@ -472,7 +523,8 @@
CtClass targetObjectCtClass = findCtClass(FieldAccessBean.class);
- InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+ InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+ _contextClassLoader);
replaceAccessToField(ct, "foo");
replaceAccessToField(ct, "bar");
@@ -568,5 +620,21 @@
// Check up on no match.
assertTrue(ct.findFieldsWithAnnotation(Deprecated.class).isEmpty());
+ }
+
+ @Test
+ public void to_class_with_primitive_type() throws Exception
+ {
+ ClassTransformation ct = createClassTransformation(AnnotatedPage.class);
+
+ assertSame(ct.toClass("float"), Float.class);
+ }
+
+ @Test
+ public void to_class_with_object_type() throws Exception
+ {
+ ClassTransformation ct = createClassTransformation(AnnotatedPage.class);
+
+ assertSame(ct.toClass("java.util.Map"), Map.class);
}
}
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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Tue Sep 5 11:14:53 2006
@@ -33,6 +33,8 @@
*/
public class ParameterWorkerTest extends InternalBaseTestCase
{
+ private final ClassLoader _contextClassLoader = Thread.currentThread().getContextClassLoader();
+
private PropertyAccess _access = new PropertyAccessImpl();
@AfterClass
@@ -342,7 +344,8 @@
loader.delegateLoadingOf("org.apache.tapestry.");
CtClass ctClass = pool.get(ParameterComponent.class.getName());
- InternalClassTransformation transformation = new InternalClassTransformationImpl(ctClass);
+ InternalClassTransformation transformation = new InternalClassTransformationImpl(ctClass,
+ _contextClassLoader);
MutableComponentModel model = newMutableComponentModel();
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java Tue Sep 5 11:14:53 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 org.apache.tapestry.internal.annotations.SuppressNullCheck;
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html Tue Sep 5 11:14:53 2006
@@ -0,0 +1,4 @@
+<t:comp id="border" type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+ <p> Demonstrates the use of the @Inject annotation. </p>
+ <p>WebRequest: <t:comp id="request" type="WriteWebRequest"/></p>
+</t:comp>