You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gr...@apache.org on 2009/06/13 19:45:24 UTC
svn commit: r784442 [4/4] - in /commons/proper/jexl/branches/2.0: ./
src/java/org/apache/commons/jexl/ src/java/org/apache/commons/jexl/logging/
src/java/org/apache/commons/jexl/parser/
src/java/org/apache/commons/jexl/util/ src/java/org/apache/commons...
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java Sat Jun 13 17:45:23 2009
@@ -1,81 +1,81 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.jexl.util;
-
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-
-
-/**
- * GetExecutor that is smart about Maps. If it detects one, it does not
- * use Reflection but a cast to access the getter.
- *
- * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
- * @version $Id$
- */
-public class MapGetExecutor extends AbstractExecutor {
- /** the property to get. */
- private final String property;
-
- /**
- * Create the instance.
- * @param rlog the logger.
- * @param clazz the class to execute the get on.
- * @param aProperty the property or key to get.
- */
- public MapGetExecutor(final Log rlog, final Class clazz, final String aProperty) {
- this.rlog = rlog;
- this.property = aProperty;
- discover(clazz);
- }
-
- /**
- * Discover the method to call.
- * @param clazz the class to find the method on.
- */
- protected void discover(final Class clazz) {
- Class[] interfaces = clazz.getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- if (interfaces[i].equals(Map.class)) {
- try {
- if (property != null) {
- method = Map.class.getMethod("get", new Class[]{Object.class});
- }
- /**
- * pass through application level runtime exceptions
- */
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- rlog.error("While looking for get('" + property + "') method:", e);
- }
- break;
- }
- }
- }
-
- /**
- * Get the property from the map.
- * @param o the map.
- * @return o.get(property)
- */
- public Object execute(final Object o) {
- return ((Map) o).get(property);
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.jexl.util;
+
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+
+
+/**
+ * GetExecutor that is smart about Maps. If it detects one, it does not
+ * use Reflection but a cast to access the getter.
+ *
+ * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
+ * @version $Id$
+ */
+public class MapGetExecutor extends AbstractExecutor {
+ /** the property to get. */
+ private final String property;
+
+ /**
+ * Create the instance.
+ * @param rlog the logger.
+ * @param clazz the class to execute the get on.
+ * @param aProperty the property or key to get.
+ */
+ public MapGetExecutor(final Log rlog, final Class clazz, final String aProperty) {
+ this.rlog = rlog;
+ this.property = aProperty;
+ discover(clazz);
+ }
+
+ /**
+ * Discover the method to call.
+ * @param clazz the class to find the method on.
+ */
+ protected void discover(final Class clazz) {
+ Class[] interfaces = clazz.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (interfaces[i].equals(Map.class)) {
+ try {
+ if (property != null) {
+ method = Map.class.getMethod("get", new Class[]{Object.class});
+ }
+ /**
+ * pass through application level runtime exceptions
+ */
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ rlog.error("While looking for get('" + property + "') method:", e);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Get the property from the map.
+ * @param o the map.
+ * @return o.get(property)
+ */
+ public Object execute(final Object o) {
+ return ((Map) o).get(property);
+ }
+}
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyExecutor.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyExecutor.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyExecutor.java Sat Jun 13 17:45:23 2009
@@ -26,7 +26,8 @@
* @since 1.0
*/
public class PropertyExecutor extends AbstractExecutor {
-
+ /* Empty param list. */
+ protected static final Object[] EMPTY_PARAMS = {};
/** index of the first character of the property. */
private static final int PROPERTY_START_INDEX = 3;
/** The JEXL introspector used. */
@@ -64,21 +65,17 @@
try {
char c;
- StringBuffer sb;
-
- Object[] params = {};
-
/*
* start with get<property>
* this leaves the property name
* as is...
*/
- sb = new StringBuffer("get");
+ StringBuilder sb = new StringBuilder("get");
sb.append(property);
methodUsed = sb.toString();
- method = introspector.getMethod(clazz, methodUsed, params);
+ method = introspector.getMethod(clazz, methodUsed, EMPTY_PARAMS);
if (method != null) {
return;
@@ -97,7 +94,7 @@
}
methodUsed = sb.toString();
- method = introspector.getMethod(clazz, methodUsed, params);
+ method = introspector.getMethod(clazz, methodUsed, EMPTY_PARAMS);
if (method != null) {
return;
@@ -108,7 +105,7 @@
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
- rlog.error("PROGRAMMER ERROR : PropertyExector() : " + e);
+ rlog.error("PROGRAMMER ERROR : PropertyExector() : ", e);
}
}
@@ -122,7 +119,7 @@
return null;
}
- return method.invoke(o, null);
+ return method.invoke(o, (Object[])null);
}
}
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java Sat Jun 13 17:45:23 2009
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.commons.jexl.util.introspection;
import java.lang.reflect.Method;
@@ -27,12 +26,11 @@
import org.apache.commons.logging.Log;
-
/**
* Taken from the Velocity tree so we can be self-sufficient
*
* A cache of introspection information for a specific class instance. Keys
- * {@link Method} objects by a concatenation of the method name and
+ * {@link MethodKey} objects by an agregation of the method name and
* the names of classes that make up the parameters.
*
* @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
@@ -44,6 +42,7 @@
* @since 1.0
*/
public class ClassMap {
+
/**
* Class passed into the constructor used to as the basis for the Method map.
*/
@@ -106,11 +105,11 @@
// until Velocity 1.4. As we always reflect all elements of the tree (that's what we have a cache for), we will
// hit the public elements sooner or later because we reflect all the public elements anyway.
//
- List classesToReflect = new ArrayList();
+ List<Class> classesToReflect = new ArrayList<Class>();
// Ah, the miracles of Java for(;;) ...
- for (Class classToReflect = getCachedClass(); classToReflect != null;
- classToReflect = classToReflect.getSuperclass()) {
+ for (Class classToReflect = getCachedClass(); classToReflect != null;
+ classToReflect = classToReflect.getSuperclass()) {
if (Modifier.isPublic(classToReflect.getModifiers())) {
classesToReflect.add(classToReflect);
}
@@ -122,8 +121,8 @@
}
}
- for (Iterator it = classesToReflect.iterator(); it.hasNext();) {
- Class classToReflect = (Class) it.next();
+ for (Iterator<Class> it = classesToReflect.iterator(); it.hasNext();) {
+ Class classToReflect = it.next();
try {
Method[] methods = classToReflect.getMethods();
@@ -143,10 +142,9 @@
}
}
}
- }
- catch (SecurityException se) // Everybody feels better with...
+ } catch (SecurityException se) // Everybody feels better with...
{
- if (rlog.isDebugEnabled()) {
+ if (rlog != null && rlog.isDebugEnabled()) {
rlog.debug("While accessing methods of " + classToReflect + ": ", se);
}
}
@@ -158,34 +156,65 @@
*
* @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
* @version $Id$
+ * <p>
+ * It stores the association between:
+ * a key made of a method name & an array of argument types. (@see MethodCache.MethodKey)
+ * a method.
+ * </p>
+ * <p>
+ * Since the invocation of the associated method is dynamic, there is no need (nor way) to differentiate between
+ * foo(int,int) & foo(Integer,Integer) since in practise, only the latter form will be used through a call.
+ * This of course, applies to all 8 primitive types.
+ * </p>
+ * @version $Id$
*/
- private static final class MethodCache {
- private static final class CacheMiss {
- }
-
- private static final CacheMiss CACHE_MISS = new CacheMiss();
-
- private static final Object OBJECT = new Object();
-
- private static final Map convertPrimitives = new HashMap();
+ static class MethodCache {
+ /**
+ * A method that returns itself used as a marker for cache miss,
+ * allows the underlying cache map to be strongly typed.
+ */
+ public static Method CacheMiss() {
+ try {
+ return MethodCache.class.getMethod("CacheMiss");
+ } // this really cant make an error...
+ catch (Exception xio) {
+ }
+ return null;
+ }
+ private static final Method CACHE_MISS = CacheMiss();
+ private static final Map<Class, Class> convertPrimitives;
static {
- convertPrimitives.put(Boolean.TYPE, Boolean.class.getName());
- convertPrimitives.put(Byte.TYPE, Byte.class.getName());
- convertPrimitives.put(Character.TYPE, Character.class.getName());
- convertPrimitives.put(Double.TYPE, Double.class.getName());
- convertPrimitives.put(Float.TYPE, Float.class.getName());
- convertPrimitives.put(Integer.TYPE, Integer.class.getName());
- convertPrimitives.put(Long.TYPE, Long.class.getName());
- convertPrimitives.put(Short.TYPE, Short.class.getName());
+ convertPrimitives = new HashMap<Class, Class>(13);
+ convertPrimitives.put(Boolean.TYPE, Boolean.class);
+ convertPrimitives.put(Byte.TYPE, Byte.class);
+ convertPrimitives.put(Character.TYPE, Character.class);
+ convertPrimitives.put(Double.TYPE, Double.class);
+ convertPrimitives.put(Float.TYPE, Float.class);
+ convertPrimitives.put(Integer.TYPE, Integer.class);
+ convertPrimitives.put(Long.TYPE, Long.class);
+ convertPrimitives.put(Short.TYPE, Short.class);
}
+ /** Converts a primitive type to its corresponding class.
+ * <p>
+ * If the argument type is primitive then we want to convert our
+ * primitive type signature to the corresponding Object type so
+ * introspection for methods with primitive types will work
+ * correctly.
+ * </p>
+ */
+ static final Class primitiveClass(Class parm) {
+ // it is marginally faster to get from the map than call isPrimitive...
+ //if (!parm.isPrimitive()) return parm;
+ Class prim = convertPrimitives.get(parm);
+ return prim == null ? parm : prim;
+ }
/**
* Cache of Methods, or CACHE_MISS, keyed by method
* name and actual arguments used to find it.
*/
- private final Map cache = new HashMap();
-
+ private final Map<MethodKey, Method> cache = new HashMap<MethodKey, Method>();
/**
* Map of methods that are searchable according to method parameters to find a match
*/
@@ -193,114 +222,165 @@
/**
* Find a Method using the method name and parameter objects.
- *
+ *<p>
* Look in the methodMap for an entry. If found,
* it'll either be a CACHE_MISS, in which case we
* simply give up, or it'll be a Method, in which
* case, we return it.
- *
+ *</p>
+ * <p>
* If nothing is found, then we must actually go
* and introspect the method from the MethodMap.
- *
+ *</p>
* @param name The method name to look up.
* @param params An array of parameters for the method.
* @return A Method object representing the method to invoke or null.
* @throws MethodMap.AmbiguousException When more than one method is a match for the parameters.
*/
- public synchronized Method get(final String name, final Object[] params)
+ public Method get(final String name, final Object[] params)
throws MethodMap.AmbiguousException {
- String methodKey = makeMethodKey(name, params);
+ return get(new MethodKey(name, params));
+ }
- Object cacheEntry = cache.get(methodKey);
+ public Method get(final MethodKey methodKey)
+ throws MethodMap.AmbiguousException {
+ synchronized (methodMap) {
+ Method cacheEntry = cache.get(methodKey);
+ // We looked this up before and failed.
+ if (cacheEntry == CACHE_MISS) {
+ return null;
+ }
+
+ if (cacheEntry == null) {
+ try {
+ // That one is expensive...
+ cacheEntry = methodMap.find(methodKey);
+ if (cacheEntry != null) {
+ cache.put(methodKey, cacheEntry);
+ } else {
+ cache.put(methodKey, CACHE_MISS);
+ }
+ } catch (MethodMap.AmbiguousException ae) {
+ // that's a miss :-)
+ cache.put(methodKey, CACHE_MISS);
+ throw ae;
+ }
+ }
- // We looked this up before and failed.
- if (cacheEntry == CACHE_MISS) {
- return null;
+ // Yes, this might just be null.
+ return cacheEntry;
}
+ }
- if (cacheEntry == null) {
- try {
- // That one is expensive...
- cacheEntry = methodMap.find(name, params);
+ public void put(Method method) {
+ synchronized (methodMap) {
+ MethodKey methodKey = new MethodKey(method);
+ // We don't overwrite methods. Especially not if we fill the
+ // cache from defined class towards java.lang.Object because
+ // abstract methods in superclasses would else overwrite concrete
+ // classes further down the hierarchy.
+ if (cache.get(methodKey) == null) {
+ cache.put(methodKey, method);
+ methodMap.add(method);
}
- catch (MethodMap.AmbiguousException ae) {
- /*
- * that's a miss :-)
- */
- cache.put(methodKey, CACHE_MISS);
- throw ae;
- }
-
- cache.put(methodKey,
- (cacheEntry != null) ? cacheEntry : CACHE_MISS);
}
+ }
+ }
- // Yes, this might just be null.
+ /**
+ * A method key for the introspector cache:
+ * This replaces the original key scheme which used to build the key by concatenating the method name and parameters
+ * class names as one string with the exception that primitive types were converted to their object class equivalents.
+ * The key is still based on the same information, it is just wrapped in an object instead.
+ * Primitive type classes are converted to they object equivalent to make a key; int foo(int) and int foo(Integer) do
+ * generate the same key.
+ * A key can be constructed either from arguments (array of objects) or from parameters (array of class).
+ * Roughly 3x faster than string key to access the map & uses less memory.
+ */
+ static class MethodKey {
+ /** The hash code */
+ final int hash;
+ /** The method name. */
+ final String method;
+ /** The parameters. */
+ final Class[] params;
+ /** A marker for empty parameter list. */
+ static final Class[] NOARGS = new Class[0];
- return (Method) cacheEntry;
+ /** Builds a MethodKey from a method.
+ * Used to store information in the method map.
+ */
+ MethodKey(Method method) {
+ this(method.getName(), method.getParameterTypes());
}
- public synchronized void put(Method method) {
- String methodKey = makeMethodKey(method);
-
- // We don't overwrite methods. Especially not if we fill the
- // cache from defined class towards java.lang.Object because
- // abstract methods in superclasses would else overwrite concrete
- // classes further down the hierarchy.
- if (cache.get(methodKey) == null) {
- cache.put(methodKey, method);
- methodMap.add(method);
+ /** Builds a MethodKey from a method name and a set of arguments (objects).
+ * Used to query the method map.
+ */
+ MethodKey(String method, Object[] args) {
+ // !! keep this in sync with the other ctor (hash code) !!
+ this.method = method;
+ int hash = this.method.hashCode();
+ final int size;
+ if (args != null && (size = args.length) > 0) {
+ this.params = new Class[size];
+ for (int p = 0; p < size; ++p) {
+ // ctor(Object) : {
+ Object arg = args[p];
+ // no need to go thru primitive type conversion since these are objects
+ Class parm = arg == null ? Object.class : arg.getClass();
+ // }
+ hash = (37 * hash) + parm.hashCode();
+ this.params[p] = parm;
+ }
+ } else {
+ this.params = NOARGS;
}
+ this.hash = hash;
}
- /**
- * Make a methodKey for the given method using
- * the concatenation of the name and the
- * types of the method parameters.
- *
- * @param method to be stored as key
- * @return key for ClassMap
+ /** Builds a MethodKey from a method name and a set of parameters (classes).
+ * Used to store information in the method map. ( @see MethodKey#primitiveClass )
*/
- private String makeMethodKey(final Method method) {
- Class[] parameterTypes = method.getParameterTypes();
-
- StringBuffer methodKey = new StringBuffer(method.getName());
-
- for (int j = 0; j < parameterTypes.length; j++) {
- /*
- * If the argument type is primitive then we want
- * to convert our primitive type signature to the
- * corresponding Object type so introspection for
- * methods with primitive types will work correctly.
- *
- * The lookup map (convertPrimitives) contains all eight
- * primitives (boolean, byte, char, double, float, int, long, short)
- * known to Java. So it should never return null for the key passed in.
- */
- if (parameterTypes[j].isPrimitive()) {
- methodKey.append((String) convertPrimitives.get(parameterTypes[j]));
- } else {
- methodKey.append(parameterTypes[j].getName());
+ MethodKey(String method, Class[] args) {
+ // !! keep this in sync with the other ctor (hash code) !!
+ this.method = method;
+ int hash = this.method.hashCode();
+ final int size;
+ if (args != null && (size = args.length) > 0) {
+ this.params = new Class[size];
+ for (int p = 0; p < size; ++p) {
+ // ctor(Class): {
+ Class parm = MethodCache.primitiveClass(args[p]);
+ // }
+ hash = (37 * hash) + parm.hashCode();
+ this.params[p] = parm;
}
+ } else {
+ this.params = NOARGS;
}
-
- return methodKey.toString();
+ this.hash = hash;
}
- private String makeMethodKey(String method, Object[] params) {
- StringBuffer methodKey = new StringBuffer().append(method);
-
- for (int j = 0; j < params.length; j++) {
- Object arg = params[j];
+ @Override
+ public int hashCode() {
+ return hash;
+ }
- if (arg == null) {
- arg = OBJECT;
- }
+ @Override
+ public boolean equals(Object arg) {
+ MethodKey key = (MethodKey) arg;
+ return method.equals(key.method) && java.util.Arrays.equals(params, key.params);
+ }
- methodKey.append(arg.getClass().getName());
+ @Override
+ /** Compatible with original string key. */
+ public String toString() {
+ StringBuilder builder = new StringBuilder(method);
+ for (Class c : params) {
+ builder.append(c.getName());
}
-
- return methodKey.toString();
+ return builder.toString();
}
}
}
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Introspector.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Introspector.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Introspector.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Introspector.java Sat Jun 13 17:45:23 2009
@@ -99,7 +99,7 @@
* whoops. Ambiguous. Make a nice log message and return null...
*/
- StringBuffer msg = new StringBuffer("Introspection Error : Ambiguous method invocation ")
+ StringBuilder msg = new StringBuilder("Introspection Error : Ambiguous method invocation ")
.append(name).append("( ");
for (int i = 0; i < params.length; i++) {
@@ -112,7 +112,7 @@
msg.append(") for class ").append(c.getName());
- rlog.error(msg.toString());
+ if (rlog != null) rlog.error(msg.toString());
}
return null;
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/IntrospectorBase.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/IntrospectorBase.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/IntrospectorBase.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/IntrospectorBase.java Sat Jun 13 17:45:23 2009
@@ -59,15 +59,16 @@
/**
* Holds the method maps for the classes we know about, keyed by Class
+ * Made WeakHashMap so we wont prevent a class from being GCed.
* object.
*/
- protected final Map classMethodMaps = new HashMap();
+ protected final Map<Class, ClassMap> classMethodMaps = new java.util.WeakHashMap<Class, ClassMap>();
/**
* Holds the qualified class names for the classes we hold in the
* classMethodMaps hash.
*/
- private Set cachedClassNames = new HashSet();
+ private Set<String> cachedClassNames = new HashSet<String>();
/**
* Create the introspector.
@@ -104,8 +105,7 @@
ClassMap classMap;
synchronized (classMethodMaps) {
- classMap = (ClassMap) classMethodMaps.get(c);
-
+ classMap = classMethodMaps.get(c);
/*
* if we don't have this, check to see if we have it by name. if so,
* then we have a classloader change so dump our caches.
@@ -157,6 +157,6 @@
/*
* for speed, we can just make a new one and let the old one be GC'd
*/
- cachedClassNames = new HashSet();
+ cachedClassNames = new HashSet<String>();
}
}
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/MethodMap.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/MethodMap.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/MethodMap.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/MethodMap.java Sat Jun 13 17:45:23 2009
@@ -19,7 +19,7 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Hashtable;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -52,7 +52,7 @@
* Keep track of all methods with the same name.
*/
// CSOFF: VisibilityModifier
- Map methodByNameMap = new Hashtable();
+ private Map<String, List<Method>> methodByNameMap = new HashMap<String, List<Method>>();
// CSON: VisibilityModifier
/**
@@ -61,13 +61,13 @@
*
* @param method the method.
*/
- public void add(Method method) {
+ public synchronized void add(Method method) {
String methodName = method.getName();
- List l = get(methodName);
+ List<Method> l = methodByNameMap.get(methodName);
if (l == null) {
- l = new ArrayList();
+ l = new ArrayList<Method>();
methodByNameMap.put(methodName, l);
}
@@ -80,8 +80,8 @@
* @param key the name.
* @return List list of methods.
*/
- public List get(String key) {
- return (List) methodByNameMap.get(key);
+ public synchronized List<Method> get(String key) {
+ return methodByNameMap.get(key);
}
/**
@@ -115,27 +115,15 @@
// CSOFF: RedundantThrows
public Method find(String methodName, Object[] args)
throws AmbiguousException {
- List methodList = get(methodName);
+ return find(new ClassMap.MethodKey(methodName, args));
+ }
+ Method find(ClassMap.MethodKey methodKey) throws AmbiguousException {
+ List<Method> methodList = get(methodKey.method);
if (methodList == null) {
return null;
}
-
- int l = args.length;
- Class[] classes = new Class[l];
-
- for (int i = 0; i < l; ++i) {
- Object arg = args[i];
-
- /*
- * if we are careful down below, a null argument goes in there
- * so we can know that the null was passed to the method
- */
- classes[i] =
- arg == null ? null : arg.getClass();
- }
-
- return getMostSpecific(methodList, classes);
+ return getMostSpecific(methodList, methodKey.params);
} // CSON: RedundantThrows
@@ -160,16 +148,16 @@
* @return the most specific method.
* @throws AmbiguousException if there is more than one.
*/
- private static Method getMostSpecific(List methods, Class[] classes)
+ private static Method getMostSpecific(List<Method> methods, Class[] classes)
throws AmbiguousException {
- LinkedList applicables = getApplicables(methods, classes);
+ LinkedList<Method> applicables = getApplicables(methods, classes);
if (applicables.isEmpty()) {
return null;
}
if (applicables.size() == 1) {
- return (Method) applicables.getFirst();
+ return applicables.getFirst();
}
/*
@@ -178,17 +166,17 @@
* (the most specific method) otherwise we have ambiguity.
*/
- LinkedList maximals = new LinkedList();
+ LinkedList<Method> maximals = new LinkedList<Method>();
- for (Iterator applicable = applicables.iterator();
+ for (Iterator<Method> applicable = applicables.iterator();
applicable.hasNext();) {
- Method app = (Method) applicable.next();
+ Method app = applicable.next();
Class[] appArgs = app.getParameterTypes();
boolean lessSpecific = false;
- for (Iterator maximal = maximals.iterator();
+ for (Iterator<Method> maximal = maximals.iterator();
!lessSpecific && maximal.hasNext();) {
- Method max = (Method) maximal.next();
+ Method max = maximal.next();
// CSOFF: MissingSwitchDefault
switch (moreSpecific(appArgs, max.getParameterTypes())) {
@@ -223,7 +211,7 @@
throw new AmbiguousException();
}
- return (Method) maximals.getFirst();
+ return maximals.getFirst();
} // CSON: RedundantThrows
@@ -295,12 +283,11 @@
* formal and actual arguments matches, and argument types are assignable
* to formal types through a method invocation conversion).
*/
- private static LinkedList getApplicables(List methods, Class[] classes) {
- LinkedList list = new LinkedList();
-
- for (Iterator imethod = methods.iterator(); imethod.hasNext();) {
- Method method = (Method) imethod.next();
+ private static LinkedList<Method> getApplicables(List<Method> methods, Class[] classes) {
+ LinkedList<Method> list = new LinkedList<Method>();
+ for (Iterator<Method> imethod = methods.iterator(); imethod.hasNext();) {
+ Method method = imethod.next();
if (isApplicable(method, classes)) {
list.add(method);
}
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Uberspect.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Uberspect.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Uberspect.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Uberspect.java Sat Jun 13 17:45:23 2009
@@ -33,6 +33,9 @@
*/
void init();
+ /** Returns the underlying introspector. */
+ public Introspector getIntrospector();
+
/**
* To support iteratives - #foreach().
* @param info template info.
Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/UberspectImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/UberspectImpl.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/UberspectImpl.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/UberspectImpl.java Sat Jun 13 17:45:23 2009
@@ -20,11 +20,9 @@
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import org.apache.commons.jexl.util.AbstractExecutor;
@@ -51,7 +49,10 @@
* index of the first character of the property.
*/
private static final int PROPERTY_START_INDEX = 3;
-
+ /*
+ * static signature for method(object,object)
+ */
+ static final Class[] OBJECT_OBJECT = { Object.class, Object.class };
/**
* Our runtime logger.
*/
@@ -62,6 +63,9 @@
*/
private Introspector introspector;
+ public Introspector getIntrospector() {
+ return introspector;
+ }
/**
* init - does nothing - we need to have setRuntimeLogger called before
* getting our introspector, as the default vel introspector depends upon
@@ -91,13 +95,13 @@
} else if (obj instanceof Map) {
return ((Map) obj).values().iterator();
} else if (obj instanceof Iterator) {
- rlog.warn("Warning! The iterative " + " is an Iterator in the #foreach() loop at [" + i.getLine() + ","
+ rlog.warn("Warning! The iterative " + " is an Iterator in the #foreach() loop at [" + i.getLine() + ","
+ i.getColumn() + "]" + " in template " + i.getTemplateName() + ". Because it's not resetable,"
+ " if used in more than once, this may lead to" + " unexpected results.");
return ((Iterator) obj);
} else if (obj instanceof Enumeration) {
- rlog.warn("Warning! The iterative " + " is an Enumeration in the #foreach() loop at [" + i.getLine() + ","
+ rlog.warn("Warning! The iterative " + " is an Enumeration in the #foreach() loop at [" + i.getLine() + ","
+ i.getColumn() + "]" + " in template " + i.getTemplateName() + ". Because it's not resetable,"
+ " if used in more than once, this may lead to" + " unexpected results.");
@@ -108,10 +112,10 @@
// foreach without implementing the Collection interface
Class type = obj.getClass();
try {
- Method iter = type.getMethod("iterator", null);
+ Method iter = type.getMethod("iterator", (Class[]) null);
Class returns = iter.getReturnType();
if (Iterator.class.isAssignableFrom(returns)) {
- return (Iterator) iter.invoke(obj, null);
+ return (Iterator) iter.invoke(obj, (Object[])null);
} else {
rlog.error("iterator() method of reference in #foreach loop at "
+ i + " does not return a true Iterator.");
@@ -129,7 +133,7 @@
}
/* we have no clue what this is */
- rlog.warn("Could not determine type of iterator in " + "#foreach loop " + " at [" + i.getLine() + ","
+ rlog.warn("Could not determine type of iterator in " + "#foreach loop " + " at [" + i.getLine() + ","
+ i.getColumn() + "]" + " in template " + i.getTemplateName());
return null;
@@ -221,7 +225,7 @@
throw new NoSuchMethodException();
}
} catch (NoSuchMethodException nsme2) {
- StringBuffer sb = new StringBuffer("set");
+ StringBuilder sb = new StringBuilder("set");
sb.append(identifier);
if (Character.isLowerCase(sb.charAt(PROPERTY_START_INDEX))) {
@@ -242,10 +246,7 @@
*/
if (Map.class.isAssignableFrom(claz)) {
- Object[] params = {new Object(), new Object()};
-
- vm = getMethod(obj, "put", params, i);
-
+ vm = getMethod(obj, "put", OBJECT_OBJECT, i);
if (vm != null) {
return new VelSetterImpl(vm, identifier);
}
@@ -494,16 +495,13 @@
* {@inheritDoc}
*/
public Object invoke(Object o, Object value) throws Exception {
- List al = new ArrayList();
-
if (putKey == null) {
- al.add(value);
+ Object[] a0 = { value };
+ return vm.invoke(o, a0);
} else {
- al.add(putKey);
- al.add(value);
+ Object[] a1 = { putKey, value };
+ return vm.invoke(o, a1);
}
-
- return vm.invoke(o, al.toArray());
}
/**
Added: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/AssignTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/AssignTest.java?rev=784442&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/AssignTest.java (added)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/AssignTest.java Sat Jun 13 17:45:23 2009
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl;
+
+import junit.framework.TestCase;
+
+/**
+ * Test cases for the if statement.
+ *
+ * @author Dion Gillard
+ * @since 1.1
+ */
+public class AssignTest extends TestCase {
+ static JexlEngine JEXL = new JexlEngine();
+ static {
+ JEXL.setSilent(false);
+ }
+
+ public static class Froboz {
+ int value;
+ public Froboz(int v) {
+ value = v;
+ }
+ public void setValue(int v) {
+ value = v;
+ }
+ public int getValue() {
+ return value;
+ }
+ }
+
+ public static class Quux {
+ String str;
+ Froboz froboz;
+ public Quux(String str, int fro) {
+ this.str = str;
+ froboz = new Froboz(fro);
+ }
+
+ public Froboz getFroboz() {
+ return froboz;
+ }
+
+ public void setFroboz(Froboz froboz) {
+ this.froboz = froboz;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+ }
+
+ public AssignTest(String testName) {
+ super(testName);
+ }
+
+ /**
+ * Make sure bean assignment works
+ *
+ * @throws Exception on any error
+ */
+ public void testAntish() throws Exception {
+ Expression assign = JEXL.createExpression("froboz.value = 10");
+ Expression check = JEXL.createExpression("froboz.value");
+ JexlContext jc = JexlHelper.createContext();
+ Object o = assign.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ o = check.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ }
+
+ public void testBeanish() throws Exception {
+ Expression assign = JEXL.createExpression("froboz.value = 10");
+ Expression check = JEXL.createExpression("froboz.value");
+ JexlContext jc = JexlHelper.createContext();
+ Froboz froboz = new Froboz(-169);
+ jc.getVars().put("froboz", froboz);
+ Object o = assign.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ o = check.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ }
+
+ public void testAmbiguous() throws Exception {
+ Expression assign = JEXL.createExpression("froboz.nosuchbean = 10");
+ JexlContext jc = JexlHelper.createContext();
+ Froboz froboz = new Froboz(-169);
+ jc.getVars().put("froboz", froboz);
+ Object o = null;
+ try {
+ o = assign.evaluate(jc);
+ }
+ catch(RuntimeException xrt) {
+ String str = xrt.toString();
+ return;
+ }
+ finally {
+ assertEquals("Should have failed", null, o);
+ }
+ }
+
+ public void testArray() throws Exception {
+ Expression assign = JEXL.createExpression("froboz[\"value\"] = 10");
+ Expression check = JEXL.createExpression("froboz[\"value\"]");
+ System.out.print(assign.dump());
+ JexlContext jc = JexlHelper.createContext();
+ Froboz froboz = new Froboz(0);
+ jc.getVars().put("froboz", froboz);
+ Object o = assign.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ o = check.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ }
+
+ public void testMore() throws Exception {
+ Expression assign = JEXL.createExpression("quux.froboz.value = 10");
+ Expression check = JEXL.createExpression("quux[\"froboz\"].value");
+ JexlContext jc = JexlHelper.createContext();
+ jc.getVars().put("quux", new Quux("xuuq", 100));
+ Object o = assign.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ o = check.evaluate(jc);
+ assertEquals("Result is not 10", new Integer(10), o);
+ }
+
+
+ public void testTernary() throws Exception {
+ JexlContext jc = JexlHelper.createContext();
+ Expression e = JEXL.createExpression("x.y.z = foo ?'bar':'quux'");
+ String canonical = e.dump();
+ System.out.print(canonical);
+ Object o = e.evaluate(jc);
+ assertEquals("Should be quux", "quux", o);
+ jc.getVars().put("foo",true);
+ o = e.evaluate(jc);
+ assertEquals("Should be bar", "bar", o);
+ o = jc.getVars().get("x.y.z");
+ assertEquals("Should be bar", "bar", o);
+ }
+
+ public void testNotNull() throws Exception {
+ JexlContext jc = JexlHelper.createContext();
+ Expression e = JEXL.createExpression("x.y.z = foo?:'quux'");
+ Object o = e.evaluate(jc);
+ assertEquals("Should be quux", "quux", o);
+ jc.getVars().put("foo","bar");
+ o = e.evaluate(jc);
+ assertEquals("Should be bar", "bar", o);
+ o = jc.getVars().get("x.y.z");
+ assertEquals("Should be bar", "bar", o);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new AssignTest("debug").testAmbiguous();
+ //new AssignTest("debug").testArray();
+ }
+}
\ No newline at end of file
Modified: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/BlockTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/BlockTest.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/BlockTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/BlockTest.java Sat Jun 13 17:45:23 2009
@@ -82,5 +82,8 @@
Object o = e.evaluate(jc);
assertEquals("Block result is wrong", "world", o);
}
-
+ public static void main(String[] args) throws Exception {
+ new BlockTest("debug").testBlockExecutesAll();
+ //new AssignTest("debug").testArray();
+ }
}
Modified: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/JexlTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/JexlTest.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/JexlTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/JexlTest.java Sat Jun 13 17:45:23 2009
@@ -551,14 +551,8 @@
assertExpression(jc, "foo.substring(2,4)", "cd");
assertExpression(jc, "foo.charAt(2)", new Character('c'));
-
- try {
assertExpression(jc, "foo.charAt(-2)", null);
- fail("this test should have thrown an exception" );
- }
- catch (Exception e) {
- // expected behaviour
- }
+
}
public void testEmptyDottedVariableName() throws Exception
Modified: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ParseFailuresTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ParseFailuresTest.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ParseFailuresTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ParseFailuresTest.java Sat Jun 13 17:45:23 2009
@@ -1,102 +1,102 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.jexl;
-
-import junit.framework.TestCase;
-
-import org.apache.commons.jexl.parser.ParseException;
-
-/**
- * Tests for malformed expressions and scripts.
- * ({@link ExpressionFactory} and {@link ScriptFactory} should throw
- * {@link ParseException}s).
- *
- * @since 1.1
- */
-public class ParseFailuresTest extends TestCase {
-
- /**
- * Create the test.
- *
- * @param testName name of the test
- */
- public ParseFailuresTest(String testName) {
- super(testName);
- }
-
- public void testMalformedExpression1() throws Exception {
- // this will throw a ParseException
- String badExpression = "eq";
- try {
- ExpressionFactory.createExpression(badExpression);
- fail("Parsing \"" + badExpression
- + "\" should result in a ParseException");
- } catch (ParseException pe) {
- // expected
- }
- }
-
- public void testMalformedExpression2() throws Exception {
- // this will throw a TokenMgrErr, which we rethrow as a ParseException
- String badExpression = "?";
- try {
- ExpressionFactory.createExpression(badExpression);
- fail("Parsing \"" + badExpression
- + "\" should result in a ParseException");
- } catch (ParseException pe) {
- // expected
- }
- }
-
- public void testMalformedScript1() throws Exception {
- // this will throw a TokenMgrErr, which we rethrow as a ParseException
- String badScript = "eq";
- try {
- ScriptFactory.createScript(badScript);
- fail("Parsing \"" + badScript
- + "\" should result in a ParseException");
- } catch (ParseException pe) {
- // expected
- }
- }
-
-
- public void testMalformedScript2() throws Exception {
- // this will throw a TokenMgrErr, which we rethrow as a ParseException
- String badScript = "?";
- try {
- ScriptFactory.createScript(badScript);
- fail("Parsing \"" + badScript
- + "\" should result in a ParseException");
- } catch (ParseException pe) {
- // expected
- }
- }
-
- public void testMalformedScript3() throws Exception {
- // this will throw a TokenMgrErr, which we rethrow as a ParseException
- String badScript = "foo=1;bar=2;a?b:c;";
- try {
- ScriptFactory.createScript(badScript);
- fail("Parsing \"" + badScript
- + "\" should result in a ParseException");
- } catch (ParseException pe) {
- // expected
- }
- }
-
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.jexl.parser.ParseException;
+
+/**
+ * Tests for malformed expressions and scripts.
+ * ({@link ExpressionFactory} and {@link ScriptFactory} should throw
+ * {@link ParseException}s).
+ *
+ * @since 1.1
+ */
+public class ParseFailuresTest extends TestCase {
+
+ /**
+ * Create the test.
+ *
+ * @param testName name of the test
+ */
+ public ParseFailuresTest(String testName) {
+ super(testName);
+ }
+
+ public void testMalformedExpression1() throws Exception {
+ // this will throw a ParseException
+ String badExpression = "eq";
+ try {
+ ExpressionFactory.createExpression(badExpression);
+ fail("Parsing \"" + badExpression
+ + "\" should result in a ParseException");
+ } catch (ParseException pe) {
+ // expected
+ }
+ }
+
+ public void testMalformedExpression2() throws Exception {
+ // this will throw a TokenMgrErr, which we rethrow as a ParseException
+ String badExpression = "?";
+ try {
+ ExpressionFactory.createExpression(badExpression);
+ fail("Parsing \"" + badExpression
+ + "\" should result in a ParseException");
+ } catch (ParseException pe) {
+ // expected
+ }
+ }
+
+ public void testMalformedScript1() throws Exception {
+ // this will throw a TokenMgrErr, which we rethrow as a ParseException
+ String badScript = "eq";
+ try {
+ ScriptFactory.createScript(badScript);
+ fail("Parsing \"" + badScript
+ + "\" should result in a ParseException");
+ } catch (ParseException pe) {
+ // expected
+ }
+ }
+
+
+ public void testMalformedScript2() throws Exception {
+ // this will throw a TokenMgrErr, which we rethrow as a ParseException
+ String badScript = "?";
+ try {
+ ScriptFactory.createScript(badScript);
+ fail("Parsing \"" + badScript
+ + "\" should result in a ParseException");
+ } catch (ParseException pe) {
+ // expected
+ }
+ }
+
+ public void testMalformedScript3() throws Exception {
+ // this will throw a TokenMgrErr, which we rethrow as a ParseException
+ String badScript = "foo=1;bar=2;a?b:c:d;";
+ try {
+ ScriptFactory.createScript(badScript);
+ fail("Parsing \"" + badScript
+ + "\" should result in a ParseException");
+ } catch (ParseException pe) {
+ // expected
+ }
+ }
+
+}
Modified: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptFactoryTest.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptFactoryTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptFactoryTest.java Sat Jun 13 17:45:23 2009
@@ -26,7 +26,7 @@
* @since 1.1
*/
public class ScriptFactoryTest extends TestCase {
-
+ static final String TEST1 = "src/test-scripts/test1.jexl";
/**
* Creates a new test case.
* @param name the test case name.
@@ -72,7 +72,7 @@
* @throws Exception on a parse error.
*/
public void testCreateFromFile() throws Exception {
- File testScript = new File("src/test-scripts/test1.jexl");
+ File testScript = new File(TEST1);
assertNotNull("No script created", ScriptFactory.createScript(testScript));
}
Modified: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptTest.java?rev=784442&r1=784441&r2=784442&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptTest.java Sat Jun 13 17:45:23 2009
@@ -26,6 +26,7 @@
* @since 1.1
*/
public class ScriptTest extends TestCase {
+ static final String TEST1 = "src/test-scripts/test1.jexl";
// test class for testScriptUpdatesContext
// making this class private static will cause the test to fail.
@@ -64,7 +65,7 @@
}
public void testScriptFromFile() throws Exception {
- File testScript = new File("src/test-scripts/test1.jexl");
+ File testScript = new File(TEST1);
Script s = ScriptFactory.createScript(testScript);
JexlContext jc = JexlHelper.createContext();
jc.getVars().put("out", System.out);
Added: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/introspection/MethodKeyTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/introspection/MethodKeyTest.java?rev=784442&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/introspection/MethodKeyTest.java (added)
+++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/introspection/MethodKeyTest.java Sat Jun 13 17:45:23 2009
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl.util.introspection;
+import junit.framework.TestCase;
+/**
+ * Checks the CacheMap.MethodKey implementation
+ */
+public class MethodKeyTest extends TestCase {
+ // A set of classes (most of them primitives)
+ static Class[] PRIMS = {
+ Boolean.TYPE,
+ Byte.TYPE,
+ Character.TYPE,
+ Double.TYPE,
+ Float.TYPE,
+ Integer.TYPE,
+ Long.TYPE,
+ Short.TYPE,
+ String.class,
+ java.util.Date.class
+ };
+
+ // A set of instances corresponding to the classes
+ static Object[] ARGS = {
+ new Boolean(true),
+ new Byte((byte) 1),
+ new Character('2'),
+ new Double(4d),
+ new Float(8f),
+ new Integer(16),
+ new Long(32l),
+ new Short((short)64),
+ "foobar",
+ new java.util.Date()
+ };
+
+ // A set of (pseudo) method names
+ static String[] METHODS = {
+ "plus",
+ "minus",
+ "execute",
+ "activate",
+ "perform",
+ "apply",
+ "invoke",
+ "executeAction",
+ "activateAction",
+ "performAction",
+ "applyAction",
+ "invokeAction",
+ "executeFunctor",
+ "activateFunctor",
+ "performFunctor",
+ "applyFunctor",
+ "invokeFunctor",
+ "executeIt",
+ "activateIt",
+ "performIt",
+ "applyIt",
+ "invokeIt"
+ };
+
+ /** from key to string */
+ static java.util.Map<ClassMap.MethodKey, String> byKey;
+ /** form string to key */
+ static java.util.Map<String, ClassMap.MethodKey> byString;
+ /** the list of keys we generated & test against */
+ static ClassMap.MethodKey[] keyList;
+
+ /** Creates & inserts a key into the byKey & byString map */
+ static void setUpKey(String name, Class[] parms) {
+ ClassMap.MethodKey key = new ClassMap.MethodKey(name, parms);
+ String str = key.toString();
+ byKey.put(key, str);
+ byString.put(str, key);
+
+ }
+
+ /** Generate a list of method*(prims*), method(prims*, prims*), method*(prims*,prims*,prims*) */
+ static {
+ byKey = new java.util.HashMap<ClassMap.MethodKey, String>();
+ byString = new java.util.HashMap<String, ClassMap.MethodKey>();
+ for (int m = 0; m < METHODS.length; ++m) {
+ String method = METHODS[m];
+ for (int p0 = 0; p0 < PRIMS.length; ++p0) {
+ Class[] arg0 = {PRIMS[p0]};
+ setUpKey(method, arg0);
+ for (int p1 = 0; p1 < PRIMS.length; ++p1) {
+ Class[] arg1 = {PRIMS[p0], PRIMS[p1]};
+ setUpKey(method, arg1);
+ for (int p2 = 0; p2 < PRIMS.length; ++p2) {
+ Class[] arg2 = {PRIMS[p0], PRIMS[p1], PRIMS[p2]};
+ setUpKey(method, arg2);
+ }
+ }
+ }
+ }
+ keyList = byKey.keySet().toArray(new ClassMap.MethodKey[byKey.size()]);
+ }
+
+ /** Builds a string key */
+ String makeStringKey(String method, Class... params) {
+ StringBuilder builder = new StringBuilder(method);
+ for(int p = 0; p < params.length; ++p) {
+ builder.append(ClassMap.MethodCache.primitiveClass(params[p]).getName());
+ }
+ return builder.toString();
+ }
+
+ /** Checks that a string key does exist */
+ void checkStringKey(String method, Class... params) {
+ String key = makeStringKey(method, params);
+ ClassMap.MethodKey out = byString.get(key);
+ assertTrue(out != null);
+ }
+
+ /** Builds a method key */
+ ClassMap.MethodKey makeKey(String method, Class... params) {
+ return new ClassMap.MethodKey(method, params);
+ }
+
+ /** Checks that a method key exists */
+ void checkKey(String method, Class... params) {
+ ClassMap.MethodKey key = makeKey(method, params);
+ String out = byKey.get(key);
+ assertTrue(out != null);
+ }
+
+ public void testObjectKey() throws Exception {
+ for(int k = 0; k < keyList.length; ++k) {
+ ClassMap.MethodKey ctl = keyList[k];
+ ClassMap.MethodKey key = makeKey(ctl.method, ctl.params);
+ String out = byKey.get(key);
+ assertTrue(out != null);
+ assertTrue(ctl.toString() + " != " + out, ctl.toString().equals(out));
+ }
+
+ }
+
+ public void testStringKey() throws Exception {
+ for(int k = 0; k < keyList.length; ++k) {
+ ClassMap.MethodKey ctl = keyList[k];
+ String key = makeStringKey(ctl.method, ctl.params);
+ ClassMap.MethodKey out = byString.get(key);
+ assertTrue(out != null);
+ assertTrue(ctl.toString() + " != " + key, ctl.equals(out));
+ }
+
+ }
+
+ static final int LOOP = 300;
+
+ public void testPerfKey() throws Exception {
+ for(int l = 0; l < LOOP; ++l)
+ for(int k = 0; k < keyList.length; ++k) {
+ ClassMap.MethodKey ctl = keyList[k];
+ ClassMap.MethodKey key = makeKey(ctl.method, ctl.params);
+ String out = byKey.get(key);
+ assertTrue(out != null);
+ }
+ }
+
+ public void testPerfString() throws Exception {
+ for(int l = 0; l < LOOP; ++l)
+ for(int k = 0; k < keyList.length; ++k) {
+ ClassMap.MethodKey ctl = keyList[k];
+ String key = makeStringKey(ctl.method, ctl.params);
+ ClassMap.MethodKey out = byString.get(key);
+ assertTrue(out != null);
+ }
+ }
+
+ public void testPerfKey2() throws Exception {
+ for(int l = 0; l < LOOP; ++l)
+ for (int m = 0; m < METHODS.length; ++m) {
+ String method = METHODS[m];
+ for (int p0 = 0; p0 < ARGS.length; ++p0) {
+ checkKey(method, ARGS[p0].getClass());
+ for (int p1 = 0; p1 < ARGS.length; ++p1) {
+ checkKey(method, ARGS[p0].getClass(), ARGS[p1].getClass());
+ for (int p2 = 0; p2 < ARGS.length; ++p2) {
+ checkKey(method, ARGS[p0].getClass(), ARGS[p1].getClass(), ARGS[p2].getClass());
+ }
+ }
+ }
+ }
+ }
+
+ public void testPerfStringKey2() throws Exception {
+ for(int l = 0; l < LOOP; ++l)
+ for (int m = 0; m < METHODS.length; ++m) {
+ String method = METHODS[m];
+ for (int p0 = 0; p0 < ARGS.length; ++p0) {
+ checkStringKey(method, ARGS[p0].getClass());
+ for (int p1 = 0; p1 < ARGS.length; ++p1) {
+ checkStringKey(method, ARGS[p0].getClass(), ARGS[p1].getClass());
+ for (int p2 = 0; p2 < ARGS.length; ++p2) {
+ checkStringKey(method, ARGS[p0].getClass(), ARGS[p1].getClass(), ARGS[p2].getClass());
+ }
+ }
+ }
+ }
+ }
+}