001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.bean;
016    
017    import java.util.Map;
018    
019    import ognl.ObjectPropertyAccessor;
020    import ognl.OgnlContext;
021    import ognl.OgnlException;
022    import ognl.OgnlRuntime;
023    import ognl.PropertyAccessor;
024    import ognl.enhance.ExpressionCompiler;
025    import ognl.enhance.UnsupportedCompilationException;
026    
027    import org.apache.tapestry.IBeanProvider;
028    
029    /**
030     *  Adapts a {@link org.apache.tapestry.IBeanProvider} to
031     *  <a href="http://www.ognl.org">OGNL</a> by exposing the named
032     *  beans provided by the provider as read-only properties of
033     *  the provider.
034     * 
035     *  <p>This is registered by {@link org.apache.tapestry.AbstractComponent}.
036     *
037     *  @author Howard Lewis Ship
038     *  @since 2.2
039     *
040     **/
041    
042    public class BeanProviderPropertyAccessor extends ObjectPropertyAccessor implements PropertyAccessor
043    {
044        /**
045         *  Checks to see if the name matches the name of a bean inside
046         *  the provider and returns that bean if so.
047         *  Otherwise, invokes the super implementation.
048         * 
049         **/
050        
051        public Object getProperty(Map context, Object target, Object name) throws OgnlException
052        {
053            IBeanProvider provider = (IBeanProvider)target;
054            String beanName = (String)name;
055            
056            if (provider.canProvideBean(beanName))
057                return provider.getBean(beanName);
058            
059            return super.getProperty(context, target, name);
060        }
061    
062        /**
063         *  Returns true if the name matches a bean provided by the provider.
064         *  Otherwise invokes the super implementation.
065         * 
066         **/
067        
068        public boolean hasGetProperty(Map context, Object target, Object oname) throws OgnlException
069        {
070            IBeanProvider provider = (IBeanProvider)target;
071            String beanName = ((String)oname).replaceAll("\"", "");
072    
073            if (provider.canProvideBean(beanName))
074                return true;
075                
076            return super.hasGetProperty(context, target, oname);
077        }
078        
079        public Class getPropertyClass(OgnlContext context, Object target, Object name)
080        {
081            IBeanProvider provider = (IBeanProvider)target;
082            String beanName = ((String)name).replaceAll("\"", "");
083            
084            if (provider.canProvideBean(beanName))
085                return provider.getBean(beanName).getClass();
086            
087            return super.getPropertyClass(context, target, name);
088        }
089        
090        public String getSourceAccessor(OgnlContext context, Object target, Object name)
091        {
092            IBeanProvider provider = (IBeanProvider)target;
093            String beanName = ((String)name).replaceAll("\"", "");
094            
095            if (provider.canProvideBean(beanName)) {
096                
097                Class type = OgnlRuntime.getCompiler().getInterfaceClass(provider.getBean(beanName).getClass());
098                
099                ExpressionCompiler.addCastString(context, "((" + type.getName() + ")");
100                
101                context.setCurrentAccessor(IBeanProvider.class);
102                context.setCurrentType(type);
103                
104                return ".getBean(" + name + "))";
105            }
106            
107            return super.getSourceAccessor(context, target, name);
108        }
109        
110        public String getSourceSetter(OgnlContext context, Object target, Object name)
111        {
112            throw new UnsupportedCompilationException("Can't set beans on IBeanProvider.");
113        }
114    }