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/01/13 23:40:52 UTC

svn commit: r495990 [1/2] - in /tapestry/tapestry4/branches/ognl-integration: ./ tapestry-examples/TimeTracker/ tapestry-examples/Workbench/src/context/ tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/ tapestry-examples/Workbench/src...

Author: jkuhnert
Date: Sat Jan 13 14:40:50 2007
New Revision: 495990

URL: http://svn.apache.org/viewvc?view=rev&rev=495990
Log:
Committing tapestry -> ognl 2.7 work before I lose it. Don't try running it yourself unless you have the new ognl 
version available. (which you won't, yet..)

Added:
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFabImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/MethodFabImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/test/org/apache/tapestry/services/impl/BasicObject.java
Modified:
    tapestry/tapestry4/branches/ognl-integration/pom.xml
    tapestry/tapestry4/branches/ognl-integration/tapestry-examples/TimeTracker/pom.xml
    tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/context/Redirect.html
    tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/Redirect.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/components/Border.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/hivemodule.xml
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/tapestry.ognl.xml
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/bean/BeanProviderPropertyAccessor.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/binding/ExpressionBinding.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceMessages.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceStrings.properties
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhancementOperationImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/form/Radio.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapPropertyAccessor.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/pageload/GlobalDefaultComponentClassProvider.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/script/AbstractToken.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionCache.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionEvaluator.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentConstructorFactoryImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionCacheImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionEvaluatorImpl.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/test/org/apache/tapestry/binding/TestExpressionBinding.java
    tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/test/org/apache/tapestry/services/impl/TestExpressionCache.java

Modified: tapestry/tapestry4/branches/ognl-integration/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/pom.xml?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/pom.xml (original)
+++ tapestry/tapestry4/branches/ognl-integration/pom.xml Sat Jan 13 14:40:50 2007
@@ -108,7 +108,7 @@
             <dependency>
                 <groupId>jboss</groupId>
                 <artifactId>javassist</artifactId>
-                <version>3.0</version>
+                <version>3.4.ga</version>
                 <scope>runtime</scope>
             </dependency>
             <dependency>

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-examples/TimeTracker/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-examples/TimeTracker/pom.xml?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-examples/TimeTracker/pom.xml (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-examples/TimeTracker/pom.xml Sat Jan 13 14:40:50 2007
@@ -111,7 +111,7 @@
                     <systemProperties>
                         <systemProperty>
                             <name>org.apache.tapestry.disable-caching</name>
-                            <value>true</value>
+                            <value>false</value>
                         </systemProperty>
                     </systemProperties>
                 </configuration>

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/context/Redirect.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/context/Redirect.html?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/context/Redirect.html (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/context/Redirect.html Sat Jan 13 14:40:50 2007
@@ -10,16 +10,16 @@
     </ul>
     <p> The code for both these cases is very simple:</p>
     <pre>
-    public void redirectInternal()
-    throws RequestCycleException
-    {
-        throw new RedirectException("redirect-target.html");
-    }
+public void redirectInternal()
+  throws RequestCycleException
+{
+	throw new RedirectException("redirect-target.html");
+}
 
-    public void redirectExternal()
-    throws RequestCycleException
-    {
-        throw new RedirectException("http://jakarta.apache.org/tapestry");
-    }
-</pre>
+public void redirectExternal()
+  throws RequestCycleException
+{
+	throw new RedirectException("http://tapestry.apache.org/");
+}
+	</pre>
 </span>

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/Redirect.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/Redirect.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/Redirect.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/Redirect.java Sat Jan 13 14:40:50 2007
@@ -33,6 +33,6 @@
 
     public void redirectExternal()
     {
-        throw new RedirectException("http://jakarta.apache.org/tapestry");
+        throw new RedirectException("http://tapestry.apache.org");
     }
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/components/Border.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/components/Border.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/components/Border.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-examples/Workbench/src/java/org/apache/tapestry/workbench/components/Border.java Sat Jan 13 14:40:50 2007
@@ -48,13 +48,13 @@
 
     @Message
     public abstract String getTabOrder();
-
+    
     public void pageBeginRender(PageEvent event)
     {
         Visit visit = getVisit();
 
         setActivePageName(visit.getActiveTabName());
-
+        
         if (_tabOrder == null)
             _tabOrder = TapestryUtils.split(getTabOrder(), ' ');
     }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/hivemodule.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/hivemodule.xml?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/hivemodule.xml (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/hivemodule.xml Sat Jan 13 14:40:50 2007
@@ -22,6 +22,14 @@
   <dependency module-id="hivemind" version="1.1.0"/>
   <dependency module-id="hivemind.lib" version="1.1.0"/>
   
+  <implementation service-id="hivemind.ClassFactory" >
+    
+    Wrapper around Javassist used to dynamically create classes such as service interceptors.
+    
+    <create-instance class="org.apache.tapestry.enhance.ClassFactoryImpl" model="primitive"/>
+    
+  </implementation>
+  
   <sub-module descriptor="tapestry.init.xml"/>
   <sub-module descriptor="tapestry.globals.xml"/>
   <sub-module descriptor="tapestry.props.xml"/>

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/tapestry.ognl.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/tapestry.ognl.xml?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/tapestry.ognl.xml (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/descriptor/META-INF/tapestry.ognl.xml Sat Jan 13 14:40:50 2007
@@ -37,6 +37,7 @@
       <construct class="impl.ExpressionCacheImpl">
         <event-listener service-id="tapestry.ResetEventHub"/>
         <event-listener service-id="tapestry.describe.ReportStatusHub"/>
+        <set-service property="evaluator" service-id="ExpressionEvaluator"/>
       </construct>
     </invoke-factory>
   </service-point>
@@ -98,7 +99,7 @@
   <contribution configuration-id="PropertyAccessors">
     
     <accessor class="org.apache.tapestry.IBeanProvider" object="instance:org.apache.tapestry.bean.BeanProviderPropertyAccessor"/>
-    <accessor class="org.apache.tapestry.listener.ListenerMap"
-      object="instance:org.apache.tapestry.listener.ListenerMapPropertyAccessor"/>
+    <accessor class="org.apache.tapestry.listener.ListenerMap" object="instance:org.apache.tapestry.listener.ListenerMapPropertyAccessor"/>
   </contribution>
-</module>
\ No newline at end of file
+  
+</module>

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/bean/BeanProviderPropertyAccessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/bean/BeanProviderPropertyAccessor.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/bean/BeanProviderPropertyAccessor.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/bean/BeanProviderPropertyAccessor.java Sat Jan 13 14:40:50 2007
@@ -17,7 +17,12 @@
 import java.util.Map;
 
 import ognl.ObjectPropertyAccessor;
+import ognl.OgnlContext;
 import ognl.OgnlException;
+import ognl.OgnlRuntime;
+import ognl.PropertyAccessor;
+import ognl.enhance.ExpressionCompiler;
+import ognl.enhance.UnsupportedCompilationException;
 
 import org.apache.tapestry.IBeanProvider;
 
@@ -34,7 +39,7 @@
  *
  **/
 
-public class BeanProviderPropertyAccessor extends ObjectPropertyAccessor
+public class BeanProviderPropertyAccessor extends ObjectPropertyAccessor implements PropertyAccessor
 {
     /**
      *  Checks to see if the name matches the name of a bean inside
@@ -63,12 +68,42 @@
     public boolean hasGetProperty(Map context, Object target, Object oname) throws OgnlException
     {
         IBeanProvider provider = (IBeanProvider)target;
-        String beanName = (String)oname;
+        String beanName = ((String)oname).replaceAll("\"", "");
 
         if (provider.canProvideBean(beanName))
             return true;
             
         return super.hasGetProperty(context, target, oname);
     }
-
+    
+    public Class getPropertyClass(OgnlContext context, Object target, Object name)
+    {
+        IBeanProvider provider = (IBeanProvider)target;
+        String beanName = ((String)name).replaceAll("\"", "");
+        
+        if (provider.canProvideBean(beanName))
+            return provider.getBean(beanName).getClass();
+        
+        return super.getPropertyClass(context, target, name);
+    }
+    
+    public String getSourceAccessor(OgnlContext context, Object target, Object name)
+    {
+        IBeanProvider provider = (IBeanProvider)target;
+        String beanName = ((String)name).replaceAll("\"", "");
+        
+        if (provider.canProvideBean(beanName)) {
+            ExpressionCompiler.addCastString(context, "((" 
+                    + OgnlRuntime.getCompiler().getInterfaceClass(provider.getBean(beanName).getClass()).getName() + ")");
+            
+            return ".getBean(" + name + "))";
+        }
+        
+        return super.getSourceAccessor(context, target, name);
+    }
+    
+    public String getSourceSetter(OgnlContext context, Object target, Object name)
+    {
+        throw new UnsupportedCompilationException("Can't set beans on IBeanProvider.");
+    }
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/binding/ExpressionBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/binding/ExpressionBinding.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/binding/ExpressionBinding.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/binding/ExpressionBinding.java Sat Jan 13 14:40:50 2007
@@ -14,6 +14,9 @@
 
 package org.apache.tapestry.binding;
 
+import ognl.Node;
+import ognl.enhance.ExpressionAccessor;
+
 import org.apache.hivemind.Location;
 import org.apache.tapestry.BindingException;
 import org.apache.tapestry.IComponent;
@@ -55,8 +58,14 @@
      * Parsed OGNL expression.
      */
 
-    private Object _parsedExpression;
-
+    private Node _parsedExpression;
+    
+    /**
+     * Compiled OGNL expression.
+     */
+    
+    private ExpressionAccessor _accessor;
+    
     /**
      * Flag set to true once the binding has initialized.
      */
@@ -107,7 +116,14 @@
     {
         try
         {
-            return _evaluator.readCompiled(_root, _parsedExpression);
+            if (_accessor == null) {
+                
+                _parsedExpression = (Node)_cache.getCompiledExpression(_root, _expression);
+                
+                _accessor = _parsedExpression.getAccessor();
+            }
+            
+            return _evaluator.read(_root, _accessor);
         }
         catch (Throwable t)
         {
@@ -140,8 +156,8 @@
 
         try
         {
-            _parsedExpression = _cache.getCompiledExpression(_expression);
-
+            _parsedExpression = (Node)_cache.getCompiledExpression(_expression);
+            
             _invariant = _evaluator.isConstant(_expression);
         }
         catch (Exception ex)
@@ -161,13 +177,17 @@
     public void setObject(Object value)
     {
         initialize();
-
+        
         if (_invariant)
             throw createReadOnlyBindingException(this);
-
+        
         try
         {
-            _evaluator.writeCompiled(_root, _parsedExpression, value);
+            if (_accessor == null) {
+                
+                _evaluator.writeCompiled(_root, _parsedExpression, value);
+            } else 
+                _evaluator.write(_root, _accessor, value);
         }
         catch (Throwable ex)
         {
@@ -186,7 +206,8 @@
         StringBuffer buffer = new StringBuffer();
 
         buffer.append("ExpressionBinding[");
-        buffer.append(_root.getExtendedId());
+        buffer.append(_root.getId());
+        //buffer.append(_root.getExtendedId());
 
         if (_expression != null)
         {

Added: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFabImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFabImpl.java?view=auto&rev=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFabImpl.java (added)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFabImpl.java Sat Jan 13 14:40:50 2007
@@ -0,0 +1,315 @@
+// Copyright 2007 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry.enhance;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.service.ClassFab;
+import org.apache.hivemind.service.MethodFab;
+import org.apache.hivemind.service.MethodSignature;
+import org.apache.hivemind.service.impl.AbstractFab;
+import org.apache.hivemind.service.impl.CtClassSource;
+
+/**
+ * Implementation replacement for hivemind {@link ClassFab} utiltity to get around some javassist
+ * incompatibilties found with the latest 3.4 version of javassist.
+ * 
+ * @author jkuhnert
+ */
+public class ClassFabImpl extends AbstractFab implements ClassFab
+{
+    /**
+     * Stores information about a constructor; used by toString().
+     * 
+     * @since 1.1
+     */
+
+    private class AddedConstructor
+    {
+
+        private Class[] _parameterTypes;
+
+        private Class[] _exceptionTypes;
+
+        private String _body;
+
+        AddedConstructor(Class[] parameterTypes, Class[] exceptionTypes, String body)
+        {
+            _parameterTypes = parameterTypes;
+            _exceptionTypes = exceptionTypes;
+            _body = body;
+        }
+
+        public String toString()
+        {
+            StringBuffer buffer = new StringBuffer();
+
+            buffer.append("public ");
+            buffer.append(getCtClass().getName());
+
+            buffer.append("(");
+
+            int count = size(_parameterTypes);
+            for(int i = 0; i < count; i++) {
+                if (i > 0) buffer.append(", ");
+
+                buffer.append(_parameterTypes[i].getName());
+
+                buffer.append(" $");
+                buffer.append(i + 1);
+            }
+
+            buffer.append(")");
+
+            count = size(_exceptionTypes);
+            for(int i = 0; i < count; i++) {
+                if (i == 0)
+                    buffer.append("\n  throws ");
+                else buffer.append(", ");
+
+                buffer.append(_exceptionTypes[i].getName());
+            }
+
+            buffer.append("\n");
+            buffer.append(_body);
+
+            buffer.append("\n");
+
+            return buffer.toString();
+        }
+
+        private int size(Object[] array)
+        {
+            return array == null ? 0 : array.length;
+        }
+    }
+
+    /**
+     * Map of {@link MethodFab}keyed on {@link MethodSignature}.
+     */
+    private Map _methods = new HashMap();
+
+    /**
+     * List of {@link AddedConstructor}.
+     * 
+     * @since 1.1
+     */
+
+    private List _constructors = new ArrayList();
+
+    public ClassFabImpl(CtClassSource source, CtClass ctClass)
+    {
+        super(source, ctClass);
+    }
+
+    /**
+     * Returns a representation of the fabricated class, including inheritance, fields,
+     * constructors, methods and method bodies.
+     * 
+     * @since 1.1
+     */
+    public String toString()
+    {
+        StringBuffer buffer = new StringBuffer("ClassFab[\n");
+
+        try {
+            buildClassAndInheritance(buffer);
+
+            buildFields(buffer);
+
+            buildConstructors(buffer);
+
+            buildMethods(buffer);
+
+        } catch (Exception ex) {
+            buffer.append(" *** ");
+            buffer.append(ex);
+        }
+
+        buffer.append("\n]");
+
+        return buffer.toString();
+    }
+
+    /** @since 1.1 */
+    private void buildMethods(StringBuffer buffer)
+    {
+        Iterator i = _methods.values().iterator();
+        while(i.hasNext()) {
+
+            MethodFab mf = (MethodFab) i.next();
+
+            buffer.append("\n");
+            buffer.append(mf);
+            buffer.append("\n");
+        }
+    }
+
+    /** @since 1.1 */
+    private void buildConstructors(StringBuffer buffer)
+    {
+        Iterator i = _constructors.iterator();
+
+        while(i.hasNext()) {
+            buffer.append("\n");
+            buffer.append(i.next());
+        }
+    }
+
+    /** @since 1.1 */
+    private void buildFields(StringBuffer buffer)
+        throws NotFoundException
+    {
+        CtField[] fields = getCtClass().getDeclaredFields();
+
+        for(int i = 0; i < fields.length; i++) {
+            buffer.append("\n");
+            buffer.append(modifiers(fields[i].getModifiers()));
+            buffer.append(" ");
+            buffer.append(fields[i].getType().getName());
+            buffer.append(" ");
+            buffer.append(fields[i].getName());
+            buffer.append(";\n");
+        }
+    }
+
+    /** @since 1.1 */
+    private void buildClassAndInheritance(StringBuffer buffer)
+        throws NotFoundException
+    {
+        buffer.append(modifiers(getCtClass().getModifiers()));
+        buffer.append(" class ");
+        buffer.append(getCtClass().getName());
+        buffer.append(" extends ");
+        buffer.append(getCtClass().getSuperclass().getName());
+        buffer.append("\n");
+
+        CtClass[] interfaces = getCtClass().getInterfaces();
+
+        if (interfaces.length > 0) {
+            buffer.append("  implements ");
+
+            for(int i = 0; i < interfaces.length; i++) {
+                if (i > 0) buffer.append(", ");
+
+                buffer.append(interfaces[i].getName());
+            }
+
+            buffer.append("\n");
+        }
+    }
+
+    private String modifiers(int modifiers)
+    {
+        return Modifier.toString(modifiers);
+    }
+
+    /**
+     * Returns the name of the class fabricated by this instance.
+     */
+    String getName()
+    {
+        return getCtClass().getName();
+    }
+
+    public void addField(String name, Class type)
+    {
+        CtClass ctType = convertClass(type);
+
+        try {
+            CtField field = new CtField(ctType, name, getCtClass());
+            field.setModifiers(Modifier.PRIVATE);
+
+            getCtClass().addField(field);
+        } catch (CannotCompileException ex) {
+            throw new ApplicationRuntimeException(EnhanceMessages.unableToAddField(name, getCtClass(), ex), ex);
+        }
+    }
+
+    public boolean containsMethod(MethodSignature ms)
+    {
+        return _methods.get(ms) != null;
+    }
+
+    public MethodFab addMethod(int modifiers, MethodSignature ms, String body)
+    {
+        if (_methods.get(ms) != null)
+            throw new ApplicationRuntimeException(EnhanceMessages.duplicateMethodInClass(ms, this));
+        
+        if (body.indexOf("isWrapperFor") > 0 || body.indexOf("unwrap") > 0)
+            return new MethodFabImpl(null, ms, null, "{ throw new UnsupportedOperationException(\"Method not implemented\"); }");
+        
+        CtClass ctReturnType = convertClass(ms.getReturnType());
+
+        CtClass[] ctParameters = convertClasses(ms.getParameterTypes());
+        CtClass[] ctExceptions = convertClasses(ms.getExceptionTypes());
+        
+        CtMethod method = new CtMethod(ctReturnType, ms.getName(), ctParameters, getCtClass());
+        
+        try {
+            method.setModifiers(modifiers);
+            method.setBody(body);
+            method.setExceptionTypes(ctExceptions);
+            
+            getCtClass().addMethod(method);
+        } catch (Exception ex) {
+            
+            throw new ApplicationRuntimeException(EnhanceMessages.unableToAddMethod(ms, getCtClass(), ex), ex);
+        }
+
+        // Return a MethodFab so the caller can add catches.
+
+        MethodFab result = new MethodFabImpl(getSource(), ms, method, body);
+
+        _methods.put(ms, result);
+
+        return result;
+    }
+    
+    public MethodFab getMethodFab(MethodSignature ms)
+    {
+        return (MethodFab) _methods.get(ms);
+    }
+
+    public void addConstructor(Class[] parameterTypes, Class[] exceptions, String body)
+    {
+        CtClass[] ctParameters = convertClasses(parameterTypes);
+        CtClass[] ctExceptions = convertClasses(exceptions);
+
+        try {
+            CtConstructor constructor = new CtConstructor(ctParameters, getCtClass());
+            constructor.setExceptionTypes(ctExceptions);
+            constructor.setBody(body);
+
+            getCtClass().addConstructor(constructor);
+
+            _constructors.add(new AddedConstructor(parameterTypes, exceptions, body));
+        } catch (Exception ex) {
+            throw new ApplicationRuntimeException(EnhanceMessages.unableToAddConstructor(getCtClass(), ex), ex);
+        }
+    }
+}

Added: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java?view=auto&rev=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java (added)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/ClassFactoryImpl.java Sat Jan 13 14:40:50 2007
@@ -0,0 +1,75 @@
+// Copyright 2004, 2005 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry.enhance;
+
+import javassist.CtClass;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.service.ClassFab;
+import org.apache.hivemind.service.ClassFactory;
+import org.apache.hivemind.service.InterfaceFab;
+import org.apache.hivemind.service.impl.CtClassSource;
+import org.apache.hivemind.service.impl.HiveMindClassPool;
+import org.apache.hivemind.service.impl.InterfaceFabImpl;
+
+/**
+ * Implementation of the hivemind core {@link ClassFactory} service to get around some incompatibilities 
+ * the current 1.1.1 implementation of hivemind has with the latest (3.4) version of javassist.
+ * 
+ * @author jkuhnert
+ */
+public class ClassFactoryImpl implements ClassFactory
+{
+    /**
+     * ClassPool shared by all modules (all CtClassSource instances).
+     */
+    private HiveMindClassPool _pool = new HiveMindClassPool();
+
+    private CtClassSource _classSource = new CtClassSource(_pool);
+
+    public ClassFab newClass(String name, Class superClass)
+    {
+        try
+        {
+            CtClass ctNewClass = _classSource.newClass(name, superClass);
+            
+            return new ClassFabImpl(_classSource, ctNewClass);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(EnhanceMessages.unableToCreateClass(
+                    name,
+                    superClass,
+                    ex), ex);
+        }
+    }
+
+    /** @since 1.1 */
+
+    public InterfaceFab newInterface(String name)
+    {
+        try
+        {
+            CtClass ctNewClass = _classSource.newInterface(name);
+
+            return new InterfaceFabImpl(_classSource, ctNewClass);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(
+                    EnhanceMessages.unableToCreateInterface(name, ex), ex);
+        }
+
+    }
+}

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceMessages.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceMessages.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceMessages.java Sat Jan 13 14:40:50 2007
@@ -17,6 +17,9 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
+import javassist.CtClass;
+import javassist.CtMethod;
+
 import org.apache.hivemind.Location;
 import org.apache.hivemind.impl.MessageFormatter;
 import org.apache.hivemind.service.ClassFabUtils;
@@ -163,5 +166,47 @@
     static String autowiring( String propertyName, IComponentSpecification spec, Object proxy )
     {
         return _formatter.format( "autowiring", propertyName, spec.getDescription(), proxy );
+    }
+    
+    static String unableToCreateClass(String name, Class superClass, Throwable cause)
+    {
+        return _formatter.format("unable-to-create-class", name, superClass.getName(), cause);
+    }
+    
+    static String unableToCreateInterface(String name, Exception cause)
+    {
+        return _formatter.format("unable-to-create-interface", name, cause);
+    }
+    
+    static String unableToAddField(String fieldName, CtClass ctClass, Throwable cause)
+    {
+        return _formatter.format("unable-to-add-field", fieldName, ctClass.getName(), cause);
+    }
+    
+    static String duplicateMethodInClass(MethodSignature ms, ClassFabImpl cf)
+    {
+        return _formatter.format("duplicate-method-in-class", ms, cf.getName());
+    }
+    
+    static String unableToAddMethod(MethodSignature methodSignature, CtClass ctClass,
+            Throwable cause)
+    {
+        return _formatter.format("unable-to-add-method", methodSignature, ctClass.getName(), cause);
+    }
+    
+    static String unableToAddConstructor(CtClass ctClass, Throwable cause)
+    {
+        return _formatter.format("unable-to-add-constructor", ctClass.getName(), cause);
+    }
+    
+    static String unableToAddCatch(Class exceptionClass, CtMethod method, Throwable cause)
+    {
+        return _formatter.format("unable-to-add-catch", exceptionClass.getName(), method
+                .getDeclaringClass().getName(), cause);
+    }
+    
+    static String unableToExtendMethod(MethodSignature ms, String className, Throwable cause)
+    {
+        return _formatter.format("unable-to-extend-method", ms, className, cause);
     }
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceStrings.properties?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceStrings.properties (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhanceStrings.properties Sat Jan 13 14:40:50 2007
@@ -32,3 +32,12 @@
 readonly-property=Property {0} should be read-only; remove method {1}.
 must-be-boolean=Property {0} must be type boolean for this type of injection.
 autowiring=Autowiring property {0} for component {1} to {2}.
+
+unable-to-create-class=Unable to create class {0} as subclass of {1}: {2}
+unable-to-create-interface=Unable to create interface {0}: {1}
+unable-to-add-field=Unable to add field {0} to class {1}: {2}
+unable-to-add-method=Unable to add method {0} to class {1}: {2}
+unable-to-add-constructor=Unable to add constructor to class {0}: {1}
+duplicate-method-in-class=Attempt to redefine method {0} of class {1}.
+unable-to-add-catch=Unable to add catch block for exception {0} to class {1}: {2}
+unable-to-extend-method=Unable to extend method {0} of class {1}: {2}

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhancementOperationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhancementOperationImpl.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhancementOperationImpl.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/EnhancementOperationImpl.java Sat Jan 13 14:40:50 2007
@@ -488,12 +488,10 @@
         if (_constructorBuilder != null)
         {
             _constructorBuilder.end();
-
-            Class[] types = (Class[]) _constructorTypes
-                    .toArray(new Class[_constructorTypes.size()]);
-
-            _classFab.addConstructor(types, null, _constructorBuilder
-                    .toString());
+            
+            Class[] types = (Class[]) _constructorTypes.toArray(new Class[_constructorTypes.size()]);
+            
+            _classFab.addConstructor(types, null, _constructorBuilder.toString());
         }
 
         if (_log != null) _log.debug("Creating class:\n\n" + _classFab);
@@ -624,8 +622,7 @@
         {
             try
             {
-                return c.getDeclaredMethod(sig.getName(), sig
-                        .getParameterTypes());
+                return c.getDeclaredMethod(sig.getName(), sig.getParameterTypes());
             }
             catch (NoSuchMethodException ex)
             {

Added: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/MethodFabImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/MethodFabImpl.java?view=auto&rev=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/MethodFabImpl.java (added)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/enhance/MethodFabImpl.java Sat Jan 13 14:40:50 2007
@@ -0,0 +1,159 @@
+// Copyright 2004, 2005 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry.enhance;
+
+import java.lang.reflect.Modifier;
+
+import javassist.CtClass;
+import javassist.CtMethod;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.service.MethodFab;
+import org.apache.hivemind.service.MethodSignature;
+import org.apache.hivemind.service.impl.CtClassSource;
+
+/**
+ * Implementation of hivemind {@link MethodFab} utiltity.
+ */
+public class MethodFabImpl implements MethodFab
+{
+    private CtClassSource _source;
+
+    private MethodSignature _signature;
+
+    private CtMethod _method;
+
+    private StringBuffer _descriptionBody = new StringBuffer();
+
+    public MethodFabImpl(CtClassSource source, MethodSignature signature, CtMethod method,
+            String body)
+    {
+        _source = source;
+        _signature = signature;
+        _method = method;
+
+        _descriptionBody.append(body);
+    }
+
+    /**
+     * Returns a a text representation of the method, parameters and method body.
+     */
+    public String toString()
+    {
+        if (_method == null)
+            return "";
+        
+        StringBuffer buffer = new StringBuffer();
+
+        try
+        {
+            buffer.append(Modifier.toString(_method.getModifiers()));
+
+            buffer.append(" ");
+            buffer.append(_method.getReturnType().getName());
+
+            buffer.append(" ");
+            buffer.append(_method.getName());
+            buffer.append("(");
+
+            CtClass[] params = _method.getParameterTypes();
+
+            for (int i = 0; i < params.length; i++)
+            {
+                if (i > 0)
+                    buffer.append(", ");
+
+                buffer.append(params[i].getName());
+
+                buffer.append(" $");
+                buffer.append(i + 1);
+            }
+            buffer.append(")");
+
+            CtClass[] exceptions = _method.getExceptionTypes();
+
+            for (int i = 0; i < exceptions.length; i++)
+            {
+                if (i == 0)
+                    buffer.append("\n  throws ");
+                else
+                    buffer.append(", ");
+
+                buffer.append(exceptions[i].getName());
+            }
+
+            buffer.append("\n");
+            buffer.append(_descriptionBody);
+        }
+        catch (Exception ex)
+        {
+            buffer.append(" *** ");
+            buffer.append(ex);
+        }
+
+        return buffer.toString();
+    }
+
+    public void addCatch(Class exceptionClass, String catchBody)
+    {
+        if (_method == null)
+            return;
+        
+        CtClass ctException = _source.getCtClass(exceptionClass);
+
+        try
+        {
+            _method.addCatch(catchBody, ctException);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(EnhanceMessages.unableToAddCatch(
+                    exceptionClass,
+                    _method,
+                    ex), ex);
+        }
+
+        _descriptionBody.append("\ncatch(");
+        _descriptionBody.append(exceptionClass.getName());
+        _descriptionBody.append(" $e)\n");
+        _descriptionBody.append(catchBody);
+    }
+
+    public void extend(String body, boolean asFinally)
+    {
+        if (_method == null)
+            return;
+        
+        try
+        {
+            _method.insertAfter(body, asFinally);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(EnhanceMessages.unableToExtendMethod(
+                    _signature,
+                    _method.getDeclaringClass().getName(),
+                    ex), ex);
+        }
+
+        _descriptionBody.append("\n");
+
+        if (asFinally)
+            _descriptionBody.append("finally\n");
+
+        _descriptionBody.append(body);
+    }
+
+
+}

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/form/Radio.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/form/Radio.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/form/Radio.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/form/Radio.java Sat Jan 13 14:40:50 2007
@@ -74,13 +74,13 @@
             
             return;
         }
-
+        
         setClientId(group.getName()+option);
         
         writer.beginEmpty("input");
-
+        
         writer.attribute("type", "radio");
-
+        
         writer.attribute("name", group.getName());
         
         renderIdAttribute(writer, cycle);

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapPropertyAccessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapPropertyAccessor.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapPropertyAccessor.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapPropertyAccessor.java Sat Jan 13 14:40:50 2007
@@ -17,7 +17,12 @@
 import java.util.Map;
 
 import ognl.ObjectPropertyAccessor;
+import ognl.OgnlContext;
 import ognl.OgnlException;
+import ognl.OgnlRuntime;
+import ognl.PropertyAccessor;
+import ognl.enhance.ExpressionCompiler;
+import ognl.enhance.UnsupportedCompilationException;
 
 /**
  * Exposes {@link org.apache.tapestry.IActionListener}&nbsp;listeners provided
@@ -28,7 +33,7 @@
  * @since 2.2
  */
 
-public class ListenerMapPropertyAccessor extends ObjectPropertyAccessor
+public class ListenerMapPropertyAccessor extends ObjectPropertyAccessor implements PropertyAccessor
 {
 
     /**
@@ -64,5 +69,35 @@
 
         return super.hasGetProperty(context, target, oname);
     }
-
+    
+    public Class getPropertyClass(OgnlContext context, Object target, Object name)
+    {
+        ListenerMap map = (ListenerMap) target;
+        String listenerName = (String) name;
+        
+        if (map.canProvideListener(listenerName))
+            return map.getListener(listenerName).getClass();
+        
+        return super.getPropertyClass(context, target, name);
+    }
+    
+    public String getSourceAccessor(OgnlContext context, Object target, Object name)
+    {
+        ListenerMap map = (ListenerMap) target;
+        String listenerName = ((String)name).replaceAll("\"", "");
+        
+        if (map.canProvideListener(listenerName)) {
+            ExpressionCompiler.addCastString(context, "((" 
+                    + OgnlRuntime.getCompiler().getInterfaceClass(map.getListener(listenerName).getClass()).getName() + ")");
+            
+            return ".getListener(" + name + "))";
+        }
+        
+        return super.getSourceAccessor(context, target, name);
+    }
+    
+    public String getSourceSetter(OgnlContext context, Object target, Object name)
+    {
+        throw new UnsupportedCompilationException("Can't set listeners on ListenerMap.");
+    }
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/pageload/GlobalDefaultComponentClassProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/pageload/GlobalDefaultComponentClassProvider.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/pageload/GlobalDefaultComponentClassProvider.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/pageload/GlobalDefaultComponentClassProvider.java Sat Jan 13 14:40:50 2007
@@ -21,8 +21,7 @@
  * @author Howard M. Lewis Ship
  * @since 4.0
  */
-public class GlobalDefaultComponentClassProvider implements
-        ComponentClassProvider
+public class GlobalDefaultComponentClassProvider implements ComponentClassProvider
 {
 
     private String _componentClassName;
@@ -32,8 +31,7 @@
         _componentClassName = componentClassName;
     }
 
-    public String provideComponentClassName(
-            ComponentClassProviderContext context)
+    public String provideComponentClassName(ComponentClassProviderContext context)
     {
         return _componentClassName;
     }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/script/AbstractToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/script/AbstractToken.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/script/AbstractToken.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/script/AbstractToken.java Sat Jan 13 14:40:50 2007
@@ -74,7 +74,7 @@
 
     /**
      * Evaluates the expression against the session's symbols, using
-     * {@link ExpressionEvaluator#read(Object, String)}and returns the result.
+     * {@link ExpressionEvaluator#read(Object, String)} and returns the result.
      */
     protected Object evaluate(String expression, ScriptSession session)
     {

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionCache.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionCache.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionCache.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionCache.java Sat Jan 13 14:40:50 2007
@@ -28,6 +28,20 @@
      * 
      * @throws org.apache.hivemind.ApplicationRuntimeException
      *             if the expression is not valid
+     * @deprecated To be removed in Tapestry 4.2, use {@link #getCompiledExpression(Object, String)} instead.
      */
     Object getCompiledExpression(String expression);
+    
+    /**
+     * Returns the compiled ognl expression for the given target object class / expression
+     * combination.
+     * 
+     * @param target
+     *          The object this expression is to be used for.
+     * @param expression
+     *          The expression.
+     * @return
+     *      The compiled (or new if neccessary) ognl statement.
+     */
+    Object getCompiledExpression(Object target, String expression);
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionEvaluator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionEvaluator.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionEvaluator.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/ExpressionEvaluator.java Sat Jan 13 14:40:50 2007
@@ -14,6 +14,9 @@
 
 package org.apache.tapestry.services;
 
+import ognl.OgnlContext;
+import ognl.enhance.ExpressionAccessor;
+
 /**
  * Wrapper around the OGNL library.
  * 
@@ -41,7 +44,20 @@
      *             expression.
      */
     Object readCompiled(Object target, Object expression);
-
+    
+    /**
+     * Reads a property of the target, defined by the (previously compiled)
+     * expression.
+     * 
+     * @param target
+     *          The object to resolve the expression against.
+     * @param expression
+     *          The compiled expression.
+     * @return
+     *          The result of reading on the expression.
+     */
+    Object read(Object target, ExpressionAccessor expression);
+    
     /**
      * Updates a property of the target, defined by the expression.
      * 
@@ -60,7 +76,20 @@
      *             expression.
      */
     void writeCompiled(Object target, Object expression, Object value);
-
+    
+    /**
+     * Updates a property of the target, defined by the (previously compiled)
+     * expression.
+     * 
+     * @param target
+     *          The target object to set a value on.
+     * @param expression
+     *          The pre-compiled expression.
+     * @param value
+     *          The value to set.
+     */
+    void write(Object target, ExpressionAccessor expression, Object value);
+    
     /**
      * Returns true if the expression evaluates to a constant or other literal
      * value.
@@ -69,4 +98,24 @@
      *             if the expression is not valid
      */
     boolean isConstant(String expression);
+    
+    /**
+     * Returns true if the expression evaluates to a constant or other literal
+     * value.
+     * 
+     * @throws org.apache.hivemind.ApplicationRuntimeException
+     *             if the expression is not valid
+     */
+    boolean isConstant(Object target, String expression);
+    
+    /**
+     * Creates a default OGNL context object that can be used against
+     * the specified object for expression evaluation.
+     * 
+     * @param target 
+     *          The object to get a context for.
+     * @return 
+     *          An ognl context map.
+     */
+    OgnlContext createContext(Object target);
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentConstructorFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentConstructorFactoryImpl.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentConstructorFactoryImpl.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentConstructorFactoryImpl.java Sat Jan 13 14:40:50 2007
@@ -74,7 +74,7 @@
     public synchronized void reportStatus(ReportStatusEvent event)
     {
         event.title(_serviceId);
-
+        
         event.property("enhanced class count", _cachedConstructors.size());
         event.collection("enhanced classes", _cachedConstructors.keySet());
     }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java Sat Jan 13 14:40:50 2007
@@ -151,7 +151,7 @@
         // Important - causes any cookies stored to properly be written out before the
         // rest of the response starts being written - see TAPESTRY-825
         
-        _writer.flush();
+        // _writer.flush();
         
         // render response
         

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java Sat Jan 13 14:40:50 2007
@@ -181,21 +181,23 @@
             _contentType.setParameter(ENCODING_KEY, encoding);
         }
         
-        // _output = new ByteArrayOutputStream();
-        
-        PrintWriter printWriter = _response.getPrintWriter(_contentType);
-        // PrintWriter printWriter = new PrintWriter(_output, true);
-        
-        _writer = _markupWriterSource.newMarkupWriter(printWriter, _contentType);
+        if (_writer == null) {
+            // _output = new ByteArrayOutputStream();
+            
+            PrintWriter printWriter = _response.getPrintWriter(_contentType);
+            // PrintWriter printWriter = new PrintWriter(_output, true);
+            
+            _writer = _markupWriterSource.newMarkupWriter(printWriter, _contentType);
+            
+            parseParameters(cycle);
+            
+            beginResponse();
+        }
         
         // Important - causes any cookies stored to properly be written out before the
         // rest of the response starts being written - see TAPESTRY-825
         
         _writer.flush();
-        
-        parseParameters(cycle);
-        
-        beginResponse();
         
         // render response
         

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionCacheImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionCacheImpl.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionCacheImpl.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionCacheImpl.java Sat Jan 13 14:40:50 2007
@@ -14,9 +14,13 @@
 
 package org.apache.tapestry.services.impl;
 
+import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
+
 import java.util.HashMap;
 import java.util.Map;
+import java.util.WeakHashMap;
 
+import ognl.Node;
 import ognl.Ognl;
 
 import org.apache.hivemind.ApplicationRuntimeException;
@@ -24,21 +28,36 @@
 import org.apache.tapestry.event.ReportStatusListener;
 import org.apache.tapestry.event.ResetEventListener;
 import org.apache.tapestry.services.ExpressionCache;
+import org.apache.tapestry.services.ExpressionEvaluator;
 
 /**
  * @author Howard M. Lewis Ship
  * @since 4.0
  */
-public class ExpressionCacheImpl implements ExpressionCache, ResetEventListener,
-        ReportStatusListener
+public class ExpressionCacheImpl implements ExpressionCache, ResetEventListener, ReportStatusListener
 {
+    private final ReentrantLock _lock = new ReentrantLock();
+    
     private String _serviceId;
 
-    private Map _cache = new HashMap();
-
-    public synchronized void resetEventDidOccur()
+    private Map _cache = new WeakHashMap();
+    
+    private Map _objectCache = new WeakHashMap();
+    
+    private ExpressionEvaluator _evaluator;
+    
+    public void resetEventDidOccur()
     {
-        _cache.clear();
+        try {
+            
+            _lock.lock();
+            
+            _cache.clear();
+            _objectCache.clear();
+        } finally {
+            
+            _lock.unlock();
+        }
     }
 
     public void reportStatus(ReportStatusEvent event)
@@ -47,21 +66,76 @@
 
         event.property("cached expression count", _cache.size());
         event.collection("cached expressions", _cache.keySet());
+        
+        event.property("cached object expression count", _objectCache.size());
     }
-
-    public synchronized Object getCompiledExpression(String expression)
+    
+    public Object getCompiledExpression(Object target, String expression)
     {
-        Object result = _cache.get(expression);
+        try {   
+            
+            _lock.lock();
+            
+            Map cached = (Map)_objectCache.get(target.getClass());
+            
+            if (cached == null) {
+                
+                cached = new HashMap();
+                _objectCache.put(target.getClass(), cached);
+            }
+            
+            Node result = (Node)cached.get(expression);
+            
+            if (result == null)
+            {
+                
+                result = parse(target, expression);
+                cached.put(expression, result);
+            }
+            
+            return result;
+            
+        } finally {
 
-        if (result == null)
-        {
-            result = parse(expression);
-            _cache.put(expression, result);
+            _lock.unlock();
         }
+    }
+    
+    public Object getCompiledExpression(String expression)
+    {
+        try {
+            
+            _lock.lock();
+            
+            Object result = _cache.get(expression);
+
+            if (result == null)
+            {
+                result = parse(expression);
+                _cache.put(expression, result);
+            }
+            
+            return result;
+        } finally {
 
-        return result;
+            _lock.unlock();
+        }
     }
 
+    private Node parse(Object target, String expression)
+    {
+        try
+        {
+            return Ognl.compileExpression(_evaluator.createContext(target), target, expression);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(ImplMessages.unableToParseExpression(
+                    expression,
+                    ex), ex);
+        }
+    }
+    
     private Object parse(String expression)
     {
         try
@@ -80,5 +154,10 @@
     {
         _serviceId = serviceId;
     }
-
+    
+    public void setEvaluator(ExpressionEvaluator evaluator)
+    {
+        _evaluator = evaluator;
+    }
+    
 }

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionEvaluatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionEvaluatorImpl.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionEvaluatorImpl.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/ExpressionEvaluatorImpl.java Sat Jan 13 14:40:50 2007
@@ -20,10 +20,13 @@
 
 import ognl.ClassResolver;
 import ognl.Ognl;
+import ognl.OgnlContext;
 import ognl.OgnlRuntime;
 import ognl.TypeConverter;
+import ognl.enhance.ExpressionAccessor;
 
 import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.service.ClassFactory;
 import org.apache.tapestry.Tapestry;
 import org.apache.tapestry.services.ExpressionCache;
 import org.apache.tapestry.services.ExpressionEvaluator;
@@ -53,7 +56,9 @@
     // to see if it is a constant.
 
     private Map _defaultContext;
-
+    
+    private ClassFactory _classFactory;
+    
     public void setApplicationSpecification(IApplicationSpecification applicationSpecification)
     {
         _applicationSpecification = applicationSpecification;
@@ -71,21 +76,22 @@
         while (i.hasNext())
         {
             PropertyAccessorContribution c = (PropertyAccessorContribution) i.next();
-
+            
             OgnlRuntime.setPropertyAccessor(c.getSubjectClass(), c.getAccessor());
         }
         
         Iterator j = _nullHandlerContributions.iterator();
-
+        
         while (j.hasNext())
         {
             NullHandlerContribution h = (NullHandlerContribution) j.next();
             
             OgnlRuntime.setNullHandler(h.getSubjectClass(), h.getHandler());
         }        
-
+        
         _defaultContext = Ognl.createDefaultContext(null, _ognlResolver, _typeConverter);
-
+        
+        OgnlRuntime.setCompiler(new HiveMindExpressionCompiler(_classFactory));
     }
 
     public Object read(Object target, String expression)
@@ -107,10 +113,25 @@
                     .parsedExpression(), target, ex), target, null, ex);
         }
     }
-
-    private Map createContext(Object target)
+    
+    public Object read(Object target, ExpressionAccessor expression)
     {
-        Map result = Ognl.createDefaultContext(target, _ognlResolver);
+        try
+        {
+            OgnlContext context = createContext(target);
+            
+            return expression.get(context, target);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(ImplMessages.unableToReadExpression(ImplMessages
+                    .parsedExpression(), target, ex), target, null, ex);
+        }
+    }
+    
+    public OgnlContext createContext(Object target)
+    {
+        OgnlContext result = (OgnlContext)Ognl.createDefaultContext(target, _ognlResolver);
 
         if (_typeConverter != null)
             Ognl.setTypeConverter(result, _typeConverter);
@@ -120,9 +141,25 @@
 
     public void write(Object target, String expression, Object value)
     {
-        writeCompiled(target, _expressionCache.getCompiledExpression(expression), value);
+        writeCompiled(target, _expressionCache.getCompiledExpression(target, expression), value);
     }
 
+    public void write(Object target, ExpressionAccessor expression, Object value)
+    {
+        try
+        {
+            OgnlContext context = createContext(target);
+            
+            expression.set(context, target, value);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(ImplMessages.unableToWriteExpression(ImplMessages
+                    .parsedExpression(), target, value, ex), target, null, ex);
+        }
+
+    }
+    
     public void writeCompiled(Object target, Object expression, Object value)
     {
         try
@@ -138,7 +175,23 @@
         }
 
     }
+    
+    public boolean isConstant(Object target, String expression)
+    {
+        Object compiled = _expressionCache.getCompiledExpression(target, expression);
 
+        try
+        {
+            return Ognl.isConstant(compiled, _defaultContext);
+        }
+        catch (Exception ex)
+        {
+            throw new ApplicationRuntimeException(ImplMessages.isConstantExpressionError(
+                    expression,
+                    ex), ex);
+        }
+    }
+    
     public boolean isConstant(String expression)
     {
         Object compiled = _expressionCache.getCompiledExpression(expression);
@@ -154,7 +207,7 @@
                     ex), ex);
         }
     }
-
+    
     public void setExpressionCache(ExpressionCache expressionCache)
     {
         _expressionCache = expressionCache;
@@ -169,4 +222,9 @@
     {
         _nullHandlerContributions = nullHandlerContributions;
     }    
+    
+    public void setClassFactory(ClassFactory classFactory)
+    {
+        _classFactory = classFactory;
+    }
 }

Added: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java?view=auto&rev=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java (added)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java Sat Jan 13 14:40:50 2007
@@ -0,0 +1,391 @@
+// Copyright 2004, 2005 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry.services.impl;
+
+import java.lang.reflect.Modifier;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import ognl.ASTAnd;
+import ognl.ASTChain;
+import ognl.ASTConst;
+import ognl.ASTMethod;
+import ognl.ASTOr;
+import ognl.ASTRootVarRef;
+import ognl.ASTSequence;
+import ognl.ASTStaticField;
+import ognl.ASTVarRef;
+import ognl.BooleanExpression;
+import ognl.ExpressionNode;
+import ognl.Node;
+import ognl.NodeType;
+import ognl.NumericExpression;
+import ognl.Ognl;
+import ognl.OgnlContext;
+import ognl.OgnlRuntime;
+import ognl.enhance.ExpressionAccessor;
+import ognl.enhance.ExpressionCompiler;
+import ognl.enhance.OgnlExpressionCompiler;
+import ognl.enhance.OrderedReturn;
+import ognl.enhance.UnsupportedCompilationException;
+
+import org.apache.hivemind.service.ClassFab;
+import org.apache.hivemind.service.ClassFactory;
+import org.apache.hivemind.service.MethodSignature;
+import org.apache.tapestry.IRender;
+
+/**
+ * Adds to default ognl compiler class pools.
+ * @author jkuhnert
+ */
+public class HiveMindExpressionCompiler extends ExpressionCompiler implements OgnlExpressionCompiler
+{
+    private ClassFactory _classFactory;
+    
+    public HiveMindExpressionCompiler(ClassFactory classfactory)
+    {
+        _classFactory = classfactory;
+    }
+    
+    public String castExpression(OgnlContext context, Node expression, String body)
+    {
+        if (context.getCurrentAccessor() == null
+                || context.getPreviousType() == null 
+                || context.getCurrentAccessor().isAssignableFrom(context.getPreviousType())
+                || body == null || body.trim().length() < 1
+                || (context.getCurrentType() != null && context.getCurrentType().isArray())
+                || ASTOr.class.isInstance(expression)
+                || ASTAnd.class.isInstance(expression)
+                || ASTRootVarRef.class.isInstance(expression)
+                || context.getCurrentAccessor() == Class.class
+                || Number.class.isAssignableFrom(context.getCurrentAccessor())
+                || (context.get(ExpressionCompiler.PRE_CAST) != null && ((String)context.get(ExpressionCompiler.PRE_CAST)).startsWith("new"))
+                || ASTStaticField.class.isInstance(expression)
+                || (OrderedReturn.class.isInstance(expression) && ((OrderedReturn)expression).getLastExpression() != null))
+            return body;
+        /*
+        System.out.println("castExpression() with expression " + expression + " currentType is: " + context.getCurrentType() 
+                + " previousType: " + context.getPreviousType()
+                + " current Accessor: " + context.getCurrentAccessor()
+                + " previous Accessor: " + context.getPreviousAccessor());
+        */
+        
+        String castClass = null;
+        if (context.getCurrentType() != null && context.getCurrentType().isArray()) {
+            
+            castClass = context.getCurrentType().getCanonicalName();
+        } else if (context.getCurrentAccessor().isArray()) {
+            
+            castClass = context.getCurrentAccessor().getCanonicalName();
+        } else
+            castClass = context.getCurrentAccessor().getName();
+        
+        ExpressionCompiler.addCastString(context, "((" + castClass + ")");
+        
+        return ")" + body;
+    }
+    
+    public String getClassName(Class clazz)
+    {
+        if (IRender.class.isAssignableFrom(clazz))
+            return clazz.getName();
+        
+        if (clazz.getName().equals("java.util.AbstractList$Itr"))
+            return Iterator.class.getName();
+        
+        if (Modifier.isPublic(clazz.getModifiers()) && clazz.isInterface())
+            return clazz.getName();
+        
+        Class[] intf = clazz.getInterfaces();
+        
+        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)
+                return intf[i].getName();
+        }
+        
+        if (clazz.getSuperclass() != null && clazz.getSuperclass().getInterfaces().length > 0)
+            return getClassName(clazz.getSuperclass());
+        
+        return clazz.getName();
+    }
+    
+    public Class getInterfaceClass(Class clazz)
+    {
+        if (IRender.class.isAssignableFrom(clazz) || clazz.isInterface())
+            return clazz;
+        
+        if (clazz.getName().equals("java.util.AbstractList$Itr"))
+            return Iterator.class;
+        
+        if (Modifier.isPublic(clazz.getModifiers())
+                && clazz.isInterface() || clazz.isPrimitive()) {
+            
+            return clazz;
+        }
+        
+        Class[] intf = clazz.getInterfaces();
+        
+        for (int i=0; i < intf.length; i++) {
+            
+            if (List.class.isAssignableFrom(intf[i]))
+                return List.class;
+            else if (Iterator.class.isAssignableFrom(intf[i]))
+                return Iterator.class;
+            else if (Map.class.isAssignableFrom(intf[i]))
+                return Map.class;
+            else if (Set.class.isAssignableFrom(intf[i]))
+                return Set.class;
+            else if (Collection.class.isAssignableFrom(intf[i]))
+                return Collection.class;
+        }
+        
+        if (clazz.getSuperclass() != null && clazz.getSuperclass().getInterfaces().length > 0)
+            return getInterfaceClass(clazz.getSuperclass());
+        
+        return clazz;
+    }
+    
+    public void compileExpression(OgnlContext context, Node expression, Object root)
+    throws Exception
+    {
+        System.out.println("Compiling expr class " + expression.getClass().getName() + " and root " + root.getClass().getName() + " with toString:" + expression.toString());
+        
+        if (expression.getAccessor() != null)
+            return;
+        
+        String getBody = null;
+        String setBody = null;
+        
+        ClassFab classFab = _classFactory.newClass(expression.getClass().getName()+expression.hashCode()+"Accessor", 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);
+        
+        MethodSignature expressionSetter = new MethodSignature(void.class, "setExpression", new Class[] {Node.class}, null);
+        
+        // must evaluate expression value at least once if object isn't null
+        
+        if (root != null)
+            Ognl.getValue(expression, context, root);
+        
+        try {
+            
+            getBody = generateGetter(context, classFab, valueGetter, expression, root);
+            
+        } catch (UnsupportedCompilationException uc) {
+            
+            //System.out.println("Unsupported getter compilation caught: " + uc.getMessage());
+            
+            getBody = generateOgnlGetter(classFab, valueGetter);
+            
+            if (!classFab.containsMethod(expressionSetter)) {
+                
+                classFab.addField("_node", Node.class);
+                classFab.addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
+            }
+        }
+        
+        classFab.addMethod(Modifier.PUBLIC, valueGetter, getBody);
+        
+        try {
+            
+            setBody = generateSetter(context, classFab, valueSetter, expression, root);
+            
+        } catch (UnsupportedCompilationException uc) {
+            
+            //System.out.println("Unsupported setter compilation caught: " + uc.getMessage());
+            
+            setBody = generateOgnlSetter(classFab, valueSetter);
+            
+            if (!classFab.containsMethod(expressionSetter)) {
+                
+                classFab.addField("_node", Node.class);
+                classFab.addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
+            }
+        }
+        
+        classFab.addMethod(Modifier.PUBLIC, valueSetter, setBody);
+        
+        try {
+            
+            classFab.addConstructor(new Class[0], new Class[0], "{}");
+            
+            Class clazz = classFab.createClass();
+            
+            expression.setAccessor((ExpressionAccessor)clazz.newInstance());
+            
+            // need to set expression on node if the field was just defined.
+            
+            if (classFab.containsMethod(expressionSetter)) {
+                
+                expression.getAccessor().setExpression(expression);
+            }
+            
+        } catch (Throwable t) {
+            throw new RuntimeException("Error compiling expression on object " + root
+                    + " with expression node " + expression + " getter body: " + getBody 
+                    + " setter body: " + setBody, t);
+        }
+    }
+    
+    protected String generateGetter(OgnlContext context, ClassFab newClass, MethodSignature valueGetter, Node expression, Object root)
+    throws Exception
+    {
+        String pre="";
+        String post="";
+        String body = null;
+        
+        context.setRoot(root);
+        context.setCurrentObject(root);
+        context.remove(PRE_CAST);
+        
+        String getterCode = expression.toGetSourceString(context, root);
+        
+        if (getterCode == null || getterCode.trim().length() <= 0 && !ASTVarRef.class.isAssignableFrom(expression.getClass()))
+            getterCode = "null";
+        
+        if (NodeType.class.isInstance(expression)) {
+            NodeType nType = (NodeType)expression;
+            Class clazz = nType.getGetterClass();
+            
+            if (clazz != null && clazz.isPrimitive()) {
+                
+                if (clazz == Boolean.TYPE) {
+                    
+                    pre = "Boolean.valueOf((";
+                    post = "))";
+                } else {
+                    
+                    pre = "new " + OgnlRuntime.getPrimitiveWrapperClass(clazz).getName() + "(";
+                    post = ")";
+                }
+            } else if (clazz != null 
+                    && (Number.class.isAssignableFrom(clazz) 
+                            && (NumericExpression.class.isInstance(expression) 
+                                    || BooleanExpression.class.isInstance(expression)
+                                    || ASTSequence.class.isInstance(expression)))) {
+                
+                if (BigInteger.class.isAssignableFrom(clazz)) {
+                    
+                    pre = "java.math.BigInteger.valueOf((long)";
+                } else {
+                    
+                    pre = "new " + clazz.getName() + "(";
+                }
+                post = ")";
+            } else if (clazz != null && Character.class.isAssignableFrom(clazz)) {
+                
+                pre = "new " + nType.getGetterClass().getName() + "(";
+                post = ")";
+            }
+        }
+        
+        String castExpression = (String)context.get(PRE_CAST);
+        
+        String rootExpr = (getterCode != null && !getterCode.equals("null")) ? getRootExpression(expression, root, false) : "";
+        
+        String noRoot = (String)context.remove("_noRoot");
+        if (noRoot != null)
+            rootExpr = "";
+        
+        if (OrderedReturn.class.isInstance(expression) && ((OrderedReturn)expression).getLastExpression() != null) {
+            
+            body = "{ "
+                + (ASTMethod.class.isInstance(expression) || ASTChain.class.isInstance(expression) ? rootExpr : "")
+                + (castExpression != null ? castExpression : "")
+                + ((OrderedReturn)expression).getCoreExpression()
+                + " return " + pre + ((OrderedReturn)expression).getLastExpression()
+                + post
+                + ";}";
+            
+        } else {
+            
+            body = "{ return " + pre 
+            + (castExpression != null ? castExpression : "")
+            + rootExpr
+            + getterCode
+            + post
+            + ";}";
+        }
+        
+        body = body.replaceAll("\\.\\.", ".");
+        
+        System.out.println("Getter Body: ===================================\n"+body);
+
+        return body;
+    }
+    
+    protected String generateSetter(OgnlContext context, ClassFab newClass, MethodSignature valueSetter, Node expression, Object root)
+    throws Exception
+    {
+        if (ExpressionNode.class.isInstance(expression) 
+                || ASTConst.class.isInstance(expression))
+            throw new UnsupportedCompilationException("Can't compile expression/constant setters.");
+        
+        context.setRoot(root);
+        context.setCurrentObject(root);
+        context.remove(PRE_CAST);
+        
+        String body = null;
+        
+        String setterCode = expression.toSetSourceString(context, root);
+        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)
+            throw new UnsupportedCompilationException("Can't compile setters with a null root object.");
+        
+        String pre = getRootExpression(expression, root, false);
+        
+        String noRoot = (String)context.remove("_noRoot");
+        if (noRoot != null)
+            pre = "";
+        
+        body = "{" 
+            + (castExpression != null ? castExpression : "")
+            + pre 
+            + setterCode + ";}";
+        
+        body = body.replaceAll("\\.\\.", ".");
+        
+        System.out.println("Setter Body: ===================================\n"+body);
+
+        return body;
+    }
+    
+    String generateOgnlGetter(ClassFab newClass, MethodSignature valueGetter)
+    throws Exception
+    {
+        String body = "{ return _node.getValue($1, $2); }";
+        
+        return body;
+    }
+    
+    String generateOgnlSetter(ClassFab newClass, MethodSignature valueSetter)
+    throws Exception
+    {
+        String body = "{ _node.setValue($1, $2, $3); }";
+        
+        return body;
+    }
+}

Modified: tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java?view=diff&rev=495990&r1=495989&r2=495990
==============================================================================
--- tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java (original)
+++ tapestry/tapestry4/branches/ognl-integration/tapestry-framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java Sat Jan 13 14:40:50 2007
@@ -135,12 +135,17 @@
             _contentType.setParameter(ENCODING_KEY, encoding);
         }
         
-        // _output = new ByteArrayOutputStream();
-        
-        PrintWriter printWriter = _response.getPrintWriter(_contentType);
-        // PrintWriter printWriter = new PrintWriter(_output, true);
-        
-        _writer = _markupWriterSource.newJSONWriter(printWriter, _contentType);
+        if (_writer == null) {
+            
+            // _output = new ByteArrayOutputStream();
+
+            PrintWriter printWriter = _response.getPrintWriter(_contentType);
+            // PrintWriter printWriter = new PrintWriter(_output, true);
+
+            _writer = _markupWriterSource.newJSONWriter(printWriter, _contentType);
+            
+            parseParameters(cycle);
+        }
         
         // Important - causes any cookies stored to properly be written out before the
         // rest of the response starts being written - see TAPESTRY-825
@@ -148,8 +153,6 @@
         _writer.flush();
         
         // render response
-        
-        parseParameters(cycle);
         
         _prs = new PageRenderSupportImpl(_assetFactory, _namespace, cycle.getPage().getLocation(), this);