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 }