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 463298 2006-10-12 16:10:32Z henning $
61   */
62  public class FieldMethodizer
63  {
64      /** Hold the field objects by field name */
65      private HashMap fieldHash = new HashMap();
66  
67      /** Hold the class objects by field name */
68      private HashMap classHash = new HashMap();
69  
70      /**
71       * Allow object to be initialized without any data. You would use
72       * addObject() to add data later.
73       */
74      public FieldMethodizer()
75      {
76      }
77  
78      /**
79       *  Constructor that takes as it's arg the name of the class
80       *  to methodize.
81       *
82       *  @param s Name of class to methodize.
83       */
84      public FieldMethodizer( String s )
85      {
86          try
87          {
88              addObject(s);
89          }
90          catch( Exception e )
91          {
92              System.err.println("Could not add " + s
93                      + " for field methodizing: "
94                      + e.getMessage());
95          }
96      }
97  
98    /**
99       *  Constructor that takes as it's arg a living
100      *  object to methodize.  Note that it will still
101      *  only methodized the public static fields of
102      *  the class.
103      *
104      *  @param o Name of class to methodize.
105      */
106     public FieldMethodizer( Object o )
107     {
108         try
109         {
110             addObject(o);
111         }
112         catch( Exception e )
113         {
114             System.err.println("Could not add " + o
115                     + " for field methodizing: "
116                     + e.getMessage());
117         }
118     }
119 
120     /**
121      * Add the Name of the class to methodize
122      * @param s
123      * @throws Exception
124      */
125     public void addObject ( String s )
126         throws Exception
127     {
128         inspect(ClassUtils.getClass(s));
129     }
130 
131     /**
132      * Add an Object to methodize
133      * @param o
134      * @throws Exception
135      */
136     public void addObject ( Object o )
137         throws Exception
138     {
139         inspect(o.getClass());
140     }
141 
142     /**
143      *  Accessor method to get the fields by name.
144      *
145      *  @param fieldName Name of static field to retrieve
146      *
147      *  @return The value of the given field.
148      */
149     public Object get( String fieldName )
150     {
151         Object value = null;
152         try
153         {
154             Field f = (Field) fieldHash.get( fieldName );
155             if (f != null)
156             {
157                 value = f.get(classHash.get(fieldName) );
158             }
159         }
160         catch( IllegalAccessException e )
161         {
162             System.err.println("IllegalAccessException while trying to access " + fieldName
163                     + ": " + e.getMessage());
164         }
165         return value;
166     }
167 
168     /**
169      *  Method that retrieves all public static fields
170      *  in the class we are methodizing.
171      */
172     private void inspect(Class clas)
173     {
174         Field[] fields = clas.getFields();
175         for( int i = 0; i < fields.length; i++)
176         {
177             /*
178              *  only if public and static
179              */
180             int mod = fields[i].getModifiers();
181             if ( Modifier.isStatic(mod) && Modifier.isPublic(mod) )
182             {
183                 fieldHash.put(fields[i].getName(), fields[i]);
184                 classHash.put(fields[i].getName(), clas);
185             }
186         }
187     }
188 }