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 [1/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-...
Author: jkuhnert
Date: Mon Jul 7 17:14:19 2008
New Revision: 674683
URL: http://svn.apache.org/viewvc?rev=674683&view=rev
Log:
Backported some of the tap4 OGNL related work, such as ExpressionEvaluator service / pooling of OgnlContext objects / etc.
Added:
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java (with props)
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java (with props)
Modified:
tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml
tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/src/org/apache/tapestry/workbench/components/Border.java
tapestry/tapestry3/trunk/tapestry-framework/pom.xml
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/IEngine.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/TapestryStrings.properties
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/IEnhancedClass.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignature.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabricator.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClass.java
tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/param/AbstractParameterConnector.java
Modified: tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml (original)
+++ tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml Mon Jul 7 17:14:19 2008
@@ -80,7 +80,7 @@
<systemProperties>
<systemProperty>
<name>org.apache.tapestry.disable-caching</name>
- <value>false</value>
+ <value>true</value>
</systemProperty>
</systemProperties>
</configuration>
Modified: tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/src/org/apache/tapestry/workbench/components/Border.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/src/org/apache/tapestry/workbench/components/Border.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/src/org/apache/tapestry/workbench/components/Border.java (original)
+++ tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/src/org/apache/tapestry/workbench/components/Border.java Mon Jul 7 17:14:19 2008
@@ -79,7 +79,7 @@
public boolean isActivePage()
{
- return getPageName().equals(getActivePageName());
+ return getPageName().equals(getActivePageName());
}
public String getPageTitle()
Modified: tapestry/tapestry3/trunk/tapestry-framework/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/pom.xml?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/pom.xml (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/pom.xml Mon Jul 7 17:14:19 2008
@@ -56,6 +56,10 @@
<artifactId>commons-lang</artifactId>
</dependency>
<dependency>
+ <groupId>commons-pool</groupId>
+ <artifactId>commons-pool</artifactId>
+ </dependency>
+ <dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java Mon Jul 7 17:14:19 2008
@@ -17,13 +17,13 @@
import ognl.OgnlRuntime;
import org.apache.tapestry.bean.BeanProvider;
import org.apache.tapestry.bean.BeanProviderPropertyAccessor;
+import org.apache.tapestry.engine.ExpressionEvaluator;
import org.apache.tapestry.engine.IPageLoader;
import org.apache.tapestry.event.*;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.param.ParameterManager;
import org.apache.tapestry.spec.BaseLocatable;
import org.apache.tapestry.spec.IComponentSpecification;
-import org.apache.tapestry.util.prop.OgnlUtils;
import org.apache.tapestry.util.prop.PropertyFinder;
import org.apache.tapestry.util.prop.PropertyInfo;
@@ -189,6 +189,8 @@
private IMessages _strings;
+ private ExpressionEvaluator _evaluator;
+
public void addAsset(String name, IAsset asset)
{
if (_assets == null)
@@ -470,9 +472,10 @@
if (info != null && info.isReadWrite() && info.getType().equals(IBinding.class))
{
- IResourceResolver resolver = getPage().getEngine().getResourceResolver();
+ return (IBinding) getEvaluator().read(this, bindingPropertyName);
+ //IResourceResolver resolver = getPage().getEngine().getResourceResolver();
- return (IBinding) OgnlUtils.get(bindingPropertyName, resolver, this);
+ //return (IBinding) OgnlUtils.get(bindingPropertyName, resolver, this);
}
if (_bindings == null)
@@ -639,8 +642,9 @@
if (info != null && info.isReadWrite() && info.getType().equals(IBinding.class))
{
- IResourceResolver resolver = getPage().getEngine().getResourceResolver();
- OgnlUtils.set(bindingPropertyName, resolver, this, binding);
+ getEvaluator().write(this, bindingPropertyName, binding);
+ // IResourceResolver resolver = getPage().getEngine().getResourceResolver();
+ // OgnlUtils.set(bindingPropertyName, resolver, this, binding);
return;
}
@@ -1111,6 +1115,16 @@
{
}
+ ExpressionEvaluator getEvaluator()
+ {
+ if (_evaluator == null)
+ {
+ _evaluator = _page.getEngine().getExpressionEvaluator();
+ }
+
+ return _evaluator;
+ }
+
/**
* Sets a property of a component.
* @see IComponent
@@ -1118,8 +1132,10 @@
*/
public void setProperty(String propertyName, Object value)
{
- IResourceResolver resolver = getResourceResolver();
- OgnlUtils.set(propertyName, resolver, this, value);
+ getEvaluator().write(this, propertyName, value);
+
+ // IResourceResolver resolver = getResourceResolver();
+ // OgnlUtils.set(propertyName, resolver, this, value);
}
/**
* Gets a property of a component.
@@ -1128,7 +1144,9 @@
*/
public Object getProperty(String propertyName)
{
- IResourceResolver resolver = getResourceResolver();
- return OgnlUtils.get(propertyName, resolver, this);
+ return getEvaluator().read(this, propertyName);
+
+ //IResourceResolver resolver = getResourceResolver();
+ //return OgnlUtils.get(propertyName, resolver, this);
}
}
\ No newline at end of file
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java Mon Jul 7 17:14:19 2008
@@ -14,32 +14,25 @@
package org.apache.tapestry;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.binding.ExpressionBinding;
import org.apache.tapestry.binding.StaticBinding;
import org.apache.tapestry.binding.StringBinding;
+import org.apache.tapestry.engine.ExpressionEvaluator;
import org.apache.tapestry.engine.IPageLoader;
import org.apache.tapestry.engine.IPageSource;
import org.apache.tapestry.engine.ITemplateSource;
-import org.apache.tapestry.parse.AttributeType;
-import org.apache.tapestry.parse.CloseToken;
-import org.apache.tapestry.parse.ComponentTemplate;
-import org.apache.tapestry.parse.LocalizationToken;
-import org.apache.tapestry.parse.OpenToken;
-import org.apache.tapestry.parse.TemplateAttribute;
-import org.apache.tapestry.parse.TemplateToken;
-import org.apache.tapestry.parse.TextToken;
-import org.apache.tapestry.parse.TokenType;
+import org.apache.tapestry.parse.*;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.spec.IContainedComponent;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
/**
* Utility class instantiated by {@link org.apache.tapestry.BaseComponent} to
* process the component's {@link org.apache.tapestry.parse.ComponentTemplate template},
@@ -65,6 +58,7 @@
private IComponent[] _stack;
private int _stackx = 0;
private IComponent _activeComponent = null;
+ private ExpressionEvaluator _evaluator;
private Set _seenIds = new HashSet();
/**
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/IEngine.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/IEngine.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/IEngine.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/IEngine.java Mon Jul 7 17:14:19 2008
@@ -14,26 +14,17 @@
package org.apache.tapestry;
-import java.io.IOException;
-import java.util.Locale;
-
-import javax.servlet.ServletException;
-
import org.apache.tapestry.asset.ResourceChecksumSource;
-import org.apache.tapestry.engine.IComponentClassEnhancer;
-import org.apache.tapestry.engine.IComponentMessagesSource;
-import org.apache.tapestry.engine.IEngineService;
-import org.apache.tapestry.engine.IPageRecorder;
-import org.apache.tapestry.engine.IPageSource;
-import org.apache.tapestry.engine.IPropertySource;
-import org.apache.tapestry.engine.IScriptSource;
-import org.apache.tapestry.engine.ISpecificationSource;
-import org.apache.tapestry.engine.ITemplateSource;
+import org.apache.tapestry.engine.*;
import org.apache.tapestry.request.RequestContext;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.util.io.DataSqueezer;
import org.apache.tapestry.util.pool.Pool;
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.util.Locale;
+
/**
* Defines the core, session-persistant object used to run a Tapestry
* application for a single client (each client will have its own instance of the engine).
@@ -230,6 +221,13 @@
public IResourceResolver getResourceResolver();
/**
+ * Gets the OGNL expression evaluator.
+ *
+ * @return The expression evaluator.
+ */
+ public ExpressionEvaluator getExpressionEvaluator();
+
+ /**
* Returns the visit object, an object that represents the client's visit
* to the application. This is where most server-side state is stored (with
* the exception of persistent page properties).
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/TapestryStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/TapestryStrings.properties?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/TapestryStrings.properties (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/TapestryStrings.properties Mon Jul 7 17:14:19 2008
@@ -42,6 +42,13 @@
must-be-contained-by-body={0} components must be contained by a Body component.
illegal-encoding=The encoding ''{0}'' is not recognized.
+unable-to-parse-expression=Unable to parse OGNL expression ''{0}'': {1}
+unable-to-read-expression=Unable to read OGNL expression ''{0}'' of {1}: {2}
+unable-to-write-expression=Unable to update OGNL expression ''{0}'' of {1} to {2}: {3}
+is-constant-expression-error=Error evaluating OGNL expression ''{0}'': {1}
+
+unable-to-lookup=Unable to lookup {0}: {1}
+
# org.apache.tapestry
AbstractComponent.attempt-to-change-container=Attempt to change existing container.
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java Mon Jul 7 17:14:19 2008
@@ -14,22 +14,19 @@
package org.apache.tapestry.binding;
-import java.util.Map;
-
+import ognl.Node;
import ognl.Ognl;
import ognl.OgnlException;
import ognl.TypeConverter;
-
-import org.apache.tapestry.BindingException;
-import org.apache.tapestry.IComponent;
-import org.apache.tapestry.ILocation;
-import org.apache.tapestry.IResourceResolver;
-import org.apache.tapestry.Tapestry;
+import ognl.enhance.ExpressionAccessor;
+import org.apache.tapestry.*;
+import org.apache.tapestry.engine.ExpressionEvaluator;
import org.apache.tapestry.spec.BeanLifecycle;
-import org.apache.tapestry.spec.IBeanSpecification;
import org.apache.tapestry.spec.IApplicationSpecification;
+import org.apache.tapestry.spec.IBeanSpecification;
import org.apache.tapestry.util.StringSplitter;
-import org.apache.tapestry.util.prop.OgnlUtils;
+
+import java.util.Map;
/**
* Implements a dynamic binding, based on getting and fetching
@@ -37,7 +34,7 @@
* upon the <a href="http://www.ognl.org">OGNL</a> library.
*
* <p><b>Optimization of the Expression</b>
- *
+ *
* <p>There's a lot of room for optimization here because we can
* count on some portions of the expression to be
* effectively static. Note that we type the root object as
@@ -56,13 +53,13 @@
* <p>This means that once an ExpressionBinding has been triggered,
* the {@link #toString()} method may return different values for the root
* component and the expression than was originally set.
- *
+ *
* <p><b>Identifying Invariants</b>
- *
+ *
* <p>Most expressions are fully dynamic; they must be
* resolved each time they are accessed. This can be somewhat inefficient.
* Tapestry can identify certain paths as invariant:
- *
+ *
* <ul>
* <li>A component within the page hierarchy
* <li>An {@link org.apache.tapestry.IAsset} from then assets map (property <code>assets</code>)
@@ -72,7 +69,7 @@
* lifecycle (property <code>beans</code>)
* <li>A binding (property <code>bindings</code>)
* </ul>
- *
+ *
* <p>
* These optimizations have some inherent dangers; they assume that
* the components have not overidden the specified properties;
@@ -80,11 +77,11 @@
* component does inherit from {@link org.apache.tapestry.AbstractComponent}.
* If this becomes a problem in the future, it may be necessary to
* have the component itself involved in these determinations.
- *
+ *
* @author Howard Lewis Ship
* @version $Id$
* @since 2.2
- *
+ *
**/
public class ExpressionBinding extends AbstractBinding
@@ -106,7 +103,7 @@
/**
* If true, then the binding is invariant, and cachedValue
* is the ultimate value.
- *
+ *
**/
private boolean _invariant = false;
@@ -114,25 +111,25 @@
/**
* Stores the cached value for the binding, if invariant
* is true.
- *
+ *
**/
private Object _cachedValue;
/**
* Parsed OGNL expression.
- *
+ *
**/
- private Object _parsedExpression;
+ private Node _parsedExpression;
/**
* Flag set once the binding has initialized.
* _cachedValue, _invariant and _final value
* for _expression
* are not valid until after initialization.
- *
- *
+ *
+ *
**/
private boolean _initialized;
@@ -142,28 +139,47 @@
/**
* The OGNL context for this binding. It is retained
* for the lifespan of the binding once created.
- *
+ *
**/
private Map _context;
/**
+ * Central OGNL expression manager.
+ */
+ private ExpressionEvaluator _evaluator;
+
+ /**
+ * Compiled OGNL expression.
+ */
+
+ private ExpressionAccessor _accessor;
+
+ /**
+ * Used to detect previous failed attempts at writing values when compiling expressions so
+ * that as many expressions as possible can be fully compiled into their java byte form when
+ * all objects in the expression are available.
+ */
+ private boolean _writeFailed;
+
+ /**
* Creates a {@link ExpressionBinding} from the root object
* and an OGNL expression.
- *
+ *
**/
public ExpressionBinding(
- IResourceResolver resolver,
- IComponent root,
- String expression,
- ILocation location)
+ IResourceResolver resolver,
+ IComponent root,
+ String expression,
+ ILocation location)
{
super(location);
_resolver = resolver;
_root = root;
_expression = expression;
+ _evaluator = root.getPage().getEngine().getExpressionEvaluator();
}
public String getExpression()
@@ -198,17 +214,26 @@
{
try
{
- return Ognl.getValue(_parsedExpression, getOgnlContext(), _root);
+ if (false && _evaluator.isCompileEnabled() && _accessor == null && !_writeFailed)
+ {
+ _evaluator.compileExpression(_root, _parsedExpression, _expression);
+ _accessor = _parsedExpression.getAccessor();
+ }
+
+ if (_accessor != null)
+ return _evaluator.read(_root, _accessor);
+
+ return _evaluator.readCompiled(_root, _parsedExpression);
}
- catch (OgnlException t)
+ catch (Throwable t)
{
throw new BindingException(
- Tapestry.format(
- "ExpressionBinding.unable-to-resolve-expression",
- _expression,
- _root),
- this,
- t);
+ Tapestry.format(
+ "ExpressionBinding.unable-to-resolve-expression",
+ _expression,
+ _root),
+ this,
+ t);
}
}
@@ -219,7 +244,7 @@
* An optional type converter will be added to the OGNL context
* if it is specified as an application extension with the name
* {@link Tapestry#OGNL_TYPE_CONVERTER}.
- *
+ *
**/
private Map getOgnlContext()
@@ -235,8 +260,7 @@
if (appSpec != null && appSpec.checkExtension(Tapestry.OGNL_TYPE_CONVERTER))
{
- TypeConverter typeConverter =
- (TypeConverter) appSpec.getExtension(
+ TypeConverter typeConverter = (TypeConverter) appSpec.getExtension(
Tapestry.OGNL_TYPE_CONVERTER,
TypeConverter.class);
@@ -251,8 +275,8 @@
/**
* Returns true if the binding is expected to always
* return the same value.
- *
- *
+ *
+ *
**/
public boolean isInvariant()
@@ -297,7 +321,7 @@
try
{
- _parsedExpression = OgnlUtils.getParsedExpression(_expression);
+ _parsedExpression = _evaluator.parse(_root, _expression);
}
catch (Exception ex)
{
@@ -317,6 +341,7 @@
throw new BindingException(ex.getMessage(), this, ex);
}
+
// Split the expression into individual property names.
// We then optimize what we can from the expression. This will
// shorten the expression and, in some cases, eliminate
@@ -327,7 +352,7 @@
int count = optimizeRootObject(split);
// We'ver removed some or all of the initial elements of split
- // but have to account for anthing left over.
+ // but have to account for anything left over.
if (count == split.length)
{
@@ -344,7 +369,7 @@
}
_expression = reassemble(count, split);
- _parsedExpression = OgnlUtils.getParsedExpression(_expression);
+ _parsedExpression = _evaluator.parse(_root, _expression);
checkForInvariant(count, split);
}
@@ -352,10 +377,10 @@
/**
* Looks for common prefixes on the expression (provided pre-split) that
* are recognized as references to other components.
- *
+ *
* @return the number of leading elements of the split expression that
* have been removed.
- *
+ *
**/
private int optimizeRootObject(String[] split)
@@ -398,26 +423,14 @@
private boolean checkForConstant()
{
- try
+
+ if (_evaluator.isConstant(_root, _expression))
{
- if (Ognl.isConstant(_parsedExpression, getOgnlContext()))
- {
- _invariant = true;
+ _invariant = true;
- _cachedValue = resolveProperty();
+ _cachedValue = resolveProperty();
- return true;
- }
- }
- catch (OgnlException ex)
- {
- throw new BindingException(
- Tapestry.format(
- "ExpressionBinding.unable-to-resolve-expression",
- _expression,
- _root),
- this,
- ex);
+ return true;
}
return false;
@@ -426,7 +439,7 @@
/**
* Reassembles the remainder of the split property path
* from the start point.
- *
+ *
**/
private String reassemble(int start, String[] split)
@@ -454,7 +467,7 @@
/**
* Checks to see if the binding can be converted to an invariant.
- *
+ *
**/
private void checkForInvariant(int start, String[] split)
@@ -473,12 +486,12 @@
catch (OgnlException ex)
{
throw new BindingException(
- Tapestry.format(
- "ExpressionBinding.unable-to-resolve-expression",
- _expression,
- _root),
- this,
- ex);
+ Tapestry.format(
+ "ExpressionBinding.unable-to-resolve-expression",
+ _expression,
+ _root),
+ this,
+ ex);
}
String first = split[start];
@@ -550,18 +563,47 @@
try
{
- Ognl.setValue(_parsedExpression, getOgnlContext(), _root, value);
+ if (_accessor != null)
+ {
+ _evaluator.write(_root, _accessor, value);
+ } else if (false && _evaluator.isCompileEnabled() && _accessor == null)
+ {
+ //_evaluator.compileExpression(_root, _parsedExpression, _expression);
+ //_accessor = _parsedExpression.getAccessor();
+
+ if (!_writeFailed)
+ {
+ // re-parse expression as compilation may be possible now that it potentially has a value
+ try
+ {
+ _evaluator.compileExpression(_root, _parsedExpression, _expression);
+ _accessor = _parsedExpression.getAccessor();
+ } catch (Throwable t)
+ {
+ // ignore re-read failures as they aren't supposed to be happening now anyways
+ // and a more user friendly version will be available if someone actually calls
+ // getObject
+
+ // if writing fails then we're probably screwed...so don't do it again
+ if (value != null)
+ _writeFailed = true;
+ }
+ }
+ } else
+ {
+ _evaluator.writeCompiled(_root, _parsedExpression, value);
+ }
}
- catch (OgnlException ex)
+ catch (Throwable ex)
{
throw new BindingException(
- Tapestry.format(
- "ExpressionBinding.unable-to-update-expression",
- _expression,
- _root,
- value),
- this,
- ex);
+ Tapestry.format(
+ "ExpressionBinding.unable-to-update-expression",
+ _expression,
+ _root,
+ value),
+ this,
+ ex);
}
}
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java Mon Jul 7 17:14:19 2008
@@ -23,6 +23,8 @@
import org.apache.tapestry.asset.ResourceChecksumSource;
import org.apache.tapestry.asset.ResourceChecksumSourceImpl;
import org.apache.tapestry.enhance.DefaultComponentClassEnhancer;
+import org.apache.tapestry.enhance.IEnhancedClassFactory;
+import org.apache.tapestry.enhance.javassist.EnhancedClassFactory;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.pageload.PageSource;
import org.apache.tapestry.request.RequestContext;
@@ -390,6 +392,10 @@
private transient IComponentClassEnhancer _enhancer;
+ protected static final String CLASS_FACTORY_NAME = "org.apache.tapestry.enhance.javassist.EnhancedClassFactory";
+
+ private transient IEnhancedClassFactory _classFactory;
+
/**
* Set to true when there is a (potential)
* change to the internal state of the engine, set
@@ -417,6 +423,18 @@
private transient ResourceChecksumSource _resourceChecksumSource;
/**
+ * The name of the context attribute for the {@link ExpressionEvaluator} instance.
+ * The application's name is appended.
+ **/
+ protected static final String EXPRESSION_EVALUATOR_NAME = "org.apache.tapestry.engine.ExpressionEvaluator";
+
+ private transient ExpressionEvaluator _expressionEvaluator;
+
+ private transient ExpressionCache _expressionCache;
+
+ private transient String _outputEncoding;
+
+ /**
* Sets the Exception page's exception property, then renders the Exception page.
*
* <p>If the render throws an exception, then copious output is sent to
@@ -1109,6 +1127,9 @@
_stringsSource.reset();
_enhancer.reset();
_resourceChecksumSource.reset();
+ _expressionCache.reset();
+ _expressionEvaluator.reset();
+ _outputEncoding = null;
}
/**
@@ -1249,6 +1270,33 @@
}
}
+ if (_classFactory == null)
+ {
+ String name = CLASS_FACTORY_NAME + ":" + servletName;
+
+ _classFactory = (IEnhancedClassFactory) servletContext.getAttribute(name);
+
+ if (_classFactory == null)
+ {
+ try
+ {
+ context.getServlet().getLock().lock();
+
+ _classFactory = (IEnhancedClassFactory) servletContext.getAttribute(name);
+
+ if (_classFactory == null)
+ {
+ _classFactory = createClassFactory();
+
+ servletContext.setAttribute(name, _classFactory);
+ }
+ } finally
+ {
+ context.getServlet().getLock().unlock();
+ }
+ }
+ }
+
if (_enhancer == null)
{
String name = ENHANCER_NAME + ":" + servletName;
@@ -1546,6 +1594,33 @@
}
}
+ if (_expressionEvaluator == null)
+ {
+ String name = EXPRESSION_EVALUATOR_NAME + ":" + servletName;
+
+ _expressionEvaluator = (ExpressionEvaluator) servletContext.getAttribute(name);
+
+ if (_expressionEvaluator == null)
+ {
+ try
+ {
+ context.getServlet().getLock().lock();
+
+ _expressionEvaluator = (ExpressionEvaluator) servletContext.getAttribute(name);
+
+ if (_expressionEvaluator == null)
+ {
+ _expressionEvaluator = createExpressionEvaluator();
+
+ servletContext.setAttribute(name, _expressionEvaluator);
+ }
+ } finally
+ {
+ context.getServlet().getLock().unlock();
+ }
+ }
+ }
+
String encoding = request.getCharacterEncoding();
if (encoding == null)
{
@@ -1662,6 +1737,18 @@
{
return new ResourceChecksumSourceImpl("MD5", new Hex());
}
+
+ protected ExpressionEvaluator createExpressionEvaluator()
+ {
+ _expressionCache = (ExpressionCacheImpl) createExpressionCache();
+
+ return new ExpressionEvaluatorImpl(_resolver, _classFactory, _expressionCache, _specification);
+ }
+
+ protected ExpressionCache createExpressionCache()
+ {
+ return new ExpressionCacheImpl();
+ }
/**
* Returns an object which can find resources and classes.
@@ -1673,6 +1760,11 @@
return _resolver;
}
+ public ExpressionEvaluator getExpressionEvaluator()
+ {
+ return _expressionEvaluator;
+ }
+
/**
* Generates a description of the instance.
* Invokes {@link #extendDescription(ToStringBuilder)}
@@ -2378,10 +2470,15 @@
"true".equals(
_propertySource.getPropertyValue(
"org.apache.tapestry.enhance.disable-abstract-method-validation"));
-
- return new DefaultComponentClassEnhancer(_resolver, disableValidation);
+
+ return new DefaultComponentClassEnhancer(_resolver, disableValidation, _classFactory);
}
+ protected IEnhancedClassFactory createClassFactory()
+ {
+ return new EnhancedClassFactory(_resolver);
+ }
+
/** @since 3.0 **/
public IComponentClassEnhancer getComponentClassEnhancer()
@@ -2478,13 +2575,18 @@
**/
public String getOutputEncoding()
{
+ if (_outputEncoding != null)
+ return _outputEncoding;
+
IPropertySource source = getPropertySource();
String encoding = source.getPropertyValue(OUTPUT_ENCODING_PROPERTY_NAME);
if (encoding == null)
encoding = getDefaultOutputEncoding();
- return encoding;
+ _outputEncoding = encoding;
+
+ return _outputEncoding;
}
}
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,42 @@
+package org.apache.tapestry.engine;
+
+import ognl.Node;
+
+/**
+ * Cache of compiled OGNL expressions.
+ *
+ * @author Howard M. Lewis Ship
+ * @since 4.0
+ */
+public interface ExpressionCache
+{
+ /**
+ * 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 get(Object target, String expression);
+
+ /**
+ * Stores a parsed ognl expression for the given object type.
+ *
+ * @param target
+ * The target object expression compiled for.
+ * @param expression
+ * The ognl string expression node represents.
+ * @param node
+ * The parsed OGNL expression to cache.
+ */
+ void cache(Object target, String expression, Node node);
+
+ /**
+ * Invoked by {@link AbstractEngine} to clear all cache data.
+ */
+ void reset();
+}
\ No newline at end of file
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCache.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,112 @@
+package org.apache.tapestry.engine;
+
+import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
+import ognl.ClassCacheInspector;
+import ognl.Node;
+import ognl.OgnlRuntime;
+import org.apache.tapestry.AbstractComponent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Howard M. Lewis Ship
+ * @since 4.0
+ */
+public class ExpressionCacheImpl implements ExpressionCache, ClassCacheInspector {
+
+ private final ReentrantLock _lock = new ReentrantLock();
+
+ private final Map _compiledExpressionCache = new HashMap();
+
+ private final Map _expressionCache = new HashMap();
+
+ private final boolean _cachingDisabled = Boolean.getBoolean("org.apache.tapestry.disable-caching");
+
+ public ExpressionCacheImpl()
+ {
+ initializeService();
+ }
+
+ public void initializeService()
+ {
+ if (_cachingDisabled)
+ {
+ OgnlRuntime.setClassCacheInspector(this);
+ }
+ }
+
+ public void reset()
+ {
+ try
+ {
+ _lock.lock();
+
+ _compiledExpressionCache.clear();
+ _expressionCache.clear();
+ } finally
+ {
+ _lock.unlock();
+ }
+ }
+
+ public boolean shouldCache(Class type)
+ {
+ if (!_cachingDisabled || type == null
+ || AbstractComponent.class.isAssignableFrom(type))
+ return false;
+
+ return true;
+ }
+
+ public Object get(Object target, String expression)
+ {
+ try
+ {
+ _lock.lock();
+
+ Map cached = (Map)_compiledExpressionCache.get(target.getClass());
+ if (cached == null)
+ {
+ return _expressionCache.get(expression);
+ } else
+ {
+ return cached.get(expression);
+ }
+
+ } finally
+ {
+ _lock.unlock();
+ }
+ }
+
+ public void cache(Object target, String expression, Node node)
+ {
+ try
+ {
+ _lock.lock();
+
+ if (node.getAccessor() != null)
+ {
+ Map cached = (Map)_compiledExpressionCache.get(target.getClass());
+
+ if (cached == null)
+ {
+ cached = new HashMap();
+ _compiledExpressionCache.put(target.getClass(), cached);
+ }
+
+ cached.put(expression, node);
+
+ _expressionCache.remove(target.getClass());
+ } else
+ {
+ _expressionCache.put(expression, node);
+ }
+
+ } finally
+ {
+ _lock.unlock();
+ }
+ }
+}
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,148 @@
+package org.apache.tapestry.engine;
+
+import ognl.Node;
+import ognl.enhance.ExpressionAccessor;
+
+/**
+ * Wrapper around the OGNL library.
+ *
+ * @author Howard M. Lewis Ship
+ * @since 4.0
+ */
+public interface ExpressionEvaluator
+{
+
+ /**
+ * Parses the given ognl expression.
+ *
+ * @param target
+ * The object the expression is to be executed against.
+ * @param expression
+ * The expression.
+ *
+ * @return The parsed OGNL AST representation of the expression.
+ */
+ Node parse(Object target, String expression);
+
+ /**
+ * Reads a property of the target, defined by the expression.
+ *
+ * @param target
+ * The object to evaluate the expression against.
+ * @param expression
+ * The expression.
+ *
+ * @return The value returned from the expression statement.
+ *
+ * @throws org.apache.tapestry.ApplicationRuntimeException
+ * if the expression can not be parsed, or if some other error
+ * occurs during evaluation of the expression.
+ */
+ Object read(Object target, String expression);
+
+ /**
+ * Reads a property of the target, defined by the (previously compiled)
+ * expression.
+ *
+ * @param target
+ * The object to evaluate the expression against.
+ * @param expression
+ * The expression.
+ *
+ * @return The value returned from the expression statement.
+ *
+ * @throws org.apache.tapestry.ApplicationRuntimeException
+ * if some other error occurs during evaluation of the
+ * 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.
+ *
+ * @param target
+ * The object to evaluate the expression against.
+ * @param expression
+ * The expression.
+ * @param value
+ * The value to set on the target object.
+ *
+ * @throws org.apache.tapestry.ApplicationRuntimeException
+ * if the expression can not be parsed, or if some other error
+ * occurs during evaluation of the expression.
+ */
+ void write(Object target, String expression, Object value);
+
+ /**
+ * Updates a property of the target, defined by the (previously compiled)
+ * expression.
+ *
+ * @param target
+ * The object to evaluate the expression against.
+ * @param expression
+ * The expression.
+ * @param value
+ * The value to set on the target object.
+ *
+ * @throws org.apache.tapestry.ApplicationRuntimeException
+ * if some other error occurs during evaluation of the
+ * 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.
+ *
+ * @param target
+ * The object to evaluate the expression against.
+ * @param expression
+ * The expression.
+ *
+ * @return True if expression represents a constant statement, false otherwise.
+ * @throws org.apache.tapestry.ApplicationRuntimeException
+ * if the expression is not valid
+ */
+ boolean isConstant(Object target, String expression);
+
+ /**
+ * Returns true only if both system properties of <code>org.apache.tapestry.disable-caching</code>
+ * and <code>org.apache.tapestry.disable-expression-compile</code> are false.
+ *
+ * @return True if ognl expressions are eligable for JIT compilation.
+ */
+ boolean isCompileEnabled();
+
+ void compileExpression(Object target, Node node, String expression);
+
+ /**
+ * Used to reset any internal state.
+ */
+ void reset();
+}
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,239 @@
+package org.apache.tapestry.engine;
+
+import ognl.*;
+import ognl.enhance.ExpressionAccessor;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.tapestry.ApplicationRuntimeException;
+import org.apache.tapestry.Tapestry;
+import org.apache.tapestry.enhance.IEnhancedClassFactory;
+import org.apache.tapestry.enhance.javassist.OGNLExpressionCompiler;
+import org.apache.tapestry.spec.IApplicationSpecification;
+
+import java.beans.Introspector;
+import java.util.Map;
+
+/**
+ * @since 4.0
+ */
+public class ExpressionEvaluatorImpl implements ExpressionEvaluator {
+
+ private static final long POOL_MIN_IDLE_TIME = 1000 * 60 * 50;
+
+ private static final long POOL_SLEEP_TIME = 1000 * 60 * 4;
+
+ // Uses Thread's context class loader
+
+ private final ClassResolver _ognlResolver;
+
+ private ExpressionCache _expressionCache;
+
+ private IApplicationSpecification _applicationSpecification;
+
+ private TypeConverter _typeConverter;
+
+ // Context, with a root of null, used when evaluating an expression
+ // to see if it is a constant.
+
+ private Map _defaultContext;
+
+ private IEnhancedClassFactory _classFactory;
+
+ private GenericObjectPool _contextPool;
+
+ private final boolean _cachingDisabled = Boolean.getBoolean("org.apache.tapestry.disable-caching");
+
+ private final boolean _compileDisabled = Boolean.getBoolean("org.apache.tapestry.disable-expression-compile");
+
+ public ExpressionEvaluatorImpl(ClassResolver resolver, IEnhancedClassFactory classFactory,
+ ExpressionCache expressionCache, IApplicationSpecification spec)
+ {
+ _ognlResolver = resolver;
+ _classFactory = classFactory;
+ _expressionCache = expressionCache;
+ _applicationSpecification = spec;
+
+ initializeService();
+ }
+
+ void initializeService()
+ {
+ if (_applicationSpecification.checkExtension(Tapestry.OGNL_TYPE_CONVERTER))
+ _typeConverter = (TypeConverter) _applicationSpecification.getExtension(Tapestry.OGNL_TYPE_CONVERTER, TypeConverter.class);
+
+ _defaultContext = Ognl.createDefaultContext(null, _ognlResolver, _typeConverter);
+
+ OgnlRuntime.setCompiler(new OGNLExpressionCompiler(_classFactory));
+
+ _contextPool = new GenericObjectPool(new PoolableOgnlContextFactory(_ognlResolver, _typeConverter));
+
+ _contextPool.setMaxActive(-1);
+ _contextPool.setMaxIdle(-1);
+ _contextPool.setMinEvictableIdleTimeMillis(POOL_MIN_IDLE_TIME);
+ _contextPool.setTimeBetweenEvictionRunsMillis(POOL_SLEEP_TIME);
+ }
+
+ public Node parse(Object target, String expression)
+ {
+ Node node = (Node)_expressionCache.get(target, expression);
+
+ if (node == null)
+ {
+ try
+ {
+ node = (Node)Ognl.parseExpression(expression);
+ _expressionCache.cache(target, expression, node);
+ } catch (OgnlException ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
+ }
+ }
+
+ return node;
+ }
+
+ public Object read(Object target, String expression)
+ {
+ Node node = parse(target, expression);
+
+ if (node.getAccessor() != null)
+ return read(target, node.getAccessor());
+
+ return readCompiled(target, node);
+ }
+
+ public Object readCompiled(Object target, Object expression)
+ {
+ OgnlContext context = null;
+ try
+ {
+ context = (OgnlContext)_contextPool.borrowObject();
+ context.setRoot(target);
+
+ return Ognl.getValue(expression, context, target);
+ }
+ catch (Exception ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
+ } finally {
+ try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+ }
+ }
+
+ public Object read(Object target, ExpressionAccessor expression)
+ {
+ OgnlContext context = null;
+ try
+ {
+ context = (OgnlContext)_contextPool.borrowObject();
+
+ return expression.get(context, target);
+ }
+ catch (Exception ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
+ } finally {
+ try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+ }
+ }
+
+ public void write(Object target, String expression, Object value)
+ {
+ writeCompiled(target, parse(target, expression), value);
+ }
+
+ public void write(Object target, ExpressionAccessor expression, Object value)
+ {
+ OgnlContext context = null;
+ try
+ {
+ context = (OgnlContext)_contextPool.borrowObject();
+
+ // set up context
+ context.setRoot(target);
+
+ expression.set(context, target, value);
+ }
+ catch (Exception ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-write-expression",
+ new Object[] {expression, target, value, ex}),
+ target, null, ex);
+ } finally {
+ try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+ }
+ }
+
+ public void writeCompiled(Object target, Object expression, Object value)
+ {
+ OgnlContext context = null;
+ try
+ {
+ context = (OgnlContext)_contextPool.borrowObject();
+
+ Ognl.setValue(expression, context, target, value);
+ }
+ catch (Exception ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-write-expression",
+ new Object[] {expression, target, value, ex}),
+ target, null, ex);
+ } finally {
+ try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+ }
+ }
+
+ public boolean isConstant(Object target, String expression)
+ {
+ Node node = parse(target, expression);
+
+ try
+ {
+ return Ognl.isConstant(node, _defaultContext);
+ }
+ catch (Exception ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("is-constant-expression-error", expression, ex), ex);
+ }
+ }
+
+ public boolean isCompileEnabled()
+ {
+ return !_cachingDisabled && !_compileDisabled;
+ }
+
+ public void compileExpression(Object target, Node node, String expression)
+ {
+ OgnlContext context = null;
+
+ try
+ {
+ context = (OgnlContext)_contextPool.borrowObject();
+
+ // set up context
+ context.setRoot(target);
+
+ OgnlRuntime.compileExpression(context, node, target);
+
+ _expressionCache.cache(target, expression, node);
+
+ } catch (Exception ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
+ } finally {
+ try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+ }
+ }
+
+ public void reset()
+ {
+ try
+ {
+ _contextPool.clear();
+
+ OgnlRuntime.clearCache();
+ Introspector.flushCaches();
+ } catch (Exception et) {
+ // ignore
+ }
+ }
+}
\ No newline at end of file
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,40 @@
+package org.apache.tapestry.engine;
+
+import ognl.ClassResolver;
+import ognl.Ognl;
+import ognl.OgnlContext;
+import ognl.TypeConverter;
+import org.apache.commons.pool.BasePoolableObjectFactory;
+
+/**
+ * Used by {@link ExpressionEvaluatorImpl} to pool {@link ognl.OgnlContext} objects.
+ */
+public class PoolableOgnlContextFactory extends BasePoolableObjectFactory {
+
+ private final ClassResolver _resolver;
+
+ private TypeConverter _typeConverter;
+
+ public PoolableOgnlContextFactory(ClassResolver resolver, TypeConverter typeConverter)
+ {
+ _resolver = resolver;
+ _typeConverter = typeConverter;
+ }
+
+ public Object makeObject()
+ throws Exception
+ {
+ return Ognl.createDefaultContext(null, _resolver, _typeConverter);
+ }
+
+ public void activateObject(Object obj)
+ throws Exception
+ {
+ OgnlContext context = (OgnlContext)obj;
+
+ if (context.getRoot() != null || context.getValues().size() > 0)
+ {
+ context.clear();
+ }
+ }
+}
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/PoolableOgnlContextFactory.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java Mon Jul 7 17:14:19 2008
@@ -21,7 +21,6 @@
import org.apache.tapestry.IResourceResolver;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.IComponentClassEnhancer;
-import org.apache.tapestry.enhance.javassist.EnhancedClassFactory;
import org.apache.tapestry.spec.IComponentSpecification;
import java.lang.reflect.Method;
@@ -58,19 +57,14 @@
* @param disableValidation if true, then validation (of unimplemented abstract methods)
* is skipped
*/
- public DefaultComponentClassEnhancer(IResourceResolver resolver, boolean disableValidation)
+ public DefaultComponentClassEnhancer(IResourceResolver resolver, boolean disableValidation, IEnhancedClassFactory classFactory)
{
_cachedClasses = new ConcurrentHashMap();
_resolver = resolver;
- _factory = createEnhancedClassFactory();
+ _factory = classFactory;
_disableValidation = disableValidation;
}
- protected IEnhancedClassFactory createEnhancedClassFactory()
- {
- return new EnhancedClassFactory(getResourceResolver());
- }
-
public synchronized void reset()
{
_cachedClasses.clear();
@@ -244,7 +238,7 @@
boolean isAbstract = Modifier.isAbstract(m.getModifiers());
- MethodSignature s = new MethodSignature(m);
+ MethodSignature s = new MethodSignatureImpl(m);
if (isAbstract)
{
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/IEnhancedClass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/IEnhancedClass.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/IEnhancedClass.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/IEnhancedClass.java Mon Jul 7 17:14:19 2008
@@ -51,4 +51,22 @@
* Adds an arbitrary enhancer.
*/
void addEnhancer(IEnhancer enhancer);
+
+ void addInterface(Class type);
+
+ void addMethod(int modifiers, MethodSignature signature, String body);
+
+ void addField(String name, Class type);
+
+ void addConstructor(Class[] parameterTypes, Class[] exceptions, String body);
+
+ /**
+ * Returns true if the same method was previously added via
+ * {@link #addMethod(int, MethodSignature, String)}.
+ *
+ * @param signature
+ * The signature to check existance of.
+ * @return True if the same method has been added already, false otherwise.
+ */
+ boolean containsMethod(MethodSignature signature);
}
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignature.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignature.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignature.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignature.java Mon Jul 7 17:14:19 2008
@@ -14,89 +14,67 @@
package org.apache.tapestry.enhance;
-import java.lang.reflect.Method;
-
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.apache.commons.lang.builder.ToStringBuilder;
-
/**
- * The signature of a {@link java.lang.reflect.Method}, including
- * the name, return type, and parameter types. Used when checking
- * for unimplemented methods in enhanced subclasses.
- *
- * <p>
- * The modifiers (i.e., "public", "abstract") and thrown
- * exceptions are not relevant for these purposes, and
- * are not part of the signature.
- *
- * <p>
- * Instances of MethodSignature are immutable and
- * implement equals() and hashCode() properly for use
- * in Sets or as Map keys.
- *
- * @author Howard Lewis Ship
- * @version $Id$
- * @since 3.0
- *
- **/
-
-public class MethodSignature
+ * A representation of a {@link java.lang.reflect.Method}, identifying the name, return type,
+ * parameter types and exception types. Actual Method objects are tied to a particular class, and
+ * don't compare well with other otherwise identical Methods from other classes or interface;
+ * MethodSignatures are distinct from classes and compare well.
+ * <p>
+ * Because the intended purpose is to compare methods from interfaces (which are always public and
+ * abstract) we don't bother to actually track the modifiers. In addition, at this time,
+ * MethodSignature <em>does not distinguish between instance and static
+ * methods</em>.
+ */
+public interface MethodSignature
{
- private String _name;
- private Class _returnType;
- private Class[] _parameterTypes;
- private int _hashCode = 0;
-
- public MethodSignature(Method m)
- {
- _name = m.getName();
- _returnType = m.getReturnType();
-
- // getParameterTypes() returns a copy for us to keep.
-
- _parameterTypes = m.getParameterTypes();
- }
-
- public boolean equals(Object obj)
- {
- if (obj == null || !(obj instanceof MethodSignature))
- return false;
-
- MethodSignature other = (MethodSignature) obj;
-
- EqualsBuilder builder = new EqualsBuilder();
- builder.append(_name, other._name);
- builder.append(_returnType, other._returnType);
- builder.append(_parameterTypes, other._parameterTypes);
-
- return builder.isEquals();
- }
-
- public int hashCode()
- {
- if (_hashCode == 0)
- {
- HashCodeBuilder builder = new HashCodeBuilder(253, 97);
-
- builder.append(_name);
- builder.append(_returnType);
- builder.append(_parameterTypes);
-
- _hashCode = builder.toHashCode();
- }
-
- return _hashCode;
- }
-
- public String toString()
- {
- ToStringBuilder builder = new ToStringBuilder(this);
- builder.append("name", _name);
- builder.append("returnType", _returnType);
- builder.append("parameterTypes", _parameterTypes);
-
- return builder.toString();
- }
-
+ /**
+ * Returns the exceptions for this method. Caution: do not modify the returned array. May return
+ * null.
+ */
+ Class[] getExceptionTypes();
+
+ /**
+ * The name of the method.
+ * @return method name
+ */
+ String getName();
+
+ /**
+ * Returns the parameter types for this method. May return null. Caution: do not modify the
+ * returned array.
+ */
+ Class[] getParameterTypes();
+
+ /**
+ * Method return type.
+ *
+ * @return The return type of the method.
+ */
+ Class getReturnType();
+
+ /**
+ * Returns a string consisting of the name of the method and its parameter values. This is
+ * similar to {@link #toString()}, but omits the return type and information about thrown
+ * exceptions. A unique id is used by MethodIterator to identify overlapping methods
+ * (methods with the same name but different thrown exceptions).
+ *
+ */
+ String getUniqueId();
+
+ /**
+ * Returns true if this signature has the same return type, name and parameters types as the
+ * method signature passed in, and this signatures exceptions "trump" (are the same as, or
+ * super-implementations of, all exceptions thrown by the other method signature).
+ *
+ */
+
+ boolean isOverridingSignatureOf(MethodSignature ms);
+
+ /**
+ * If the method definition has generic parameters or return types it
+ * is expected that this will return true.
+ *
+ * @return True if this is a generics based method, false otherwise.
+ */
+ boolean isGeneric();
}
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,241 @@
+package org.apache.tapestry.enhance;
+
+import org.apache.tapestry.enhance.javassist.ClassFabUtils;
+
+import java.lang.reflect.Method;
+
+/**
+ * JDK 1.4 based version of {@link MethodSignature}.
+ */
+public class MethodSignatureImpl implements MethodSignature
+{
+ protected int _hashCode = -1;
+
+ protected Class _returnType;
+
+ protected String _name;
+
+ protected Class[] _parameterTypes;
+
+ protected Class[] _exceptionTypes;
+
+ public MethodSignatureImpl(Class returnType, String name,
+ Class[] parameterTypes, Class[] exceptionTypes)
+ {
+ _returnType = returnType;
+ _name = name;
+ _parameterTypes = parameterTypes;
+ _exceptionTypes = exceptionTypes;
+ }
+
+ public MethodSignatureImpl(Method m)
+ {
+ this(m.getReturnType(), m.getName(), m.getParameterTypes(), m.getExceptionTypes());
+ }
+
+ public Class[] getExceptionTypes()
+ {
+ return _exceptionTypes;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public Class[] getParameterTypes()
+ {
+ return _parameterTypes;
+ }
+
+ public Class getReturnType()
+ {
+ return _returnType;
+ }
+
+ public int hashCode()
+ {
+ if (_hashCode == -1)
+ {
+ _hashCode = _returnType.hashCode();
+
+ _hashCode = 31 * _hashCode + _name.hashCode();
+
+ int count = count(_parameterTypes);
+
+ for (int i = 0; i < count; i++)
+ _hashCode = 31 * _hashCode + _parameterTypes[i].hashCode();
+
+ count = count(_exceptionTypes);
+
+ for (int i = 0; i < count; i++)
+ _hashCode = 31 * _hashCode + _exceptionTypes[i].hashCode();
+ }
+
+ return _hashCode;
+ }
+
+ protected static int count(Object[] array)
+ {
+ return array == null ? 0 : array.length;
+ }
+
+ /**
+ * Returns true if the other object is an instance of MethodSignature with identical values for
+ * return type, name, parameter types and exception types.
+ */
+ public boolean equals(Object o)
+ {
+ if (o == null || !(o instanceof MethodSignatureImpl))
+ return false;
+
+ MethodSignatureImpl ms = (MethodSignatureImpl) o;
+
+ if (_returnType != ms._returnType)
+ return false;
+
+ if (!_name.equals(ms._name))
+ return false;
+
+ if (mismatch(_parameterTypes, ms._parameterTypes))
+ return false;
+
+ return !mismatch(_exceptionTypes, ms._exceptionTypes);
+ }
+
+ protected boolean mismatch(Class[] a1, Class[] a2)
+ {
+ int a1Count = count(a1);
+ int a2Count = count(a2);
+
+ if (a1Count != a2Count)
+ return true;
+
+ // Hm. What if order is important (for exceptions)? We're really saying here that they
+ // were derived from the name Method.
+
+ for (int i = 0; i < a1Count; i++)
+ {
+ if (!a1[i].isAssignableFrom(a2[i]))
+ return true;
+ }
+
+ return false;
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(ClassFabUtils.getJavaClassName(_returnType));
+ buffer.append(" ");
+ buffer.append(_name);
+ buffer.append("(");
+
+ for (int i = 0; i < count(_parameterTypes); i++)
+ {
+ if (i > 0)
+ buffer.append(", ");
+
+ buffer.append(ClassFabUtils.getJavaClassName(_parameterTypes[i]));
+ }
+
+ buffer.append(")");
+
+ for (int i = 0; i < count(_exceptionTypes); i++)
+ {
+ if (i == 0)
+ buffer.append(" throws ");
+ else
+ buffer.append(", ");
+
+ buffer.append(_exceptionTypes[i].getName());
+ }
+
+ return buffer.toString();
+ }
+
+ public String getUniqueId()
+ {
+ StringBuffer buffer = new StringBuffer(_name);
+ buffer.append("(");
+
+ for (int i = 0; i < count(_parameterTypes); i++)
+ {
+ if (i > 0)
+ buffer.append(",");
+
+ buffer.append(ClassFabUtils.getJavaClassName(_parameterTypes[i]));
+ }
+
+ buffer.append(")");
+
+ return buffer.toString();
+ }
+
+ public boolean isGeneric()
+ {
+ return false;
+ }
+
+ public boolean isOverridingSignatureOf(MethodSignature ms)
+ {
+ if (!(ms instanceof MethodSignatureImpl))
+ return false;
+
+ MethodSignatureImpl sig = (MethodSignatureImpl)ms;
+
+ if (!sig._returnType.isAssignableFrom(_returnType))
+ return false;
+
+ if (!_name.equals(sig._name))
+ return false;
+
+ if (mismatch(_parameterTypes, sig._parameterTypes))
+ return false;
+
+ return exceptionsEncompass(sig._exceptionTypes);
+ }
+
+ /**
+ * The nuts and bolts of checking that another method signature's exceptions are a subset of
+ * this signature's.
+ */
+
+ protected boolean exceptionsEncompass(Class[] otherExceptions)
+ {
+ int ourCount = count(_exceptionTypes);
+ int otherCount = count(otherExceptions);
+
+ // If we have no exceptions, then ours encompass theirs only if they
+ // have no exceptions, either.
+
+ if (ourCount == 0)
+ return otherCount == 0;
+
+ boolean[] matched = new boolean[otherCount];
+ int unmatched = otherCount;
+
+ for (int i = 0; i < ourCount && unmatched > 0; i++)
+ {
+ for (int j = 0; j < otherCount; j++)
+ {
+ // Ignore exceptions that have already been matched
+
+ if (matched[j])
+ continue;
+
+ // When one of our exceptions is a super-class of one of their exceptions,
+ // then their exceptions is matched.
+
+ if (_exceptionTypes[i].isAssignableFrom(otherExceptions[j]))
+ {
+ matched[j] = true;
+ unmatched--;
+ }
+ }
+ }
+
+ return unmatched == 0;
+ }
+}
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/MethodSignatureImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,74 @@
+package org.apache.tapestry.enhance.javassist;
+
+import java.lang.reflect.Method;
+
+/**
+ * Static class containing utility methods.
+ *
+ * @author Howard Lewis Ship
+ */
+public class ClassFabUtils
+{
+ private static long _uid = System.currentTimeMillis();
+
+ private static final char QUOTE = '"';
+
+ private ClassFabUtils()
+ {
+ }
+
+ /**
+ * Generates a unique class name, which will be in the default package.
+ */
+
+ public static synchronized String generateClassName(String baseName)
+ {
+ return "$" + baseName + "_" + Long.toHexString(_uid++);
+ }
+
+ /**
+ * Returns a class name derived from the provided interfaceClass. The package part of the
+ * interface name is stripped out, and the result passed to {@link #generateClassName(String)}.
+ *
+ * @since 1.1
+ */
+
+ public static synchronized String generateClassName(Class interfaceClass)
+ {
+ String name = interfaceClass.getName();
+
+ int dotx = name.lastIndexOf('.');
+
+ return generateClassName(name.substring(dotx + 1));
+ }
+
+ /**
+ * Javassist needs the class name to be as it appears in source code, even for arrays. Invoking
+ * getName() on a Class instance representing an array returns the internal format (i.e, "[...;"
+ * or something). This returns it as it would appear in Java code.
+ */
+ public static String getJavaClassName(Class inputClass)
+ {
+ if (inputClass.isArray())
+ return getJavaClassName(inputClass.getComponentType()) + "[]";
+
+ return inputClass.getName();
+ }
+
+ /**
+ * Returns true if the method is the standard toString() method. Very few interfaces will ever
+ * include this method as part of the interface, but we have to be sure.
+ */
+ public static boolean isToString(Method method)
+ {
+ if (!method.getName().equals("toString"))
+ return false;
+
+ if (method.getParameterTypes().length > 0)
+ return false;
+
+ return method.getReturnType().equals(String.class);
+ }
+}
+
+
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabUtils.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabricator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabricator.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabricator.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/ClassFabricator.java Mon Jul 7 17:14:19 2008
@@ -17,7 +17,10 @@
import javassist.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.tapestry.ApplicationRuntimeException;
+import org.apache.tapestry.Tapestry;
import org.apache.tapestry.enhance.CodeGenerationException;
+import org.apache.tapestry.enhance.MethodSignature;
import java.io.IOException;
import java.text.MessageFormat;
@@ -87,7 +90,12 @@
return null;
}
}
-
+
+ public void addInterface(Class interfaceType)
+ {
+ _genClass.addInterface(getCtClass(interfaceType));
+ }
+
public void createField(CtClass fieldType, String fieldName)
{
if (LOG.isDebugEnabled())
@@ -261,11 +269,81 @@
}
}
-
+ public CtClass getCtClass(Class searchClass)
+ {
+ String name = ClassFabUtils.getJavaClassName(searchClass);
+
+ try
+ {
+ return _classPool.get(name);
+ }
+ catch (NotFoundException ex)
+ {
+ throw new ApplicationRuntimeException(Tapestry.format("unable-to-lookup", name, ex), ex);
+ }
+ }
+
+ public void addMethod(int modifiers, MethodSignature ms, String body)
+ {
+ CtClass ctReturnType = getCtClass(ms.getReturnType());
+
+ CtClass[] ctParameters = convertClasses(ms.getParameterTypes());
+ CtClass[] ctExceptions = convertClasses(ms.getExceptionTypes());
+
+ CtMethod method = new CtMethod(ctReturnType, ms.getName(), ctParameters, _genClass);
+
+ try {
+ method.setModifiers(modifiers);
+ method.setBody(body);
+ method.setExceptionTypes(ctExceptions);
+
+ _genClass.addMethod(method);
+ } catch (Exception ex)
+ {
+ throw new CodeGenerationException(ex);
+ }
+ }
+
+ public void addConstructor(Class[] parameterTypes, Class[] exceptions, String body)
+ {
+ CtClass[] ctParameters = convertClasses(parameterTypes);
+ CtClass[] ctExceptions = convertClasses(exceptions);
+
+ try
+ {
+ CtConstructor constructor = new CtConstructor(ctParameters, _genClass);
+ constructor.setExceptionTypes(ctExceptions);
+ constructor.setBody(body);
+
+ _genClass.addConstructor(constructor);
+ } catch (Exception ex)
+ {
+ throw new CodeGenerationException(ex);
+ }
+ }
+
public void commit()
{
}
+ protected CtClass[] convertClasses(Class[] inputClasses)
+ {
+ if (inputClasses == null || inputClasses.length == 0)
+ return null;
+
+ int count = inputClasses.length;
+ CtClass[] result = new CtClass[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ CtClass ctClass = getCtClass(inputClasses[i]);
+
+ result[i] = ctClass;
+ }
+
+ return result;
+ }
+
public byte[] getByteCode()
{
try
Added: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java?rev=674683&view=auto
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java (added)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java Mon Jul 7 17:14:19 2008
@@ -0,0 +1,93 @@
+package org.apache.tapestry.enhance.javassist;
+
+import ognl.Node;
+import org.apache.tapestry.enhance.IEnhancedClass;
+import org.apache.tapestry.enhance.MethodSignature;
+
+/**
+ * Simple struct used by {@link OGNLExpressionCompiler} to hold temporary references to
+ * all of the objects involved in compiling / generating a compiled ognl expression.
+ */
+public class CompiledExpression {
+
+ IEnhancedClass _generatedClass;
+ Node _expression;
+ Object _root;
+ MethodSignature _getterMethod;
+ MethodSignature _setterMethod;
+
+ public CompiledExpression(Node expression, Object root,
+ MethodSignature getter, MethodSignature setter)
+ {
+ _expression = expression;
+ _root = root;
+ _getterMethod = getter;
+ _setterMethod = setter;
+ }
+
+ public IEnhancedClass getGeneratedClass()
+ {
+ return _generatedClass;
+ }
+
+ public void setGeneratedClass(IEnhancedClass generatedClass)
+ {
+ _generatedClass = generatedClass;
+ }
+
+ public Node getExpression()
+ {
+ return _expression;
+ }
+
+ public void setExpression(Node expression)
+ {
+ _expression = expression;
+ }
+
+ public Object getRoot()
+ {
+ return _root;
+ }
+
+ public void setRoot(Object root)
+ {
+ _root = root;
+ }
+
+ public MethodSignature getGetterMethod()
+ {
+ return _getterMethod;
+ }
+
+ public void setGetterMethod(MethodSignature method)
+ {
+ _getterMethod = method;
+ }
+
+ public MethodSignature getSettermethod()
+ {
+ return _setterMethod;
+ }
+
+ public void setSetterMethod(MethodSignature method)
+ {
+ _setterMethod = method;
+ }
+
+ public String toString()
+ {
+ return "CompiledExpression[" +
+ "_generatedClass=" + _generatedClass +
+ '\n' +
+ ", _expression=" + _expression +
+ '\n' +
+ ", _root=" + _root +
+ '\n' +
+ ", _getterMethod=" + _getterMethod +
+ '\n' +
+ ", _setterMethod=" + _setterMethod +
+ '\n' +
+ ']';
+ }
+}
\ No newline at end of file
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/CompiledExpression.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClass.java?rev=674683&r1=674682&r2=674683&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClass.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClass.java Mon Jul 7 17:14:19 2008
@@ -16,16 +16,19 @@
import javassist.ClassPool;
import javassist.CtClass;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.enhance.BaseEnhancedClass;
import org.apache.tapestry.enhance.EnhancedClassLoader;
import org.apache.tapestry.enhance.IEnhancer;
+import org.apache.tapestry.enhance.MethodSignature;
+
+import java.util.HashSet;
+import java.util.Set;
/**
* Represents a class to be enhanced using Javassist.
- *
+ *
* @author Mindbridge
* @version $Id$
* @since 3.0
@@ -40,6 +43,8 @@
private ClassFabricator _classFabricator = null;
+ private Set _methods = new HashSet();
+
public EnhancedClass(String className, Class parentClass, EnhancedClassFactory classFactory)
{
_className = className;
@@ -83,17 +88,17 @@
* @see org.apache.tapestry.enhance.IEnhancedClass#createProperty(java.lang.String, java.lang.String, java.lang.String, boolean)
*/
public void createProperty(
- String propertyName,
- String propertyType,
- String readMethodName,
- boolean persistent)
+ String propertyName,
+ String propertyType,
+ String readMethodName,
+ boolean persistent)
{
IEnhancer enhancer =
- new CreatePropertyEnhancer(
- propertyName,
- getObjectType(propertyType),
- readMethodName,
- persistent);
+ new CreatePropertyEnhancer(
+ propertyName,
+ getObjectType(propertyType),
+ readMethodName,
+ persistent);
addEnhancer(enhancer);
}
@@ -101,18 +106,18 @@
* @see org.apache.tapestry.enhance.IEnhancedClass#createAutoParameter(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public void createAutoParameter(
- String propertyName,
- String parameterName,
- String typeClassName,
- String readMethodName)
+ String propertyName,
+ String parameterName,
+ String typeClassName,
+ String readMethodName)
{
IEnhancer enhancer =
- new CreateAutoParameterEnhancer(
- this,
- propertyName,
- parameterName,
- getObjectType(typeClassName),
- readMethodName);
+ new CreateAutoParameterEnhancer(
+ this,
+ propertyName,
+ parameterName,
+ getObjectType(typeClassName),
+ readMethodName);
addEnhancer(enhancer);
}
@@ -131,9 +136,34 @@
EnhancedClassLoader loader = _classFactory.getEnhancedClassLoader();
return loader.defineClass(
- enhancedClassName,
- enhancedClassBytes,
- _parentClass.getProtectionDomain());
+ enhancedClassName,
+ enhancedClassBytes,
+ _parentClass.getProtectionDomain());
+ }
+
+ public void addInterface(Class type)
+ {
+ getClassFabricator().addInterface(type);
+ }
+
+ public void addMethod(int modifiers, MethodSignature signature, String body)
+ {
+ getClassFabricator().addMethod(modifiers, signature, body);
+ _methods.add(signature);
}
+ public void addField(String name, Class type)
+ {
+ getClassFabricator().createField(getClassFabricator().getCtClass(type), name);
+ }
+
+ public void addConstructor(Class[] parameterTypes, Class[] exceptions, String body)
+ {
+ getClassFabricator().addConstructor(parameterTypes, exceptions, body);
+ }
+
+ public boolean containsMethod(MethodSignature signature)
+ {
+ return _methods.contains(signature);
+ }
}