You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/04/07 23:16:38 UTC

svn commit: r1090016 - in /tapestry/tapestry5/trunk/plastic/src: main/java/org/apache/tapestry5/internal/plastic/ main/java/org/apache/tapestry5/plastic/ test/groovy/org/apache/tapestry5/plastic/

Author: hlship
Date: Thu Apr  7 21:16:38 2011
New Revision: 1090016

URL: http://svn.apache.org/viewvc?rev=1090016&view=rev
Log:
TAP5-853: Make it easy to efficiently inject an InstanceContext value

Modified:
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticInternalUtils.java
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilder.java
    tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticField.java
    tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java?rev=1090016&r1=1090015&r2=1090016&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java Thu Apr  7 21:16:38 2011
@@ -170,6 +170,13 @@ public class InstructionBuilderImpl exte
                 cache.toMethodDescriptor(returnType, argumentTypes));
     }
 
+    public InstructionBuilder invokeStatic(Class clazz, Class returnType, String methodName, Class... argumentTypes)
+    {
+        doInvoke(INVOKESTATIC, clazz, returnType, methodName, argumentTypes);
+
+        return this;
+    }
+
     private void doInvoke(int opcode, Class clazz, Class returnType, String methodName, Class... argumentTypes)
     {
         doInvoke(opcode, clazz.getName(), cache.toTypeName(returnType), methodName,

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java?rev=1090016&r1=1090015&r2=1090016&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java Thu Apr  7 21:16:38 2011
@@ -631,6 +631,34 @@ public class PlasticClassImpl extends Lo
             constructorBuilder.putField(className, node.name, typeName);
         }
 
+        public PlasticField injectFromInstanceContext()
+        {
+            check();
+
+            verifyInitialState("inject instance context value into");
+
+            // Easiest to load this, for the putField(), early, in case the field is
+            // wide (long or double primitive)
+            
+            constructorBuilder.loadThis();
+            
+            // Add the InstanceContext to the stack
+
+            constructorBuilder.loadArgument(1);
+            constructorBuilder.loadConstant(typeName);
+
+            constructorBuilder.invokeStatic(PlasticInternalUtils.class, Object.class, "getFromInstanceContext",
+                    InstanceContext.class, String.class).castOrUnbox(typeName);
+
+            constructorBuilder.putField(className, node.name, typeName);
+
+            makeReadOnly();
+
+            state = FieldState.INJECTED;
+
+            return this;
+        }
+
         public PlasticField setConduit(FieldConduit<?> conduit)
         {
             assert conduit != null;

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticInternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticInternalUtils.java?rev=1090016&r1=1090015&r2=1090016&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticInternalUtils.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticInternalUtils.java Thu Apr  7 21:16:38 2011
@@ -31,6 +31,7 @@ import org.apache.tapestry5.internal.pla
 import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
 import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
 import org.apache.tapestry5.internal.plastic.asm.util.TraceClassVisitor;
+import org.apache.tapestry5.plastic.InstanceContext;
 import org.apache.tapestry5.plastic.MethodDescription;
 
 @SuppressWarnings("rawtypes")
@@ -355,4 +356,20 @@ public class PlasticInternalUtils
 
         return Class.forName(builder.toString(), true, loader);
     }
+
+    public static Object getFromInstanceContext(InstanceContext context, String javaName)
+    {
+        ClassLoader loader = context.getInstanceType().getClassLoader();
+
+        try
+        {
+            Class valueType = toClass(loader, javaName);
+
+            return context.get(valueType);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
 }

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilder.java?rev=1090016&r1=1090015&r2=1090016&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilder.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilder.java Thu Apr  7 21:16:38 2011
@@ -98,6 +98,12 @@ public interface InstructionBuilder
     InstructionBuilder invoke(Class clazz, Class returnType, String methodName, Class... argumentTypes);
 
     /**
+     * Invokes a static method of a class.
+     */
+    @Opcodes("INVOKESTATIC")
+    InstructionBuilder invokeStatic(Class clazz, Class returnType, String methodName, Class... argumentTypes);
+
+    /**
      * Returns the top value on the stack. For void methods, no value should
      * be on the stack and the method will simply return.
      */

Modified: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticField.java?rev=1090016&r1=1090015&r2=1090016&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticField.java (original)
+++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticField.java Thu Apr  7 21:16:38 2011
@@ -92,6 +92,13 @@ public interface PlasticField extends An
     PlasticField injectComputed(ComputedValue<?> computedValue);
 
     /**
+     * As with {@link #inject(Object)}, but the value is extracted from the {@link InstanceContext}.
+     * 
+     * @return this field for further manipulation
+     */
+    PlasticField injectFromInstanceContext();
+
+    /**
      * Intercepts all access to the field, replacing such access with calls on the conduit. Even access via
      * the FieldHandle will instead delegate to the conduit. Once a conduit is provided, it is not possible
      * to inject a value into the field.

Modified: tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy?rev=1090016&r1=1090015&r2=1090016&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy (original)
+++ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy Thu Apr  7 21:16:38 2011
@@ -72,6 +72,27 @@ class FieldInjection extends Specificati
         thrown(IllegalStateException)
     }
 
+    def "injection from instance context"() {
+
+        String injected = "InstanceContext value injected into the StringPropertyHolder class"
+
+        def pc = mgr.getPlasticClass("testsubjects.StringPropertyHolder")
+
+        pc.allFields.first().injectFromInstanceContext()
+
+        def o = pc.createInstantiator().with(String.class, injected).newInstance()
+
+        expect:
+
+        o.value.is(injected)
+
+        when:
+        o.value = "attempt to update"
+
+        then:
+        thrown(IllegalStateException)
+    }
+
     def "injection of primitive value"() {
 
         def pc = mgr.getPlasticClass("testsubjects.Empty")
@@ -94,9 +115,9 @@ class FieldInjection extends Specificati
         def pc = mgr.getPlasticClass("testsubjects.InjectFieldSubject")
 
         def pf = pc.allFields.first();
-        
+
         def handle = pf.handle;
-        
+
         pf.inject(99)
 
         def ins = pc.createInstantiator()
@@ -111,12 +132,12 @@ class FieldInjection extends Specificati
         then:
         def e = thrown(IllegalStateException)
         e.message == "Field value of class testsubjects.InjectFieldSubject is read-only."
-        
+
         when:
         handle.set(o, 456)
-        
+
         then:
-        
+
         thrown(IllegalStateException)
     }