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 2011/04/07 23:16:46 UTC

svn commit: r1090017 - in /tapestry/tapestry5/trunk/tapestry-ioc/src: main/java/org/apache/tapestry5/ioc/internal/ test/java/org/apache/tapestry5/ioc/internal/

Author: hlship
Date: Thu Apr  7 21:16:46 2011
New Revision: 1090017

URL: http://svn.apache.org/viewvc?rev=1090017&view=rev
Log:
TAP5-853: Convert creation of outer service proxies to PlasticProxyFactory

(note: 1 ioc test failure, related to copying of class/method annotations to proxy)

Modified:
    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/ServiceProxyToken.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ModuleImplTest.java

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=1090017&r1=1090016&r2=1090017&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 Thu Apr  7 21:16:46 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -20,6 +20,7 @@ import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.Collection;
@@ -51,10 +52,17 @@ import org.apache.tapestry5.ioc.internal
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.internal.util.MapInjectionResources;
 import org.apache.tapestry5.ioc.services.AspectDecorator;
-import org.apache.tapestry5.ioc.services.ClassFab;
 import org.apache.tapestry5.ioc.services.ClassFactory;
-import org.apache.tapestry5.ioc.services.MethodSignature;
+import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
 import org.apache.tapestry5.ioc.services.Status;
+import org.apache.tapestry5.plastic.ClassInstantiator;
+import org.apache.tapestry5.plastic.InstructionBuilder;
+import org.apache.tapestry5.plastic.InstructionBuilderCallback;
+import org.apache.tapestry5.plastic.MethodDescription;
+import org.apache.tapestry5.plastic.PlasticClass;
+import org.apache.tapestry5.plastic.PlasticClassTransformer;
+import org.apache.tapestry5.plastic.PlasticField;
+import org.apache.tapestry5.plastic.PlasticMethod;
 import org.slf4j.Logger;
 
 @SuppressWarnings("all")
@@ -68,6 +76,8 @@ public class ModuleImpl implements Modul
 
     private final ClassFactory classFactory;
 
+    private final PlasticProxyFactory proxyFactory;
+
     private final Logger logger;
 
     /**
@@ -94,10 +104,11 @@ public class ModuleImpl implements Modul
     private final static ConcurrentBarrier BARRIER = new ConcurrentBarrier();
 
     public ModuleImpl(InternalRegistry registry, ServiceActivityTracker tracker, ModuleDef moduleDef,
-            ClassFactory classFactory, Logger logger)
+            ClassFactory classFactory, PlasticProxyFactory proxyFactory, Logger logger)
     {
         this.registry = registry;
         this.tracker = tracker;
+        this.proxyFactory = proxyFactory;
         this.moduleDef = InternalUtils.toModuleDef2(moduleDef);
         this.classFactory = classFactory;
         this.logger = logger;
@@ -472,62 +483,77 @@ public class ModuleImpl implements Modul
 
         String toString = format("<Proxy for %s(%s)>", serviceId, serviceInterface.getName());
 
-        return createProxyInstance(creator, serviceId, serviceInterface, resources.getImplementationClass(), toString);
-    }
-
-    private Object createProxyInstance(ObjectCreator creator, String serviceId, Class serviceInterface,
-            Class serviceImplementation, String description)
-    {
         ServiceProxyToken token = SerializationSupport.createToken(serviceId);
 
-        ClassFab classFab = registry.newClass(serviceInterface);
-
-        classFab.addField("creator", Modifier.PRIVATE | Modifier.FINAL, ObjectCreator.class);
-        classFab.addField("token", Modifier.PRIVATE | Modifier.FINAL, ServiceProxyToken.class);
-
-        classFab.addConstructor(new Class[]
-        { ObjectCreator.class, ServiceProxyToken.class }, null, "{ creator = $1; token = $2; }");
-
-        // Make proxies serializable by writing the token to the stream.
-
-        classFab.addInterface(Serializable.class);
+        return createProxyInstance(creator, token, serviceInterface, resources.getImplementationClass(), toString);
+    }
 
-        // This is the "magic" signature that allows an object to substitute some other
-        // object for itself.
-        MethodSignature writeReplaceSig = new MethodSignature(Object.class, "writeReplace", null, new Class[]
-        { ObjectStreamException.class });
+    /** "Magic" method related to Externalizable that allows the Proxy object to replace itself with the token. */
+    private static final MethodDescription WRITE_REPLACE = new MethodDescription(Modifier.PRIVATE, "java.lang.Object",
+            "writeReplace", null, new String[]
+            { ObjectStreamException.class.getName() });
 
