001: package org.apache.velocity.app;
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: import java.util.HashMap;
025: import org.apache.velocity.util.ClassUtils;
026:
027: /**
028: * <p>
029: * This is a small utility class allow easy access to static fields in a class,
030: * such as string constants. Velocity will not introspect for class
031: * fields (and won't in the future :), but writing setter/getter methods to do
032: * this really is a pain, so use this if you really have
033: * to access fields.
034: *
035: * <p>
036: * The idea it so enable access to the fields just like you would in Java.
037: * For example, in Java, you would access a static field like
038: * <blockquote><pre>
039: * MyClass.STRING_CONSTANT
040: * </pre></blockquote>
041: * and that is the same thing we are trying to allow here.
042: *
043: * <p>
044: * So to use in your Java code, do something like this :
045: * <blockquote><pre>
046: * context.put("runtime", new FieldMethodizer( "org.apache.velocity.runtime.Runtime" ));
047: * </pre></blockquote>
048: * and then in your template, you can access any of your static fields in this way :
049: * <blockquote><pre>
050: * $runtime.COUNTER_NAME
051: * </pre></blockquote>
052: *
053: * <p>
054: * Right now, this class only methodizes <code>public static</code> fields. It seems
055: * that anything else is too dangerous. This class is for convenience accessing
056: * 'constants'. If you have fields that aren't <code>static</code> it may be better
057: * to handle them by explicitly placing them into the context.
058: *
059: * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
060: * @version $Id: FieldMethodizer.java 463298 2006-10-12 16:10:32Z henning $
061: */
062: public class FieldMethodizer {
063: /** Hold the field objects by field name */
064: private HashMap fieldHash = new HashMap();
065:
066: /** Hold the class objects by field name */
067: private HashMap classHash = new HashMap();
068:
069: /**
070: * Allow object to be initialized without any data. You would use
071: * addObject() to add data later.
072: */
073: public FieldMethodizer() {
074: }
075:
076: /**
077: * Constructor that takes as it's arg the name of the class
078: * to methodize.
079: *
080: * @param s Name of class to methodize.
081: */
082: public FieldMethodizer(String s) {
083: try {
084: addObject(s);
085: } catch (Exception e) {
086: System.err.println("Could not add " + s
087: + " for field methodizing: " + e.getMessage());
088: }
089: }
090:
091: /**
092: * Constructor that takes as it's arg a living
093: * object to methodize. Note that it will still
094: * only methodized the public static fields of
095: * the class.
096: *
097: * @param o Name of class to methodize.
098: */
099: public FieldMethodizer(Object o) {
100: try {
101: addObject(o);
102: } catch (Exception e) {
103: System.err.println("Could not add " + o
104: + " for field methodizing: " + e.getMessage());
105: }
106: }
107:
108: /**
109: * Add the Name of the class to methodize
110: * @param s
111: * @throws Exception
112: */
113: public void addObject(String s) throws Exception {
114: inspect(ClassUtils.getClass(s));
115: }
116:
117: /**
118: * Add an Object to methodize
119: * @param o
120: * @throws Exception
121: */
122: public void addObject(Object o) throws Exception {
123: inspect(o.getClass());
124: }
125:
126: /**
127: * Accessor method to get the fields by name.
128: *
129: * @param fieldName Name of static field to retrieve
130: *
131: * @return The value of the given field.
132: */
133: public Object get(String fieldName) {
134: Object value = null;
135: try {
136: Field f = (Field) fieldHash.get(fieldName);
137: if (f != null) {
138: value = f.get(classHash.get(fieldName));
139: }
140: } catch (IllegalAccessException e) {
141: System.err
142: .println("IllegalAccessException while trying to access "
143: + fieldName + ": " + e.getMessage());
144: }
145: return value;
146: }
147:
148: /**
149: * Method that retrieves all public static fields
150: * in the class we are methodizing.
151: */
152: private void inspect(Class clas) {
153: Field[] fields = clas.getFields();
154: for (int i = 0; i < fields.length; i++) {
155: /*
156: * only if public and static
157: */
158: int mod = fields[i].getModifiers();
159: if (Modifier.isStatic(mod) && Modifier.isPublic(mod)) {
160: fieldHash.put(fields[i].getName(), fields[i]);
161: classHash.put(fields[i].getName(), clas);
162: }
163: }
164: }
165: }
|