// 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 源码的更多相关文章

  1. struts2拦截器源码分析

    前面博客我们介绍了开发struts2应用程序的基本流程(开发一个struts2的实例),通过前面我们知道了struts2实现请求转发和配置文件加载都是拦截器进行的操作,这也就是为什么我们要在web.x ...

  2. Struts2 源码分析-----拦截器源码解析 --- ParametersInterceptor

    ParametersInterceptor拦截器其主要功能是把ActionContext中的请求参数设置到ValueStack中,如果栈顶是当前Action则把请求参数设置到了Action中,如果栈顶 ...

  3. 精尽 MyBatis 源码分析 - MyBatis 初始化(三)之 SQL 初始化(上)

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  4. 源码解析之 Mybatis 对 Integer 参数做了什么手脚?

    title: 源码解析之 Mybatis 对 Integer 参数做了什么手脚? date: 2021-03-11 updated: 2021-03-11 categories: Mybatis 源码 ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  6. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  7. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  8. 从源码看Azkaban作业流下发过程

    上一篇零散地罗列了看源码时记录的一些类的信息,这篇完整介绍一个作业流在Azkaban中的执行过程,希望可以帮助刚刚接手Azkaban相关工作的开发.测试. 一.Azkaban简介 Azkaban作为开 ...

  9. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

随机推荐

  1. 从.net到java,从基础架构到解决方案。

    这一年,职业生涯中的最大变化,是从.net到java的直接跨越,是从平台架构到解决方案的不断完善. 砥砺前行 初出茅庐,天下无敌.再学三年,寸步难行.很多时候不是别人太强,真的是自己太弱,却不自知. ...

  2. PHP:php遍历数组each()方法总结

    each()的作用是将数组当前元素的键值对拆成一个新数组,并把下一个元素作为当前元素.比如Array(...,'Robert'=>'Bob',...)中的'Robert'=>'Bob'键值 ...

  3. springboot集成shiro的session污染问题

    问题起因是这样的,有两套系统,系统a和系统b.两套系统均使用shiro做的权限管理,之前部署在两台机器上.使用浏览器打开a系统后另开页签打开b系统,互不干扰都能正常使用,后因业务迁移,两套系统部署到了 ...

  4. 题解 P2626 【斐波那契数列(升级版)】

    这道题,大家一定要注意: 要对2^31取模 ! ( 本蒟蒻开始没注意到这一点,WA了 ) (不过大家在试样例的时候,试试47,出不了结果,就说明你没模2^31) 总体来说,这道题考查的知识点就两个: ...

  5. java Html&JavaScript面试题:用table显示n条记录,每3行换一次颜色,即1,2,3用红色字体,4,5,6用绿色字体,7,8,9用红颜色字体。

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Android驱动开发读书笔记六

    第六章 Linux 驱动的工作和访问方式是 Linux 的亮点之一,Linux 系统将每一个驱动都映射成一个文件.这些文件称为设备文件或驱动文件,都保存在/dev目录中,由于大多数Linux驱动都有与 ...

  7. STMS传输队列中的请求状态一直是Running不能结束

    通过STMS传输请求时,遇到了如下问题: STMS传输请求,不论等多久的时间,请求状态一直是running,不能结束.但检查传输的内容时,发现CHANGE REQUEST包含的内容已经传输到目标Cli ...

  8. select * 比select column快很多奇怪案例分析

    遇到MYSQL傻傻的地方,下面给个案例,大家感受下: 注意以下两个sql只有select *和select g.id区别. SQL1:SELECT g.idFROM table1 gINNER JOI ...

  9. django+xadmin在线教育平台(二)

    老话总是没错的,工欲善其事,必先利其器 教你安装pycharm,mysql,navicat,python相关环境. windows下搭建开发环境 2-1 pycharm,mysql,Navicat安装 ...

  10. Python周末21天笔记

    模块一: 基础相互据类型之间的相互转换 1. 字符串str 与 列表 list 与字典 dict 以及 元祖tuple的转换 例一: 把字典的key和value的值取出来,按照顺序存入到list中 d ...