📄 ognlruntime.java
字号:
//--------------------------------------------------------------------------
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// Neither the name of the Drew Davidson nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//--------------------------------------------------------------------------
package ognl;
import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This is an abstract class with static methods that define runtime
* caching information in OGNL.
* @author Luke Blanshard (blanshlu@netscape.net)
* @author Drew Davidson (drew@ognl.org)
*/
public abstract class OgnlRuntime extends Object
{
public static final Object NotFound = new Object();
public static final List NotFoundList = new ArrayList();
public static final Map NotFoundMap = new HashMap();
public static final Object[] NoArguments = new Object[] {};
public static final Class[] NoArgumentTypes = new Class[] {};
/** Token returned by TypeConverter for no conversion possible */
public static final Object NoConversionPossible = "ognl.NoConversionPossible";
/** Not an indexed property */
public static int INDEXED_PROPERTY_NONE = 0;
/** JavaBeans IndexedProperty */
public static int INDEXED_PROPERTY_INT = 1;
/** OGNL ObjectIndexedProperty */
public static int INDEXED_PROPERTY_OBJECT = 2;
public static final String NULL_STRING = "" + null;
private static final String SET_PREFIX = "set";
private static final String GET_PREFIX = "get";
private static final String IS_PREFIX = "is";
/**
Prefix padding for hexadecimal numbers to HEX_LENGTH.
*/
private static final Map HEX_PADDING = new HashMap();
/**
Hexadecimal prefix for printing "pointers".
*/
private static final String HEX_PREFIX = "0x";
private static final int HEX_LENGTH = 8;
/**
Returned by <CODE>getUniqueDescriptor()</CODE> when the
object is <CODE>null</CODE>.
*/
private static final String NULL_OBJECT_STRING = "<null>";
private static ClassCache methodAccessors = new ClassCache();
private static ClassCache propertyAccessors = new ClassCache();
private static ClassCache elementsAccessors = new ClassCache();
private static ClassCache nullHandlers = new ClassCache();
private static ClassCache propertyDescriptorCache = new ClassCache();
private static ClassCache constructorCache = new ClassCache();
private static ClassCache staticMethodCache = new ClassCache();
private static ClassCache instanceMethodCache = new ClassCache();
private static ClassCache invokePermissionCache = new ClassCache();
private static ClassCache fieldCache = new ClassCache();
private static List superclasses = new ArrayList(); /* Used by fieldCache lookup */
private static ClassCache[] declaredMethods = new ClassCache[] { new ClassCache(), new ClassCache() }; /* set, get */
private static Map primitiveTypes = new HashMap(101);
private static ClassCache primitiveDefaults = new ClassCache();
private static Map methodParameterTypesCache = new HashMap(101);
private static Map ctorParameterTypesCache = new HashMap(101);
private static SecurityManager securityManager = System.getSecurityManager();
private static EvaluationPool evaluationPool = new EvaluationPool();
private static ObjectArrayPool objectArrayPool = new ObjectArrayPool();
/**
This is a highly specialized map for storing values keyed by Class objects.
*/
private static class ClassCache extends Object
{
/* this MUST be a power of 2 */
private static final int TABLE_SIZE = 512;
/* ...and now you see why. The table size is used as a mask for generating hashes */
private static final int TABLE_SIZE_MASK = TABLE_SIZE - 1;
private Entry[] table;
private static class Entry extends Object
{
protected Entry next;
protected Class key;
protected Object value;
public Entry(Class key, Object value)
{
super();
this.key = key;
this.value = value;
}
}
public ClassCache()
{
super();
this.table = new Entry[TABLE_SIZE];
}
public final Object get(Class key)
{
Object result = null;
int i = key.hashCode() & TABLE_SIZE_MASK;
for (Entry entry = table[i]; entry != null; entry = entry.next) {
if (entry.key == key) {
result = entry.value;
break;
}
}
return result;
}
public final Object put(Class key, Object value)
{
Object result = null;
int i = key.hashCode() & TABLE_SIZE_MASK;
Entry entry = table[i];
if (entry == null) {
table[i] = new Entry(key, value);
} else {
if (entry.key == key) {
result = entry.value;
entry.value = value;
} else {
while (true) {
if (entry.key == key) {
/* replace value */
result = entry.value;
entry.value = value;
break;
} else {
if (entry.next == null) {
/* add value */
entry.next = new Entry(key, value);
break;
}
}
entry = entry.next;
}
}
}
return result;
}
}
static
{
PropertyAccessor p = new ArrayPropertyAccessor();
setPropertyAccessor( Object.class, new ObjectPropertyAccessor() );
setPropertyAccessor( byte[].class, p );
setPropertyAccessor( short[].class, p );
setPropertyAccessor( char[].class, p );
setPropertyAccessor( int[].class, p );
setPropertyAccessor( long[].class, p );
setPropertyAccessor( float[].class, p );
setPropertyAccessor( double[].class, p );
setPropertyAccessor( Object[].class, p );
setPropertyAccessor( List.class, new ListPropertyAccessor() );
setPropertyAccessor( Map.class, new MapPropertyAccessor() );
setPropertyAccessor( Set.class, new SetPropertyAccessor() );
setPropertyAccessor( Iterator.class, new IteratorPropertyAccessor() );
setPropertyAccessor( Enumeration.class, new EnumerationPropertyAccessor() );
ElementsAccessor e = new ArrayElementsAccessor();
setElementsAccessor( Object.class, new ObjectElementsAccessor() );
setElementsAccessor( byte[].class, e );
setElementsAccessor( short[].class, e );
setElementsAccessor( char[].class, e );
setElementsAccessor( int[].class, e );
setElementsAccessor( long[].class, e );
setElementsAccessor( float[].class, e );
setElementsAccessor( double[].class, e );
setElementsAccessor( Object[].class, e );
setElementsAccessor( Collection.class, new CollectionElementsAccessor() );
setElementsAccessor( Map.class, new MapElementsAccessor() );
setElementsAccessor( Iterator.class, new IteratorElementsAccessor() );
setElementsAccessor( Enumeration.class, new EnumerationElementsAccessor() );
setElementsAccessor( Number.class, new NumberElementsAccessor() );
NullHandler nh = new ObjectNullHandler();
setNullHandler( Object.class, nh);
setNullHandler( byte[].class, nh );
setNullHandler( short[].class, nh );
setNullHandler( char[].class, nh );
setNullHandler( int[].class, nh );
setNullHandler( long[].class, nh );
setNullHandler( float[].class, nh );
setNullHandler( double[].class, nh );
setNullHandler( Object[].class, nh );
MethodAccessor ma = new ObjectMethodAccessor();
setMethodAccessor( Object.class, ma );
setMethodAccessor( byte[].class, ma );
setMethodAccessor( short[].class, ma );
setMethodAccessor( char[].class, ma );
setMethodAccessor( int[].class, ma );
setMethodAccessor( long[].class, ma );
setMethodAccessor( float[].class, ma );
setMethodAccessor( double[].class, ma );
setMethodAccessor( Object[].class, ma );
primitiveTypes.put("boolean", Boolean.TYPE );
primitiveTypes.put("byte", Byte.TYPE );
primitiveTypes.put("short", Short.TYPE );
primitiveTypes.put("char", Character.TYPE );
primitiveTypes.put("int", Integer.TYPE );
primitiveTypes.put("long", Long.TYPE );
primitiveTypes.put("float", Float.TYPE );
primitiveTypes.put("double", Double.TYPE );
primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
primitiveDefaults.put(Byte.TYPE, new Byte((byte)0));
primitiveDefaults.put(Short.TYPE, new Short((short)0));
primitiveDefaults.put(Character.TYPE, new Character((char)0));
primitiveDefaults.put(Integer.TYPE, new Integer(0));
primitiveDefaults.put(Long.TYPE, new Long(0L));
primitiveDefaults.put(Float.TYPE, new Float(0.0f));
primitiveDefaults.put(Double.TYPE, new Double(0.0));
primitiveDefaults.put(BigInteger.class, new BigInteger("0"));
primitiveDefaults.put(BigDecimal.class, new BigDecimal(0.0));
}
/**
Gets the "target" class of an object for looking up accessors that
are registered on the target. If the object is a Class object this
will return the Class itself, else it will return object's getClass()
result.
*/
public static Class getTargetClass(Object o)
{
return (o == null) ? null : ((o instanceof Class) ? (Class)o : o.getClass());
}
/**
Returns the base name (the class name without the
package name prepended) of the object given.
*/
public static String getBaseName(Object o)
{
return (o == null) ? null : getClassBaseName(o.getClass());
}
/**
Returns the base name (the class name without the
package name prepended) of the class given.
*/
public static String getClassBaseName(Class c)
{
String s = c.getName();
return s.substring(s.lastIndexOf('.') + 1);
}
public static String getClassName(Object o, boolean fullyQualified)
{
if (!(o instanceof Class)) {
o = o.getClass();
}
return getClassName((Class)o, fullyQualified);
}
public static String getClassName(Class c, boolean fullyQualified)
{
return fullyQualified ? c.getName() : getClassBaseName(c);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -