Author: markt Date: Wed Jul 3 18:56:14 2013 New Revision: 1499513 URL: http://svn.apache.org/r1499513 Log: EL 3.0 Implement new class Refactor common code to Util class
Added: tomcat/trunk/java/javax/el/StaticFieldELResolver.java (with props) Modified: tomcat/trunk/java/javax/el/BeanELResolver.java tomcat/trunk/java/javax/el/LocalStrings.properties tomcat/trunk/java/javax/el/Util.java Modified: tomcat/trunk/java/javax/el/BeanELResolver.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/el/BeanELResolver.java?rev=1499513&r1=1499512&r2=1499513&view=diff ============================================================================== --- tomcat/trunk/java/javax/el/BeanELResolver.java (original) +++ tomcat/trunk/java/javax/el/BeanELResolver.java Wed Jul 3 18:56:14 2013 @@ -22,10 +22,8 @@ import java.beans.FeatureDescriptor; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; -import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -168,93 +166,26 @@ public class BeanELResolver extends ELRe return null; } - ExpressionFactory factory = ExpressionFactory.newInstance(); + ExpressionFactory factory = Util.getExpressionFactory(); String methodName = (String) factory.coerceToType(method, String.class); // Find the matching method - Method matchingMethod = null; - Class<?> clazz = base.getClass(); - if (paramTypes != null) { - try { - matchingMethod = - getMethod(clazz, clazz.getMethod(methodName, paramTypes)); - } catch (NoSuchMethodException e) { - throw new MethodNotFoundException(e); - } - } else { - int paramCount = 0; - if (params != null) { - paramCount = params.length; - } - Method[] methods = clazz.getMethods(); - for (Method m : methods) { - if (methodName.equals(m.getName())) { - if (m.getParameterTypes().length == paramCount) { - // Same number of parameters - use the first match - matchingMethod = getMethod(clazz, m); - break; - } - if (m.isVarArgs() - && paramCount > m.getParameterTypes().length - 2) { - matchingMethod = getMethod(clazz, m); - } - } - } - if (matchingMethod == null) { - throw new MethodNotFoundException( - "Unable to find method [" + methodName + "] with [" - + paramCount + "] parameters"); - } - } + Method matchingMethod = + Util.findMethod(base, methodName, paramTypes, params); + + Object[] parameters = Util.buildParameters( + matchingMethod.getParameterTypes(), matchingMethod.isVarArgs(), + params); - Class<?>[] parameterTypes = matchingMethod.getParameterTypes(); - Object[] parameters = null; - if (parameterTypes.length > 0) { - parameters = new Object[parameterTypes.length]; - @SuppressWarnings("null") // params.length >= parameterTypes.length - int paramCount = params.length; - if (matchingMethod.isVarArgs()) { - int varArgIndex = parameterTypes.length - 1; - // First argCount-1 parameters are standard - for (int i = 0; (i < varArgIndex); i++) { - parameters[i] = factory.coerceToType(params[i], - parameterTypes[i]); - } - // Last parameter is the varargs - Class<?> varArgClass = - parameterTypes[varArgIndex].getComponentType(); - final Object varargs = Array.newInstance( - varArgClass, - (paramCount - varArgIndex)); - for (int i = (varArgIndex); i < paramCount; i++) { - Array.set(varargs, i - varArgIndex, - factory.coerceToType(params[i], varArgClass)); - } - parameters[varArgIndex] = varargs; - } else { - parameters = new Object[parameterTypes.length]; - for (int i = 0; i < parameterTypes.length; i++) { - parameters[i] = factory.coerceToType(params[i], - parameterTypes[i]); - } - } - } Object result = null; try { result = matchingMethod.invoke(base, parameters); - } catch (IllegalArgumentException e) { - throw new ELException(e); - } catch (IllegalAccessException e) { + } catch (IllegalArgumentException | IllegalAccessException e) { throw new ELException(e); } catch (InvocationTargetException e) { Throwable cause = e.getCause(); - if (cause instanceof ThreadDeath) { - throw (ThreadDeath) cause; - } - if (cause instanceof VirtualMachineError) { - throw (VirtualMachineError) cause; - } + Util.handleThrowable(cause); throw new ELException(cause); } @@ -378,7 +309,7 @@ public class BeanELResolver extends ELRe public boolean isReadOnly() { return this.write == null - && (null == (this.write = getMethod(this.owner, descriptor.getWriteMethod()))); + && (null == (this.write = Util.getMethod(this.owner, descriptor.getWriteMethod()))); } public Method getWriteMethod() { @@ -391,7 +322,7 @@ public class BeanELResolver extends ELRe private Method write(ELContext ctx) { if (this.write == null) { - this.write = getMethod(this.owner, descriptor.getWriteMethod()); + this.write = Util.getMethod(this.owner, descriptor.getWriteMethod()); if (this.write == null) { throw new PropertyNotFoundException(Util.message(ctx, "propertyNotWritable", new Object[] { @@ -403,7 +334,7 @@ public class BeanELResolver extends ELRe private Method read(ELContext ctx) { if (this.read == null) { - this.read = getMethod(this.owner, descriptor.getReadMethod()); + this.read = Util.getMethod(this.owner, descriptor.getReadMethod()); if (this.read == null) { throw new PropertyNotFoundException(Util.message(ctx, "propertyNotReadable", new Object[] { @@ -428,38 +359,6 @@ public class BeanELResolver extends ELRe return props.get(ctx, prop); } - private static final Method getMethod(Class<?> type, Method m) { - if (m == null || Modifier.isPublic(type.getModifiers())) { - return m; - } - Class<?>[] inf = type.getInterfaces(); - Method mp = null; - for (int i = 0; i < inf.length; i++) { - try { - mp = inf[i].getMethod(m.getName(), m.getParameterTypes()); - mp = getMethod(mp.getDeclaringClass(), mp); - if (mp != null) { - return mp; - } - } catch (NoSuchMethodException e) { - // Ignore - } - } - Class<?> sup = type.getSuperclass(); - if (sup != null) { - try { - mp = sup.getMethod(m.getName(), m.getParameterTypes()); - mp = getMethod(mp.getDeclaringClass(), mp); - if (mp != null) { - return mp; - } - } catch (NoSuchMethodException e) { - // Ignore - } - } - return null; - } - private static final class ConcurrentCache<K,V> { private final int size; Modified: tomcat/trunk/java/javax/el/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/el/LocalStrings.properties?rev=1499513&r1=1499512&r2=1499513&view=diff ============================================================================== --- tomcat/trunk/java/javax/el/LocalStrings.properties (original) +++ tomcat/trunk/java/javax/el/LocalStrings.properties Wed Jul 3 18:56:14 2013 @@ -30,4 +30,8 @@ importHandler.invalidClass=The class [{0 importHandler.invalidClassName=Name of class to import [{0}] must include a package importHandler.invalidClassNameForStatic=The class [{0}] specified for static import [{1}] is not valid importHandler.invalidStaticName=Name of static method or field to import [{0}] must include a class -importHandler.staticNotFound=The static import [{0}] could not be found in class [{1}] for import [{2}] \ No newline at end of file +importHandler.staticNotFound=The static import [{0}] could not be found in class [{1}] for import [{2}] + +staticFieldELResolver.methodNotFound=No matching public static method named [{0}] found on class [{1}] +staticFieldELResolver.notFound=No public static field named [{0}] was found on class [{1}] +staticFieldELResolver.notWriteable=Writing to static fields (in this case field [{0}] on class [{1}]) is not permitted \ No newline at end of file Added: tomcat/trunk/java/javax/el/StaticFieldELResolver.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/el/StaticFieldELResolver.java?rev=1499513&view=auto ============================================================================== --- tomcat/trunk/java/javax/el/StaticFieldELResolver.java (added) +++ tomcat/trunk/java/javax/el/StaticFieldELResolver.java Wed Jul 3 18:56:14 2013 @@ -0,0 +1,231 @@ +/* + * 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 javax.el; + +import java.beans.FeatureDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Iterator; + +/** + * @since EL 3.0 + */ +public class StaticFieldELResolver { + + public Object getValue(ELContext context, Object base, Object property) { + + if (context == null) { + throw new NullPointerException(); + } + + if (base instanceof ELClass && property instanceof String) { + context.setPropertyResolved(true); + + Class<?> clazz = ((ELClass) base).getKlass(); + String name = (String) property; + Exception exception = null; + try { + Field field = clazz.getField(name); + int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) && + Modifier.isPublic(modifiers)) { + return field.get(null); + } + } catch (IllegalArgumentException | IllegalAccessException + | NoSuchFieldException | SecurityException e) { + exception = e; + } + String msg = Util.message(context, "staticFieldELResolver.notFound", + name, clazz.getName()); + if (exception == null) { + throw new PropertyNotFoundException(msg); + } else { + throw new PropertyNotFoundException(msg, exception); + } + } + return null; + } + + + /** + * + * @param context + * @param base + * @param property + * @param value + */ + public void setValue(ELContext context, Object base, Object property, + Object value) { + + if (context == null) { + throw new NullPointerException(); + } + + if (base instanceof ELClass && property instanceof String) { + Class<?> clazz = ((ELClass) base).getKlass(); + String name = (String) property; + + throw new PropertyNotWritableException(Util.message(context, + "staticFieldELResolver.notWriteable", name, + clazz.getName())); + } + } + + + public Object invoke(ELContext context, Object base, Object method, + Class<?>[] paramTypes, Object[] params) { + + if (context == null) { + throw new NullPointerException(); + } + + if (base instanceof ELClass && method instanceof String) { + context.setPropertyResolved(true); + + Class<?> clazz = ((ELClass) base).getKlass(); + String methodName = (String) method; + + if ("<init>".equals(methodName)) { + Constructor<?> match = + Util.findConstructor(base, paramTypes, params); + + int modifiers = match.getModifiers(); + if (!Modifier.isStatic(modifiers)) { + throw new MethodNotFoundException(Util.message(context, + "staticFieldELResolver.methodNotFound", methodName, + clazz.getName())); + } + + Object[] parameters = Util.buildParameters( + match.getParameterTypes(), match.isVarArgs(), params); + + Object result = null; + + try { + result = match.newInstance(parameters); + } catch (IllegalArgumentException | IllegalAccessException | + InstantiationException e) { + throw new ELException(e); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + Util.handleThrowable(cause); + throw new ELException(cause); + } + return result; + + } else { + Method match = + Util.findMethod(base, methodName, paramTypes, params); + + int modifiers = match.getModifiers(); + if (!Modifier.isStatic(modifiers)) { + throw new MethodNotFoundException(Util.message(context, + "staticFieldELResolver.methodNotFound", methodName, + clazz.getName())); + } + + Object[] parameters = Util.buildParameters( + match.getParameterTypes(), match.isVarArgs(), params); + + Object result = null; + try { + result = match.invoke(base, parameters); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new ELException(e); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + Util.handleThrowable(cause); + throw new ELException(cause); + } + return result; + } + } + return null; + } + + public Class<?> getType(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + if (base instanceof ELClass && property instanceof String) { + context.setPropertyResolved(true); + + Class<?> clazz = ((ELClass) base).getKlass(); + String name = (String) property; + Exception exception = null; + try { + Field field = clazz.getField(name); + int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) && + Modifier.isPublic(modifiers)) { + return field.getType(); + } + } catch (IllegalArgumentException | NoSuchFieldException | + SecurityException e) { + exception = e; + } + String msg = Util.message(context, "staticFieldELResolver.notFound", + name, clazz.getName()); + if (exception == null) { + throw new PropertyNotFoundException(msg); + } else { + throw new PropertyNotFoundException(msg, exception); + } + } + return null; + } + + + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + if (base instanceof ELClass && property instanceof String) { + context.setPropertyResolved(true); + + return true; + } + return false; + } + + + /** + * Always returns <code>null</code>. + * + * @param context + * @param base + */ + public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, + Object base) { + return null; + } + + /** + * Always returns <code>String.class</code>. + * + * @param context + * @param base + */ + public Class<?> getCommonPropertyType(ELContext context, Object base) { + return String.class; + } +} Propchange: tomcat/trunk/java/javax/el/StaticFieldELResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/javax/el/Util.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/el/Util.java?rev=1499513&r1=1499512&r2=1499513&view=diff ============================================================================== --- tomcat/trunk/java/javax/el/Util.java (original) +++ tomcat/trunk/java/javax/el/Util.java Wed Jul 3 18:56:14 2013 @@ -17,6 +17,10 @@ package javax.el; import java.lang.ref.WeakReference; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; @@ -179,4 +183,178 @@ class Util { ref = new WeakReference<>(factory); } } + + + static Method findMethod(Object base, String methodName, + Class<?>[] paramTypes, Object[] params) { + + Method matchingMethod = null; + + Class<?> clazz = base.getClass(); + if (paramTypes != null) { + try { + matchingMethod = + getMethod(clazz, clazz.getMethod(methodName, paramTypes)); + } catch (NoSuchMethodException e) { + throw new MethodNotFoundException(e); + } + } else { + int paramCount = 0; + if (params != null) { + paramCount = params.length; + } + Method[] methods = clazz.getMethods(); + for (Method m : methods) { + if (methodName.equals(m.getName())) { + if (m.getParameterTypes().length == paramCount) { + // Same number of parameters - use the first match + matchingMethod = getMethod(clazz, m); + break; + } + if (m.isVarArgs() + && paramCount > m.getParameterTypes().length - 2) { + matchingMethod = getMethod(clazz, m); + } + } + } + if (matchingMethod == null) { + throw new MethodNotFoundException( + "Unable to find method [" + methodName + "] with [" + + paramCount + "] parameters"); + } + } + + return matchingMethod; + } + + + static Method getMethod(Class<?> type, Method m) { + if (m == null || Modifier.isPublic(type.getModifiers())) { + return m; + } + Class<?>[] inf = type.getInterfaces(); + Method mp = null; + for (int i = 0; i < inf.length; i++) { + try { + mp = inf[i].getMethod(m.getName(), m.getParameterTypes()); + mp = getMethod(mp.getDeclaringClass(), mp); + if (mp != null) { + return mp; + } + } catch (NoSuchMethodException e) { + // Ignore + } + } + Class<?> sup = type.getSuperclass(); + if (sup != null) { + try { + mp = sup.getMethod(m.getName(), m.getParameterTypes()); + mp = getMethod(mp.getDeclaringClass(), mp); + if (mp != null) { + return mp; + } + } catch (NoSuchMethodException e) { + // Ignore + } + } + return null; + } + + + static Constructor<?> findConstructor(Object base, Class<?>[] paramTypes, + Object[] params) { + + Constructor<?> match = null; + + Class<?> clazz = base.getClass(); + if (paramTypes != null) { + try { + match = getConstructor(clazz, clazz.getConstructor(paramTypes)); + } catch (NoSuchMethodException e) { + throw new MethodNotFoundException(e); + } + } else { + int paramCount = 0; + if (params != null) { + paramCount = params.length; + } + Constructor<?>[] constructors = clazz.getConstructors(); + for (Constructor<?> c : constructors) { + if (c.getParameterTypes().length == paramCount) { + // Same number of parameters - use the first match + match = getConstructor(clazz, c); + break; + } + if (c.isVarArgs() + && paramCount > c.getParameterTypes().length - 2) { + match = getConstructor(clazz, c); + } + } + if (match == null) { + throw new MethodNotFoundException( + "Unable to find constructor with [" + paramCount + + "] parameters"); + } + } + + return match; + } + + + static Constructor<?> getConstructor(Class<?> type, Constructor<?> c) { + if (c == null || Modifier.isPublic(type.getModifiers())) { + return c; + } + Constructor<?> cp = null; + Class<?> sup = type.getSuperclass(); + if (sup != null) { + try { + cp = sup.getConstructor(c.getParameterTypes()); + cp = getConstructor(cp.getDeclaringClass(), cp); + if (cp != null) { + return cp; + } + } catch (NoSuchMethodException e) { + // Ignore + } + } + return null; + } + + + static Object[] buildParameters(Class<?>[] parameterTypes, + boolean isVarArgs,Object[] params) { + ExpressionFactory factory = getExpressionFactory(); + Object[] parameters = null; + if (parameterTypes.length > 0) { + parameters = new Object[parameterTypes.length]; + int paramCount = params.length; + if (isVarArgs) { + int varArgIndex = parameterTypes.length - 1; + // First argCount-1 parameters are standard + for (int i = 0; (i < varArgIndex); i++) { + parameters[i] = factory.coerceToType(params[i], + parameterTypes[i]); + } + // Last parameter is the varargs + Class<?> varArgClass = + parameterTypes[varArgIndex].getComponentType(); + final Object varargs = Array.newInstance( + varArgClass, + (paramCount - varArgIndex)); + for (int i = (varArgIndex); i < paramCount; i++) { + Array.set(varargs, i - varArgIndex, + factory.coerceToType(params[i], varArgClass)); + } + parameters[varArgIndex] = varargs; + } else { + parameters = new Object[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + parameters[i] = factory.coerceToType(params[i], + parameterTypes[i]); + } + } + } + return parameters; + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org