KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nextapp > echo2 > app > componentxml > ComponentIntrospector


1 /*
2  * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3  * Copyright (C) 2002-2005 NextApp, Inc.
4  *
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either the GNU General Public License Version 2 or later (the "GPL"), or
19  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the MPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the MPL, the GPL or the LGPL.
28  */

29
30 package nextapp.echo2.app.componentxml;
31
32 import java.beans.BeanInfo JavaDoc;
33 import java.beans.IndexedPropertyDescriptor JavaDoc;
34 import java.beans.IntrospectionException JavaDoc;
35 import java.beans.Introspector JavaDoc;
36 import java.beans.PropertyDescriptor JavaDoc;
37 import java.lang.reflect.Field JavaDoc;
38 import java.lang.reflect.Method JavaDoc;
39 import java.lang.reflect.Modifier JavaDoc;
40 import java.util.HashMap JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.Map JavaDoc;
43
44 /**
45  * Provides introspection into Echo components.
46  *
47  * A wrapper for JavaBean APIs to preform introspection on
48  * Echo Components. Provides convenience methods to retrieve
49  * available property names, types, and other bean-related
50  * information.
51  */

52 public class ComponentIntrospector {
53
54     /**
55      * Modifier requirements for style constant name fields.
56      */

57     private static final int CONSTANT_MODIFERS = Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL;
58     
59     /**
60      * A map containing references from <code>ClassLoader</code> to
61      * <code>ComponentIntrospector</code> caches.
62      */

63     private static final Map JavaDoc classLoaderCache = new HashMap JavaDoc();
64     
65     /**
66      * Creates a new <code>ComponentIntrospector</code> for a type of
67      * Echo component.
68      *
69      * @param typeName the type name of Echo component
70      * @param classLoader the class loader from which the type class
71      * may be retrieved
72      */

73     public static ComponentIntrospector forName(String JavaDoc typeName, ClassLoader JavaDoc classLoader)
74     throws ClassNotFoundException JavaDoc {
75         // Find or Create Component Introspector Store based on ClassLoader Cache.
76
Map JavaDoc ciStore;
77         synchronized (classLoaderCache) {
78             ciStore = (Map JavaDoc) classLoaderCache.get(classLoader);
79             if (ciStore == null) {
80                 ciStore = new HashMap JavaDoc();
81                 classLoaderCache.put(classLoader, ciStore);
82             }
83         }
84         
85         // Find or Create Component Introspector from Component Introspector Store.
86
ComponentIntrospector ci;
87         synchronized (ciStore) {
88             ci = (ComponentIntrospector) ciStore.get(typeName);
89             if (ci == null) {
90                 ci = new ComponentIntrospector(typeName, classLoader);
91                 ciStore.put(typeName, ci);
92             }
93         }
94         return ci;
95     }
96     
97     
98     private Class JavaDoc componentClass;
99     private BeanInfo JavaDoc beanInfo;
100     private Map JavaDoc constants;
101     
102     /**
103      * A mapping between the component's property names and JavaBean
104      * <code>PropertyDescriptor</code>s.
105      */

106     private Map JavaDoc propertyDescriptorMap = new HashMap JavaDoc();
107     
108     /**
109      * Creates a new <code>ComponentIntrospector</code> for the specified
110      * type.
111      *
112      * @param typeName the component type name
113      */

114     private ComponentIntrospector(String JavaDoc typeName, ClassLoader JavaDoc classLoader)
115     throws ClassNotFoundException JavaDoc {
116         super();
117         componentClass = Class.forName(typeName, true, classLoader);
118         try {
119             beanInfo = Introspector.getBeanInfo(componentClass, Introspector.IGNORE_ALL_BEANINFO);
120         } catch (IntrospectionException JavaDoc ex) {
121             // Should not occur.
122
throw new RuntimeException JavaDoc("Introspection Error", ex);
123         }
124
125         loadConstants();
126         loadPropertyData();
127     }
128
129     /**
130      * Retrieves the names of all constants.
131      * A constant is defined to be any public static final variable
132      * declared in the introspected class.
133      *
134      * @return an iterator over the constant names
135      */

136     public Iterator JavaDoc getConstantNames() {
137         return constants.keySet().iterator();
138     }
139     
140     /**
141      * Retrieves the value of the constant with the specified name.
142      *
143      * @param constantName the name of the constant (unqualified)
144      * @return the constant value, or null if no such constant exists
145      * @see #getConstantNames()
146      */

147     public Object JavaDoc getConstantValue(String JavaDoc constantName) {
148         return constants.get(constantName);
149     }
150     
151     /**
152      * Returns the class being introspected.
153      *
154      * @return the introspected class
155      */

156     public Class JavaDoc getObjectClass() {
157         return componentClass;
158     }
159     
160     /**
161      * Returns the <code>Class</code> of a specific property.
162      *
163      * @param propertyName the name of the property
164      * @return the <code>Class</code> of the property
165      */

166     public Class JavaDoc getPropertyClass(String JavaDoc propertyName) {
167         PropertyDescriptor JavaDoc propertyDescriptor = getPropertyDescriptor(propertyName);
168         if (propertyDescriptor == null) {
169             return null;
170         } else if (propertyDescriptor instanceof IndexedPropertyDescriptor JavaDoc) {
171             return ((IndexedPropertyDescriptor JavaDoc) propertyDescriptor).getIndexedPropertyType();
172         } else {
173             return propertyDescriptor.getPropertyType();
174         }
175     }
176     
177     /**
178      * Returns the <code>PropertyDescriptor</code> for the specified property.
179      *
180      * @param propertyName the name of the property
181      * @return the <code>PropertyDescriptor</code> associated with the property
182      */

183     public PropertyDescriptor JavaDoc getPropertyDescriptor(String JavaDoc propertyName) {
184         return (PropertyDescriptor JavaDoc) propertyDescriptorMap.get(propertyName);
185     }
186
187     /**
188      * Returns a write (setter) method for a specific property.
189      *
190      * @param propertyName the name of the property
191      * @return the write method (if available)
192      */

193     public Method JavaDoc getWriteMethod(String JavaDoc propertyName) {
194         PropertyDescriptor JavaDoc propertyDescriptor = getPropertyDescriptor(propertyName);
195         if (propertyDescriptor == null) {
196             return null;
197         } else {
198             if (propertyDescriptor instanceof IndexedPropertyDescriptor JavaDoc) {
199                 return ((IndexedPropertyDescriptor JavaDoc) propertyDescriptor).getIndexedWriteMethod();
200             } else {
201                 return propertyDescriptor.getWriteMethod();
202             }
203         }
204     }
205     
206     /**
207      * Determines whether a property is an indexed property.
208      *
209      * @param propertyName the name of the property to query
210      * @return true if the specified property is indexed
211      */

212     public boolean isIndexedProperty(String JavaDoc propertyName) {
213         return propertyDescriptorMap.get(propertyName) instanceof IndexedPropertyDescriptor JavaDoc;
214     }
215
216     /**
217      * Initialization method to load data related to style constants.
218      */

219     private void loadConstants() {
220         constants = new HashMap JavaDoc();
221         Field JavaDoc[] fields = componentClass.getFields();
222         for (int index = 0; index < fields.length; ++index) {
223             if ((fields[index].getModifiers() & CONSTANT_MODIFERS) != 0) {
224                 String JavaDoc constantName = fields[index].getName();
225                 try {
226                     Object JavaDoc constantValue = fields[index].get(null);
227                     constants.put(constantName, constantValue);
228                 } catch (IllegalAccessException JavaDoc ex) {
229                     // Should not occur.
230
}
231             }
232         }
233     }
234     
235     /**
236      * Initialization method to load property information.
237      */

238     private void loadPropertyData() {
239         PropertyDescriptor JavaDoc[] propertyDescriptors = beanInfo.getPropertyDescriptors();
240         for (int index = 0; index < propertyDescriptors.length; ++index) {
241             // Limit to mutable properties only.
242

243             if (propertyDescriptors[index] instanceof IndexedPropertyDescriptor JavaDoc) {
244                 if (((IndexedPropertyDescriptor JavaDoc) propertyDescriptors[index]).getIndexedWriteMethod() != null) {
245                     String JavaDoc name = propertyDescriptors[index].getName();
246                     
247                     // Store JavaBean PropertyDescriptor.
248
propertyDescriptorMap.put(name, propertyDescriptors[index]);
249                 }
250             } else {
251                 if (propertyDescriptors[index].getWriteMethod() != null) {
252                     String JavaDoc name = propertyDescriptors[index].getName();
253                     
254                     // Store JavaBean PropertyDescriptor.
255
propertyDescriptorMap.put(name, propertyDescriptors[index]);
256                 }
257             }
258         }
259     }
260 }
261
Popular Tags