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 2010/03/12 06:21:02 UTC

svn commit: r922143 - in /tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc: internal/RegistryImpl.java internal/services/ClassFactoryImpl.java services/ClassFabUtils.java services/ClassFactory.java

Author: hlship
Date: Fri Mar 12 05:21:02 2010
New Revision: 922143

URL: http://svn.apache.org/viewvc?rev=922143&view=rev
Log:
TAP5-1013: Add new method createProxy() to ClassFactory

Modified:
    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/services/ClassFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFactory.java

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=922143&r1=922142&r2=922143&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 Fri Mar 12 05:21:02 2010
@@ -195,53 +195,49 @@ public class RegistryImpl implements Reg
         for (ContributionDef cd : contributionDefs)
         {
             String serviceId = cd.getServiceId();
-            
+
             ContributionDef2 cd2 = InternalUtils.toContributionDef2(cd);
-            
+
             if (cd2.getServiceId() != null)
             {
-                if (!serviceIdToModule.containsKey(serviceId)) 
-                { 
-                    throw new IllegalArgumentException(IOCMessages.contributionForNonexistentService(cd)); 
-                }
-            }
-            else if(!isContributionForExistentService(cd2))
-            {
-                throw new IllegalArgumentException(IOCMessages.contributionForUnqualifiedService(cd2));
+                if (!serviceIdToModule.containsKey(serviceId)) { throw new IllegalArgumentException(IOCMessages
+                        .contributionForNonexistentService(cd)); }
             }
+            else if (!isContributionForExistentService(cd2)) { throw new IllegalArgumentException(IOCMessages
+                    .contributionForUnqualifiedService(cd2)); }
         }
-            
+
     }
-    
+
     private boolean isContributionForExistentService(ContributionDef2 cd)
     {
         Set<Class> markers = CollectionFactory.newSet(cd.getMarkers());
-        markers.remove(Local.class); 
+        markers.remove(Local.class);
 
         for (Class markerClass : markers)
         {
             boolean exists = existsServiceDefWithTypeAndMarker(cd.getServiceInterface(), markerClass);
-            
-            if(!exists)
+
+            if (!exists)
                 return false;
         }
-        
+
         return true;
     }
-    
+
     private boolean existsServiceDefWithTypeAndMarker(Class serviceInterface, Class markerClass)
     {
         List<ServiceDef2> serviceDefs = markerToServiceDef.get(markerClass);
-        
-        if(serviceDefs == null)
+
+        if (serviceDefs == null)
             return false;
-        
+
         for (ServiceDef2 serviceDef : serviceDefs)
         {
-            if(serviceDef.getServiceInterface() == serviceInterface)
+            if (serviceDef.getServiceInterface() == serviceInterface)
                 return true;
         }
-        
+
         return false;
     }
 
@@ -981,12 +977,8 @@ public class RegistryImpl implements Reg
             }
         };
 
-        ClassFab cf = classFactory.newClass(interfaceClass);
-
-        String description = String.format("<Autobuild proxy %s(%s)>", implementationClass.getName(), interfaceClass
-                .getName());
-
-        return ClassFabUtils.createObjectCreatorProxy(cf, interfaceClass, justInTime, description);
+        return classFactory.createProxy(interfaceClass, justInTime, String.format("<Autobuild proxy %s(%s)>",
+                implementationClass.getName(), interfaceClass.getName()));
     }
 
     public Object provideServiceProxy(String serviceId)

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=922143&r1=922142&r2=922143&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 Fri Mar 12 05:21:02 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 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
+// 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,
@@ -18,16 +18,21 @@ import javassist.CtClass;
 import javassist.CtConstructor;
 import javassist.CtMethod;
 import org.apache.tapestry5.ioc.Location;
