From e32b64d161654e654012f343e795d069bcf40ff8 Mon Sep 17 00:00:00 2001 From: antelder Date: Mon, 19 Sep 2011 11:45:40 +0000 Subject: TUSCANY-3948: Apply patch from Greg Dritschler to support @Remotable on implementation class, reference field, or reference setter method git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1172577 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/introspect/impl/ReferenceProcessor.java | 21 +++++++++++++++-- .../java/introspect/impl/ServiceProcessor.java | 20 +++++++---------- .../interfacedef/java/JavaInterfaceFactory.java | 10 ++++++++- .../java/impl/JavaInterfaceFactoryImpl.java | 26 +++++++++++++++++++--- .../org/oasisopen/sca/annotation/Remotable.java | 5 ++++- 5 files changed, 63 insertions(+), 19 deletions(-) diff --git a/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java b/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java index 225099758d..cb612bd224 100644 --- a/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java +++ b/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java @@ -45,6 +45,7 @@ import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; import org.oasisopen.sca.ServiceReference; import org.oasisopen.sca.annotation.AllowsPassByReference; import org.oasisopen.sca.annotation.Reference; +import org.oasisopen.sca.annotation.Remotable; /** * Processes an {@link @Reference} annotation, updating the component type with @@ -219,11 +220,27 @@ public class ReferenceProcessor extends BaseJavaClassVisitor { } baseType = JavaIntrospectionHelper.getBusinessInterface(baseType, genericType); } + // The reference can have a Remotable annotation. This forces the interface to be + // remotable even if the interface doesn't have a Remotable annotation. + boolean forceRemotable = element.getAnnotation(Remotable.class) != null; + // If the reference element is a setter method, element.getAnnotation() looks at + // the method-level annotations only. Compliance test POJO_8017 puts the + // Remotable annotation on the setter method's argument, so we need some special + // logic to look at the argument. + if (!forceRemotable && element.getElementType() == ElementType.PARAMETER && (element.getAnchor() instanceof Method)) { + Annotation argAnnotations[] = ((Method)element.getAnchor()).getParameterAnnotations()[0]; + for (int j = 0; j < argAnnotations.length; j++) { + if (argAnnotations[j].annotationType() == Remotable.class) { + forceRemotable = true; + break; + } + } + } try { - JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(baseType); + JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(baseType, forceRemotable); reference.getInterfaceContract().setInterface(callInterface); if (callInterface.getCallbackClass() != null) { - JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callInterface.getCallbackClass()); + JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callInterface.getCallbackClass(), forceRemotable); reference.getInterfaceContract().setCallbackInterface(callbackInterface); } } catch (InvalidInterfaceException e) { diff --git a/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java b/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java index 6ad2140304..b2aa01ab92 100644 --- a/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java +++ b/sca-java-2.x/trunk/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java @@ -195,8 +195,12 @@ public class ServiceProcessor extends BaseJavaClassVisitor { Service service = assemblyFactory.createService(); JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); service.setInterfaceContract(interfaceContract); - - JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(interfaze); + + // The implementation class can have a Remotable annotation. This forces all service + // interfaces to be remotable even if the interfaces do not have a Remotable annotation. + boolean forceRemotable = clazz.getAnnotation(Remotable.class) != null; + + JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(interfaze, forceRemotable); if (name == null) { String serviceName = interfaze.getSimpleName(); @@ -212,19 +216,11 @@ public class ServiceProcessor extends BaseJavaClassVisitor { } else { service.setName(name); } - - - boolean remotable = clazz.getAnnotation(Remotable.class) != null; - if (remotable){ - callInterface.setRemotable(true); - } + service.getInterfaceContract().setInterface(callInterface); if (callInterface.getCallbackClass() != null) { - JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callInterface.getCallbackClass()); - if (remotable){ - callbackInterface.setRemotable(true); - } + JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callInterface.getCallbackClass(), forceRemotable); service.getInterfaceContract().setCallbackInterface(callbackInterface); } return service; diff --git a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java index 4f4e9d8268..55d694d7f8 100644 --- a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java +++ b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java @@ -45,7 +45,15 @@ public interface JavaInterfaceFactory { * @return */ JavaInterface createJavaInterface(Class interfaceClass) throws InvalidInterfaceException; - + + /** + * Creates a new Java interface model from an interface class. + * @param interfaceClass the interface class to introspect. + * @param forceRemotable allows the caller to force the interface remotable to be remotable. + * @return + */ + JavaInterface createJavaInterface(Class interfaceClass, boolean forceRemotable) throws InvalidInterfaceException; + /** * Creates the contents of a Java interface model from an interface class. * @param javaInterface the Java interface model diff --git a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java index dbedf1d55a..8229c7812d 100644 --- a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java +++ b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java @@ -41,8 +41,9 @@ public abstract class JavaInterfaceFactoryImpl implements JavaInterfaceFactory { private List visitors = new ArrayList(); private JavaInterfaceIntrospectorImpl introspector; - private Map, JavaInterface> cache = Collections.synchronizedMap(new WeakHashMap, JavaInterface>()); - + private Map, JavaInterface> normalCache = Collections.synchronizedMap(new WeakHashMap, JavaInterface>()); + private Map, JavaInterface> forceRemotableCache = Collections.synchronizedMap(new WeakHashMap, JavaInterface>()); + public JavaInterfaceFactoryImpl() { introspector = new JavaInterfaceIntrospectorImpl(this); } @@ -50,13 +51,32 @@ public abstract class JavaInterfaceFactoryImpl implements JavaInterfaceFactory { public JavaInterface createJavaInterface() { return new JavaInterfaceImpl(); } - + public JavaInterface createJavaInterface(Class interfaceClass) throws InvalidInterfaceException { + return createJavaInterface(interfaceClass, false); + } + + /** + * Creates a new Java interface model from an interface class. + * + * The forceRemotable argument allows the caller to force the interface to be remotable. + * The ServiceProcessor and ReferenceProcessor introspectors use this argument to + * propagate a @Remotable annotation on an implementation class, field, or setter method + * to the corresponding service or reference interface. The remotable flag must be set + * on the interface model prior to instrospection since some introspectors build + * different models for remotable vs local interfaces. This also means separate caches + * must be kept for interfaces that are processed normally vs. those forced to be remotable. + */ + public JavaInterface createJavaInterface(Class interfaceClass, boolean forceRemotable) throws InvalidInterfaceException { // TODO: Review if the sharing of JavaInterface is ok synchronized (interfaceClass) { + Map, JavaInterface> cache = (forceRemotable ? forceRemotableCache : normalCache); JavaInterface javaInterface = cache.get(interfaceClass); if (javaInterface == null) { javaInterface = createJavaInterface(); + if (forceRemotable) { + javaInterface.setRemotable(true); + } introspector.introspectInterface(javaInterface, interfaceClass); // Now that all introspection is complete we can mark the interface resolved javaInterface.setUnresolved(false); diff --git a/sca-java-2.x/trunk/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Remotable.java b/sca-java-2.x/trunk/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Remotable.java index 50f3557bed..e7ddbace7d 100644 --- a/sca-java-2.x/trunk/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Remotable.java +++ b/sca-java-2.x/trunk/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Remotable.java @@ -5,6 +5,9 @@ package org.oasisopen.sca.annotation; import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -16,7 +19,7 @@ import java.lang.annotation.Target; * * The @Remotable annotation has no attributes. */ -@Target(TYPE) +@Target({TYPE,METHOD,FIELD,PARAMETER}) @Retention(RUNTIME) public @interface Remotable { -- cgit v1.2.3