Author: henning
Date: Wed Sep 6 08:37:44 2006
New Revision: 440737
URL: http://svn.apache.org/viewvc?view=rev&rev=440737
Log:
remodel the whole getPropertySet framework to look like the getPropertyGet
framework. Modularize
the method look-ups using Executors. This fixes most of the issues of
VELOCITY-456 and also in
a rare double-whammy patch, it also resolves the issues of VELOCITY-449.
Added:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java
(with props)
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java
(with props)
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java
(with props)
Modified:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/GetExecutor.java
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PropertyExecutor.java
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
Modified:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/GetExecutor.java
URL:
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/GetExecutor.java?view=diff&rev=440737&r1=440736&r2=440737
==============================================================================
---
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/GetExecutor.java
(original)
+++
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/GetExecutor.java
Wed Sep 6 08:37:44 2006
@@ -1,6 +1,6 @@
package org.apache.velocity.runtime.parser.node;
/*
- * Copyright 2000-2004 The Apache Software Foundation.
+ * Copyright 2000-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
@@ -37,8 +37,9 @@
*/
public class GetExecutor extends AbstractExecutor
{
- private Introspector introspector = null;
+ private final Introspector introspector;
+ // This is still threadsafe because this object is only read except in the
C'tor.
private Object [] params = {};
public GetExecutor(final Log log, final Introspector introspector,
@@ -56,8 +57,7 @@
if (property != null)
{
- this.params = new Object[1];
- this.params[0] = property;
+ this.params = new Object[] { property };
}
discover(clazz);
}
Modified:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PropertyExecutor.java
URL:
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PropertyExecutor.java?view=diff&rev=440737&r1=440736&r2=440737
==============================================================================
---
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PropertyExecutor.java
(original)
+++
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PropertyExecutor.java
Wed Sep 6 08:37:44 2006
@@ -1,6 +1,6 @@
package org.apache.velocity.runtime.parser.node;
/*
- * Copyright 2000-2004 The Apache Software Foundation.
+ * Copyright 2000-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
*/
public class PropertyExecutor extends AbstractExecutor
{
- private Introspector introspector = null;
+ private final Introspector introspector;
public PropertyExecutor(final Log log, final Introspector introspector,
final Class clazz, final String property)
Added:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java
URL:
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java?view=auto&rev=440737
==============================================================================
---
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java
(added)
+++
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java
Wed Sep 6 08:37:44 2006
@@ -0,0 +1,113 @@
+package org.apache.velocity.runtime.parser.node;
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.velocity.runtime.log.Log;
+import org.apache.velocity.util.introspection.Introspector;
+
+
+/**
+ * Executor that simply tries to execute a put(key, value)
+ * operation. This will try to find a put(key) method
+ * for any type of object, not just objects that
+ * implement the Map interface as was previously
+ * the case.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
+ * @version $Id$
+ */
+public class PutExecutor extends SetExecutor
+{
+ private final Introspector introspector;
+ private final String property;
+
+ public PutExecutor(final Log log, final Introspector introspector,
+ final Class clazz, final Object arg, final String property)
+ {
+ this.log = log;
+ this.introspector = introspector;
+ this.property = property;
+
+ discover(clazz, arg);
+ }
+
+ protected void discover(final Class clazz, final Object arg)
+ {
+ Object [] params;
+
+ // If you passed in null as property, we don't use the value
+ // for parameter lookup. Instead we just look for put(Object) without
+ // any parameters.
+ //
+ // In any other case, the following condition will set up an array
+ // for looking up put(String, Object) on the class.
+
+ if (property == null)
+ {
+ // The passed in arg object is used by the Cache to look up the
method.
+ params = new Object[] { arg };
+ }
+ else
+ {
+ params = new Object[] { property, arg };
+ }
+
+ try
+ {
+ setMethod(introspector.getMethod(clazz, "put", params));
+ }
+ /**
+ * pass through application level runtime exceptions
+ */
+ catch( RuntimeException e )
+ {
+ throw e;
+ }
+ catch(Exception e)
+ {
+ log.error("While looking for put('" + params[0] + "') method:", e);
+ }
+ }
+
+ /**
+ * Execute method against context.
+ */
+ public Object execute(final Object o, final Object value)
+ throws IllegalAccessException, InvocationTargetException
+ {
+ Object [] params;
+
+ if (isAlive())
+ {
+ // If property != null, pass in the name for put(key, value). Else
just put(value).
+ if (property == null)
+ {
+ params = new Object [] { value };
+ }
+ else
+ {
+ params = new Object [] { property, value };
+ }
+
+ return getMethod().invoke(o, params);
+ }
+
+ return null;
+ }
+}
Propchange:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/PutExecutor.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java
URL:
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java?view=auto&rev=440737
==============================================================================
---
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java
(added)
+++
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java
Wed Sep 6 08:37:44 2006
@@ -0,0 +1,71 @@
+package org.apache.velocity.runtime.parser.node;
+
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.velocity.runtime.log.Log;
+
+/**
+ * Abstract class that is used to execute an arbitrary
+ * method that is in introspected. This is the superclass
+ * for the PutExecutor and SetPropertyExecutor.
+ *
+ * There really should be a superclass for this and AbstractExecutor (which
should
+ * be refactored to GetExecutor) because they differ only in the execute()
method.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
+ * @version $Id$
+ */
+public abstract class SetExecutor
+{
+ protected Log log = null;
+
+ /**
+ * Method to be executed.
+ */
+ private Method method = null;
+
+ /**
+ * Execute method against context.
+ */
+ public abstract Object execute(Object o, Object value)
+ throws IllegalAccessException, InvocationTargetException;
+
+ /**
+ * Tell whether the executor is alive by looking
+ * at the value of the method.
+ */
+ public boolean isAlive()
+ {
+ return (method != null);
+ }
+
+ public Method getMethod()
+ {
+ return method;
+ }
+
+ protected void setMethod(final Method method)
+ {
+ this.method = method;
+ }
+}
Propchange:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetExecutor.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java
URL:
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java?view=auto&rev=440737
==============================================================================
---
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java
(added)
+++
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java
Wed Sep 6 08:37:44 2006
@@ -0,0 +1,109 @@
+package org.apache.velocity.runtime.parser.node;
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.runtime.log.Log;
+import org.apache.velocity.util.introspection.Introspector;
+
+/**
+ * Executor for looking up property names in the passed in class
+ * This will try to find a set<foo>(key, value) method
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
+ * @version $Id$
+ */
+public class SetPropertyExecutor
+ extends SetExecutor
+{
+ private final Introspector introspector;
+
+ public SetPropertyExecutor(final Log log, final Introspector introspector,
+ final Class clazz, final String property, final Object arg)
+ {
+ this.log = log;
+ this.introspector = introspector;
+
+ // Don't allow passing in the empty string or null because
+ // it will either fail with a StringIndexOutOfBounds error
+ // or the introspector will get confused.
+ if (StringUtils.isNotEmpty(property))
+ {
+ discover(clazz, property, arg);
+ }
+ }
+
+ protected Introspector getIntrospector()
+ {
+ return this.introspector;
+ }
+
+ protected void discover(final Class clazz, final String property, final
Object arg)
+ {
+ Object [] params = new Object [] { arg };
+
+ try
+ {
+ StringBuffer sb = new StringBuffer("set");
+ sb.append(property);
+
+ setMethod(introspector.getMethod(clazz, sb.toString(), params));
+
+ if (!isAlive())
+ {
+ /*
+ * now the convenience, flip the 1st character
+ */
+
+ char c = sb.charAt(3);
+
+ if (Character.isLowerCase(c))
+ {
+ sb.setCharAt(3, Character.toUpperCase(c));
+ }
+ else
+ {
+ sb.setCharAt(3, Character.toLowerCase(c));
+ }
+
+ setMethod(introspector.getMethod(clazz, sb.toString(),
params));
+ }
+ }
+ /**
+ * pass through application level runtime exceptions
+ */
+ catch( RuntimeException e )
+ {
+ throw e;
+ }
+ catch(Exception e)
+ {
+ log.error("While looking for property setter for '" + property +
"':", e);
+ }
+ }
+
+ /**
+ * Execute method against context.
+ */
+ public Object execute(final Object o, final Object value)
+ throws IllegalAccessException, InvocationTargetException
+ {
+ Object [] params = new Object [] { value };
+ return isAlive() ? getMethod().invoke(o, params) : null;
+ }
+}
Propchange:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/SetPropertyExecutor.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Modified:
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
URL:
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java?view=diff&rev=440737&r1=440736&r2=440737
==============================================================================
---
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
(original)
+++
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
Wed Sep 6 08:37:44 2006
@@ -17,18 +17,21 @@
*/
import java.lang.reflect.Method;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
+
+import org.apache.velocity.runtime.RuntimeLogger;
import org.apache.velocity.runtime.log.Log;
import org.apache.velocity.runtime.log.RuntimeLoggerLog;
-import org.apache.velocity.runtime.RuntimeLogger;
import org.apache.velocity.runtime.parser.node.AbstractExecutor;
import org.apache.velocity.runtime.parser.node.BooleanPropertyExecutor;
import org.apache.velocity.runtime.parser.node.GetExecutor;
import org.apache.velocity.runtime.parser.node.PropertyExecutor;
+import org.apache.velocity.runtime.parser.node.PutExecutor;
+import org.apache.velocity.runtime.parser.node.SetExecutor;
+import org.apache.velocity.runtime.parser.node.SetPropertyExecutor;
import org.apache.velocity.util.ArrayIterator;
import org.apache.velocity.util.EnumerationIterator;
@@ -37,6 +40,7 @@
* functionality of Velocity
*
* @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
* @version $Id$
*/
public class UberspectImpl implements Uberspect, UberspectLoggable
@@ -140,7 +144,9 @@
throws Exception
{
if (obj == null)
+ {
return null;
+ }
Method m = introspector.getMethod(obj.getClass(), methodName, args);
@@ -164,7 +170,7 @@
* first try for a getFoo() type of property
* (also getfoo() )
*/
- AbstractExecutor executor = new PropertyExecutor(log,introspector,
claz, identifier);
+ AbstractExecutor executor = new PropertyExecutor(log, introspector,
claz, identifier);
/*
* if that didn't work, look for get("foo")
@@ -195,66 +201,29 @@
Object arg, Info i)
throws Exception
{
- Class claz = obj.getClass();
-
- VelMethod vm = null;
- try
+ if (obj == null)
{
- /*
- * first, we introspect for the set<identifier> setter method
- */
-
- Object[] params = {arg};
-
- try
- {
- vm = getMethod(obj, "set" + identifier, params, i);
-
- if (vm == null)
- {
- throw new NoSuchMethodException();
- }
- }
- catch(NoSuchMethodException nsme2)
- {
- StringBuffer sb = new StringBuffer("set");
- sb.append(identifier);
-
- if (Character.isLowerCase( sb.charAt(3)))
- {
- sb.setCharAt(3, Character.toUpperCase(sb.charAt(3)));
- }
- else
- {
- sb.setCharAt(3, Character.toLowerCase(sb.charAt(3)));
- }
-
- vm = getMethod(obj, sb.toString(), params, i);
-
- if (vm == null)
- {
- throw new NoSuchMethodException();
- }
- }
+ return null;
}
- catch (NoSuchMethodException nsme)
- {
- /*
- * right now, we only support the Map interface
- */
+
+ Class claz = obj.getClass();
- if (Map.class.isAssignableFrom(claz))
- {
- Object[] params = {new Object(), new Object()};
+ /*
+ * first try for a setFoo() type of property
+ * (also setfoo() )
+ */
+ SetExecutor executor = new SetPropertyExecutor(log, introspector,
claz, identifier, arg);
- vm = getMethod(obj, "put", params, i);
+ /*
+ * if that didn't work, look for put("foo", arg)
+ */
- if (vm!=null)
- return new VelSetterImpl(vm, identifier);
- }
- }
+ if (!executor.isAlive())
+ {
+ executor = new PutExecutor(log, introspector, claz, arg,
identifier);
+ }
- return (vm!=null) ? new VelSetterImpl(vm) : null;
+ return (executor.isAlive()) ? new VelSetterImpl(executor) : null;
}
/**
@@ -262,7 +231,7 @@
*/
public static class VelMethodImpl implements VelMethod
{
- Method method = null;
+ final Method method;
public VelMethodImpl(Method m)
{
@@ -271,6 +240,7 @@
private VelMethodImpl()
{
+ method = null;
}
public Object invoke(Object o, Object[] params)
@@ -297,21 +267,22 @@
public static class VelGetterImpl implements VelPropertyGet
{
- AbstractExecutor ae = null;
+ final AbstractExecutor getExecutor;
public VelGetterImpl(AbstractExecutor exec)
{
- ae = exec;
+ getExecutor = exec;
}
private VelGetterImpl()
{
+ getExecutor = null;
}
public Object invoke(Object o)
throws Exception
{
- return ae.execute(o);
+ return getExecutor.execute(o);
}
public boolean isCacheable()
@@ -321,46 +292,34 @@
public String getMethodName()
{
- return ae.getMethod().getName();
+ return getExecutor.isAlive() ? getExecutor.getMethod().getName() :
null;
}
}
public static class VelSetterImpl implements VelPropertySet
{
- VelMethod vm = null;
- String putKey = null;
+ private final SetExecutor setExecutor;
- public VelSetterImpl(VelMethod velmethod)
+ public VelSetterImpl(final SetExecutor setExecutor)
{
- this.vm = velmethod;
- }
-
- public VelSetterImpl(VelMethod velmethod, String key)
- {
- this.vm = velmethod;
- putKey = key;
+ this.setExecutor = setExecutor;
}
private VelSetterImpl()
{
+ setExecutor = null;
}
- public Object invoke(Object o, Object value)
+ /**
+ * Invoke the found Set Executor.
+ *
+ * @param o is the Object to invoke it on.
+ * @param value in the Value to set.
+ */
+ public Object invoke(final Object o, final Object value)
throws Exception
{
- ArrayList al = new ArrayList();
-
- if (putKey != null)
- {
- al.add(putKey);
- al.add(value);
- }
- else
- {
- al.add(value);
- }
-
- return vm.invoke(o,al.toArray());
+ return setExecutor.execute(o, value);
}
public boolean isCacheable()
@@ -370,7 +329,7 @@
public String getMethodName()
{
- return vm.getMethodName();
+ return setExecutor.isAlive() ? setExecutor.getMethod().getName() :
null;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]