+import org.apache.tapestry5.ioc.ObjectCreator;
+
+import static java.lang.String.format;
 import static org.apache.tapestry5.ioc.internal.util.Defense.notNull;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.services.ClassFab;
 import org.apache.tapestry5.ioc.services.ClassFabUtils;
 import org.apache.tapestry5.ioc.services.ClassFactory;
+import org.apache.tapestry5.ioc.services.MethodSignature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 
 /**
  * Implementation of {@link org.apache.tapestry5.ioc.services.ClassFactory}.
@@ -72,7 +77,7 @@ public class ClassFactoryImpl implements
     }
 
     public ClassFactoryImpl(ClassLoader classLoader, ClassFactoryClassPool pool, CtClassSource classSource,
-                            Logger logger)
+            Logger logger)
     {
         loader = classLoader;
 
@@ -83,7 +88,6 @@ public class ClassFactoryImpl implements
         this.logger = logger;
     }
 
-
     public ClassFab newClass(Class serviceInterface)
     {
         String name = ClassFabUtils.generateClassName(serviceInterface);
@@ -98,8 +102,7 @@ public class ClassFactoryImpl implements
     public ClassFab newClass(String name, Class superClass)
     {
         if (logger.isDebugEnabled())
-            logger.debug(String.format("Create ClassFab for %s (extends %s)", name, superClass
-                    .getName()));
+            logger.debug(String.format("Create ClassFab for %s (extends %s)", name, superClass.getName()));
 
         try
         {
@@ -188,7 +191,8 @@ public class ClassFactoryImpl implements
         {
             Class parameterType = parameterTypes[i];
 
-            if (i > 0) builder.append(", ");
+            if (i > 0)
+                builder.append(", ");
 
             builder.append(parameterType.getSimpleName());
 
@@ -219,4 +223,37 @@ public class ClassFactoryImpl implements
 
         return new StringLocation(builder.toString(), lineNumber);
     }
+
+    public <T> T createProxy(Class<T> proxyInterface, ObjectCreator delegateCreator, String description)
+    {
+        ClassFab classFab = newClass(proxyInterface);
+
+        classFab.addField("_creator", Modifier.PRIVATE | Modifier.FINAL, ObjectCreator.class);
+
+        classFab.addConstructor(new Class[]
+        { ObjectCreator.class }, null, "_creator = $1;");
+
+        String body = format("return (%s) _creator.createObject();", proxyInterface.getName());
+
+        MethodSignature sig = new MethodSignature(proxyInterface, "_delegate", null, null);
+
+        classFab.addMethod(Modifier.PRIVATE, sig, body);
+
+        classFab.proxyMethodsToDelegate(proxyInterface, "_delegate()", description);
+        Class proxyClass = classFab.createClass();
+
+        try
+        {
+            Object proxy = proxyClass.getConstructors()[0].newInstance(delegateCreator);
+
+            return proxyInterface.cast(proxy);
+        }
+        catch (Exception ex)
+        {
+            // This should never happen, so we won't go to a lot of trouble
+            // reporting it.
+            throw new RuntimeException(ex.getMessage(), ex);
+        }
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java?rev=922143&r1=922142&r2=922143&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java Fri Mar 12 05:21:02 2010
@@ -4,7 +4,7 @@
 // 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
+// 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,
@@ -59,7 +59,8 @@ public final class ClassFabUtils
      */
     public static String toJavaClassName(Class inputClass)
     {
-        if (inputClass.isArray()) return toJavaClassName(inputClass.getComponentType()) + "[]";
+        if (inputClass.isArray())
+            return toJavaClassName(inputClass.getComponentType()) + "[]";
 
         return inputClass.getName();
     }
@@ -70,9 +71,11 @@ public final class ClassFabUtils
      */
     public static boolean isToString(Method method)
     {
-        if (!method.getName().equals("toString")) return false;
+        if (!method.getName().equals("toString"))
+            return false;
 
-        if (method.getParameterTypes().length > 0) return false;
+        if (method.getParameterTypes().length > 0)
+            return false;
 
         return method.getReturnType().equals(String.class);
     }
