You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2007/09/07 18:57:11 UTC

svn commit: r573632 - in /tapestry/tapestry4/trunk/tapestry-framework/src: java/org/apache/tapestry/components/ java/org/apache/tapestry/dojo/form/ java/org/apache/tapestry/enhance/ java/org/apache/tapestry/link/ java/org/apache/tapestry/multipart/ jav...

Author: jkuhnert
Date: Fri Sep  7 09:57:10 2007
New Revision: 573632

URL: http://svn.apache.org/viewvc?rev=573632&view=rev
Log:
-) Hopefully puts to rest any remaining memory consumption issues.
-) Fixed up some unit tests related to new upload form parameters logic.

Added:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java   (with props)
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java   (with props)
Modified:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/components/Insert.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/GTimePicker.jwc
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/multipart/UploadFormParametersWrapper.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
    tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateExpr.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/binding/TestExpressionBinding.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/BasicObject.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestHiveMindExpressionCompiler.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/multipart/TestUploadFormParametersWrapper.java

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/components/Insert.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/components/Insert.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/components/Insert.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/components/Insert.java Fri Sep  7 09:57:10 2007
@@ -14,22 +14,22 @@
 
 package org.apache.tapestry.components;
 
-import java.io.IOException;
-import java.io.LineNumberReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.text.Format;
-
+import org.apache.commons.io.IOUtils;
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.tapestry.AbstractComponent;
 import org.apache.tapestry.IMarkupWriter;
 import org.apache.tapestry.IRequestCycle;
 
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.StringReader;
+import java.text.Format;
+
 /**
  * Used to insert some text (from a parameter) into the HTML. [ <a
  * href="../../../../../ComponentReference/Insert.html">Component Reference
  * </a>]
- * 
+ *
  * @author Howard Lewis Ship
  */
 
@@ -42,18 +42,18 @@
 
     protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
     {
-        if (cycle.isRewinding()) 
+        if (cycle.isRewinding())
             return;
-        
+
         Object value = getValue();
-        
-        if (value == null) 
+
+        if (value == null)
             return;
-        
+
         String insert = null;
-        
+
         Format format = getFormat();
-        
+
         if (format == null)
         {
             insert = value.toString();
@@ -71,85 +71,75 @@
                         "format").getLocation(), ex);
             }
         }
-        
+
         boolean render = getRenderTag() || isParameterBound("class");
-        
-        if (render) {
+
+        if (render)
+        {
             writer.begin(getTemplateTagName());
-            
+
             renderInformalParameters(writer, cycle);
-            
+
             if (getId() != null && !isParameterBound("id"))
                 renderIdAttribute(writer, cycle);
         }
-        
+
         printText(writer, cycle, insert);
-        
-        if (render) {
+
+        if (render)
             writer.end();
-        }
     }
