001    /*
002     * Apache License
003     * Version 2.0, January 2004
004     * http://www.apache.org/licenses/
005     *
006     * Copyright 1996-2008 by Sven Homburg
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     */
014    
015    package org.chenillekit.tapestry.core.bindings;
016    
017    import java.util.Map;
018    
019    import org.apache.tapestry5.internal.bindings.AbstractBinding;
020    import org.apache.tapestry5.ioc.Location;
021    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
022    import org.apache.tapestry5.ioc.internal.util.TapestryException;
023    
024    import ognl.Ognl;
025    
026    /**
027     * Binding type for OGNL expressions.
028     * This binding called by expression "ognl:".
029     *
030     * @version $Id: OgnlBinding.java 594 2009-12-05 15:17:26Z mlusetti $
031     */
032    public class OgnlBinding extends AbstractBinding
033    {
034        private static final Map<String, Object> _cache = CollectionFactory.newMap();
035    
036        private String _expression;
037        private Object _root;
038    
039        public OgnlBinding(final Location location, final Object root, final String expression)
040        {
041            super(location);
042            _expression = expression;
043            _root = root;
044        }
045    
046        /**
047         * Gets a parsed OGNL expression from the input string.
048         *
049         * @throws TapestryException if the expression can not be parsed.
050         */
051        public synchronized Object getParsedExpression(String expression)
052        {
053            Object result = _cache.get(expression);
054    
055            if (result == null)
056            {
057                try
058                {
059                    result = Ognl.parseExpression(expression);
060                }
061                catch (Exception ex)
062                {
063                    throw new TapestryException(ex.getLocalizedMessage(), getLocation(), ex);
064                }
065    
066                _cache.put(expression, result);
067            }
068    
069            return result;
070        }
071    
072        /**
073         * Reads the current value of the property (or other resource). When reading properties of
074         * objects that are primitive types, this will return an instance of the wrapper type. In some
075         * cases, a binding is read only and this method will throw a runtime exception.
076         */
077        public Object get()
078        {
079            Object ognlExpression = getParsedExpression(_expression);
080    
081            try
082            {
083                Map context = Ognl.createDefaultContext(_root);
084                return Ognl.getValue(ognlExpression, context, _root);
085            }
086            catch (Exception ex)
087            {
088                throw new TapestryException(ex.getLocalizedMessage(), getLocation(), ex);
089            }
090        }
091    
092        /**
093         * Returns false; these properties are always dynamic.
094         */
095        @Override
096        public boolean isInvariant()
097        {
098            return false;
099        }
100    
101        @Override
102        public String toString()
103        {
104            return String.format("OgnlBinding[%s]", _expression);
105        }
106    }