OgnlContext 源码
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
package ognl; import ognl.enhance.LocalReference; import java.util.*; /**
* This class defines the execution context for an OGNL expression
*
* @author Luke Blanshard (blanshlu@netscape.net)
* @author Drew Davidson (drew@ognl.org)
*/
public class OgnlContext extends Object implements Map
{ public static final String CONTEXT_CONTEXT_KEY = "context";
public static final String ROOT_CONTEXT_KEY = "root";
public static final String THIS_CONTEXT_KEY = "this";
public static final String TRACE_EVALUATIONS_CONTEXT_KEY = "_traceEvaluations";
public static final String LAST_EVALUATION_CONTEXT_KEY = "_lastEvaluation";
public static final String KEEP_LAST_EVALUATION_CONTEXT_KEY = "_keepLastEvaluation";
public static final String CLASS_RESOLVER_CONTEXT_KEY = "_classResolver";
public static final String TYPE_CONVERTER_CONTEXT_KEY = "_typeConverter";
public static final String MEMBER_ACCESS_CONTEXT_KEY = "_memberAccess"; private static final String PROPERTY_KEY_PREFIX = "ognl";
private static boolean DEFAULT_TRACE_EVALUATIONS = false;
private static boolean DEFAULT_KEEP_LAST_EVALUATION = false; public static final ClassResolver DEFAULT_CLASS_RESOLVER = new DefaultClassResolver();
public static final TypeConverter DEFAULT_TYPE_CONVERTER = new DefaultTypeConverter();
public static final MemberAccess DEFAULT_MEMBER_ACCESS = new DefaultMemberAccess(false); private static Map RESERVED_KEYS = new HashMap(11); private Object _root;
private Object _currentObject;
private Node _currentNode;
private boolean _traceEvaluations = DEFAULT_TRACE_EVALUATIONS;
private Evaluation _rootEvaluation;
private Evaluation _currentEvaluation;
private Evaluation _lastEvaluation;
private boolean _keepLastEvaluation = DEFAULT_KEEP_LAST_EVALUATION; private Map _values = new HashMap(23); private ClassResolver _classResolver = DEFAULT_CLASS_RESOLVER;
private TypeConverter _typeConverter = DEFAULT_TYPE_CONVERTER;
private MemberAccess _memberAccess = DEFAULT_MEMBER_ACCESS; static {
String s; RESERVED_KEYS.put(CONTEXT_CONTEXT_KEY, null);
RESERVED_KEYS.put(ROOT_CONTEXT_KEY, null);
RESERVED_KEYS.put(THIS_CONTEXT_KEY, null);
RESERVED_KEYS.put(TRACE_EVALUATIONS_CONTEXT_KEY, null);
RESERVED_KEYS.put(LAST_EVALUATION_CONTEXT_KEY, null);
RESERVED_KEYS.put(KEEP_LAST_EVALUATION_CONTEXT_KEY, null);
RESERVED_KEYS.put(CLASS_RESOLVER_CONTEXT_KEY, null);
RESERVED_KEYS.put(TYPE_CONVERTER_CONTEXT_KEY, null);
RESERVED_KEYS.put(MEMBER_ACCESS_CONTEXT_KEY, null); try {
if ((s = System.getProperty(PROPERTY_KEY_PREFIX + ".traceEvaluations")) != null) {
DEFAULT_TRACE_EVALUATIONS = Boolean.valueOf(s.trim()).booleanValue();
}
if ((s = System.getProperty(PROPERTY_KEY_PREFIX + ".keepLastEvaluation")) != null) {
DEFAULT_KEEP_LAST_EVALUATION = Boolean.valueOf(s.trim()).booleanValue();
}
} catch (SecurityException ex) {
// restricted access environment, just keep defaults
}
} private List _typeStack = new ArrayList();
private List _accessorStack = new ArrayList(); private int _localReferenceCounter = 0;
private Map _localReferenceMap = null; /**
* Constructs a new OgnlContext with the default class resolver, type converter and member
* access.
*/
public OgnlContext()
{
} /**
* Constructs a new OgnlContext with the given class resolver, type converter and member access.
* If any of these parameters is null the default will be used.
*/
public OgnlContext(ClassResolver classResolver, TypeConverter typeConverter, MemberAccess memberAccess)
{
this();
if (classResolver != null) {
this._classResolver = classResolver;
}
if (typeConverter != null) {
this._typeConverter = typeConverter;
}
if (memberAccess != null) {
this._memberAccess = memberAccess;
}
} public OgnlContext(Map values)
{
super();
this._values = values;
} public OgnlContext(ClassResolver classResolver, TypeConverter typeConverter, MemberAccess memberAccess, Map values)
{
this(classResolver, typeConverter, memberAccess);
this._values = values;
} public void setValues(Map value)
{
for(Iterator it = value.keySet().iterator(); it.hasNext();) {
Object k = it.next(); _values.put(k, value.get(k));
}
} public Map getValues()
{
return _values;
} public void setClassResolver(ClassResolver value)
{
if (value == null) { throw new IllegalArgumentException("cannot set ClassResolver to null"); }
_classResolver = value;
} public ClassResolver getClassResolver()
{
return _classResolver;
} public void setTypeConverter(TypeConverter value)
{
if (value == null) { throw new IllegalArgumentException("cannot set TypeConverter to null"); }
_typeConverter = value;
} public TypeConverter getTypeConverter()
{
return _typeConverter;
} public void setMemberAccess(MemberAccess value)
{
if (value == null) { throw new IllegalArgumentException("cannot set MemberAccess to null"); }
_memberAccess = value;
} public MemberAccess getMemberAccess()
{
return _memberAccess;
} public void setRoot(Object value)
{
_root = value;
_accessorStack.clear();
_typeStack.clear();
_currentObject = value; if (_currentObject != null)
{
setCurrentType(_currentObject.getClass());
}
} public Object getRoot()
{
return _root;
} public boolean getTraceEvaluations()
{
return _traceEvaluations;
} public void setTraceEvaluations(boolean value)
{
_traceEvaluations = value;
} public Evaluation getLastEvaluation()
{
return _lastEvaluation;
} public void setLastEvaluation(Evaluation value)
{
_lastEvaluation = value;
} /**
* This method can be called when the last evaluation has been used and can be returned for
* reuse in the free pool maintained by the runtime. This is not a necessary step, but is useful
* for keeping memory usage down. This will recycle the last evaluation and then set the last
* evaluation to null.
*/
public void recycleLastEvaluation()
{
OgnlRuntime.getEvaluationPool().recycleAll(_lastEvaluation);
_lastEvaluation = null;
} /**
* Returns true if the last evaluation that was done on this context is retained and available
* through <code>getLastEvaluation()</code>. The default is true.
*/
public boolean getKeepLastEvaluation()
{
return _keepLastEvaluation;
} /**
* Sets whether the last evaluation that was done on this context is retained and available
* through <code>getLastEvaluation()</code>. The default is true.
*/
public void setKeepLastEvaluation(boolean value)
{
_keepLastEvaluation = value;
} public void setCurrentObject(Object value)
{
_currentObject = value;
} public Object getCurrentObject()
{
return _currentObject;
} public void setCurrentAccessor(Class type)
{
_accessorStack.add(type);
} public Class getCurrentAccessor()
{
if (_accessorStack.isEmpty())
return null; return (Class) _accessorStack.get(_accessorStack.size() - 1);
} public Class getPreviousAccessor()
{
if (_accessorStack.isEmpty())
return null; if (_accessorStack.size() > 1)
return (Class) _accessorStack.get(_accessorStack.size() - 2);
else
return null;
} public Class getFirstAccessor()
{
if (_accessorStack.isEmpty())
return null; return (Class)_accessorStack.get(0);
} /**
* Gets the current class type being evaluated on the stack, as set by {@link #setCurrentType(Class)}.
*
* @return The current object type, may be null.
*/
public Class getCurrentType()
{
if (_typeStack.isEmpty())
return null; return (Class) _typeStack.get(_typeStack.size() - 1);
} public void setCurrentType(Class type)
{
_typeStack.add(type);
} /**
* Represents the last known object type on the evaluation stack, will be the value of
* the last known {@link #getCurrentType()}.
*
* @return The previous type of object on the stack, may be null.
*/
public Class getPreviousType()
{
if (_typeStack.isEmpty())
return null; if (_typeStack.size() > 1)
return (Class)_typeStack.get(_typeStack.size() - 2);
else
return null;
} public void setPreviousType(Class type)
{
if (_typeStack.isEmpty() || _typeStack.size() < 2)
return; _typeStack.set(_typeStack.size() - 2, type);
} public Class getFirstType()
{
if (_typeStack.isEmpty())
return null; return (Class)_typeStack.get(0);
} public void setCurrentNode(Node value)
{
_currentNode = value;
} public Node getCurrentNode()
{
return _currentNode;
} /**
* Gets the current Evaluation from the top of the stack. This is the Evaluation that is in
* process of evaluating.
*/
public Evaluation getCurrentEvaluation()
{
return _currentEvaluation;
} public void setCurrentEvaluation(Evaluation value)
{
_currentEvaluation = value;
} /**
* Gets the root of the evaluation stack. This Evaluation contains the node representing the
* root expression and the source is the root source object.
*/
public Evaluation getRootEvaluation()
{
return _rootEvaluation;
} public void setRootEvaluation(Evaluation value)
{
_rootEvaluation = value;
} /**
* Returns the Evaluation at the relative index given. This should be zero or a negative number
* as a relative reference back up the evaluation stack. Therefore getEvaluation(0) returns the
* current Evaluation.
*/
public Evaluation getEvaluation(int relativeIndex)
{
Evaluation result = null; if (relativeIndex <= 0) {
result = _currentEvaluation;
while((++relativeIndex < 0) && (result != null)) {
result = result.getParent();
}
}
return result;
} /**
* Pushes a new Evaluation onto the stack. This is done before a node evaluates. When evaluation
* is complete it should be popped from the stack via <code>popEvaluation()</code>.
*/
public void pushEvaluation(Evaluation value)
{
if (_currentEvaluation != null) {
_currentEvaluation.addChild(value);
} else {
setRootEvaluation(value);
}
setCurrentEvaluation(value);
} /**
* Pops the current Evaluation off of the top of the stack. This is done after a node has
* completed its evaluation.
*/
public Evaluation popEvaluation()
{
Evaluation result; result = _currentEvaluation;
setCurrentEvaluation(result.getParent());
if (_currentEvaluation == null) {
setLastEvaluation(getKeepLastEvaluation() ? result : null);
setRootEvaluation(null);
setCurrentNode(null);
}
return result;
} public int incrementLocalReferenceCounter()
{
return ++_localReferenceCounter;
} public void addLocalReference(String key, LocalReference reference)
{
if (_localReferenceMap == null)
{
_localReferenceMap = new LinkedHashMap();
} _localReferenceMap.put(key, reference);
} public Map getLocalReferences()
{
return _localReferenceMap;
} /* ================= Map interface ================= */
public int size()
{
return _values.size();
} public boolean isEmpty()
{
return _values.isEmpty();
} public boolean containsKey(Object key)
{
return _values.containsKey(key);
} public boolean containsValue(Object value)
{
return _values.containsValue(value);
} public Object get(Object key)
{
Object result; if (RESERVED_KEYS.containsKey(key)) {
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
} else {
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
} else {
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
result = this;
} else {
if (key.equals(OgnlContext.TRACE_EVALUATIONS_CONTEXT_KEY)) {
result = getTraceEvaluations() ? Boolean.TRUE : Boolean.FALSE;
} else {
if (key.equals(OgnlContext.LAST_EVALUATION_CONTEXT_KEY)) {
result = getLastEvaluation();
} else {
if (key.equals(OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY)) {
result = getKeepLastEvaluation() ? Boolean.TRUE : Boolean.FALSE;
} else {
if (key.equals(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY)) {
result = getClassResolver();
} else {
if (key.equals(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY)) {
result = getTypeConverter();
} else {
if (key.equals(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY)) {
result = getMemberAccess();
} else {
throw new IllegalArgumentException("unknown reserved key '" + key + "'");
}
}
}
}
}
}
}
}
}
} else {
result = _values.get(key);
}
return result;
} public Object put(Object key, Object value)
{
Object result; if (RESERVED_KEYS.containsKey(key)) {
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
setCurrentObject(value);
} else {
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
setRoot(value);
} else {
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
throw new IllegalArgumentException("can't change " + OgnlContext.CONTEXT_CONTEXT_KEY
+ " in context");
} else {
if (key.equals(OgnlContext.TRACE_EVALUATIONS_CONTEXT_KEY)) {
result = getTraceEvaluations() ? Boolean.TRUE : Boolean.FALSE;
setTraceEvaluations(OgnlOps.booleanValue(value));
} else {
if (key.equals(OgnlContext.LAST_EVALUATION_CONTEXT_KEY)) {
result = getLastEvaluation();
_lastEvaluation = (Evaluation) value;
} else {
if (key.equals(OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY)) {
result = getKeepLastEvaluation() ? Boolean.TRUE : Boolean.FALSE;
setKeepLastEvaluation(OgnlOps.booleanValue(value));
} else {
if (key.equals(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY)) {
result = getClassResolver();
setClassResolver((ClassResolver) value);
} else {
if (key.equals(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY)) {
result = getTypeConverter();
setTypeConverter((TypeConverter) value);
} else {
if (key.equals(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY)) {
result = getMemberAccess();
setMemberAccess((MemberAccess) value);
} else {
throw new IllegalArgumentException("unknown reserved key '" + key + "'");
}
}
}
}
}
}
}
}
}
} else {
result = _values.put(key, value);
} return result;
} public Object remove(Object key)
{
Object result; if (RESERVED_KEYS.containsKey(key)) {
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
setCurrentObject(null);
} else {
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
setRoot(null);
} else {
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
throw new IllegalArgumentException("can't remove " + OgnlContext.CONTEXT_CONTEXT_KEY
+ " from context");
} else {
if (key.equals(OgnlContext.TRACE_EVALUATIONS_CONTEXT_KEY)) {
throw new IllegalArgumentException("can't remove "
+ OgnlContext.TRACE_EVALUATIONS_CONTEXT_KEY + " from context");
} else {
if (key.equals(OgnlContext.LAST_EVALUATION_CONTEXT_KEY)) {
result = _lastEvaluation;
setLastEvaluation(null);
} else {
if (key.equals(OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY)) {
throw new IllegalArgumentException("can't remove "
+ OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY + " from context");
} else {
if (key.equals(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY)) {
result = getClassResolver();
setClassResolver(null);
} else {
if (key.equals(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY)) {
result = getTypeConverter();
setTypeConverter(null);
} else {
if (key.equals(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY)) {
result = getMemberAccess();
setMemberAccess(null);
} else {
throw new IllegalArgumentException("unknown reserved key '" + key + "'");
}
}
}
}
}
}
}
}
}
} else {
result = _values.remove(key);
}
return result;
} public void putAll(Map t)
{
for(Iterator it = t.keySet().iterator(); it.hasNext();) {
Object k = it.next(); put(k, t.get(k));
}
} public void clear()
{
_values.clear();
_typeStack.clear();
_accessorStack.clear(); _localReferenceCounter = 0;
if (_localReferenceMap != null)
{
_localReferenceMap.clear();
} setRoot(null);
setCurrentObject(null);
setRootEvaluation(null);
setCurrentEvaluation(null);
setLastEvaluation(null);
setCurrentNode(null);
setClassResolver(DEFAULT_CLASS_RESOLVER);
setTypeConverter(DEFAULT_TYPE_CONVERTER);
setMemberAccess(DEFAULT_MEMBER_ACCESS);
} public Set keySet()
{
/* Should root, currentObject, classResolver, typeConverter & memberAccess be included here? */
return _values.keySet();
} public Collection values()
{
/* Should root, currentObject, classResolver, typeConverter & memberAccess be included here? */
return _values.values();
} public Set entrySet()
{
/* Should root, currentObject, classResolver, typeConverter & memberAccess be included here? */
return _values.entrySet();
} public boolean equals(Object o)
{
return _values.equals(o);
} public int hashCode()
{
return _values.hashCode();
}
}
OgnlContext 源码的更多相关文章
- struts2拦截器源码分析
前面博客我们介绍了开发struts2应用程序的基本流程(开发一个struts2的实例),通过前面我们知道了struts2实现请求转发和配置文件加载都是拦截器进行的操作,这也就是为什么我们要在web.x ...
- Struts2 源码分析-----拦截器源码解析 --- ParametersInterceptor
ParametersInterceptor拦截器其主要功能是把ActionContext中的请求参数设置到ValueStack中,如果栈顶是当前Action则把请求参数设置到了Action中,如果栈顶 ...
- 精尽 MyBatis 源码分析 - MyBatis 初始化(三)之 SQL 初始化(上)
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 源码解析之 Mybatis 对 Integer 参数做了什么手脚?
title: 源码解析之 Mybatis 对 Integer 参数做了什么手脚? date: 2021-03-11 updated: 2021-03-11 categories: Mybatis 源码 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- C# ini文件操作【源码下载】
介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 从源码看Azkaban作业流下发过程
上一篇零散地罗列了看源码时记录的一些类的信息,这篇完整介绍一个作业流在Azkaban中的执行过程,希望可以帮助刚刚接手Azkaban相关工作的开发.测试. 一.Azkaban简介 Azkaban作为开 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
随机推荐
- WIN7 64位对Excel操作异常
在本地做Excel导出功能的测试时,报出“检索COM 类工厂中CLSID 为 {00024500-0000-0000-C000-000000000046}的组件时失败”的异常,知道要对Excel进行D ...
- 为PyCharm添加不同解释器
正常大家会使用Python官网的安装包,即Python.由于自己尝试了下IronPython,但打开PyCharm查看配置,发现并没有IronPython的解释器,这个需要自己加进去,如图: &quo ...
- UVALive 4731 Cellular Network(贪心,dp)
分析: 状态是一些有序的集合,这些集合互不相交,并集为所有区域.显然枚举集合元素是哪些是无法承受的, 写出期望的计算式,会发现,当每个集合的大小确定了以后,概率大的优先访问是最优的. 因此先对u从大到 ...
- iOS开发学习之大牛们的博客
http://blog.csdn.net/iosbird/article/details/51981023 唐巧:http://blog.devtang.com/blog/archives/ 王巍:h ...
- [超详细] Python3爬取豆瓣影评、去停用词、词云图、评论关键词绘图处理
爬取豆瓣电影<大侦探皮卡丘>的影评,并做词云图和关键词绘图第一步:找到评论的网页url.https://movie.douban.com/subject/26835471/comments ...
- form 表单 和 jQuery HTML / CSS 方法($().html 类似的样式)
1 有关链接 :http://www.runoob.com/tags/tag-form.html https://www.cnblogs.com/Jxwz/p/4509618.html https:/ ...
- javaweb基础(28)_jstl的核心标签
一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心 ...
- 【图论】[USACO]控制公司 Controlling Companies
玄妙的搜索 题目描述 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.(此处略去一句废话)据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了: 公司A = 公司B ...
- 【bug】【yii】配置log时,报错 Setting read-only property: yii\web\Application::log
Setting read-only property: yii\web\Application::log 配置放在了 components 外面,应该放在里面
- 19.VUE学习之- v-for与computed结合功能 筛选实例讲解
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...