-    
+
     protected void printText(IMarkupWriter writer, IRequestCycle cycle, String value)
     {
-        if (getMode() == null) {
-            
+        if (getMode() == null)
+        {
             writer.print(value, getRaw());
             return;
         }
-        
+
         StringReader reader = null;
         LineNumberReader lineReader = null;
         InsertMode mode = getMode();
         boolean raw = getRaw();
-        
+
         try {
             reader = new StringReader(value);
             lineReader = new LineNumberReader(reader);
-            
+
             int lineNumber = 0;
-            
-            while(true) {
+
+            while(true)
+            {
                 String line = lineReader.readLine();
-                
+
                 // Exit loop at end of file.
-                
-                if (line == null) 
+
+                if (line == null)
                     break;
-                
+
                 mode.writeLine(lineNumber, line, writer, raw);
-                
+
                 lineNumber++;
             }
-            
-        } catch (IOException ex) {
-            
+
+        } catch (IOException ex)
+        {
             throw new ApplicationRuntimeException(ComponentMessages.textConversionError(ex), this, null, ex);
-        } finally {
-            
-            close(lineReader);
-            close(reader);
+        } finally
+        {
+            IOUtils.closeQuietly(lineReader);
+            IOUtils.closeQuietly(reader);
         }
     }
-    
-    private void close(Reader reader)
-    {
-        if (reader == null) 
-            return;
 
-        try
-        {
-            reader.close();
-        } catch (IOException e){}
-    }
-    
     public abstract Object getValue();
 
     public abstract Format getFormat();
-    
+
     public abstract boolean getRaw();
-    
+
     public abstract boolean getRenderTag();
-    
+
     public abstract InsertMode getMode();
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/GTimePicker.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/GTimePicker.jwc?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/GTimePicker.jwc (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/GTimePicker.jwc Fri Sep  7 09:57:10 2007
@@ -26,8 +26,8 @@
 
   <parameter name="displayName"/>
   <parameter name="translator" default-value="translator:date,pattern=h:mm a"/>
-  <parameter name="validators"/>
-
+  <parameter name="validators" />
+    
   <inject property="script" type="script" object="GTimePicker.script"/>
   <inject property="translatedFieldSupport" object="service:tapestry.form.TranslatedFieldSupport"/>
   <inject property="validatableFieldSupport" object="service:tapestry.form.ValidatableFieldSupport"/>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java Fri Sep  7 09:57:10 2007
@@ -35,7 +35,7 @@
 
     private CtClassSource _classSource = new CtClassSource(_pool);
 
-    private int _classCounter = 0;
+    int _classCounter = 0;
 
     public ClassFab newClass(String name, Class superClass)
     {

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java Fri Sep  7 09:57:10 2007
@@ -94,9 +94,7 @@
         if (!disabled) {
             
             afterBodyRender(writer, cycle, linkComponent);
-            
-            // linkComponent.renderAdditionalAttributes(writer, cycle);
-            
+                        
             if (hasBody) {
                 wrappedWriter.close();
                 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/multipart/UploadFormParametersWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/multipart/UploadFormParametersWrapper.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/multipart/UploadFormParametersWrapper.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/multipart/UploadFormParametersWrapper.java Fri Sep  7 09:57:10 2007
@@ -14,14 +14,13 @@
 
 package org.apache.tapestry.multipart;
 
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Map;
+import org.apache.hivemind.util.Defense;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
-
-import org.apache.hivemind.util.Defense;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
 
 /**
  * {@link javax.servlet.http.HttpServletRequest}&nbsp; wrapper that provides
@@ -43,14 +42,19 @@
      *            a map whose keys are parameter names and whose values are
      *            arrays of Strings.
      */
-    public UploadFormParametersWrapper(HttpServletRequest request,
-            Map parameterMap)
+    public UploadFormParametersWrapper(HttpServletRequest request, Map parameterMap)
     {
         super(request);
 
         Defense.notNull(parameterMap, "parameterMap");
+
         // add Parameter from the URL, typically added by JavaScript-URL-manipulation
-        parameterMap.putAll(request.getParameterMap());
+
+        if (request.getParameterMap() != null)
+        {
+            parameterMap.putAll(request.getParameterMap());
+        }
+        
         _parameterMap = Collections.unmodifiableMap(parameterMap );
     }
 

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java?rev=573632&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java Fri Sep  7 09:57:10 2007
@@ -0,0 +1,93 @@
+package org.apache.tapestry.services.impl;
+
+import ognl.Node;
+import org.apache.hivemind.service.ClassFab;
+import org.apache.hivemind.service.MethodSignature;
+
+/**
+ * Simple struct used by {@link HiveMindExpressionCompiler} to hold temporary references to
+ * all of the objects involved in compiling / generating a compiled ognl expression.
+ */
+public class CompiledExpression {
+
+    ClassFab _generatedClass;
+    Node _expression;
+    Object _root;
+    MethodSignature _getterMethod;
+    MethodSignature _setterMethod;
+
+    public CompiledExpression(Node expression, Object root,
+                              MethodSignature getter, MethodSignature setter)
+    {
+        _expression = expression;
+        _root = root;
+        _getterMethod = getter;
+        _setterMethod = setter;
+    }
+
+    public ClassFab getGeneratedClass()
+    {
+        return _generatedClass;
+    }
+
+    public void setGeneratedClass(ClassFab generatedClass)
+    {
+        _generatedClass = generatedClass;
+    }
+
+    public Node getExpression()
+    {
+        return _expression;
+    }
+
+    public void setExpression(Node expression)
+    {
+        _expression = expression;
+    }
+
+    public Object getRoot()
+    {
+        return _root;
+    }
+
+    public void setRoot(Object root)
+    {
+        _root = root;
+    }
+
+    public MethodSignature getGetterMethod()
+    {
+        return _getterMethod;
+    }
+
+    public void setGetterMethod(MethodSignature method)
+    {
+        _getterMethod = method;
+    }
+
+    public MethodSignature getSettermethod()
+    {
+        return _setterMethod;
+    }
+
+    public void setSetterMethod(MethodSignature method)
+    {
+        _setterMethod = method;
+    }
+
+    public String toString()
+    {
+        return "CompiledExpression[" +
+               "_generatedClass=" + _generatedClass +
+               '\n' +
+               ", _expression=" + _expression +
+               '\n' +
+               ", _root=" + _root +
+               '\n' +
+               ", _getterMethod=" + _getterMethod +
+               '\n' +
+               ", _setterMethod=" + _setterMethod +
+               '\n' +
+               ']';
+    }
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/CompiledExpression.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java Fri Sep  7 09:57:10 2007
@@ -34,9 +34,9 @@
  *
  */
 public class HiveMindExpressionCompiler extends ExpressionCompiler implements OgnlExpressionCompiler {
-    
+
     private static final Log _log = LogFactory.getLog(HiveMindExpressionCompiler.class);
-    
+
     private ClassFactory _classFactory;
 
     public HiveMindExpressionCompiler(ClassFactory classfactory)
@@ -57,7 +57,8 @@
 
         Class[] intf = clazz.getInterfaces();
 
-        for (int i = 0; i < intf.length; i++) {
+        for (int i = 0; i < intf.length; i++)
+        {
             if (intf[i].getName().indexOf("util.List") > 0)
                 return intf[i].getName();
             else if (intf[i].getName().indexOf("Iterator") > 0)
@@ -80,15 +81,15 @@
             return Iterator.class;
 
         if (Modifier.isPublic(clazz.getModifiers())
-            && clazz.isInterface() || clazz.isPrimitive()) {
-
+            && clazz.isInterface() || clazz.isPrimitive())
+        {
             return clazz;
         }
 
         Class[] intf = clazz.getInterfaces();
 
-        for (int i = 0; i < intf.length; i++) {
-
+        for (int i = 0; i < intf.length; i++)
+        {
             if (List.class.isAssignableFrom(intf[i]))
                 return List.class;
             else if (Iterator.class.isAssignableFrom(intf[i]))
@@ -114,8 +115,12 @@
 
         Class ret = context.getRoot().getClass();
 
-        if (!IRender.class.isInstance(context.getRoot()) && context.getFirstAccessor() != null && context.getFirstAccessor().isInstance(context.getRoot()))
+        if (!IRender.class.isInstance(context.getRoot())
+            && context.getFirstAccessor() != null
+            && context.getFirstAccessor().isInstance(context.getRoot()))
+        {
             ret = context.getFirstAccessor();
+        }
 
         return ret;
     }
@@ -124,22 +129,22 @@
             throws Exception
     {
         if (_log.isDebugEnabled())
-            _log.debug("Compiling expr class " + expression.getClass().getName() + " and root " + root.getClass().getName() + " with toString:" + expression.toString());
-
-        synchronized (expression) {
+            _log.debug("Compiling expr class " + expression.getClass().getName()
+                       + " and root " + root.getClass().getName() + " with toString:" + expression.toString());
 
+        synchronized (expression)
+        {
             if (expression.getAccessor() != null)
                 return;
 
             String getBody = null;
             String setBody;
-
-            ClassFab classFab = _classFactory.newClass(ClassFabUtils.generateClassName(expression.getClass()), Object.class);
-            classFab.addInterface(ExpressionAccessor.class);
-
+            
             MethodSignature valueGetter = new MethodSignature(Object.class, "get", new Class[]{OgnlContext.class, Object.class}, null);
             MethodSignature valueSetter = new MethodSignature(void.class, "set", new Class[]{OgnlContext.class, Object.class, Object.class}, null);
 
+            CompiledExpression compiled = new CompiledExpression(expression, root, valueGetter, valueSetter);
+
             MethodSignature expressionSetter = new MethodSignature(void.class, "setExpression", new Class[]{Node.class}, null);
 
             // must evaluate expression value at least once if object isn't null
@@ -147,18 +152,17 @@
             if (root != null)
                 Ognl.getValue(expression, context, root);
 
-            try {
-
-                getBody = generateGetter(context, classFab, valueGetter, expression, root);
-
-            } catch (UnsupportedCompilationException uc) {
-
+            try
+            {
+                getBody = generateGetter(context, compiled);
+            } catch (UnsupportedCompilationException uc)
+            {
                 // uc.printStackTrace();
                 // The target object may not fully resolve yet because of a partial tree with a null somewhere, we
                 // don't want to bail out forever because it might be enhancable on another pass eventually
                 return;
-            } catch (javassist.CannotCompileException e) {
-
+            } catch (javassist.CannotCompileException e)
+            {
                 _log.error("Error generating OGNL getter for expression " + expression + " with root " + root + " and body:\n" + getBody, e);
 
                 e.printStackTrace();
@@ -167,12 +171,11 @@
                 return;
             }
 
-            try {
-
-                classFab.addMethod(Modifier.PUBLIC, valueGetter, getBody);
-
-            } catch (Throwable t) {
-
+            try
+            {
+                generateClassFab(compiled).addMethod(Modifier.PUBLIC, valueGetter, getBody);
+            } catch (Throwable t)
+            {
                 _log.error("Error generating OGNL getter for expression " + expression + " with root " + root + " and body:\n" + getBody, t);
 
                 t.printStackTrace();
@@ -181,46 +184,46 @@
                 return;
             }
 
-            try {
-
-                setBody = generateSetter(context, classFab, valueSetter, expression, root);
-
-            } catch (UnsupportedCompilationException uc) {
-                
+            try
+            {
+                setBody = generateSetter(context, compiled);
+            } catch (UnsupportedCompilationException uc)
+            {
                 //_log.warn("Unsupported setter compilation caught: " + uc.getMessage() + " for expression: " + expression.toString(), uc);
 
-                setBody = generateOgnlSetter(classFab, valueSetter);
-
-                if (!classFab.containsMethod(expressionSetter)) {
+                setBody = generateOgnlSetter(generateClassFab(compiled), valueSetter);
 
-                    classFab.addField("_node", Node.class);
-                    classFab.addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
+                if (!generateClassFab(compiled).containsMethod(expressionSetter))
+                {
+                    generateClassFab(compiled).addField("_node", Node.class);
+                    generateClassFab(compiled).addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
                 }
             }
 
-            try {
-
-                if (setBody == null) {
-                    setBody = generateOgnlSetter(classFab, valueSetter);
-
-                    if (!classFab.containsMethod(expressionSetter)) {
-
-                        classFab.addField("_node", Node.class);
-                        classFab.addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
+            try
+            {
+                if (setBody == null)
+                {
+                    setBody = generateOgnlSetter(generateClassFab(compiled), valueSetter);
+
+                    if (!generateClassFab(compiled).containsMethod(expressionSetter))
+                    {
+                        generateClassFab(compiled).addField("_node", Node.class);
+                        generateClassFab(compiled).addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
                     }
                 }
 
                 if (setBody != null)
-                    classFab.addMethod(Modifier.PUBLIC, valueSetter, setBody);
+                    generateClassFab(compiled).addMethod(Modifier.PUBLIC, valueSetter, setBody);
 
-                classFab.addConstructor(new Class[0], new Class[0], "{}");
+                generateClassFab(compiled).addConstructor(new Class[0], new Class[0], "{}");
 
-                Class clazz = ((AbstractFab) classFab).createClass(true);
+                Class clazz = ((AbstractFab) generateClassFab(compiled)).createClass(true);
 
                 expression.setAccessor((ExpressionAccessor) clazz.newInstance());
 
-            }  catch (Throwable t) {
-
+            }  catch (Throwable t)
+            {
                 _log.error("Error generating OGNL statements for expression " + expression + " with root " + root, t);
                 t.printStackTrace();
 
@@ -230,20 +233,34 @@
 
             // need to set expression on node if the field was just defined.
 
-            if (classFab.containsMethod(expressionSetter)) {
-
+            if (generateClassFab(compiled).containsMethod(expressionSetter))
+            {
                 expression.getAccessor().setExpression(expression);
             }
-
         }
     }
 
+    ClassFab generateClassFab(CompiledExpression compiled)
+            throws Exception
+    {
+        if (compiled.getGeneratedClass() != null)
+            return compiled.getGeneratedClass();
+
+        ClassFab classFab = _classFactory.newClass(ClassFabUtils.generateClassName(compiled.getExpression().getClass()), Object.class);
+        classFab.addInterface(ExpressionAccessor.class);
+        
+        compiled.setGeneratedClass(classFab);
+
+        return classFab;
+    }
+
     protected void generateFailSafe(OgnlContext context, Node expression, Object root)
     {
         if (expression.getAccessor() != null)
             return;
-        
-        try {
+
+        try
+        {
             ClassFab classFab = _classFactory.newClass(expression.getClass().getName() + expression.hashCode() + "Accessor", Object.class);
             classFab.addInterface(ExpressionAccessor.class);
 
@@ -252,15 +269,15 @@
 
             MethodSignature expressionSetter = new MethodSignature(void.class, "setExpression", new Class[]{Node.class}, null);
 
-            if (!classFab.containsMethod(expressionSetter)) {
-
+            if (!classFab.containsMethod(expressionSetter))
+            {
                 classFab.addField("_node", Node.class);
                 classFab.addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
             }
 
             classFab.addMethod(Modifier.PUBLIC, valueGetter, generateOgnlGetter(classFab, valueGetter));
             classFab.addMethod(Modifier.PUBLIC, valueSetter, generateOgnlSetter(classFab, valueSetter));
-            
+
             classFab.addConstructor(new Class[0], new Class[0], "{}");
 
             Class clazz = ((AbstractFab) classFab).createClass(true);
@@ -269,18 +286,18 @@
 
             // need to set expression on node if the field was just defined.
 
-            if (classFab.containsMethod(expressionSetter)) {
-
+            if (classFab.containsMethod(expressionSetter))
+            {
                 expression.getAccessor().setExpression(expression);
             }
 
-        } catch (Throwable t) {
-            
+        } catch (Throwable t)
+        {
             t.printStackTrace();
         }
     }
 
-    protected String generateGetter(OgnlContext context, ClassFab newClass, MethodSignature valueGetter, Node expression, Object root)
+    protected String generateGetter(OgnlContext context, CompiledExpression compiled)
             throws Exception
     {
         String pre = "";
@@ -288,22 +305,26 @@
         String body;
         String getterCode;
 
-        context.setRoot(root);
-        context.setCurrentObject(root);
+        context.setRoot(compiled.getRoot());
+        context.setCurrentObject(compiled.getRoot());
         context.remove(PRE_CAST);
-        
-        try {
 
-            getterCode = expression.toGetSourceString(context, root);
-        } catch (NullPointerException e) {
+        try
+        {
+            getterCode = compiled.getExpression().toGetSourceString(context, compiled.getRoot());
+        } catch (NullPointerException e)
+        {
             if (_log.isDebugEnabled())
                 _log.warn("NullPointer caught compiling getter, may be normal ognl method artifact.", e);
 
             throw new UnsupportedCompilationException("Statement threw nullpointer.");
         }
 
-        if (getterCode == null || getterCode.trim().length() <= 0 && !ASTVarRef.class.isAssignableFrom(expression.getClass()))
+        if (getterCode == null || getterCode.trim().length() <= 0
+                                  && !ASTVarRef.class.isAssignableFrom(compiled.getExpression().getClass()))
+        {
             getterCode = "null";
+        }
 
         String castExpression = (String) context.get(PRE_CAST);
 
@@ -316,26 +337,26 @@
             post = post + ")";
         }
 
-        String rootExpr = !getterCode.equals("null") ? getRootExpression(expression, root, context) : "";
+        String rootExpr = !getterCode.equals("null") ? getRootExpression(compiled.getExpression(), compiled.getRoot(), context) : "";
 
         String noRoot = (String) context.remove("_noRoot");
         if (noRoot != null)
             rootExpr = "";
 
-        createLocalReferences(context, newClass, valueGetter.getParameterTypes());
-
-        if (OrderedReturn.class.isInstance(expression) && ((OrderedReturn) expression).getLastExpression() != null) {
+        createLocalReferences(context, generateClassFab(compiled), compiled.getGetterMethod().getParameterTypes());
 
+        if (OrderedReturn.class.isInstance(compiled.getExpression()) && ((OrderedReturn) compiled.getExpression()).getLastExpression() != null)
+        {
             body = "{ "
-                   + (ASTMethod.class.isInstance(expression) || ASTChain.class.isInstance(expression) ? rootExpr : "")
+                   + (ASTMethod.class.isInstance(compiled.getExpression()) || ASTChain.class.isInstance(compiled.getExpression()) ? rootExpr : "")
                    + (castExpression != null ? castExpression : "")
-                   + ((OrderedReturn) expression).getCoreExpression()
-                   + " return " + pre + ((OrderedReturn) expression).getLastExpression()
+                   + ((OrderedReturn) compiled.getExpression()).getCoreExpression()
+                   + " return " + pre + ((OrderedReturn) compiled.getExpression()).getLastExpression()
                    + post
                    + ";}";
 
-        } else {
-
+        } else
+        {
             body = "{ return " + pre
                    + (castExpression != null ? castExpression : "")
                    + rootExpr
@@ -343,7 +364,7 @@
                    + post
                    + ";}";
         }
-        
+
         body = body.replaceAll("\\.\\.", ".");
 
         if (_log.isDebugEnabled())
@@ -361,8 +382,8 @@
 
         Iterator it = referenceMap.keySet().iterator();
 
-        while (it.hasNext()) {
-
+        while (it.hasNext())
+        {
             String key = (String) it.next();
             LocalReference ref = (LocalReference) referenceMap.get(key);
 
@@ -384,29 +405,29 @@
         }
     }
 
-    protected String generateSetter(OgnlContext context, ClassFab newClass, MethodSignature valueSetter, Node expression, Object root)
+    protected String generateSetter(OgnlContext context, CompiledExpression compiled)
             throws Exception
     {
-        if (ExpressionNode.class.isInstance(expression)
-            || ASTConst.class.isInstance(expression))
+        if (ExpressionNode.class.isInstance(compiled.getExpression())
+            || ASTConst.class.isInstance(compiled.getExpression()))
             throw new UnsupportedCompilationException("Can't compile expression/constant setters.");
 
-        context.setRoot(root);
-        context.setCurrentObject(root);
+        context.setRoot(compiled.getRoot());
+        context.setCurrentObject(compiled.getRoot());
         context.remove(PRE_CAST);
 
         String body;
 
-        String setterCode = expression.toSetSourceString(context, root);
+        String setterCode = compiled.getExpression().toSetSourceString(context, compiled.getRoot());
         String castExpression = (String) context.get(PRE_CAST);
 
         if (setterCode == null || setterCode.trim().length() < 1)
             throw new UnsupportedCompilationException("Can't compile null setter body.");
 
-        if (root == null)
+        if (compiled.getRoot() == null)
             throw new UnsupportedCompilationException("Can't compile setters with a null root object.");
 
-        String pre = getRootExpression(expression, root, context);
+        String pre = getRootExpression(compiled.getExpression(), compiled.getRoot(), context);
 
         String noRoot = (String) context.remove("_noRoot");
         if (noRoot != null)
@@ -416,7 +437,7 @@
         if (setterValue == null)
             setterValue = "";
 
-        createLocalReferences(context, newClass, valueSetter.getParameterTypes());
+        createLocalReferences(context, generateClassFab(compiled), compiled.getSettermethod().getParameterTypes());
 
         body = "{"
                + setterValue

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js Fri Sep  7 09:57:10 2007
@@ -301,11 +301,11 @@
 
     	// apply disabled/not disabled
     	var disabled = element.getAttribute("disabled");
-    	if (!disabled && node["disabled"]) {
-    		node.disabled = false;
-    	} else if (disabled) {
+        if (!disabled && node["disabled"]) {
+            node.disabled = false;
+        } else if (disabled) {
     		node.disabled = true;
-    	}
+        }
 	},
 
 	/**

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateExpr.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateExpr.xml?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateExpr.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateExpr.xml Fri Sep  7 09:57:10 2007
@@ -36,7 +36,7 @@
 		
 	  	<assert-output name="Specifying informal parameters">
 <![CDATA[
-Second example: <span class="styleClass">JUnit Mock Application</span>
+Second example: <span class="styleClass" id="insertAppName2">JUnit Mock Application</span>
 ]]>
 		</assert-output> 	
 	</request>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/binding/TestExpressionBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/binding/TestExpressionBinding.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/binding/TestExpressionBinding.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/binding/TestExpressionBinding.java Fri Sep  7 09:57:10 2007
@@ -28,7 +28,7 @@
 
 /**
  * Tests for {@link org.apache.tapestry.binding.ExpressionBinding}.
- * 
+ *
  * @author Howard M. Lewis Ship
  * @since 4.0
  */
@@ -37,46 +37,46 @@
 {
 
     public void test_Invariant()
-    {   
+    {
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         IComponent component = newMock(IComponent.class);
         Location l = fabricateLocation(1);
-        
+
         Node compiled = newMock(Node.class);
         //ExpressionAccessor accessor = newMock(ExpressionAccessor.class);
-        
+
         Object expressionValue = "EXPRESSION-VALUE";
-        
+
         ValueConverter vc = newValueConverter();
-        
+
         expect(ec.getCompiledExpression("exp")).andReturn(compiled);
-        
+
         expect(compiled.getAccessor()).andReturn(null);
-        
+
         expect(ev.isConstant("exp")).andReturn(true);
-        
+
         expect(ec.getCompiledExpression(component, "exp")).andReturn(compiled);
-        
+
         expect(ev.readCompiled(component, compiled)).andReturn(expressionValue);
-        
+
         expect(component.getExtendedId()).andReturn("Foo/bar");
 
         replay();
-        
+
         ExpressionBinding b = new ExpressionBinding("param", l, vc, component, "exp", ev, ec);
-        
+
         assertEquals(true, b.isInvariant());
-        
+
         // A second time, to test the 'already initialized'
         // code path.
-        
+
         assertEquals(true, b.isInvariant());
-        
+
         // Get the object, which should be cached.
 
         assertSame(expressionValue, b.getObject());
-        
+
         assertSame(component, b.getComponent());
 
         assertEquals(b.toString(), "ExpressionBinding[Foo/bar exp]");
@@ -89,7 +89,7 @@
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         Location l = fabricateLocation(1);
-        
+
         IComponent component = newComponent();
         Node compiled = newMock(Node.class);
         ExpressionAccessor accessor = newMock(ExpressionAccessor.class);
@@ -98,31 +98,29 @@
         Object expressionValue2 = new Object();
 
         ValueConverter vc = newValueConverter();
-        
+
         expect(ec.getCompiledExpression("exp")).andReturn(compiled);
-        
+
         expect(ev.isConstant("exp")).andReturn(false);
 
         expect(ec.getCompiledExpression(component, "exp")).andReturn(compiled);
-        
+
         expect(compiled.getAccessor()).andReturn(accessor);
-        
+
         expect(ev.read(component, accessor)).andReturn(expressionValue1);
-        
         expect(ev.read(component, accessor)).andReturn(expressionValue2);
-        
+
         replay();
-        
+
         ExpressionBinding b = new ExpressionBinding("param", l, vc, component,
-                "exp", ev, ec);
-        
+                                                    "exp", ev, ec);
+
         assertEquals(false, b.isInvariant());
 
         // Check that the expression is re-evaluated on
         // each call to getObject().
-        
-        assertSame(expressionValue1, b.getObject());
 
+        assertSame(expressionValue1, b.getObject());
         assertSame(expressionValue2, b.getObject());
 
         verify();
@@ -133,11 +131,11 @@
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         Location l = fabricateLocation(1);
-        
+
         IComponent component = newComponent();
         Node compiled = newMock(Node.class);
         ValueConverter vc = newValueConverter();
-        
+
         expect(ec.getCompiledExpression("exp")).andReturn(compiled);
 
         expect(ev.isConstant("exp")).andReturn(false);
@@ -147,13 +145,12 @@
         ev.writeCompiled(component, compiled, newValue);
 
         expect(ec.getCompiledExpression(component, "exp")).andReturn(compiled);
-
         expect(compiled.getAccessor()).andReturn(null);
 
         replay();
 
         ExpressionBinding b = new ExpressionBinding("param", l, vc, component,
-                "exp", ev, ec);
+                                                    "exp", ev, ec);
 
         b.setObject(newValue);
 
@@ -165,17 +162,13 @@
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         Location l = fabricateLocation(1);
-        
+
         IComponent component = newComponent();
         Node compiled = newMock(Node.class);
-        //ExpressionAccessor accessor = newMock(ExpressionAccessor.class);
-        
+
         ValueConverter vc = newValueConverter();
 
         expect(ec.getCompiledExpression("exp")).andReturn(compiled);
-        
-       // expect(compiled.getAccessor()).andReturn(accessor);
-        
         expect(ev.isConstant("exp")).andReturn(true);
 
         expect(component.getExtendedId()).andReturn("Foo/bar.baz");
@@ -183,7 +176,7 @@
         replay();
 
         ExpressionBinding b = new ExpressionBinding("parameter foo", l, vc, component,
-                "exp", ev, ec);
+                                                    "exp", ev, ec);
 
         try
         {
@@ -193,7 +186,7 @@
         catch (BindingException ex)
         {
             assertEquals("Binding with value exp (ExpressionBinding[Foo/bar.baz exp]) may not be updated.",
-                    ex.getMessage());
+                         ex.getMessage());
         }
 
         verify();
@@ -204,27 +197,27 @@
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         Location l = fabricateLocation(1);
-        
+
         IComponent component = newComponent();
         Node compiled = newMock(Node.class);
 
         ValueConverter vc = newValueConverter();
 
         expect(ec.getCompiledExpression("exp")).andReturn(compiled);
-        
+
         expect(ev.isConstant("exp")).andReturn(false);
 
         Object newValue = new Object();
 
         RuntimeException innerException = new RuntimeException("Failure");
-        
+
         ev.writeCompiled(component, compiled, newValue);
         expectLastCall().andThrow(innerException);
 
         replay();
 
         ExpressionBinding b = new ExpressionBinding("param", l, vc, component,
-                "exp", ev, ec);
+                                                    "exp", ev, ec);
 
         try
         {
@@ -245,7 +238,7 @@
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         Location l = fabricateLocation(1);
-        
+
         IComponent component = newComponent();
         ValueConverter vc = newValueConverter();
 
@@ -256,7 +249,7 @@
         replay();
 
         ExpressionBinding b = new ExpressionBinding("param", l, vc, component,
-                "exp", ev, ec);
+                                                    "exp", ev, ec);
 
         try
         {
@@ -277,13 +270,13 @@
         ExpressionEvaluator ev = newMock(ExpressionEvaluator.class);
         ExpressionCache ec = newMock(ExpressionCache.class);
         Location l = fabricateLocation(1);
-        
+
         IComponent component = newComponent();
         Node compiled = newMock(Node.class);
         ValueConverter vc = newValueConverter();
 
         expect(ec.getCompiledExpression("exp")).andReturn(compiled);
-        
+
         expect(ev.isConstant("exp")).andReturn(false);
 
         Throwable innerException = new RuntimeException("Failure");
@@ -294,7 +287,7 @@
         replay();
 
         ExpressionBinding b = new ExpressionBinding("param", l, vc, component,
-                "exp", ev, ec);
+                                                    "exp", ev, ec);
 
         try
         {

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/BasicObject.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/BasicObject.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/BasicObject.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/BasicObject.java Fri Sep  7 09:57:10 2007
@@ -5,8 +5,20 @@
  */
 public class BasicObject {
 
+    User _user;
+
     public String getName()
     {
         return "Henry the eith I am.";
+    }
+
+    public User getUser()
+    {
+        return _user;
+    }
+
+    public void setUser(User user)
+    {
+        _user = user;
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestHiveMindExpressionCompiler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestHiveMindExpressionCompiler.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestHiveMindExpressionCompiler.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestHiveMindExpressionCompiler.java Fri Sep  7 09:57:10 2007
@@ -13,7 +13,8 @@
 @Test
 public class TestHiveMindExpressionCompiler extends TestBase {
 
-    HiveMindExpressionCompiler _compiler = new HiveMindExpressionCompiler(new ClassFactoryImpl());
+    ClassFactoryImpl _classFactory = new ClassFactoryImpl();
+    HiveMindExpressionCompiler _compiler = new HiveMindExpressionCompiler(_classFactory);
 
     public void test_Duplicate_Class_Compiler()
     throws Exception
@@ -46,5 +47,53 @@
         _compiler.compileExpression(context, expression, expr);
         
         assertEquals(expression.getAccessor().get(context, null), Integer.valueOf(1));
+    }
+
+    public void test_ClassFab_Generation_Count_With_Uncompilable_Expression()
+            throws Exception
+    {
+        OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null);
+        BasicObject root = new BasicObject();
+
+        String exprStr = "user != null && user.name != null ? user.name : name";
+        Node expression = (Node) Ognl.parseExpression(exprStr);
+
+        int prevCount = _classFactory._classCounter;
+
+        _compiler.compileExpression(context, expression, root);
+        assert expression.getAccessor() == null;
+
+        assertEquals(_classFactory._classCounter, prevCount);
+
+        root.setUser(new User());
+
+        _compiler.compileExpression(context, expression, root);
+        assert expression.getAccessor() != null;
+
+        assertEquals(_classFactory._classCounter, prevCount + 1);
+    }
+
+    public void test_ClassFab_Generation_Count_With_Uncompilable_Expression2()
+            throws Exception
+    {
+        OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null);
+        BasicObject root = new BasicObject();
+
+        String exprStr = "user ? user.name : name";
+        Node expression = (Node) Ognl.parseExpression(exprStr);
+
+        int prevCount = _classFactory._classCounter;
+
+        _compiler.compileExpression(context, expression, root);
+        assert expression.getAccessor() == null;
+
+        assertEquals(_classFactory._classCounter, prevCount);
+
+        root.setUser(new User());
+
+        _compiler.compileExpression(context, expression, root);
+        assert expression.getAccessor() != null;
+
+        assertEquals(_classFactory._classCounter, prevCount + 1);
     }
 }

Added: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java?rev=573632&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java Fri Sep  7 09:57:10 2007
@@ -0,0 +1,12 @@
+package org.apache.tapestry.enhance;
+
+/**
+ * Simple test class for expression compiling.
+ */
+public class User {
+
+    public String getName()
+    {
+        return "A monsterous mistake!";
+    }
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/User.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/multipart/TestUploadFormParametersWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/multipart/TestUploadFormParametersWrapper.java?rev=573632&r1=573631&r2=573632&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/multipart/TestUploadFormParametersWrapper.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/multipart/TestUploadFormParametersWrapper.java Fri Sep  7 09:57:10 2007
@@ -14,16 +14,14 @@
 
 package org.apache.tapestry.multipart;
 
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.tapestry.BaseComponentTestCase;
-import org.easymock.EasyMock;
-import org.testng.annotations.ExpectedExceptions;
+import static org.easymock.EasyMock.expect;
 import org.testng.annotations.Test;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Tests for {@link org.apache.tapestry.multipart.UploadFormParametersWrapper}.
@@ -37,15 +35,13 @@
     private HttpServletRequest newHttpRequest()
     {
         HttpServletRequest req = newMock(HttpServletRequest.class);
-        EasyMock.expect(req.getParameterMap()).andReturn( new HashMap() );
+        expect(req.getParameterMap()).andReturn( new HashMap() ).anyTimes();
         return req;
     }
     
-       
     public void testMapIsNotModifiable()
     {
         HttpServletRequest request = newHttpRequest();
-        
 
         replay();
 
@@ -148,8 +144,7 @@
     public void testGetUrlParameter()  // Test fix for TAPESTRY-340
     {
         HttpServletRequest req = newMock(HttpServletRequest.class);
-        EasyMock.expect(req.getParameterMap()).andReturn(
-                new HashMap(){{put("urlParam", new String[]{"urlParamValue"} );}} );
+        expect(req.getParameterMap()).andReturn(new HashMap(){{put("urlParam", new String[]{"urlParamValue"} );}} ).anyTimes();
 
         replay();