001    package org.apache.commons.ognl;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.lang.reflect.Field;
023    import java.lang.reflect.Modifier;
024    
025    /**
026     * $Id: ASTStaticField.java 1198661 2011-11-07 09:14:07Z mcucchiara $
027     * @author Luke Blanshard (blanshlu@netscape.net)
028     * @author Drew Davidson (drew@ognl.org)
029     */
030    public class ASTStaticField
031        extends SimpleNode
032        implements NodeType
033    {
034    
035        private String className;
036    
037        private String fieldName;
038    
039        private Class getterClass;
040    
041        public ASTStaticField( int id )
042        {
043            super( id );
044        }
045    
046        public ASTStaticField( OgnlParser p, int id )
047        {
048            super( p, id );
049        }
050    
051        /** Called from parser action. */
052        void init( String className, String fieldName )
053        {
054            this.className = className;
055            this.fieldName = fieldName;
056        }
057    
058        protected Object getValueBody( OgnlContext context, Object source )
059            throws OgnlException
060        {
061            return OgnlRuntime.getStaticField( context, className, fieldName );
062        }
063    
064        public boolean isNodeConstant( OgnlContext context )
065            throws OgnlException
066        {
067            boolean result = false;
068            Exception cause = null;
069    
070            try
071            {
072                Class clazz = OgnlRuntime.classForName( context, className );
073    
074                /*
075                 * Check for virtual static field "class"; this cannot interfere with normal static fields because it is a
076                 * reserved word. It is considered constant.
077                 */
078                if ( "class".equals( fieldName ) )
079                {
080                    result = true;
081                }
082                else if ( clazz.isEnum() )
083                {
084                    result = true;
085                }
086                else
087                {
088                    Field field = clazz.getField( fieldName );
089    
090                    if ( !Modifier.isStatic( field.getModifiers() ) )
091                    {
092                        throw new OgnlException( "Field " + fieldName + " of class " + className + " is not static" );
093                    }
094                    result = Modifier.isFinal( field.getModifiers() );
095                }
096            }
097            catch ( ClassNotFoundException e )
098            {
099                cause = e;
100            }
101            catch ( NoSuchFieldException e )
102            {
103                cause = e;
104            }
105            catch ( SecurityException e )
106            {
107                cause = e;
108            }
109    
110            if ( cause != null )
111            {
112                throw new OgnlException( "Could not get static field " + fieldName + " from class " + className, cause );
113            }
114            
115            return result;
116        }
117    
118        Class getFieldClass( OgnlContext context )
119            throws OgnlException
120        {
121            Exception cause;
122    
123            try
124            {
125                Class clazz = OgnlRuntime.classForName( context, className );
126    
127                /*
128                 * Check for virtual static field "class"; this cannot interfere with normal static fields because it is a
129                 * reserved word. It is considered constant.
130                 */
131                if ( "class".equals( fieldName ) )
132                {
133                    return clazz;
134                }
135                else if ( clazz.isEnum() )
136                {
137                    return clazz;
138                }
139                else
140                {
141                    Field field = clazz.getField( fieldName );
142    
143                    return field.getType();
144                }
145            }
146            catch ( ClassNotFoundException e )
147            {
148                cause = e;
149            }
150            catch ( NoSuchFieldException e )
151            {
152                cause = e;
153            }
154            catch ( SecurityException e )
155            {
156                cause = e;
157            }
158            throw new OgnlException( "Could not get static field " + fieldName + " from class " + className, cause );
159        }
160    
161        public Class getGetterClass()
162        {
163            return getterClass;
164        }
165    
166        public Class getSetterClass()
167        {
168            return getterClass;
169        }
170    
171        public String toGetSourceString( OgnlContext context, Object target )
172        {
173            try
174            {
175    
176                Object obj = OgnlRuntime.getStaticField( context, className, fieldName );
177    
178                context.setCurrentObject( obj );
179    
180                getterClass = getFieldClass( context );
181    
182                context.setCurrentType( getterClass );
183    
184            }
185            catch ( Throwable t )
186            {
187                throw OgnlOps.castToRuntime( t );
188            }
189    
190            return className + "." + fieldName;
191        }
192    
193        public String toSetSourceString( OgnlContext context, Object target )
194        {
195            try
196            {
197    
198                Object obj = OgnlRuntime.getStaticField( context, className, fieldName );
199    
200                context.setCurrentObject( obj );
201    
202                getterClass = getFieldClass( context );
203    
204                context.setCurrentType( getterClass );
205    
206            }
207            catch ( Throwable t )
208            {
209                throw OgnlOps.castToRuntime( t );
210            }
211    
212            return className + "." + fieldName;
213        }
214        
215        public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
216            throws OgnlException
217        {
218            return visitor.visit( this, data );
219        }
220    
221        /**
222         * Get the field name for this field.
223         *
224         * @return the field name.
225         * @since 4.0
226         */
227        String getFieldName()
228        {
229            return fieldName;
230        }
231    
232        /**
233         * Get the class name for this field.
234         *
235         * @return the class name.
236         * @since 4.0
237         */
238        String getClassName()
239        {
240            return className;
241        }
242    }