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 }