@@ -132,7 +135,8 @@ public final class ClassFabUtils
     public static String toJVMBinaryName(String type)
     {
         // if it is not an array, just return the type itself
-        if (!type.endsWith("[]")) return type;
+        if (!type.endsWith("[]"))
+            return type;
 
         // if it is an array, convert it to JavaVM-style format
         StringBuilder buffer = new StringBuilder();
@@ -168,10 +172,11 @@ public final class ClassFabUtils
     }
 
     /**
-     * Returns the wrapper type for an input type; for most types, this is the type.  For primitive types, it is the
+     * Returns the wrapper type for an input type; for most types, this is the type. For primitive types, it is the
      * corresponding wrapper type.
-     *
-     * @param type type to check
+     * 
+     * @param type
+     *            type to check
      * @return type or corresponding wrapper type
      */
     public static Class getWrapperType(Class type)
@@ -182,12 +187,14 @@ public final class ClassFabUtils
     }
 
     /**
-     * Takes a reference and casts it to the desired type.  If the desired type is a primitive type, then the reference
+     * Takes a reference and casts it to the desired type. If the desired type is a primitive type, then the reference
      * is cast to the correct wrapper type and a call to the correct unwrapper method is added. The end result is code
      * that can be assigned to a field or parameter of the desired type (even if desired type is a primitive).
-     *
-     * @param reference   to be cast
-     * @param desiredType desired object or primitive type
+     * 
+     * @param reference
+     *            to be cast
+     * @param desiredType
+     *            desired object or primitive type
      * @return Javassist code to peform the cast
      */
     public static String castReference(String reference, String desiredType)
@@ -196,9 +203,7 @@ public final class ClassFabUtils
         {
             PrimitiveInfo info = PRIMITIVE_TYPE_NAME_TO_PRIMITIVE_INFO.get(desiredType);
 
-            return String.format("((%s)%s).%s()",
-                                 info.wrapperType.getName(), reference,
-                                 info.unwrapMethod);
+            return String.format("((%s)%s).%s()", info.wrapperType.getName(), reference, info.unwrapMethod);
         }
 
         return String.format("(%s)%s", desiredType, reference);
@@ -206,7 +211,7 @@ public final class ClassFabUtils
 
     /**
      * Given a primitive type, finds the unwrap method of the corresponding wrapper type.
-     *
+     * 
      * @param primitiveType
      * @return method name
      */
@@ -215,7 +220,6 @@ public final class ClassFabUtils
         return PRIMITIVE_TYPE_NAME_TO_PRIMITIVE_INFO.get(primitiveType.getName()).unwrapMethod;
     }
 
-
     /**
      * Given a type name, determines if that is the name of a primitive type.
      */
@@ -229,11 +233,14 @@ public final class ClassFabUtils
      */
     public static String getTypeCode(Class type)
     {
-        if (type.equals(void.class)) return "V";
+        if (type.equals(void.class))
+            return "V";
 
-        if (type.isPrimitive()) return PRIMITIVE_TYPE_NAME_TO_PRIMITIVE_INFO.get(type.getName()).typeCode;
+        if (type.isPrimitive())
+            return PRIMITIVE_TYPE_NAME_TO_PRIMITIVE_INFO.get(type.getName()).typeCode;
 
-        if (type.isArray()) return "[" + getTypeCode(type.getComponentType());
+        if (type.isArray())
+            return "[" + getTypeCode(type.getComponentType());
 
         return "L" + type.getName().replace('.', '/') + ";";
     }
@@ -242,20 +249,26 @@ public final class ClassFabUtils
      * Creates a proxy for a given service interface around an {@link org.apache.tapestry5.ioc.ObjectCreator} that can
      * provide (on demand) an object (implementing the service interface) to delegate to. The ObjectCreator will be
      * invoked on every method invocation (if it is caching, that should be internal to its implementation).
