You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2008/07/08 02:14:20 UTC
svn commit: r674683 [2/2] - in /tapestry/tapestry3/trunk:
tapestry-examples/tapestry-workbench/
tapestry-examples/tapestry-workbench/src/org/apache/tapestry/workbench/components/
tapestry-framework/ tapestry-framework/src/org/apache/tapestry/ tapestry-...
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,451 @@
+package org.apache.tapestry.enhance.javassist;
+
+import javassist.CannotCompileException;
+import javassist.NotFoundException;
+import ognl.*;
+import ognl.enhance.*;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tapestry.IRender;
+import org.apache.tapestry.enhance.IEnhancedClass;
+import org.apache.tapestry.enhance.IEnhancedClassFactory;
+import org.apache.tapestry.enhance.MethodSignature;
+import org.apache.tapestry.enhance.MethodSignatureImpl;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+/**
+ * Adds to default ognl compiler class pools.
+ *
+ */
+public class OGNLExpressionCompiler extends ExpressionCompiler implements OgnlExpressionCompiler {
+
+ private static final Log _log = LogFactory.getLog(OGNLExpressionCompiler.class);
+
+ private IEnhancedClassFactory _classFactory;
+
+ public OGNLExpressionCompiler(IEnhancedClassFactory classfactory)
+ {
+ _classFactory = classfactory;
+ }
+
+ public String getClassName(Class clazz)
+ {
+ if (IRender.class.isAssignableFrom(clazz) || Modifier.isPublic(clazz.getModifiers()))
+ 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()
+ || Modifier.isPublic(clazz.getModifiers()))
+ 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 Class getRootExpressionClass(Node rootNode, OgnlContext context)
+ {
+ if (context.getRoot() == null)
+ return null;
+
+ Class ret = context.getRoot().getClass();
+
+ if (!IRender.class.isInstance(context.getRoot())
+ && context.getFirstAccessor() != null
+ && context.getFirstAccessor().isInstance(context.getRoot()))
+ {
+ ret = context.getFirstAccessor();
+ }
+
+ return ret;
+ }
+
+ public void compileExpression(OgnlContext context, Node expression, Object root)
+ throws Exception
+ {
+ if (_log.isDebugEnabled())
+ _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;
+
+ MethodSignature valueGetter = new MethodSignatureImpl(Object.class, "get", new Class[]{OgnlContext.class, Object.class}, null);
+ MethodSignature valueSetter = new MethodSignatureImpl(void.class, "set", new Class[]{OgnlContext.class, Object.class, Object.class}, null);
+
+ CompiledExpression compiled = new CompiledExpression(expression, root, valueGetter, valueSetter);
+
+ MethodSignature expressionSetter = new MethodSignatureImpl(void.class, "setExpression", new Class[]{Node.class}, null);
+
+ 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)
+ {
+ _log.error("Error generating OGNL getter for expression " + expression + " with root " + root + " and body:\n" + getBody, e);
+
+ e.printStackTrace();
+
+ generateFailSafe(context, expression, root);
+ return;
+ }
+
+ 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();
+
+ generateFailSafe(context, expression, root);
+ return;
+ }
+
+ try
+ {
+ setBody = generateSetter(context, compiled);
+ } catch (UnsupportedCompilationException uc)
+ {
+ //_log.warn("Unsupported setter compilation caught: " + uc.getMessage() + " for expression: " + expression.toString(), uc);
+
+ setBody = generateOgnlSetter(generateClassFab(compiled), valueSetter);
+
+ 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(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)
+ generateClassFab(compiled).addMethod(Modifier.PUBLIC, valueSetter, setBody);
+
+ generateClassFab(compiled).addConstructor(new Class[0], new Class[0], "{}");
+
+ Class clazz = generateClassFab(compiled).createEnhancedSubclass();
+
+ expression.setAccessor((ExpressionAccessor) clazz.newInstance());
+
+ } catch (Throwable t)
+ {
+ _log.error("Error generating OGNL statements for expression " + expression + " with root " + root, t);
+ t.printStackTrace();
+
+ generateFailSafe(context, expression, root);
+ return;
+ }
+
+ // need to set expression on node if the field was just defined.
+
+ if (generateClassFab(compiled).containsMethod(expressionSetter))
+ {
+ expression.getAccessor().setExpression(expression);
+ }
+ }
+ }
+
+ IEnhancedClass generateClassFab(CompiledExpression compiled)
+ throws Exception
+ {
+ if (compiled.getGeneratedClass() != null)
+ return compiled.getGeneratedClass();
+
+ IEnhancedClass classFab = _classFactory.createEnhancedClass(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
+ {
+ IEnhancedClass classFab = _classFactory.createEnhancedClass(ClassFabUtils
+ .generateClassName(
+ ClassFabUtils.getJavaClassName(expression.getClass()) + "Accessor"),
+ Object.class);
+ classFab.addInterface(ExpressionAccessor.class);
+
+ MethodSignature valueGetter = new MethodSignatureImpl(Object.class, "get", new Class[]{OgnlContext.class, Object.class}, null);
+ MethodSignature valueSetter = new MethodSignatureImpl(void.class, "set", new Class[]{OgnlContext.class, Object.class, Object.class}, null);
+
+ MethodSignature expressionSetter = new MethodSignatureImpl(void.class, "setExpression", new Class[]{Node.class}, null);
+
+ 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 = classFab.createEnhancedSubclass();
+
+ 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)
+ {
+ t.printStackTrace();
+ }
+ }
+
+ protected String generateGetter(OgnlContext context, CompiledExpression compiled)
+ throws Exception
+ {
+ String pre = "";
+ String post = "";
+ String body;
+ String getterCode;
+
+ context.setRoot(compiled.getRoot());
+ context.setCurrentObject(compiled.getRoot());
+ context.remove(PRE_CAST);
+
+ 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(compiled.getExpression().getClass()))
+ {
+ getterCode = "null";
+ }
+
+ String castExpression = (String) context.get(PRE_CAST);
+
+ if (context.getCurrentType() == null
+ || context.getCurrentType().isPrimitive()
+ || Character.class.isAssignableFrom(context.getCurrentType())
+ || Object.class == context.getCurrentType())
+ {
+ pre = pre + " ($w) (";
+ post = post + ")";
+ }
+
+ String rootExpr = !getterCode.equals("null") ? getRootExpression(compiled.getExpression(), compiled.getRoot(), context) : "";
+
+ String noRoot = (String) context.remove("_noRoot");
+ if (noRoot != null)
+ rootExpr = "";
+
+ createLocalReferences(context, generateClassFab(compiled), compiled.getGetterMethod().getParameterTypes());
+
+ if (OrderedReturn.class.isInstance(compiled.getExpression()) && ((OrderedReturn) compiled.getExpression()).getLastExpression() != null)
+ {
+ body = "{ "
+ + (ASTMethod.class.isInstance(compiled.getExpression()) || ASTChain.class.isInstance(compiled.getExpression()) ? rootExpr : "")
+ + (castExpression != null ? castExpression : "")
+ + ((OrderedReturn) compiled.getExpression()).getCoreExpression()
+ + " return " + pre + ((OrderedReturn) compiled.getExpression()).getLastExpression()
+ + post
+ + ";}";
+
+ } else
+ {
+ body = "{ return " + pre
+ + (castExpression != null ? castExpression : "")
+ + rootExpr
+ + getterCode
+ + post
+ + ";}";
+ }
+
+ body = body.replaceAll("\\.\\.", ".");
+
+ if (_log.isDebugEnabled())
+ _log.debug("Getter Body: ===================================\n" + body);
+
+ return body;
+ }
+
+ void createLocalReferences(OgnlContext context, IEnhancedClass classFab, Class[] params)
+ throws CannotCompileException, NotFoundException
+ {
+ Map referenceMap = context.getLocalReferences();
+ if (referenceMap == null || referenceMap.size() < 1)
+ return;
+
+ Iterator it = referenceMap.keySet().iterator();
+
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ LocalReference ref = (LocalReference) referenceMap.get(key);
+
+ String widener = ref.getType().isPrimitive() ? " " : " ($w) ";
+
+ String body = "{";
+ body += " return " + widener + ref.getExpression() + ";";
+ body += "}";
+
+ body = body.replaceAll("\\.\\.", ".");
+
+ if (_log.isDebugEnabled())
+ _log.debug("createLocalReferences() body is:\n" + body);
+
+ MethodSignature method = new MethodSignatureImpl(ref.getType(), ref.getName(), params, null);
+ classFab.addMethod(Modifier.PUBLIC, method, body);
+
+ it.remove();
+ }
+ }
+
+ protected String generateSetter(OgnlContext context, CompiledExpression compiled)
+ throws Exception
+ {
+ if (ExpressionNode.class.isInstance(compiled.getExpression())
+ || ASTConst.class.isInstance(compiled.getExpression()))
+ throw new UnsupportedCompilationException("Can't compile expression/constant setters.");
+
+ context.setRoot(compiled.getRoot());
+ context.setCurrentObject(compiled.getRoot());
+ context.remove(PRE_CAST);
+
+ String body;
+
+ 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 (compiled.getRoot() == null)
+ throw new UnsupportedCompilationException("Can't compile setters with a null root object.");
+
+ String pre = getRootExpression(compiled.getExpression(), compiled.getRoot(), context);
+
+ String noRoot = (String) context.remove("_noRoot");
+ if (noRoot != null)
+ pre = "";
+
+ String setterValue = (String) context.remove("setterConversion");
+ if (setterValue == null)
+ setterValue = "";
+
+ createLocalReferences(context, generateClassFab(compiled), compiled.getSettermethod().getParameterTypes());
+
+ body = "{"
+ + setterValue
+ + (castExpression != null ? castExpression : "")
+ + pre
+ + setterCode + ";}";
+
+ body = body.replaceAll("\\.\\.", ".");
+
+ if (_log.isDebugEnabled())
+ _log.debug("Setter Body: ===================================\n" + body);
+
+ return body;
+ }
+
+ String generateOgnlGetter(IEnhancedClass newClass, MethodSignature valueGetter)
+ throws Exception
+ {
+ return "{ return _node.getValue($1, $2); }";
+ }
+
+ String generateOgnlSetter(IEnhancedClass newClass, MethodSignature valueSetter)
+ throws Exception
+ {
+ return "{ _node.setValue($1, $2, $3); }";
+ }
+}
\ No newline at end of file
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/param/AbstractParameterConnector.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/param/AbstractParameterConnector.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/param/AbstractParameterConnector.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/param/AbstractParameterConnector.java Mon Jul 7 17:14:19 2008
@@ -18,12 +18,11 @@
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IForm;
import org.apache.tapestry.IRequestCycle;
-import org.apache.tapestry.IResourceResolver;
+import org.apache.tapestry.engine.ExpressionEvaluator;
import org.apache.tapestry.form.Form;
import org.apache.tapestry.form.IFormComponent;
import org.apache.tapestry.spec.Direction;
import org.apache.tapestry.spec.IParameterSpecification;
-import org.apache.tapestry.util.prop.OgnlUtils;
/**
* Standard implementation of {@link IParameterConnector}.
@@ -44,7 +43,7 @@
private boolean _required;
private Object _clearValue;
private Direction _direction;
- private IResourceResolver _resolver;
+ private ExpressionEvaluator _evaluator;
/**
* Creates a connector. In addition, obtains the current value
@@ -59,7 +58,7 @@
_parameterName = parameterName;
_binding = binding;
- _resolver = component.getPage().getEngine().getResourceResolver();
+ _evaluator = component.getPage().getEngine().getExpressionEvaluator();
IParameterSpecification pspec = _component.getSpecification().getParameter(_parameterName);
_required = pspec.isRequired();
@@ -73,7 +72,7 @@
private Object readCurrentPropertyValue()
{
- return OgnlUtils.get(_propertyName, _resolver, _component);
+ return _evaluator.read(_component, _propertyName);
}
/**
@@ -83,7 +82,7 @@
protected void setPropertyValue(Object value)
{
- OgnlUtils.set(_propertyName, _resolver, _component, value);
+ _evaluator.write(_component, _propertyName, value);
}
/**