View Javadoc

1   package org.apache.velocity.app;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.lang.reflect.Field;
23  import java.lang.reflect.Modifier;
24  import java.util.HashMap;
25  import org.apache.velocity.util.ClassUtils;
26  
27  /**
28   *  <p>
29   *  This is a small utility class allow easy access to static fields in a class,
30   *  such as string constants.  Velocity will not introspect for class
31   *  fields (and won't in the future :), but writing setter/getter methods to do
32   *  this really is a pain,  so use this if you really have
33   *  to access fields.
34   *
35   *  <p>
36   *  The idea it so enable access to the fields just like you would in Java.
37   *  For example, in Java, you would access a static field like
38   *  <blockquote><pre>
39   *  MyClass.STRING_CONSTANT
40   *  </pre></blockquote>
41   *  and that is the same thing we are trying to allow here.
42   *
43   *  <p>
44   *  So to use in your Java code, do something like this :
45   *  <blockquote><pre>
46   *   context.put("runtime", new FieldMethodizer( "org.apache.velocity.runtime.Runtime" ));
47   *  </pre></blockquote>
48   *  and then in your template, you can access any of your static fields in this way :
49   *  <blockquote><pre>
50   *   $runtime.COUNTER_NAME
51   *  </pre></blockquote>
52   *
53   *  <p>
54   *  Right now, this class only methodizes <code>public static</code> fields.  It seems
55   *  that anything else is too dangerous.  This class is for convenience accessing
56   *  'constants'.  If you have fields that aren't <code>static</code> it may be better
57   *  to handle them by explicitly placing them into the context.
58   *
59   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
60   * @version $Id: FieldMethodizer.java 652755 2008-05-02 04:00:58Z nbubna $
61   */
62  public class FieldMethodizer
63  {
64      /** Hold the field objects by field name */
65      private HashMap fieldHash = new HashMap();
66  
67      /**
68       * Allow object to be initialized without any data. You would use
69       * addObject() to add data later.
70       */
71      public FieldMethodizer()
72      {
73      }
74  
75      /**
76       *  Constructor that takes as it's arg the name of the class
77       *  to methodize.
78       *
79       *  @param s Name of class to methodize.
80       */
81      public FieldMethodizer( String s )
82      {
83          try
84          {
85              addObject(s);
86          }
87          catch( Exception e )
88          {
89              System.err.println("Could not add " + s
90                      + " for field methodizing: "
91                      + e.getMessage());
92          }
93      }
94  
95    /**
96       *  Constructor that takes as it's arg a living
97       *  object to methodize.  Note that it will still
98       *  only methodized the public static fields of
99       *  the class.
100      *
101      *  @param o Name of class to methodize.
102      */
103     public FieldMethodizer( Object o )
104     {
105         try
106         {
107             addObject(o);
108         }
109         catch( Exception e )
110         {
111             System.err.println("Could not add " + o
112                     + " for field methodizing: "
113                     + e.getMessage());
114         }
115     }
116 
117     /**
118      * Add the Name of the class to methodize
119      * @param s
120      * @throws Exception
121      */
122     public void addObject ( String s )
123         throws Exception
124     {
125         inspect(ClassUtils.getClass(s));
126     }
127 
128     /**
129      * Add an Object to methodize
130      * @param o
131      * @throws Exception
132      */
133     public void addObject ( Object o )
134         throws Exception
135     {
136         inspect(o.getClass());
137     }
138 
139     /**
140      *  Accessor method to get the fields by name.
141      *
142      *  @param fieldName Name of static field to retrieve
143      *
144      *  @return The value of the given field.
145      */
146     public Object get( String fieldName )
147     {
148         Object value = null;
149         try
150         {
151             Field f = (Field) fieldHash.get( fieldName );
152             if (f != null)
153             {
154                 value = f.get(null);
155             }
156         }
157         catch( IllegalAccessException e )
158         {
159             System.err.println("IllegalAccessException while trying to access " + fieldName
160                     + ": " + e.getMessage());
161         }
162         return value;
163     }
164 
165     /**
166      *  Method that retrieves all public static fields
167      *  in the class we are methodizing.
168      */
169     private void inspect(Class clas)
170     {
171         Field[] fields = clas.getFields();
172         for( int i = 0; i < fields.length; i++)
173         {
174             /*
175              *  only if public and static
176              */
177             int mod = fields[i].getModifiers();
178             if ( Modifier.isStatic(mod) && Modifier.isPublic(mod) )
179             {
180                 fieldHash.put(fields[i].getName(), fields[i]);
181             }
182         }
183     }
184 }