-     *
+     * 
      * @param <T>
-     * @param classFab         used to create the new class
-     * @param serviceInterface the interface the proxy will implement
-     * @param creator          the createor which will provide an instance of the interface
-     * @param description      description to be returned from the proxy's toString() method
+     * @param classFab
+     *            used to create the new class
+     * @param serviceInterface
+     *            the interface the proxy will implement
+     * @param creator
+     *            the createor which will provide an instance of the interface
+     * @param description
+     *            description to be returned from the proxy's toString() method
      * @return the instantiated proxy object
+     * @deprecated Use {@link ClassFactory#createProxy(Class, ObjectCreator, String)} instead
      */
     public static <T> T createObjectCreatorProxy(ClassFab classFab, Class<T> serviceInterface, ObjectCreator creator,
-                                                 String description)
+            String description)
     {
         classFab.addField("_creator", Modifier.PRIVATE | Modifier.FINAL, ObjectCreator.class);
 
-        classFab.addConstructor(new Class[] {ObjectCreator.class}, null, "_creator = $1;");
+        classFab.addConstructor(new Class[]
+        { ObjectCreator.class }, null, "_creator = $1;");
 
         String body = format("return (%s) _creator.createObject();", serviceInterface.getName());
 

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=922143&r1=922142&r2=922143&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 Fri Mar 12 05:21:02 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 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
+// 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,
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.ioc.services;
 
 import org.apache.tapestry5.ioc.Location;
+import org.apache.tapestry5.ioc.ObjectCreator;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
@@ -28,7 +29,7 @@ public interface ClassFactory
      * Simplified version of {@link #newClass(String, Class)} that generates a name based on the service interface name,
      * extends from java.lang.Object, and automatically adds the serviceInterface to the returned ClassFab. This is the
      * most common use when creating the kinds of proxies used throughout Tapestry IoC.
-     *
+     * 
      * @param serviceInterface
      */
     ClassFab newClass(Class serviceInterface);
@@ -36,10 +37,12 @@ public interface ClassFactory
     /**
      * Creates a {@link ClassFab} object for the given name; the new class is a subclass of the indicated class. The new
      * class is always public and concrete.
-     *
-     * @param name       the full qualified name of the class to create (note that it is common to place created classes
-     *                   in the default package)
-     * @param superClass the parent class, which is often java.lang.Object
+     * 
+     * @param name
+     *            the full qualified name of the class to create (note that it is common to place created classes
+     *            in the default package)
+     * @param superClass
+     *            the parent class, which is often java.lang.Object
      */
 
     ClassFab newClass(String name, Class superClass);
@@ -49,9 +52,9 @@ public interface ClassFactory
      * class path. The class itself is returned, if its bytecode is available. If not, a search up the inhertance occurs
      * until a proper class (that can be referenced in generated bytecode) is found. This is necessary to handle cases
      * where a class is generated at runtime, outside of the class factory, and bytecode is not available for it.
-     *
+     * 
      * @param clazz
-     * @return a referencable super-class
+     * @return a referenceable super-class
      */
     Class importClass(Class clazz);
 
@@ -69,15 +72,32 @@ public interface ClassFactory
 
     /**
      * Converts a method to a {@link Location}, which includes information about the source file name and line number.
-     *
-     * @param method to look up
+     * 
+     * @param method
+     *            to look up
      * @return the location, or null if the necessary information is not available
      */
     Location getMethodLocation(Method method);
 
     /**
-     * Return a string representation fo the constructor (including class and parameters) and (if available) file name
+     * Return a string representation for the constructor (including class and parameters) and (if available) file name
      * and line number.
      */
     Location getConstructorLocation(Constructor constructor);
+
+    /**
+     * 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
+     * @param description
+     *            used for the toString() method
+     * @since 5.2.0
+     */
+    <T> T createProxy(Class<T> proxyInterface, ObjectCreator delegateCreator, String description);
 }