KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > standard > lang > jstl > BeanInfoManager


1 /*
2  * Copyright 1999-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
17 package org.apache.taglibs.standard.lang.jstl;
18
19 import java.beans.BeanInfo JavaDoc;
20 import java.beans.EventSetDescriptor JavaDoc;
21 import java.beans.IndexedPropertyDescriptor JavaDoc;
22 import java.beans.IntrospectionException JavaDoc;
23 import java.beans.Introspector JavaDoc;
24 import java.beans.PropertyDescriptor JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Modifier JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Map JavaDoc;
29
30 /**
31  *
32  * <p>Manages the BeanInfo for one class - contains the BeanInfo, and
33  * also a mapping from property name to BeanInfoProperty. There are
34  * also static methods for accessing the BeanInfoManager for a class -
35  * those mappings are cached permanently so that once the
36  * BeanInfoManager is calculated, it doesn't have to be calculated
37  * again.
38  *
39  * @author Nathan Abramson - Art Technology Group
40  * @version $Change: 181181 $$DateTime: 2001/06/26 09:55:09 $$Author: pierred $
41  **/

42
43 public class BeanInfoManager
44 {
45   //-------------------------------------
46
// Properties
47
//-------------------------------------
48
// property beanClass
49

50   Class JavaDoc mBeanClass;
51   public Class JavaDoc getBeanClass ()
52   { return mBeanClass; }
53
54   //-------------------------------------
55
// Member variables
56
//-------------------------------------
57

58   // The BeanInfo
59
BeanInfo JavaDoc mBeanInfo;
60
61   // Mapping from property name to BeanInfoProperty
62
Map JavaDoc mPropertyByName;
63
64   // Mapping from property name to BeanInfoIndexedProperty
65
Map JavaDoc mIndexedPropertyByName;
66
67   // Mapping from event set name to event set descriptor
68
Map JavaDoc mEventSetByName;
69
70   // Flag if this is initialized
71
boolean mInitialized;
72
73   // The global mapping from class to BeanInfoManager
74
static Map JavaDoc mBeanInfoManagerByClass = new HashMap JavaDoc ();
75
76   //-------------------------------------
77
/**
78    *
79    * Constructor
80    **/

81   BeanInfoManager (Class JavaDoc pBeanClass)
82   {
83     mBeanClass = pBeanClass;
84   }
85
86   //-------------------------------------
87
/**
88    *
89    * Returns the BeanInfoManager for the specified class
90    **/

91   public static BeanInfoManager getBeanInfoManager (Class JavaDoc pClass)
92   {
93     BeanInfoManager ret = (BeanInfoManager)
94       mBeanInfoManagerByClass.get (pClass);
95     if (ret == null) {
96       ret = createBeanInfoManager (pClass);
97     }
98     return ret;
99   }
100
101   //-------------------------------------
102
/**
103    *
104    * Creates and registers the BeanInfoManager for the given class if
105    * it isn't already registered.
106    **/

107   static synchronized BeanInfoManager createBeanInfoManager (Class JavaDoc pClass)
108   {
109     // Because this method is synchronized statically, the
110
// BeanInfoManager is not initialized at this time (otherwise it
111
// could end up being a bottleneck for the entire system). It is
112
// put into the map in an uninitialized state. The first time
113
// someone tries to use it, it will be initialized (with proper
114
// synchronizations in place to make sure it is only initialized
115
// once).
116

117     BeanInfoManager ret = (BeanInfoManager)
118       mBeanInfoManagerByClass.get (pClass);
119     if (ret == null) {
120       ret = new BeanInfoManager (pClass);
121       mBeanInfoManagerByClass.put (pClass, ret);
122     }
123     return ret;
124   }
125
126   //-------------------------------------
127
/**
128    *
129    * Returns the BeanInfoProperty for the specified property in the
130    * given class, or null if not found.
131    **/

132   public static BeanInfoProperty getBeanInfoProperty
133     (Class JavaDoc pClass,
134      String JavaDoc pPropertyName,
135      Logger pLogger)
136     throws ELException
137   {
138     return getBeanInfoManager (pClass).getProperty (pPropertyName, pLogger);
139   }
140
141   //-------------------------------------
142
/**
143    *
144    * Returns the BeanInfoIndexedProperty for the specified property in
145    * the given class, or null if not found.
146    **/

147   public static BeanInfoIndexedProperty getBeanInfoIndexedProperty
148     (Class JavaDoc pClass,
149      String JavaDoc pIndexedPropertyName,
150      Logger pLogger)
151     throws ELException
152   {
153     return getBeanInfoManager
154       (pClass).getIndexedProperty (pIndexedPropertyName, pLogger);
155   }
156
157   //-------------------------------------
158
/**
159    *
160    * Makes sure that this class has been initialized, and synchronizes
161    * the initialization if it's required.
162    **/

163   void checkInitialized (Logger pLogger)
164     throws ELException
165   {
166     if (!mInitialized) {
167       synchronized (this) {
168     if (!mInitialized) {
169       initialize (pLogger);
170       mInitialized = true;
171     }
172       }
173     }
174   }
175
176   //-------------------------------------
177
/**
178    *
179    * Initializes by mapping property names to BeanInfoProperties
180    **/

181   void initialize (Logger pLogger)
182     throws ELException
183   {
184     try {
185       mBeanInfo = Introspector.getBeanInfo (mBeanClass);
186
187       mPropertyByName = new HashMap JavaDoc ();
188       mIndexedPropertyByName = new HashMap JavaDoc ();
189       PropertyDescriptor JavaDoc [] pds = mBeanInfo.getPropertyDescriptors ();
190       for (int i = 0; pds != null && i < pds.length; i++) {
191     // Treat as both an indexed property and a normal property
192
PropertyDescriptor JavaDoc pd = pds [i];
193     if (pd instanceof IndexedPropertyDescriptor JavaDoc) {
194       IndexedPropertyDescriptor JavaDoc ipd = (IndexedPropertyDescriptor JavaDoc) pd;
195       Method JavaDoc readMethod = getPublicMethod (ipd.getIndexedReadMethod ());
196       Method JavaDoc writeMethod = getPublicMethod (ipd.getIndexedWriteMethod ());
197       BeanInfoIndexedProperty property = new BeanInfoIndexedProperty
198         (readMethod,
199          writeMethod,
200          ipd);
201
202       mIndexedPropertyByName.put (ipd.getName (), property);
203     }
204
205     Method JavaDoc readMethod = getPublicMethod (pd.getReadMethod ());
206     Method JavaDoc writeMethod = getPublicMethod (pd.getWriteMethod ());
207     BeanInfoProperty property = new BeanInfoProperty
208       (readMethod,
209        writeMethod,
210        pd);
211
212     mPropertyByName.put (pd.getName (), property);
213       }
214
215       mEventSetByName = new HashMap JavaDoc ();
216       EventSetDescriptor JavaDoc [] esds = mBeanInfo.getEventSetDescriptors ();
217       for (int i = 0; esds != null && i < esds.length; i++) {
218     EventSetDescriptor JavaDoc esd = esds [i];
219     mEventSetByName.put (esd.getName (), esd);
220       }
221     }
222     catch (IntrospectionException JavaDoc exc) {
223       if (pLogger.isLoggingWarning ()) {
224     pLogger.logWarning
225       (Constants.EXCEPTION_GETTING_BEANINFO,
226        exc,
227        mBeanClass.getName ());
228       }
229     }
230   }
231
232   //-------------------------------------
233
/**
234    *
235    * Returns the BeanInfo for the class
236    **/

237   BeanInfo JavaDoc getBeanInfo (Logger pLogger)
238     throws ELException
239   {
240     checkInitialized (pLogger);
241     return mBeanInfo;
242   }
243
244   //-------------------------------------
245
/**
246    *
247    * Returns the BeanInfoProperty for the given property name, or null
248    * if not found.
249    **/

250   public BeanInfoProperty getProperty (String JavaDoc pPropertyName,
251                        Logger pLogger)
252     throws ELException
253   {
254     checkInitialized (pLogger);
255     return (BeanInfoProperty) mPropertyByName.get (pPropertyName);
256   }
257
258   //-------------------------------------
259
/**
260    *
261    * Returns the BeanInfoIndexedProperty for the given property name,
262    * or null if not found.
263    **/

264   public BeanInfoIndexedProperty getIndexedProperty
265     (String JavaDoc pIndexedPropertyName,
266      Logger pLogger)
267     throws ELException
268   {
269     checkInitialized (pLogger);
270     return (BeanInfoIndexedProperty)
271       mIndexedPropertyByName.get (pIndexedPropertyName);
272   }
273
274   //-------------------------------------
275
/**
276    *
277    * Returns the EventSetDescriptor for the given event set name, or
278    * null if not found.
279    **/

280   public EventSetDescriptor JavaDoc getEventSet (String JavaDoc pEventSetName,
281                      Logger pLogger)
282     throws ELException
283   {
284     checkInitialized (pLogger);
285     return (EventSetDescriptor JavaDoc) mEventSetByName.get (pEventSetName);
286   }
287
288   //-------------------------------------
289
// Finding the public version of a method - if a PropertyDescriptor
290
// is obtained for a non-public class that implements a public
291
// interface, the read/write methods will be for the class, and
292
// therefore inaccessible. To correct this, a version of the same
293
// method must be found in a superclass or interface.
294
//-------------------------------------
295
/**
296    *
297    * Returns a publicly-accessible version of the given method, by
298    * searching for a public declaring class.
299    **/

300   static Method JavaDoc getPublicMethod (Method JavaDoc pMethod)
301   {
302     if (pMethod == null) {
303       return null;
304     }
305
306     // See if the method is already available from a public class
307
Class JavaDoc cl = pMethod.getDeclaringClass ();
308     if (Modifier.isPublic (cl.getModifiers ())) {
309       return pMethod;
310     }
311
312     // Otherwise, try to find a public class that declares the method
313
Method JavaDoc ret = getPublicMethod (cl, pMethod);
314     if (ret != null) {
315       return ret;
316     }
317     else {
318       return pMethod;
319     }
320   }
321
322   //-------------------------------------
323
/**
324    *
325    * If the given class is public and has a Method that declares the
326    * same name and arguments as the given method, then that method is
327    * returned. Otherwise the superclass and interfaces are searched
328    * recursively.
329    **/

330   static Method JavaDoc getPublicMethod (Class JavaDoc pClass,
331                  Method JavaDoc pMethod)
332   {
333     // See if this is a public class declaring the method
334
if (Modifier.isPublic (pClass.getModifiers ())) {
335       try {
336         Method JavaDoc m;
337         try {
338       m = pClass.getDeclaredMethod (pMethod.getName (),
339                          pMethod.getParameterTypes ());
340         } catch (java.security.AccessControlException JavaDoc ex) {
341       // kludge to accommodate J2EE RI's default settings
342
// TODO: see if we can simply replace
343
// getDeclaredMethod() with getMethod() ...?
344
m = pClass.getMethod(pMethod.getName (),
345                                              pMethod.getParameterTypes ());
346         }
347     if (Modifier.isPublic (m.getModifiers ())) {
348       return m;
349     }
350       }
351       catch (NoSuchMethodException JavaDoc exc) {}
352     }
353
354     // Search the interfaces
355
{
356       Class JavaDoc [] interfaces = pClass.getInterfaces ();
357       if (interfaces != null) {
358     for (int i = 0; i < interfaces.length; i++) {
359       Method JavaDoc m = getPublicMethod (interfaces [i], pMethod);
360       if (m != null) {
361         return m;
362       }
363     }
364       }
365     }
366
367     // Search the superclass
368
{
369       Class JavaDoc superclass = pClass.getSuperclass ();
370       if (superclass != null) {
371     Method JavaDoc m = getPublicMethod (superclass, pMethod);
372     if (m != null) {
373       return m;
374     }
375       }
376     }
377
378     return null;
379   }
380
381   //-------------------------------------
382
}
383
Popular Tags