Source Code Cross Referenced for BeanModel.java in  » Template-Engine » freemarker-2.3.10 » freemarker » ext » beans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Template Engine » freemarker 2.3.10 » freemarker.ext.beans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2003 The Visigoth Software Society. All rights
003:         * reserved.
004:         *
005:         * Redistribution and use in source and binary forms, with or without
006:         * modification, are permitted provided that the following conditions
007:         * are met:
008:         *
009:         * 1. Redistributions of source code must retain the above copyright
010:         *    notice, this list of conditions and the following disclaimer.
011:         *
012:         * 2. Redistributions in binary form must reproduce the above copyright
013:         *    notice, this list of conditions and the following disclaimer in
014:         *    the documentation and/or other materials provided with the
015:         *    distribution.
016:         *
017:         * 3. The end-user documentation included with the redistribution, if
018:         *    any, must include the following acknowledgement:
019:         *       "This product includes software developed by the
020:         *        Visigoth Software Society (http://www.visigoths.org/)."
021:         *    Alternately, this acknowledgement may appear in the software itself,
022:         *    if and wherever such third-party acknowledgements normally appear.
023:         *
024:         * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
025:         *    project contributors may be used to endorse or promote products derived
026:         *    from this software without prior written permission. For written
027:         *    permission, please contact visigoths@visigoths.org.
028:         *
029:         * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030:         *    nor may "FreeMarker" or "Visigoth" appear in their names
031:         *    without prior written permission of the Visigoth Software Society.
032:         *
033:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036:         * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044:         * SUCH DAMAGE.
045:         * ====================================================================
046:         *
047:         * This software consists of voluntary contributions made by many
048:         * individuals on behalf of the Visigoth Software Society. For more
049:         * information on the Visigoth Software Society, please see
050:         * http://www.visigoths.org/
051:         */
052:
053:        package freemarker.ext.beans;
054:
055:        import java.beans.IndexedPropertyDescriptor;
056:        import java.beans.PropertyDescriptor;
057:        import java.lang.reflect.Field;
058:        import java.lang.reflect.InvocationTargetException;
059:        import java.lang.reflect.Method;
060:        import java.util.ArrayList;
061:        import java.util.Collection;
062:        import java.util.HashMap;
063:        import java.util.List;
064:        import java.util.Map;
065:        import java.util.Set;
066:
067:        import freemarker.core.CollectionAndSequence;
068:        import freemarker.ext.util.ModelFactory;
069:        import freemarker.ext.util.WrapperTemplateModel;
070:        import freemarker.log.Logger;
071:        import freemarker.template.AdapterTemplateModel;
072:        import freemarker.template.ObjectWrapper;
073:        import freemarker.template.SimpleScalar;
074:        import freemarker.template.SimpleSequence;
075:        import freemarker.template.TemplateCollectionModel;
076:        import freemarker.template.TemplateHashModelEx;
077:        import freemarker.template.TemplateModel;
078:        import freemarker.template.TemplateModelException;
079:        import freemarker.template.TemplateModelIterator;
080:        import freemarker.template.TemplateScalarModel;
081:
082:        /**
083:         * A class that will wrap an arbitrary object into {@link freemarker.template.TemplateHashModel}
084:         * interface allowing calls to arbitrary property getters and invocation of
085:         * accessible methods on the object from a template using the
086:         * <tt>object.foo</tt> to access properties and <tt>object.bar(arg1, arg2)</tt> to
087:         * invoke methods on it. You can also use the <tt>object.foo[index]</tt> syntax to
088:         * access indexed properties. It uses Beans {@link java.beans.Introspector}
089:         * to dynamically discover the properties and methods. 
090:         * @author Attila Szegedi
091:         * @version $Id: BeanModel.java,v 1.49.2.4 2006/11/12 10:20:37 szegedia Exp $
092:         */
093:
094:        public class BeanModel implements  TemplateHashModelEx,
095:                AdapterTemplateModel, WrapperTemplateModel {
096:            private static final Logger logger = Logger
097:                    .getLogger("freemarker.beans");
098:            protected final Object object;
099:            protected final BeansWrapper wrapper;
100:
101:            // We use this to represent an unknown value as opposed to known value of null (JR)
102:            private static final TemplateModel UNKNOWN = new SimpleScalar(
103:                    "UNKNOWN");
104:
105:            static final ModelFactory FACTORY = new ModelFactory() {
106:                public TemplateModel create(Object object, ObjectWrapper wrapper) {
107:                    return new BeanModel(object, (BeansWrapper) wrapper);
108:                }
109:            };
110:
111:            // Cached template models that implement member properties and methods for this
112:            // instance. Keys are FeatureDescriptor instances (from classCache values),
113:            // values are either ReflectionMethodModels/ReflectionScalarModels
114:            private final HashMap memberMap = new HashMap();
115:
116:            /**
117:             * Creates a new model that wraps the specified object. Note that there are
118:             * specialized subclasses of this class for wrapping arrays, collections,
119:             * enumeration, iterators, and maps. Note also that the superclass can be
120:             * used to wrap String objects if only scalar functionality is needed. You
121:             * can also choose to delegate the choice over which model class is used for
122:             * wrapping to {@link BeansWrapper#wrap(Object)}.
123:             * @param object the object to wrap into a model.
124:             * @param wrapper the {@link BeansWrapper} associated with this model.
125:             * Every model has to have an associated {@link BeansWrapper} instance. The
126:             * model gains many attributes from its wrapper, including the caching 
127:             * behavior, method exposure level, method-over-item shadowing policy etc.
128:             */
129:            public BeanModel(Object object, BeansWrapper wrapper) {
130:                this .object = object;
131:                this .wrapper = wrapper;
132:                if (object == null) {
133:                    return;
134:                }
135:                wrapper.introspectClass(object.getClass());
136:            }
137:
138:            /**
139:             * Uses Beans introspection to locate a property or method with name
140:             * matching the key name. If a method or property is found, it is wrapped
141:             * into {@link freemarker.template.TemplateMethodModelEx} (for a method or
142:             * indexed property), or evaluated on-the-fly and the return value wrapped
143:             * into appropriate model (for a simple property) Models for various
144:             * properties and methods are cached on a per-class basis, so the costly
145:             * introspection is performed only once per property or method of a class.
146:             * (Side-note: this also implies that any class whose method has been called
147:             * will be strongly referred to by the framework and will not become
148:             * unloadable until this class has been unloaded first. Normally this is not
149:             * an issue, but can be in a rare scenario where you create many classes on-
150:             * the-fly. Also, as the cache grows with new classes and methods introduced
151:             * to the framework, it may appear as if it were leaking memory. The
152:             * framework does, however detect class reloads (if you happen to be in an
153:             * environment that does this kind of things--servlet containers do it when
154:             * they reload a web application) and flushes the cache. If no method or
155:             * property matching the key is found, the framework will try to invoke
156:             * methods with signature
157:             * <tt>non-void-return-type get(java.lang.String)</tt>,
158:             * then <tt>non-void-return-type get(java.lang.Object)</tt>, or 
159:             * alternatively (if the wrapped object is a resource bundle) 
160:             * <tt>Object getObject(java.lang.String)</tt>.
161:             * @throws TemplateModelException if there was no property nor method nor
162:             * a generic <tt>get</tt> method to invoke.
163:             */
164:            public TemplateModel get(String key) throws TemplateModelException {
165:                Class clazz = object.getClass();
166:                Map classInfo = wrapper.getClassKeyMap(clazz);
167:                TemplateModel retval = null;
168:
169:                try {
170:                    if (wrapper.isMethodsShadowItems()) {
171:                        Object fd = classInfo.get(key);
172:                        if (fd != null) {
173:                            retval = invokeThroughDescriptor(fd, classInfo);
174:                        } else {
175:                            retval = invokeGenericGet(classInfo, clazz, key);
176:                        }
177:                    } else {
178:                        TemplateModel model = invokeGenericGet(classInfo,
179:                                clazz, key);
180:                        final TemplateModel nullModel = wrapper.wrap(null);
181:                        if (model != nullModel && model != UNKNOWN) {
182:                            return model;
183:                        }
184:                        Object fd = classInfo.get(key);
185:                        if (fd != null) {
186:                            retval = invokeThroughDescriptor(fd, classInfo);
187:                            if (retval == UNKNOWN && model == nullModel) {
188:                                // This is the (somewhat subtle) case where the generic get() returns null
189:                                // and we have no bean info, so we respect the fact that
190:                                // the generic get() returns null and return null. (JR)
191:                                retval = nullModel;
192:                            }
193:                        }
194:                    }
195:                    if (retval == UNKNOWN) {
196:                        if (wrapper.isStrict()) {
197:                            throw new InvalidPropertyException(
198:                                    "No such bean property: " + key);
199:                        } else if (logger.isDebugEnabled()) {
200:                            logNoSuchKey(key, classInfo);
201:                        }
202:                        retval = wrapper.wrap(null);
203:                    }
204:                    return retval;
205:                } catch (TemplateModelException e) {
206:                    throw e;
207:                } catch (Exception e) {
208:                    throw new TemplateModelException("get(" + key
209:                            + ") failed on " + "instance of "
210:                            + object.getClass().getName(), e);
211:                }
212:            }
213:
214:            private void logNoSuchKey(String key, Map keyMap) {
215:                logger.debug("Key '" + key + "' was not found on instance of "
216:                        + object.getClass().getName()
217:                        + ". Introspection information for " + "the class is: "
218:                        + keyMap);
219:            }
220:
221:            /**
222:             * Whether the model has a plain get(String) or get(Object) method
223:             */
224:
225:            protected boolean hasPlainGetMethod() {
226:                return wrapper.getClassKeyMap(object.getClass()).get(
227:                        BeansWrapper.GENERIC_GET_KEY) != null;
228:            }
229:
230:            private TemplateModel invokeThroughDescriptor(Object desc,
231:                    Map classInfo) throws IllegalAccessException,
232:                    InvocationTargetException, TemplateModelException {
233:                // See if this particular instance has a cached implementation
234:                // for the requested feature descriptor
235:                TemplateModel member = null;
236:                synchronized (memberMap) {
237:                    member = (TemplateModel) memberMap.get(desc);
238:                }
239:
240:                if (member != null)
241:                    return member;
242:
243:                TemplateModel retval = UNKNOWN;
244:                if (desc instanceof  IndexedPropertyDescriptor) {
245:                    Method readMethod = ((IndexedPropertyDescriptor) desc)
246:                            .getIndexedReadMethod();
247:                    retval = member = new SimpleMethodModel(object, readMethod,
248:                            BeansWrapper.getArgTypes(classInfo, readMethod),
249:                            wrapper);
250:                } else if (desc instanceof  PropertyDescriptor) {
251:                    PropertyDescriptor pd = (PropertyDescriptor) desc;
252:                    retval = wrapper.invokeMethod(object, pd.getReadMethod(),
253:                            null);
254:                    // (member == null) condition remains, as we don't cache these
255:                } else if (desc instanceof  Field) {
256:                    retval = wrapper.wrap(((Field) desc).get(object));
257:                    // (member == null) condition remains, as we don't cache these
258:                } else if (desc instanceof  Method) {
259:                    Method method = (Method) desc;
260:                    retval = member = new SimpleMethodModel(object, method,
261:                            BeansWrapper.getArgTypes(classInfo, method),
262:                            wrapper);
263:                } else if (desc instanceof  MethodMap) {
264:                    retval = member = new OverloadedMethodModel(object,
265:                            (MethodMap) desc, wrapper);
266:                }
267:
268:                // If new cacheable member was created, cache it
269:                if (member != null) {
270:                    synchronized (memberMap) {
271:                        memberMap.put(desc, member);
272:                    }
273:                }
274:                return retval;
275:            }
276:
277:            protected TemplateModel invokeGenericGet(Map keyMap, Class clazz,
278:                    String key) throws IllegalAccessException,
279:                    InvocationTargetException, TemplateModelException {
280:                Method genericGet = (Method) keyMap
281:                        .get(BeansWrapper.GENERIC_GET_KEY);
282:                if (genericGet == null)
283:                    return UNKNOWN;
284:
285:                return wrapper.invokeMethod(object, genericGet,
286:                        new Object[] { key });
287:            }
288:
289:            protected TemplateModel wrap(Object obj)
290:                    throws TemplateModelException {
291:                return wrapper.getOuterIdentity().wrap(obj);
292:            }
293:
294:            protected Object unwrap(TemplateModel model)
295:                    throws TemplateModelException {
296:                return wrapper.unwrap(model);
297:            }
298:
299:            /**
300:             * Tells whether the model is empty. It is empty if either the wrapped 
301:             * object is null, or it is a Boolean with false value.
302:             */
303:            public boolean isEmpty() {
304:                if (object instanceof  String) {
305:                    return ((String) object).length() == 0;
306:                }
307:                if (object instanceof  Collection) {
308:                    return ((Collection) object).isEmpty();
309:                }
310:                if (object instanceof  Map) {
311:                    return ((Map) object).isEmpty();
312:                }
313:                return object == null || Boolean.FALSE.equals(object);
314:            }
315:
316:            public Object getAdaptedObject(Class hint) {
317:                return object;
318:            }
319:
320:            public Object getWrappedObject() {
321:                return object;
322:            }
323:
324:            public int size() {
325:                return wrapper.keyCount(object.getClass());
326:            }
327:
328:            public TemplateCollectionModel keys() {
329:                return new CollectionAndSequence(new SimpleSequence(keySet(),
330:                        wrapper));
331:            }
332:
333:            public TemplateCollectionModel values()
334:                    throws TemplateModelException {
335:                List values = new ArrayList(size());
336:                TemplateModelIterator it = keys().iterator();
337:                while (it.hasNext()) {
338:                    String key = ((TemplateScalarModel) it.next())
339:                            .getAsString();
340:                    values.add(get(key));
341:                }
342:                return new CollectionAndSequence(new SimpleSequence(values,
343:                        wrapper));
344:            }
345:
346:            public String toString() {
347:                return object.toString();
348:            }
349:
350:            /**
351:             * Helper method to support TemplateHashModelEx. Returns the Set of
352:             * Strings which are available via the TemplateHashModel
353:             * interface. Subclasses that override <tt>invokeGenericGet</tt> to
354:             * provide additional hash keys should also override this method.
355:             */
356:            protected Set keySet() {
357:                return wrapper.keySet(object.getClass());
358:            }
359:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.