You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by dr...@apache.org on 2010/07/28 08:36:49 UTC
svn commit: r979956 - in /tapestry/tapestry5/trunk/tapestry-ioc/src:
main/java/org/apache/tapestry5/ioc/
main/java/org/apache/tapestry5/ioc/internal/
main/java/org/apache/tapestry5/ioc/internal/services/
main/java/org/apache/tapestry5/ioc/internal/util...
Author: drobiazko
Date: Wed Jul 28 06:36:48 2010
New Revision: 979956
URL: http://svn.apache.org/viewvc?rev=979956&view=rev
Log:
TAP5-335: Provide access to annotations of service implementation class
Added:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java (with props)
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java (with props)
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java (with props)
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java (with props)
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AbstractFab.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFabImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFab.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFactory.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/StringHolderImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/RecursiveServiceCreationCheckWrapperTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFabImplTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImplTest.java
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java Wed Jul 28 06:36:48 2010
@@ -45,4 +45,11 @@ public interface ServiceResources extend
* initializing the service.
*/
OperationTracker getTracker();
+
+ /**
+ * Returns the service implementation class.
+ *
+ * @since 5.2.0
+ */
+ Class getImplementationClass();
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java Wed Jul 28 06:36:48 2010
@@ -461,7 +461,7 @@ public class DefaultModuleDefImpl implem
Set<Class> markers = CollectionFactory.newSet(defaultMarkers);
markers.addAll(extractServiceDefMarkers(method));
- ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, serviceId, markers, scope, eagerLoad,
+ ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, null, serviceId, markers, scope, eagerLoad,
preventDecoration, source);
addServiceDef(serviceDef);
Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java?rev=979956&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java Wed Jul 28 06:36:48 2010
@@ -0,0 +1,26 @@
+// Copyright 2010 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.tapestry5.ioc.internal;
+
+import org.apache.tapestry5.ioc.def.ServiceDef2;
+
+public interface InternalServiceDef extends ServiceDef2
+{
+ /**
+ * Returns the service implementation class.
+ *
+ * @return implementations class or {@code null}
+ */
+ Class getImplementationClass();
+}
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalServiceDef.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java Wed Jul 28 06:36:48 2010
@@ -472,10 +472,10 @@ public class ModuleImpl implements Modul
String toString = format("<Proxy for %s(%s)>", serviceId, serviceInterface.getName());
- return createProxyInstance(creator, serviceId, serviceInterface, toString);
+ return createProxyInstance(creator, serviceId, serviceInterface, resources.getImplementationClass(), toString);
}
- private Object createProxyInstance(ObjectCreator creator, String serviceId, Class serviceInterface,
+ private Object createProxyInstance(ObjectCreator creator, String serviceId, Class serviceInterface, Class serviceImplementation,
String description)
{
ServiceProxyToken token = SerializationSupport.createToken(serviceId);
@@ -508,6 +508,13 @@ public class ModuleImpl implements Modul
classFab.addMethod(Modifier.PRIVATE, sig, body);
classFab.proxyMethodsToDelegate(serviceInterface, "delegate()", description);
+
+ if(serviceImplementation != null)
+ {
+ classFab.copyClassAnnotationsFromDelegate(serviceImplementation);
+
+ classFab.copyMethodAnnotationsFromDelegate(serviceInterface, serviceImplementation);
+ }
Class proxyClass = classFab.createClass();
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java Wed Jul 28 06:36:48 2010
@@ -1026,7 +1026,7 @@ public class RegistryImpl implements Reg
}
};
- return classFactory.createProxy(interfaceClass, justInTime,
+ return classFactory.createProxy(interfaceClass, implementationClass, justInTime,
String.format("<Autobuild proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
}
@@ -1038,7 +1038,7 @@ public class RegistryImpl implements Reg
getService(UpdateListenerHub.class).addUpdateListener(creator);
- return classFactory.createProxy(interfaceClass, creator,
+ return classFactory.createProxy(interfaceClass, implementationClass, creator,
String.format("<Autoreload proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java Wed Jul 28 06:36:48 2010
@@ -73,6 +73,6 @@ public class ReloadableObjectCreatorSour
if (eagerLoad)
reloadableCreator.createObject();
- return classFactory.createProxy(serviceInterfaceClass, reloadableCreator, getDescription());
+ return classFactory.createProxy(serviceInterfaceClass, serviceImplementationClass, reloadableCreator, getDescription());
}
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java Wed Jul 28 06:36:48 2010
@@ -104,7 +104,7 @@ public class ServiceBinderImpl implement
Set<Class> markers = CollectionFactory.newSet(defaultMarkers);
markers.addAll(this.markers);
- ServiceDef serviceDef = new ServiceDefImpl(serviceInterface, serviceId, markers, scope, eagerLoad,
+ ServiceDef serviceDef = new ServiceDefImpl(serviceInterface, serviceImplementation, serviceId, markers, scope, eagerLoad,
preventDecoration, source);
accumulator.addServiceDef(serviceDef);
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java Wed Jul 28 06:36:48 2010
@@ -14,15 +14,16 @@
package org.apache.tapestry5.ioc.internal;
+import java.util.Set;
+
import org.apache.tapestry5.ioc.ObjectCreator;
import org.apache.tapestry5.ioc.ServiceBuilderResources;
-import org.apache.tapestry5.ioc.def.ServiceDef2;
-
-import java.util.Set;
-public class ServiceDefImpl implements ServiceDef2
+public class ServiceDefImpl implements InternalServiceDef
{
private final Class serviceInterface;
+
+ private final Class serviceImplementation;
private final String serviceId;
@@ -39,6 +40,7 @@ public class ServiceDefImpl implements S
/**
* @param serviceInterface interface implemented by the service (or the service implementation class, for
* non-proxied services)
+ * @param serviceImplementation service implementation class if exists
* @param serviceId unique id for the service
* @param markers set of marker annotation classes (will be retained not copied)
* @param scope scope of the service (i.e., {@link org.apache.tapestry5.ioc.ScopeConstants#DEFAULT}).
@@ -46,10 +48,11 @@ public class ServiceDefImpl implements S
* @param preventDecoration if true, the service may not be decorated
* @param source used to create the service implementation when needed
*/
- ServiceDefImpl(Class serviceInterface, String serviceId, Set<Class> markers, String scope,
+ ServiceDefImpl(Class serviceInterface, Class serviceImplementation, String serviceId, Set<Class> markers, String scope,
boolean eagerLoad, boolean preventDecoration, ObjectCreatorSource source)
{
this.serviceInterface = serviceInterface;
+ this.serviceImplementation = serviceImplementation;
this.serviceId = serviceId;
this.scope = scope;
this.eagerLoad = eagerLoad;
@@ -99,4 +102,9 @@ public class ServiceDefImpl implements S
{
return preventDecoration;
}
+
+ public Class getImplementationClass()
+ {
+ return serviceImplementation;
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java Wed Jul 28 06:36:48 2010
@@ -44,7 +44,7 @@ public class ServiceResourcesImpl extend
private final Module module;
- private final ServiceDef serviceDef;
+ private final InternalServiceDef serviceDef;
private final Logger logger;
@@ -57,7 +57,7 @@ public class ServiceResourcesImpl extend
this.registry = registry;
this.module = module;
- this.serviceDef = serviceDef;
+ this.serviceDef = InternalUtils.toInternalServiceDef(serviceDef);
this.classFactory = classFactory;
this.logger = logger;
}
@@ -174,4 +174,9 @@ public class ServiceResourcesImpl extend
{
return registry;
}
+
+ public Class getImplementationClass()
+ {
+ return serviceDef.getImplementationClass();
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AbstractFab.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AbstractFab.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AbstractFab.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AbstractFab.java Wed Jul 28 06:36:48 2010
@@ -98,5 +98,10 @@ public class AbstractFab
{
return source;
}
+
+ protected Logger getLogger()
+ {
+ return logger;
+ }
}
Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java?rev=979956&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java Wed Jul 28 06:36:48 2010
@@ -0,0 +1,178 @@
+// Copyright 2010 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.tapestry5.ioc.internal.services;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import javassist.bytecode.ConstPool;
+import javassist.bytecode.annotation.Annotation;
+import javassist.bytecode.annotation.AnnotationMemberValue;
+import javassist.bytecode.annotation.ArrayMemberValue;
+import javassist.bytecode.annotation.BooleanMemberValue;
+import javassist.bytecode.annotation.ByteMemberValue;
+import javassist.bytecode.annotation.CharMemberValue;
+import javassist.bytecode.annotation.ClassMemberValue;
+import javassist.bytecode.annotation.DoubleMemberValue;
+import javassist.bytecode.annotation.EnumMemberValue;
+import javassist.bytecode.annotation.FloatMemberValue;
+import javassist.bytecode.annotation.IntegerMemberValue;
+import javassist.bytecode.annotation.LongMemberValue;
+import javassist.bytecode.annotation.MemberValue;
+import javassist.bytecode.annotation.MemberValueVisitor;
+import javassist.bytecode.annotation.ShortMemberValue;
+import javassist.bytecode.annotation.StringMemberValue;
+
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+public class AnnotationMemberValueVisitor implements MemberValueVisitor
+{
+ private final ConstPool constPool;
+
+ private final CtClassSource classSource;
+
+ private final Object value;
+
+ public AnnotationMemberValueVisitor(final ConstPool constPool, final CtClassSource classSource, final Object value)
+ {
+ this.constPool = constPool;
+ this.classSource = classSource;
+ this.value = value;
+ }
+
+ public void visitAnnotationMemberValue(final AnnotationMemberValue mb)
+ {
+ Class annotationType = getClass(value);
+
+ final Method[] methods = annotationType.getDeclaredMethods();
+
+ for (final Method method : methods)
+ {
+ try
+ {
+ final Object result = method.invoke(value);
+
+ final MemberValue memberValue = Annotation.createMemberValue(
+ this.constPool,
+ this.classSource.toCtClass(result.getClass()));
+
+ memberValue.accept(new AnnotationMemberValueVisitor(this.constPool, this.classSource, result));
+
+ mb.getValue().addMemberValue(method.getName(), memberValue);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ public void visitArrayMemberValue(final ArrayMemberValue mb)
+ {
+ final Object[] array = (Object[]) this.value;
+
+ final List<MemberValue> members = CollectionFactory.newList();
+
+ for (final Object object : array)
+ {
+ try
+ {
+ final MemberValue memberValue = Annotation.createMemberValue(
+ this.constPool,
+ this.classSource.toCtClass(getClass(object)));
+
+ memberValue.accept(new AnnotationMemberValueVisitor(this.constPool, this.classSource, object));
+
+ members.add(memberValue);
+ }
+ catch (final Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ mb.setValue(members.toArray(new MemberValue[] {}));
+ }
+
+ private Class getClass(Object object)
+ {
+ if(object instanceof java.lang.annotation.Annotation)
+ {
+ return ((java.lang.annotation.Annotation)object).annotationType();
+ }
+
+ return object.getClass();
+ }
+
+ public void visitBooleanMemberValue(final BooleanMemberValue mb)
+ {
+ mb.setValue((Boolean) this.value);
+ }
+
+ public void visitByteMemberValue(final ByteMemberValue mb)
+ {
+ mb.setValue((Byte) this.value);
+ }
+
+ public void visitCharMemberValue(final CharMemberValue mb)
+ {
+ mb.setValue((Character) this.value);
+ }
+
+ public void visitDoubleMemberValue(final DoubleMemberValue mb)
+ {
+ mb.setValue((Double) this.value);
+ }
+
+ public void visitEnumMemberValue(final EnumMemberValue mb)
+ {
+ final Enum enumeration = (Enum) this.value;
+
+ final Class type = enumeration.getDeclaringClass();
+ mb.setType(type.getName());
+ mb.setValue(enumeration.name());
+ }
+
+ public void visitFloatMemberValue(final FloatMemberValue mb)
+ {
+ mb.setValue((Float) this.value);
+ }
+
+ public void visitIntegerMemberValue(final IntegerMemberValue mb)
+ {
+ mb.setValue((Integer) this.value);
+ }
+
+ public void visitLongMemberValue(final LongMemberValue mb)
+ {
+ mb.setValue((Long) this.value);
+ }
+
+ public void visitShortMemberValue(final ShortMemberValue mb)
+ {
+ mb.setValue((Short) this.value);
+ }
+
+ public void visitStringMemberValue(final StringMemberValue mb)
+ {
+ mb.setValue((String) this.value);
+ }
+
+ public void visitClassMemberValue(final ClassMemberValue mb)
+ {
+ mb.setValue(((Class) this.value).getName());
+ }
+
+}
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AnnotationMemberValueVisitor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFabImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFabImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFabImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFabImpl.java Wed Jul 28 06:36:48 2010
@@ -18,6 +18,8 @@ import static java.lang.String.format;
import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newSet;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Formatter;
import java.util.Map;
@@ -29,6 +31,11 @@ import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.NotFoundException;
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.ConstPool;
+import javassist.bytecode.MethodInfo;
+import javassist.bytecode.annotation.MemberValue;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.services.ClassFab;
@@ -337,4 +344,164 @@ public class ClassFabImpl extends Abstra
description.append("\n");
description.append(body);
}
+
+ public void copyClassAnnotationsFromDelegate(Class delegateClass)
+ {
+ lock.check();
+
+ for (Annotation annotation : delegateClass.getAnnotations())
+ {
+ try
+ {
+ addAnnotation(annotation);
+ }
+ catch (RuntimeException ex)
+ {
+ //Annotation processing may cause exceptions thrown by Javassist.
+ //To provide backward compatibility we have to continue even though copying a particular annotation failed.
+ getLogger().error(String.format("Failed to copy annotation '%s' from '%s'", annotation.annotationType(), delegateClass.getName()));
+ }
+ }
+ }
+
+ public void copyMethodAnnotationsFromDelegate(Class serviceInterface, Class delegateClass)
+ {
+ lock.check();
+
+ for(MethodSignature sig: addedSignatures)
+ {
+ if(getMethod(sig, serviceInterface) == null)
+ continue;
+
+ Method method = getMethod(sig, delegateClass);
+
+ assert method != null;
+
+ Annotation[] annotations = method.getAnnotations();
+
+ for (Annotation annotation : annotations)
+ {
+ try
+ {
+ addMethodAnnotation(getCtMethod(sig), annotation);
+ }
+ catch (RuntimeException ex)
+ {
+ //Annotation processing may cause exceptions thrown by Javassist.
+ //To provide backward compatibility we have to continue even though copying a particular annotation failed.
+ getLogger().error(String.format("Failed to copy annotation '%s' from method '%s' of class '%s'",
+ annotation.annotationType(), method.getName(), delegateClass.getName()));
+ }
+ }
+ }
+ }
+
+ private CtMethod getCtMethod(MethodSignature sig)
+ {
+ try
+ {
+ return getCtClass().getDeclaredMethod(sig.getName(), toCtClasses(sig.getParameterTypes()));
+ }
+ catch (NotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Method getMethod(MethodSignature sig, Class clazz)
+ {
+ try
+ {
+ return clazz.getMethod(sig.getName(), sig.getParameterTypes());
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ private void addAnnotation(Annotation annotation)
+ {
+
+ final ClassFile classFile = getClassFile();
+
+ AnnotationsAttribute attribute = (AnnotationsAttribute) classFile.getAttribute(AnnotationsAttribute.visibleTag);
+
+ if (attribute == null)
+ {
+ attribute = new AnnotationsAttribute(getConstPool(), AnnotationsAttribute.visibleTag);
+ }
+
+ final javassist.bytecode.annotation.Annotation copy = toJavassistAnnotation(annotation);
+
+
+ attribute.addAnnotation(copy);
+
+ classFile.addAttribute(attribute);
+
+ }
+
+ private void addMethodAnnotation(final CtMethod ctMethod, final Annotation annotation) {
+
+ MethodInfo methodInfo = ctMethod.getMethodInfo();
+
+ AnnotationsAttribute attribute = (AnnotationsAttribute) methodInfo
+ .getAttribute(AnnotationsAttribute.visibleTag);
+
+ if (attribute == null) {
+ attribute = new AnnotationsAttribute(getConstPool(), AnnotationsAttribute.visibleTag);
+ }
+
+ final javassist.bytecode.annotation.Annotation copy = toJavassistAnnotation(annotation);
+
+ attribute.addAnnotation(copy);
+
+ methodInfo.addAttribute(attribute);
+
+ }
+
+
+ private ClassFile getClassFile()
+ {
+ return getCtClass().getClassFile();
+ }
+
+ private ConstPool getConstPool()
+ {
+ return getClassFile().getConstPool();
+ }
+
+ private javassist.bytecode.annotation.Annotation toJavassistAnnotation(final Annotation source)
+ {
+
+ final Class<? extends Annotation> annotationType = source.annotationType();
+
+ final ConstPool constPool = getConstPool();
+
+ final javassist.bytecode.annotation.Annotation copy = new javassist.bytecode.annotation.Annotation(
+ annotationType.getName(), constPool);
+
+ final Method[] methods = annotationType.getDeclaredMethods();
+
+ for (final Method method : methods)
+ {
+ try
+ {
+ CtClass ctType = toCtClass(method.getReturnType());
+
+ final MemberValue memberValue = javassist.bytecode.annotation.Annotation.createMemberValue(constPool, ctType);
+ final Object value = method.invoke(source);
+
+ memberValue.accept(new AnnotationMemberValueVisitor(constPool, getSource(), value));
+
+ copy.addMemberValue(method.getName(), memberValue);
+ }
+ catch (final Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return copy;
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImpl.java Wed Jul 28 06:36:48 2010
@@ -16,6 +16,7 @@ package org.apache.tapestry5.ioc.interna
import static java.lang.String.format;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -227,6 +228,11 @@ public class ClassFactoryImpl implements
public <T> T createProxy(Class<T> proxyInterface, ObjectCreator delegateCreator, String description)
{
+ return createProxy(proxyInterface, null, delegateCreator, description);
+ }
+
+ public <T> T createProxy(Class<T> proxyInterface, Class<? extends T> delegateClass, ObjectCreator delegateCreator, String description)
+ {
ClassFab classFab = newClass(proxyInterface);
classFab.addField("_creator", Modifier.PRIVATE | Modifier.FINAL, ObjectCreator.class);
@@ -239,8 +245,16 @@ public class ClassFactoryImpl implements
MethodSignature sig = new MethodSignature(proxyInterface, "_delegate", null, null);
classFab.addMethod(Modifier.PRIVATE, sig, body);
-
+
classFab.proxyMethodsToDelegate(proxyInterface, "_delegate()", description);
+
+ if(delegateClass != null)
+ {
+ classFab.copyClassAnnotationsFromDelegate(delegateClass);
+
+ classFab.copyMethodAnnotationsFromDelegate(proxyInterface, (Class)delegateClass);
+ }
+
Class proxyClass = classFab.createClass();
try
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java Wed Jul 28 06:36:48 2010
@@ -48,6 +48,7 @@ import org.apache.tapestry5.ioc.def.Modu
import org.apache.tapestry5.ioc.def.ServiceDef;
import org.apache.tapestry5.ioc.def.ServiceDef2;
import org.apache.tapestry5.ioc.def.StartupDef;
+import org.apache.tapestry5.ioc.internal.InternalServiceDef;
import org.apache.tapestry5.ioc.services.ClassFabUtils;
import org.apache.tapestry5.ioc.services.ClassFactory;
import org.apache.tapestry5.ioc.services.Coercion;
@@ -797,6 +798,55 @@ public class InternalUtils
+ "You should make the constructor public, or mark an alternate public constructor with the @Inject annotation.",
constructor));
}
+
+ public static InternalServiceDef toInternalServiceDef(final ServiceDef sd)
+ {
+ if (sd instanceof InternalServiceDef)
+ return (InternalServiceDef) sd;
+
+ return new InternalServiceDef()
+ {
+ public boolean isPreventDecoration()
+ {
+ return false;
+ }
+
+ public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
+ {
+ return sd.createServiceCreator(resources);
+ }
+
+ public String getServiceId()
+ {
+ return sd.getServiceId();
+ }
+
+ public Set<Class> getMarkers()
+ {
+ return sd.getMarkers();
+ }
+
+ public Class getServiceInterface()
+ {
+ return sd.getServiceInterface();
+ }
+
+ public String getServiceScope()
+ {
+ return sd.getServiceScope();
+ }
+
+ public boolean isEagerLoad()
+ {
+ return sd.isEagerLoad();
+ }
+
+ public Class getImplementationClass()
+ {
+ return null;
+ }
+ };
+ }
public static ServiceDef2 toServiceDef2(final ServiceDef sd)
{
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFab.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFab.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFab.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFab.java Wed Jul 28 06:36:48 2010
@@ -90,6 +90,25 @@ public interface ClassFab
* @param toString fixed value to be returned as the description of the resultant object
*/
void proxyMethodsToDelegate(Class serviceInterface, String delegateExpression, String toString);
+
+ /**
+ * Copies annotations from delegate class to the fabricated class.
+ *
+ * @param delegateClass class of the delegate
+ *
+ * @since 5.2.0
+ */
+ void copyClassAnnotationsFromDelegate(Class delegateClass);
+
+ /**
+ * Copies method annotations from delegate class to the methods of the fabricated class.
+ *
+ * @param serviceInterface service interface
+ * @param delegateClass class of the delegate
+ *
+ * @since 5.2.0
+ */
+ void copyMethodAnnotationsFromDelegate(Class serviceInterface, Class delegateClass);
/**
* Invoked last to create the class. This will enforce that all abstract methods have been implemented in the
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFactory.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFactory.java Wed Jul 28 06:36:48 2010
@@ -95,9 +95,31 @@ public interface ClassFactory
* type of proxy
* @param proxyInterface
* proxy interface class
+ * @parame delegateCreator
+ * creates the delegate
* @param description
* used for the toString() method
* @since 5.2.0
*/
<T> T createProxy(Class<T> proxyInterface, ObjectCreator delegateCreator, String description);
+
+ /**
+ * Creates a proxy for an interface. All methods of the interface are delegated through the
+ * object returned from the {@link ObjectCreator} (which is accessed on each method invocation, so it
+ * is responsible for caching of the true delegate). The description will be used for the toString() method
+ * (unless toString() is part of the proxy interface).
+ *
+ * @param <T>
+ * type of proxy
+ * @param proxyInterface
+ * proxy interface class
+ * @parame delegateClass
+ * delegate class
+ * @parame delegateCreator
+ * creates the delegate
+ * @param description
+ * used for the toString() method
+ * @since 5.2.0
+ */
+ <T> T createProxy(Class<T> proxyInterface, Class<? extends T> delegateClass, ObjectCreator delegateCreator, String description);
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java Wed Jul 28 06:36:48 2010
@@ -15,6 +15,7 @@
package org.apache.tapestry5.ioc;
import java.io.File;
+import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.PreparedStatement;
@@ -31,6 +32,7 @@ import org.apache.tapestry5.ioc.internal
import org.apache.tapestry5.ioc.internal.IOCInternalTestCase;
import org.apache.tapestry5.ioc.internal.PrivateConstructorModule;
import org.apache.tapestry5.ioc.internal.UpcaseService;
+import org.apache.tapestry5.ioc.internal.services.SimpleAnnotation;
import org.apache.tapestry5.ioc.internal.services.StartupModule2;
import org.apache.tapestry5.ioc.services.Builtin;
import org.apache.tapestry5.ioc.services.ServiceActivity;
@@ -409,6 +411,26 @@ public class IntegrationTest extends IOC
r.shutdown();
}
+
+ @Test
+ public void proxy_annotations() throws Exception
+ {
+ Registry r = buildRegistry(AutobuildModule.class);
+
+ StringHolder sh = r.getService(StringHolder.class);
+
+ SimpleAnnotation annotation = sh.getClass().getAnnotation(SimpleAnnotation.class);
+ assertNotNull(annotation);
+ assertEquals(annotation.value(), "StringHolderImpl");
+
+ Method method = sh.getClass().getMethod("getValue");
+
+ annotation = method.getAnnotation(SimpleAnnotation.class);
+ assertNotNull(annotation);
+ assertEquals(annotation.value(), "StringHolderImpl#getValue()");
+
+ r.shutdown();
+ }
@Test
public void exception_in_autobuild_service_constructor()
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/StringHolderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/StringHolderImpl.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/StringHolderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/StringHolderImpl.java Wed Jul 28 06:36:48 2010
@@ -14,13 +14,17 @@
package org.apache.tapestry5.ioc;
+import org.apache.tapestry5.ioc.internal.services.SimpleAnnotation;
+
/**
*
*/
+@SimpleAnnotation("StringHolderImpl")
public class StringHolderImpl implements StringHolder
{
private String value;
+ @SimpleAnnotation("StringHolderImpl#getValue()")
public String getValue()
{
return value;
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/RecursiveServiceCreationCheckWrapperTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/RecursiveServiceCreationCheckWrapperTest.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/RecursiveServiceCreationCheckWrapperTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/RecursiveServiceCreationCheckWrapperTest.java Wed Jul 28 06:36:48 2010
@@ -32,7 +32,7 @@ public class RecursiveServiceCreationChe
ObjectCreator delegate = mockObjectCreator();
Object service = new Object();
- ServiceDef def = new ServiceDefImpl(Runnable.class, "Bar", null, "singleton", false, false, source);
+ ServiceDef def = new ServiceDefImpl(Runnable.class, null, "Bar", null, "singleton", false, false, source);
train_createObject(delegate, service);
@@ -70,7 +70,7 @@ public class RecursiveServiceCreationChe
ObjectCreator delegate = mockObjectCreator();
Object service = new Object();
- ServiceDef def = new ServiceDefImpl(Runnable.class, "Bar", null, "singleton", false, false, source);
+ ServiceDef def = new ServiceDefImpl(Runnable.class, null, "Bar", null, "singleton", false, false, source);
expect(delegate.createObject()).andThrow(failure);
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFabImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFabImplTest.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFabImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFabImplTest.java Wed Jul 28 06:36:48 2010
@@ -14,9 +14,24 @@
package org.apache.tapestry5.ioc.internal.services;
+import static java.util.Arrays.asList;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.DataFormatException;
+
import javassist.CtClass;
+
import org.apache.tapestry5.ioc.BaseLocatable;
+import org.apache.tapestry5.ioc.annotations.ServiceId;
import org.apache.tapestry5.ioc.internal.services.LoggingDecoratorImplTest.ToStringService;
+import org.apache.tapestry5.ioc.internal.services.TestAnnotation.Color;
+import org.apache.tapestry5.ioc.internal.services.TestAnnotation.TestAnnotation2;
import org.apache.tapestry5.ioc.services.ClassFab;
import org.apache.tapestry5.ioc.services.MethodSignature;
import org.apache.tapestry5.ioc.services.PropertyAccess;
@@ -24,13 +39,6 @@ import org.apache.tapestry5.ioc.test.IOC
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
-import java.io.Serializable;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.DataFormatException;
-
public class ClassFabImplTest extends IOCTestCase
{
private final CtClassSource source;
@@ -50,6 +58,46 @@ public class ClassFabImplTest extends IO
{
String toString();
}
+
+ public interface AnnotatedService
+ {
+ void doWork(final String value);
+ }
+
+ @ServiceId(value = "myService")
+ @TestAnnotation(annotationValue={@TestAnnotation2(colors={Color.RED, Color.GREEN})},
+ booleanValue = true,
+ charValue = 'I',
+ byteValue = 97,
+ classValue = AnnotatedServiceImpl.class,
+ doubleValue = 3.14,
+ enumValue = Color.RED,
+ floatValue = 2.718F,
+ intValue = 123,
+ longValue = 456L,
+ shortValue = 3,
+ stringValue = "foo")
+ public class AnnotatedServiceImpl implements AnnotatedService
+ {
+
+ @TestAnnotation(annotationValue=@TestAnnotation2(colors={Color.BLUE, Color.GREEN}),
+ arrayValue={"barney"},
+ booleanValue = false,
+ charValue = 'D',
+ byteValue = 56,
+ classValue = String.class,
+ doubleValue = 3.14,
+ enumValue = Color.BLUE,
+ floatValue = 2.718F,
+ intValue = 456,
+ longValue = 789L,
+ shortValue = 4,
+ stringValue = "bar")
+ public void doWork(final String value)
+ {
+
+ }
+ }
public ClassFabImplTest()
{
@@ -424,6 +472,68 @@ public class ClassFabImplTest extends IO
assertEquals(access.get(instance, "int"), 0);
assertEquals(access.get(instance, "double"), 0.0d);
}
+
+
+ @Test
+ public void add_annotation() throws Exception
+ {
+ final ClassFab cf = newClassFab("AnnotatedClass", Object.class);
+
+ cf.addField("_delegate", AnnotatedService.class);
+ cf.addConstructor(new Class[] { AnnotatedService.class }, null, "_delegate = $1;");
+
+ cf.proxyMethodsToDelegate(AnnotatedService.class, "_delegate", "Bla bla");
+ cf.copyClassAnnotationsFromDelegate(AnnotatedServiceImpl.class);
+ cf.copyMethodAnnotationsFromDelegate(AnnotatedService.class, AnnotatedServiceImpl.class);
+
+ final Class targetClass = cf.createClass();
+
+ final TestAnnotation a = (TestAnnotation) targetClass.getAnnotation(TestAnnotation.class);
+
+ assertNotNull(a);
+
+ TestAnnotation2 a2 = a.annotationValue()[0];
+
+ assertNotNull(a2);
+ assertEquals(asList(a2.colors()), asList(Color.RED, Color.GREEN));
+
+ assertEquals(asList(a.arrayValue()), asList("foo", "bar"));
+ assertTrue(a.booleanValue());
+ assertEquals(a.byteValue(), 97);
+ assertEquals(a.charValue(), 'I');
+ assertEquals(a.classValue(), AnnotatedServiceImpl.class);
+ assertEquals(a.doubleValue(), 3.14);
+ assertEquals(a.enumValue(), Color.RED);
+ assertEquals(a.floatValue(), 2.718F);
+ assertEquals(a.intValue(), 123);
+ assertEquals(a.longValue(), 456L);
+ assertEquals(a.shortValue(), 3);
+ assertEquals(a.stringValue(), "foo");
+
+ assertNotNull(targetClass.getAnnotation(ServiceId.class));
+
+ Method method = targetClass.getMethod("doWork", String.class);
+ TestAnnotation methodAnnotation = method.getAnnotation(TestAnnotation.class);
+
+ assertNotNull(methodAnnotation);
+
+ a2 = methodAnnotation.annotationValue()[0];
+
+ assertNotNull(a2);
+ assertEquals(asList(a2.colors()), asList(Color.BLUE, Color.GREEN));
+ assertEquals(Arrays.asList(methodAnnotation.arrayValue()), Arrays.asList("barney"));
+ assertFalse(methodAnnotation.booleanValue());
+ assertEquals(methodAnnotation.byteValue(), 56);
+ assertEquals(methodAnnotation.charValue(), 'D');
+ assertEquals(methodAnnotation.classValue(), String.class);
+ assertEquals(methodAnnotation.doubleValue(), 3.14);
+ assertEquals(methodAnnotation.enumValue(), Color.BLUE);
+ assertEquals(methodAnnotation.floatValue(), 2.718F);
+ assertEquals(methodAnnotation.intValue(), 456);
+ assertEquals(methodAnnotation.longValue(), 789L);
+ assertEquals(methodAnnotation.shortValue(), 4);
+ assertEquals(methodAnnotation.stringValue(), "bar");
+ }
private void assertContains(String actual, String expectedSubstring)
{
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImplTest.java?rev=979956&r1=979955&r2=979956&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClassFactoryImplTest.java Wed Jul 28 06:36:48 2010
@@ -14,7 +14,12 @@
package org.apache.tapestry5.ioc.internal.services;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
import org.apache.tapestry5.ioc.Location;
+import org.apache.tapestry5.ioc.ObjectCreator;
import org.apache.tapestry5.ioc.internal.util.LocationImpl;
import org.apache.tapestry5.ioc.services.ClassFab;
import org.apache.tapestry5.ioc.services.ClassFabUtils;
@@ -23,10 +28,6 @@ import org.apache.tapestry5.ioc.services
import org.apache.tapestry5.ioc.test.IOCTestCase;
import org.testng.annotations.Test;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
public class ClassFactoryImplTest extends IOCTestCase
{
public static class BaseClass
@@ -170,4 +171,47 @@ public class ClassFactoryImplTest extend
assertSame(factory.importClass(alienClass), clazz);
}
+
+
+ @Test
+ public void with_annotations() throws Exception
+ {
+ ClassFactory factory = new ClassFactoryImpl();
+
+ TestService proxy = factory.createProxy(TestService.class, TestServiceImpl.class, new ObjectCreator()
+ {
+ public Object createObject()
+ {
+ return new TestServiceImpl();
+ }
+ }, "Proxy<TestService>");
+
+ Class clazz = proxy.getClass();
+
+ SimpleAnnotation annotation = (SimpleAnnotation) clazz.getAnnotation(SimpleAnnotation.class);
+
+ assertNotNull(annotation);
+ assertEquals(annotation.value(), "TestServiceImpl");
+
+ Method method = clazz.getMethod("doSomething");
+
+ annotation = method.getAnnotation(SimpleAnnotation.class);
+ assertEquals(annotation.value(), "TestServiceImpl#doSomething");
+ }
+
+
+ public interface TestService
+ {
+ void doSomething();
+ }
+
+ @SimpleAnnotation("TestServiceImpl")
+ public class TestServiceImpl implements TestService
+ {
+ @SimpleAnnotation("TestServiceImpl#doSomething")
+ public void doSomething()
+ {
+
+ }
+ }
}
Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java?rev=979956&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java Wed Jul 28 06:36:48 2010
@@ -0,0 +1,30 @@
+// Copyright 2010 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.tapestry5.ioc.internal.services;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({ TYPE, METHOD })
+@Retention(RUNTIME)
+@Documented
+public @interface SimpleAnnotation
+{
+ String value();
+}
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/SimpleAnnotation.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java?rev=979956&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java Wed Jul 28 06:36:48 2010
@@ -0,0 +1,68 @@
+// Copyright 2010 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.tapestry5.ioc.internal.services;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({ TYPE, METHOD })
+@Retention(RUNTIME)
+@Documented
+public @interface TestAnnotation
+{
+
+ TestAnnotation2[] annotationValue();
+
+ String[] arrayValue() default { "foo", "bar" };
+
+ boolean booleanValue();
+
+ byte byteValue();
+
+ char charValue();
+
+ Class classValue();
+
+ double doubleValue();
+
+ Color enumValue();
+
+ float floatValue();
+
+ int intValue();
+
+ long longValue();
+
+ short shortValue();
+
+ String stringValue();
+
+ public enum Color
+ {
+ RED, GREEN, BLUE
+ }
+
+ @Target({ TYPE, METHOD })
+ @Retention(RUNTIME)
+ @Documented
+ public @interface TestAnnotation2
+ {
+ Color[] colors();
+ }
+}
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TestAnnotation.java
------------------------------------------------------------------------------
svn:mime-type = text/plain