KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > ext > beans > StaticModel


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.ext.beans;
54
55 import java.lang.reflect.Field JavaDoc;
56 import java.lang.reflect.Method JavaDoc;
57 import java.lang.reflect.Modifier JavaDoc;
58 import java.util.HashMap JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import java.util.Map JavaDoc;
61
62 import freemarker.log.Logger;
63 import freemarker.template.TemplateCollectionModel;
64 import freemarker.template.TemplateHashModelEx;
65 import freemarker.template.TemplateModel;
66 import freemarker.template.TemplateModelException;
67
68 /**
69  * Wraps the static fields and methods of a class in a {@link TemplateHashModel}.
70  * Fields are wrapped using {@link BeansWrapper#wrap(Object)}, and
71  * methods are wrapped into an appropriate {@link freemarker.template.TemplateMethodModelEx} instance.
72  * Unfortunately, there is currently no support for bean property-style
73  * calls of static methods, similar to that in {@link BeanModel}.
74  * @author Attila Szegedi
75  * @version $Id: StaticModel.java,v 1.22 2004/11/11 13:15:19 szegedia Exp $
76  */

77 final class StaticModel implements TemplateHashModelEx
78 {
79     private static final Logger logger = Logger.getLogger("freemarker.beans");
80     private final Class JavaDoc clazz;
81     private final BeansWrapper wrapper;
82     private final Map JavaDoc map = new HashMap JavaDoc();
83
84     StaticModel(Class JavaDoc clazz, BeansWrapper wrapper) throws IllegalAccessException JavaDoc, TemplateModelException
85     {
86         this.clazz = clazz;
87         this.wrapper = wrapper;
88         populate();
89     }
90
91     /**
92      * Returns the field or method named by the <tt>key</tt>
93      * parameter.
94      */

95     public TemplateModel get(String JavaDoc key) throws TemplateModelException
96     {
97         Object JavaDoc model = map.get(key);
98         // Simple method, overloaded method or final field -- these have cached
99
// template models
100
if (model instanceof TemplateModel)
101             return (TemplateModel) model;
102         // Non-final field; this must be evaluated on each call.
103
if (model instanceof Field JavaDoc)
104         {
105             try
106             {
107                 return wrapper.getOuterIdentity().wrap(((Field JavaDoc) model).get(null));
108             }
109             catch (IllegalAccessException JavaDoc e)
110             {
111                 throw new TemplateModelException(
112                     "Illegal access for field " + key + " of class " + clazz.getName());
113             }
114         }
115
116         throw new TemplateModelException(
117             "No such key: " + key + " in class " + clazz.getName());
118     }
119
120     /**
121      * Returns true if there is at least one public static
122      * field or method in the underlying class.
123      */

124     public boolean isEmpty()
125     {
126         return map.isEmpty();
127     }
128
129     public int size()
130     {
131         return map.size();
132     }
133     
134     public TemplateCollectionModel keys() throws TemplateModelException
135     {
136         return (TemplateCollectionModel)wrapper.getOuterIdentity().wrap(map.keySet());
137     }
138     
139     public TemplateCollectionModel values() throws TemplateModelException
140     {
141         return (TemplateCollectionModel)wrapper.getOuterIdentity().wrap(map.values());
142     }
143
144     private void populate() throws IllegalAccessException JavaDoc, TemplateModelException
145     {
146         if (!Modifier.isPublic(clazz.getModifiers()))
147         {
148             throw new IllegalAccessException JavaDoc(
149                 "Can't wrap the non-public class " + clazz.getName());
150         }
151         
152         if(wrapper.getExposureLevel() == BeansWrapper.EXPOSE_NOTHING)
153         {
154             return;
155         }
156
157         Field JavaDoc[] fields = clazz.getFields();
158         for (int i = 0; i < fields.length; ++i)
159         {
160             Field JavaDoc field = fields[i];
161             int mod = field.getModifiers();
162             if (Modifier.isPublic(mod) && Modifier.isStatic(mod))
163             {
164                 if (Modifier.isFinal(mod))
165                     try
166                     {
167                         // public static final fields are evaluated once and
168
// stored in the map
169
map.put(field.getName(), wrapper.getOuterIdentity().wrap(field.get(null)));
170                     }
171                     catch (IllegalAccessException JavaDoc e)
172                     {
173                         // Intentionally ignored
174
}
175                 else
176                     // This is a special flagging value: Field in the map means
177
// that this is a non-final field, and it must be evaluated
178
// on each get() call.
179
map.put(field.getName(), field);
180             }
181         }
182         if(wrapper.getExposureLevel() < BeansWrapper.EXPOSE_PROPERTIES_ONLY)
183         {
184             Method JavaDoc[] methods = clazz.getMethods();
185             for (int i = 0; i < methods.length; ++i)
186             {
187                 Method JavaDoc method = methods[i];
188                 int mod = method.getModifiers();
189                 if (Modifier.isPublic(mod) && Modifier.isStatic(mod) && wrapper.isSafeMethod(method))
190                 {
191                     String JavaDoc name = method.getName();
192                     Object JavaDoc obj = map.get(name);
193                     if (obj instanceof Method JavaDoc)
194                     {
195                         MethodMap methodMap = new MethodMap(name);
196                         methodMap.addMethod((Method JavaDoc) obj);
197                         methodMap.addMethod(method);
198                         map.put(name, methodMap);
199                     }
200                     else if(obj instanceof MethodMap)
201                     {
202                         MethodMap methodMap = (MethodMap) obj;
203                         methodMap.addMethod(method);
204                     }
205                     else
206                     {
207                         if(obj != null)
208                         {
209                             logger.info("Overwriting value [" + obj + "] for " +
210                                     " key '" + name + "' with [" + method +
211                                     "] in static model for " + clazz.getName());
212                         }
213                         map.put(name, method);
214                     }
215                 }
216             }
217             for (Iterator JavaDoc entries = map.entrySet().iterator(); entries.hasNext();)
218             {
219                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
220                 Object JavaDoc value = entry.getValue();
221                 if (value instanceof Method JavaDoc)
222                 {
223                     entry.setValue(new SimpleMethodModel(null, (Method JavaDoc) value, wrapper));
224                 }
225                 else if (value instanceof MethodMap)
226                 {
227                     entry.setValue(new OverloadedMethodModel(null, (MethodMap) value, wrapper));
228                 }
229             }
230         }
231     }
232 }
233
Popular Tags