zoukankan      html  css  js  c++  java
  • 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();
        }
    }
  • 相关阅读:
    JavaScript模态对话框类
    事件模块的演变(1)
    html5中可通过document.head获取head元素
    How to search for just a specific file type in Visual Studio code?
    What do 'lazy' and 'greedy' mean in the context of regular expressions?
    正则非获取匹配 Lookahead and Lookbehind ZeroLength Assertions
    regex length 正则长度问题
    Inversion of Control vs Dependency Injection
    How to return View with QueryString in ASP.NET MVC 2?
    今天才发现Google Reader
  • 原文地址:https://www.cnblogs.com/shaohz2014/p/3653429.html
Copyright © 2011-2022 走看看