KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > util > internal > cache > PropertyCache


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * $Header:$
17  */

18 package org.apache.beehive.netui.util.internal.cache;
19
20 import java.beans.Introspector JavaDoc;
21 import java.beans.IntrospectionException JavaDoc;
22 import java.beans.PropertyDescriptor JavaDoc;
23 import java.lang.reflect.Method JavaDoc;
24 import java.lang.reflect.Modifier JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27
28 import org.apache.beehive.netui.util.internal.concurrent.InternalConcurrentHashMap;
29 import org.apache.beehive.netui.util.logging.Logger;
30
31 /**
32  * The PropertyCache is used to track the JavaBean properties and public
33  * fields of a set of classes that are stored in the cache. This implementation
34  * provides a significant speed-up when looking-up reflected metadata
35  * of Java classes. It is primarily used in the NetUI expression engine
36  * to provide fast access to the properties and fields of classes
37  * against which expressions are being evaluated.
38  */

39 public final class PropertyCache {
40
41     private static final Logger LOGGER = Logger.getInstance(PropertyCache.class);
42
43     private final InternalConcurrentHashMap _classCache;
44
45     public PropertyCache() {
46         _classCache = new InternalConcurrentHashMap();
47     }
48
49     /**
50      * Get an array of {@link java.beans.PropertyDescriptor} objects that
51      * describe JavaBean properties of the given <code>_type</code>. This
52      * array <b>should not</b> be modified.
53      *
54      * @param type the {@link java.lang.Class} whose JavaBean properties to find
55      * @return an array of {@link java.beans.PropertyDescriptor} objects that describe the JavaBean properties
56      */

57     public final PropertyDescriptor JavaDoc[] getPropertyDescriptors(Class JavaDoc type) {
58         CachedClass cc = getCachedClass(type);
59         return (cc != null ? cc.getPropertyDescriptors() : null);
60     }
61
62     public final Method JavaDoc getPropertyGetter(Class JavaDoc type, String JavaDoc property) {
63         CachedClass cc = getCachedClass(type);
64         if(cc == null)
65             return null;
66         CachedProperty cp = cc.getProperty(property);
67         return (cp != null ? cp.getReadMethod() : null);
68     }
69
70     public final Method JavaDoc getPropertySetter(Class JavaDoc type, String JavaDoc property) {
71         CachedClass cc = getCachedClass(type);
72         if(cc == null)
73             return null;
74         CachedProperty cp = cc.getProperty(property);
75         return (cp != null ? cp.getWriteMethod() : null);
76     }
77
78     public final Class JavaDoc getPropertyType(Class JavaDoc type, String JavaDoc property) {
79         CachedClass cc = getCachedClass(type);
80         if(cc == null)
81             return null;
82         CachedProperty cp = cc.getProperty(property);
83         return (cp != null ? cp.getType() : null);
84     }
85
86     private final CachedClass getCachedClass(Class JavaDoc type) {
87         Object JavaDoc obj = _classCache.get(type);
88         if(obj == null) {
89             try {
90                 obj = new CachedClass(type);
91                 _classCache.put(type, obj);
92             } catch(Exception JavaDoc e) {
93                 LOGGER.error("Error introspecting a class of _type \"" + type + "\" when determining its JavaBean property info", e);
94                 return null;
95             }
96         }
97
98         return (CachedClass)obj;
99     }
100
101     /**
102      *
103      */

104     private class CachedClass {
105
106         private Class JavaDoc _type = null;
107         private HashMap JavaDoc _properties = null;
108         private PropertyDescriptor JavaDoc[] _propertyDescriptors = null;
109
110         CachedClass(Class JavaDoc type)
111             throws IntrospectionException JavaDoc {
112             this._type = type;
113             init(type);
114         }
115
116         private void init(Class JavaDoc type)
117             throws IntrospectionException JavaDoc {
118             _properties = new HashMap JavaDoc();
119
120             if(Modifier.isPublic(type.getModifiers())) {
121                 PropertyDescriptor JavaDoc[] pds = Introspector.getBeanInfo(type).getPropertyDescriptors();
122                 for(int i = 0; i < pds.length; i++) {
123                     _properties.put(pds[i].getName(), new CachedProperty(pds[i]));
124                 }
125             }
126             // not looking at a public class, get all of the JavaBean PDs off of its interfaces
127
else {
128                 // look on the public interfaces on this class and all superclasses
129
for(Class JavaDoc c = type; c != null; c = c.getSuperclass()) {
130                     Class JavaDoc[] interfaces = c.getInterfaces();
131                     for(int i = 0; i < interfaces.length; i++) {
132                         Class JavaDoc iface = interfaces[i];
133                         if(Modifier.isPublic(iface.getModifiers())) {
134                             PropertyDescriptor JavaDoc[] pds = Introspector.getBeanInfo(iface).getPropertyDescriptors();
135                             for(int j = 0; j < pds.length; j++) {
136                                 if(!_properties.containsKey(pds[j].getName()))
137                                     _properties.put(pds[j].getName(), new CachedProperty(pds[j]));
138                             }
139                         }
140                     }
141                 }
142
143                 // look on the nearest public base class
144
Class JavaDoc baseClass = type.getSuperclass();
145                 while(!Modifier.isPublic(baseClass.getModifiers())) {
146                     baseClass = baseClass.getSuperclass();
147                 }
148
149                 PropertyDescriptor JavaDoc[] pds = Introspector.getBeanInfo(baseClass).getPropertyDescriptors();
150                 for(int j = 0; j < pds.length; j++) {
151                     if(!_properties.containsKey(pds[j].getName()))
152                         _properties.put(pds[j].getName(), new CachedProperty(pds[j]));
153                 }
154             }
155
156             if(_properties.size() > 0) {
157                 _propertyDescriptors = new PropertyDescriptor JavaDoc[_properties.size()];
158                 Iterator JavaDoc iterator = _properties.values().iterator();
159                 for(int i = 0; iterator.hasNext(); i++) {
160                     _propertyDescriptors[i] = ((CachedProperty)iterator.next()).getPropertyDescriptor();
161                 }
162             }
163         }
164
165         PropertyDescriptor JavaDoc[] getPropertyDescriptors() {
166             return _propertyDescriptors;
167         }
168
169         CachedProperty getProperty(String JavaDoc name) {
170             return (CachedProperty)_properties.get(name);
171         }
172     }
173
174     /**
175      *
176      */

177     private class CachedProperty {
178
179         private Method JavaDoc _readMethod = null;
180         private Method JavaDoc _writeMethod = null;
181         private String JavaDoc _name = null;
182         private PropertyDescriptor JavaDoc _pd = null;
183         private Class JavaDoc _type = null;
184
185         CachedProperty(PropertyDescriptor JavaDoc pd) {
186             _pd = pd;
187             _name = pd.getName();
188             _readMethod = pd.getReadMethod();
189             _writeMethod = pd.getWriteMethod();
190             _type = pd.getPropertyType();
191         }
192
193         PropertyDescriptor JavaDoc getPropertyDescriptor() {
194             return _pd;
195         }
196
197         Method JavaDoc getReadMethod() {
198             return _readMethod;
199         }
200
201         Method JavaDoc getWriteMethod() {
202             return _writeMethod;
203         }
204
205         String JavaDoc getName() {
206             return _name;
207         }
208
209         Class JavaDoc getType() {
210             return _type;
211         }
212     }
213 }
214
Popular Tags