-        classFab.addMethod(Modifier.PRIVATE, writeReplaceSig, "return token;");
+    private Object createProxyInstance(final ObjectCreator creator, final ServiceProxyToken token,
+            final Class serviceInterface, Class serviceImplementation, final String description)
+    {
+        ClassInstantiator instantiator = proxyFactory.createProxy(serviceInterface, new PlasticClassTransformer()
+        {
+            public void transform(final PlasticClass plasticClass)
+            {
+                plasticClass.introduceInterface(Serializable.class);
 
-        // Now delegate all the methods.
+                final PlasticField creatorField = plasticClass.introduceField(ObjectCreator.class, "creator").inject(
+                        creator);
 
-        String body = format("return (%s) creator.createObject();", serviceInterface.getName());
+                final PlasticField tokenField = plasticClass.introduceField(ServiceProxyToken.class, "token").inject(
+                        token);
 
-        MethodSignature sig = new MethodSignature(serviceInterface, "delegate", null, null);
+                // TODO: Choose a simpler name, unless it conflicts with a service interface method name.
 
-        classFab.addMethod(Modifier.PRIVATE, sig, body);
+                PlasticMethod delegateMethod = plasticClass.introduceMethod(new MethodDescription(Modifier.PRIVATE,
+                        serviceInterface.getName(), "_$delegate", null, null));
 
-        classFab.proxyMethodsToDelegate(serviceInterface, "delegate()", description);
+                // If not concerned with efficiency, this might be done with method advice instead.
+                delegateMethod.changeImplementation(new InstructionBuilderCallback()
+                {
+                    public void doBuild(InstructionBuilder builder)
+                    {
+                        builder.loadThis().getField(plasticClass.getClassName(), creatorField.getName(),
+                                ObjectCreator.class);
+                        builder.invoke(ObjectCreator.class, Object.class, "createObject").checkcast(serviceInterface)
+                                .returnResult();
+                    }
+                });
 
-        if (serviceImplementation != null)
-        {
-            classFab.copyClassAnnotationsFromDelegate(serviceImplementation);
+                for (Method m : serviceInterface.getMethods())
+                {
+                    plasticClass.introduceMethod(m).delegateTo(delegateMethod);
+                }
 
-            classFab.copyMethodAnnotationsFromDelegate(serviceInterface, serviceImplementation);
-        }
+                plasticClass.introduceMethod(WRITE_REPLACE).changeImplementation(new InstructionBuilderCallback()
+                {
+                    public void doBuild(InstructionBuilder builder)
+                    {
+                        builder.loadThis()
+                                .getField(plasticClass.getClassName(), tokenField.getName(), ServiceProxyToken.class)
+                                .returnResult();
+                    }
+                });
 
-        Class proxyClass = classFab.createClass();
+                /*
+                 * TODO:
+                 * if (serviceImplementation != null)
+                 * {
+                 * classFab.copyClassAnnotationsFromDelegate(serviceImplementation);
+                 * classFab.copyMethodAnnotationsFromDelegate(serviceInterface, serviceImplementation);
+                 * }
+                 */
 
-        try
-        {
-            return proxyClass.getConstructors()[0].newInstance(creator, token);
-        }
-        catch (Exception ex)
-        {
-            // Exceptions should not happen.
+                plasticClass.addToString(description);
+            }
+        });
 
-            throw new RuntimeException(ex.getMessage(), ex);
-        }
+        return instantiator.newInstance();
     }
 
     @SuppressWarnings("all")
@@ -545,7 +571,7 @@ public class ModuleImpl implements Modul
             }
             else
             {
-                if(markerMatched(serviceDef, def))
+                if (markerMatched(serviceDef, def))
                 {
                     result.add(def);
                 }
@@ -554,11 +580,12 @@ public class ModuleImpl implements Modul
 
         return result;
     }
-   
+
     private boolean markerMatched(ServiceDef serviceDef, Markable markable)
     {
         if (!serviceDef.getServiceInterface().equals(markable.getServiceInterface()))
-            return false;;
+            return false;
+        ;
 
         Set<Class> contributionMarkers = CollectionFactory.newSet(markable.getMarkers());
 

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=1090017&r1=1090016&r2=1090017&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 Thu Apr  7 21:16:46 2011
@@ -209,7 +209,7 @@ public class RegistryImpl implements Reg
         {
             logger = this.loggerSource.getLogger(def.getLoggerName());
 
-            Module module = new ModuleImpl(this, tracker, def, classFactory, logger);
+            Module module = new ModuleImpl(this, tracker, def, classFactory, proxyFactory, logger);
 
             Set<ServiceDef2> moduleServiceDefs = CollectionFactory.newSet();
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceProxyToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceProxyToken.java?rev=1090017&r1=1090016&r2=1090017&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceProxyToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceProxyToken.java Thu Apr  7 21:16:46 2011
@@ -1,10 +1,10 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2011 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,
@@ -21,11 +21,13 @@ import java.io.Serializable;
 /**
  * Token that replaces a service proxy when the proxy is serialized.
  */
-class ServiceProxyToken implements Serializable
+public class ServiceProxyToken implements Serializable
 {
+    private static final long serialVersionUID = 4119675138731356650L;
+
     private final String serviceId;
 
-    ServiceProxyToken(String serviceId)
+    public ServiceProxyToken(String serviceId)
     {
         this.serviceId = serviceId;
     }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ModuleImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ModuleImplTest.java?rev=1090017&r1=1090016&r2=1090017&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ModuleImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ModuleImplTest.java Thu Apr  7 21:16:46 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2011 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.
@@ -43,7 +43,7 @@ public class ModuleImplTest extends IOCI
 
         ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, logger, null);
 
-        Module module = new ModuleImpl(registry, null, moduleDef, null, logger);
+        Module module = new ModuleImpl(registry, null, moduleDef, null, null, logger);
 
         replay();
 
@@ -82,7 +82,7 @@ public class ModuleImplTest extends IOCI
 
         replay();
 
-        Module module = new ModuleImpl(registry, null, moduleDef, null, logger);
+        Module module = new ModuleImpl(registry, null, moduleDef, null, null, logger);
 
         Set<DecoratorDef> defs = module.findMatchingDecoratorDefs(serviceDef);