KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > util > BeanUtil


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.util;
30
31 import com.caucho.vfs.Path;
32 import com.caucho.vfs.Vfs;
33
34 import java.beans.BeanInfo JavaDoc;
35 import java.beans.PropertyDescriptor JavaDoc;
36 import java.lang.reflect.Constructor JavaDoc;
37 import java.lang.reflect.Method JavaDoc;
38 import java.lang.reflect.Modifier JavaDoc;
39 import java.util.HashMap JavaDoc;
40 import java.util.logging.Logger JavaDoc;
41
42 /**
43  * Bean utilities.
44  */

45 public class BeanUtil {
46   static final Logger JavaDoc log = Log.open(BeanUtil.class);
47   static L10N L = new L10N(BeanUtil.class);
48
49   /**
50    * Returns the bean property type.
51    *
52    * @param obj the bean object
53    * @param name the property name
54    */

55   public static Class JavaDoc
56   getBeanPropertyClass(Object JavaDoc obj, String JavaDoc name)
57   {
58     Method JavaDoc method = getBeanPropertyMethod(obj, name);
59
60     if (method == null)
61       return null;
62
63     Class JavaDoc []paramTypes = method.getParameterTypes();
64     if (paramTypes.length == 1)
65       return paramTypes[0];
66     else
67       return null;
68   }
69
70   /**
71    * Returns the bean property type.
72    *
73    * @param obj the bean object
74    * @param name the property name
75    */

76   public static Method JavaDoc
77   getBeanPropertyMethod(Object JavaDoc obj, String JavaDoc name)
78   {
79     name = configToBeanName(name);
80
81     Class JavaDoc beanClass = obj.getClass();
82     Method JavaDoc method = getSetMethod(beanClass, name);
83
84     if (method == null)
85       method = getAddMethod(beanClass, name);
86
87     return method;
88   }
89
90   public static void
91   validateClass(Class JavaDoc cl, Class JavaDoc parent)
92     throws RegistryException
93   {
94     if (parent.isAssignableFrom(cl)) {
95     }
96     else if (parent.isInterface())
97       throw new RegistryException(L.l("{0} must implement {1}",
98                                       cl.getName(), parent.getName()));
99     else
100       throw new RegistryException(L.l("{0} must extend {1}",
101                                       cl.getName(), parent.getName()));
102
103     if (cl.isInterface())
104       throw new RegistryException(L.l("{0} must be a concrete class.",
105                                       cl.getName()));
106     
107     if (Modifier.isAbstract(cl.getModifiers()))
108       throw new RegistryException(L.l("{0} must not be abstract.",
109                                       cl.getName()));
110     
111     if (! Modifier.isPublic(cl.getModifiers()))
112       throw new RegistryException(L.l("{0} must be public.",
113                                       cl.getName()));
114
115     Constructor JavaDoc zero = null;
116     try {
117       zero = cl.getConstructor(new Class JavaDoc[0]);
118     } catch (Throwable JavaDoc e) {
119     }
120
121     if (zero == null)
122       throw new RegistryException(L.l("{0} must have a public zero-arg constructor.",
123                                       cl.getName()));
124   }
125
126   /**
127    * Returns the native path for a configured path name. The special cases
128    * $app-dir and $resin-home specify the root directory.
129    *
130    * @param pathName the configuration path name.
131    * @param varMap the map of path variables.
132    * @param pwd the default path.
133    *
134    * @return a real path corresponding to the path name
135    */

136   public static Path lookupPath(String JavaDoc pathName, HashMap JavaDoc varMap, Path pwd)
137   {
138     if (pwd == null)
139       pwd = Vfs.lookup();
140     
141     if (pathName.startsWith("$")) {
142       int p = pathName.indexOf('/');
143       String JavaDoc prefix;
144       String JavaDoc suffix;
145       
146       if (p > 0) {
147         prefix = pathName.substring(1, p);
148         suffix = pathName.substring(p + 1);
149       }
150       else {
151         prefix = pathName.substring(1);
152         suffix = null;
153       }
154
155       Object JavaDoc value = varMap != null ? varMap.get(prefix) : null;
156       if (value instanceof Path) {
157         pwd = (Path) value;
158         pathName = suffix;
159       }
160     }
161
162     if (pathName == null)
163       return pwd;
164     else if (pathName.indexOf('$') < 0)
165       return pwd.lookup(pathName);
166     
167     CharBuffer cb = CharBuffer.allocate();
168     int head = 0;
169     int tail = 0;
170     while ((tail = pathName.indexOf('$', head)) >= 0) {
171       cb.append(pathName.substring(head, tail));
172
173       if (tail + 1 == pathName.length()) {
174         cb.append('$');
175         continue;
176       }
177
178       int ch = pathName.charAt(tail + 1);
179       
180       if (ch >= '0' && ch <= '9') {
181         for (head = tail + 1; head < pathName.length(); head++) {
182           ch = pathName.charAt(head);
183         
184           if (ch < '0' || ch > '9')
185             break;
186         }
187       }
188       else {
189         for (head = tail + 1; head < pathName.length(); head++) {
190           ch = pathName.charAt(head);
191         
192           if (ch == '/' || ch == '\\' || ch == '$' || ch == ' ')
193             break;
194         }
195       }
196
197       String JavaDoc key = pathName.substring(tail + 1, head);
198       Object JavaDoc value = varMap != null ? varMap.get(key) : null;
199
200       if (value == null)
201         value = System.getProperty(key);
202
203       if (value != null)
204         cb.append(value);
205       else
206         cb.append(pathName.substring(tail, head));
207     }
208
209     if (head > 0 && head < pathName.length())
210       cb.append(pathName.substring(head));
211     
212     return pwd.lookupNative(cb.close());
213   }
214
215   /**
216    * Translates a configuration name to a bean name.
217    *
218    * <pre>
219    * foo-bar maps to fooBar
220    * </pre>
221    */

222   private static String JavaDoc configToBeanName(String JavaDoc name)
223   {
224     CharBuffer cb = CharBuffer.allocate();
225
226     for (int i = 0; i < name.length(); i++) {
227       char ch = name.charAt(i);
228       
229       if (ch == '-')
230         cb.append(Character.toUpperCase(name.charAt(++i)));
231       else
232         cb.append(ch);
233     }
234
235     return cb.close();
236   }
237
238   /**
239    * Returns an add method matching the name.
240    */

241   private static Method JavaDoc getAddMethod(Class JavaDoc cl, String JavaDoc name)
242   {
243     name = "add" + name;
244
245     Method JavaDoc []methods = cl.getMethods();
246
247     for (int i = 0; i < methods.length; i++) {
248       if (! Modifier.isPublic(methods[i].getModifiers()))
249         continue;
250
251       if (! name.equalsIgnoreCase(methods[i].getName()))
252         continue;
253
254       if (methods[i].getParameterTypes().length == 1)
255         return methods[i];
256     }
257
258     return null;
259   }
260
261   /**
262    * Returns the method matching the name.
263    */

264   static private Method JavaDoc getMethod(Method JavaDoc []methods, String JavaDoc name)
265   {
266     Method JavaDoc method = null;
267     for (int i = 0; i < methods.length; i++) {
268       method = methods[i];
269
270       if (! Modifier.isPublic(method.getModifiers()))
271           continue;
272       
273       if (! Modifier.isPublic(method.getDeclaringClass().getModifiers()))
274           continue;
275       
276       if (method.getName().equals(name))
277         return method;
278     }
279
280     return null;
281   }
282
283   /**
284    * Returns the method matching the name.
285    */

286   static private Method JavaDoc getMethod(Method JavaDoc []methods, String JavaDoc name,
287                                   Class JavaDoc []params)
288   {
289     Method JavaDoc method = null;
290
291     loop:
292     for (int i = 0; i < methods.length; i++) {
293       method = methods[i];
294       
295       if (! Modifier.isPublic(method.getModifiers()))
296         continue;
297       
298       if (! Modifier.isPublic(method.getDeclaringClass().getModifiers()))
299         continue;
300       
301       if (! method.getName().equals(name))
302         continue;
303
304       Class JavaDoc []actual = method.getParameterTypes();
305
306       if (actual.length != params.length)
307         continue;
308
309       for (int j = 0; j < actual.length; j++) {
310         if (! actual[j].isAssignableFrom(params[j]))
311           continue loop;
312       }
313       
314       return method;
315     }
316
317     return null;
318   }
319   
320   /**
321    * Returns a set method matching the property name.
322    */

323   public static Method JavaDoc getSetMethod(BeanInfo JavaDoc info, String JavaDoc propertyName)
324   {
325     PropertyDescriptor JavaDoc []pds = info.getPropertyDescriptors();
326
327     Method JavaDoc method = null;
328     for (int i = 0; i < pds.length; i++) {
329       if (pds[i].getName().equals(propertyName) &&
330           pds[i].getWriteMethod() != null) {
331         method = pds[i].getWriteMethod();
332
333         if (method.getParameterTypes()[0].equals(String JavaDoc.class))
334           return method;
335       }
336     }
337
338     if (method != null)
339       return method;
340
341     return getSetMethod(info.getBeanDescriptor().getBeanClass(), propertyName);
342   }
343   
344   /**
345    * Returns a set method matching the property name.
346    */

347   public static Method JavaDoc getSetMethod(Class JavaDoc cl, String JavaDoc propertyName)
348   {
349     Method JavaDoc method = getSetMethod(cl, propertyName, false);
350
351     if (method != null)
352       return method;
353
354     return getSetMethod(cl, propertyName, true);
355   }
356
357   /**
358    * Returns a set method matching the property name.
359    */

360   public static Method JavaDoc getSetMethod(Class JavaDoc cl,
361                                     String JavaDoc propertyName,
362                                     boolean ignoreCase)
363   {
364     String JavaDoc setName = "set" + propertyNameToMethodName(propertyName);
365
366     Method JavaDoc bestMethod = null;
367     
368     for (Class JavaDoc ptrCl = cl; ptrCl != null; ptrCl = ptrCl.getSuperclass()) {
369       Method JavaDoc method = getSetMethod(ptrCl.getMethods(),
370                                    setName,
371                                    ignoreCase);
372
373       if (method != null && method.getParameterTypes()[0].equals(String JavaDoc.class))
374         return method;
375       else if (method != null)
376         bestMethod = method;
377     }
378
379     if (bestMethod != null)
380       return bestMethod;
381
382     Class JavaDoc []interfaces = cl.getInterfaces();
383     for (int i = 0; i < interfaces.length; i++) {
384       Method JavaDoc method = getSetMethod(interfaces[i].getMethods(),
385                                    setName,
386                                    ignoreCase);
387
388       if (method != null && method.getParameterTypes()[0].equals(String JavaDoc.class))
389         return method;
390       else if (method != null)
391         bestMethod = method;
392     }
393
394     if (bestMethod != null)
395       return bestMethod;
396
397     return null;
398   }
399
400   /**
401    * Finds the matching set method
402    *
403    * @param method the methods for the class
404    * @param setName the method name
405    */

406   private static Method JavaDoc getSetMethod(Method JavaDoc []methods,
407                                      String JavaDoc setName,
408                                      boolean ignoreCase)
409   {
410     for (int i = 0; i < methods.length; i++) {
411       Method JavaDoc method = methods[i];
412
413       // The method name must match
414
if (! ignoreCase && ! method.getName().equals(setName))
415         continue;
416       
417       // The method name must match
418
if (ignoreCase && ! method.getName().equalsIgnoreCase(setName))
419         continue;
420       
421       // The method must be public
422
if (! Modifier.isPublic(method.getModifiers()))
423         continue;
424
425       // It must be in a public class or interface
426
if (! Modifier.isPublic(method.getDeclaringClass().getModifiers()))
427         continue;
428
429       // It must have a single parameter
430
if (method.getParameterTypes().length != 1)
431         continue;
432       
433       // It must return void
434
if (method.getReturnType().equals(void.class)) {
435         return method;
436       }
437     }
438
439     return null;
440   }
441   
442   /**
443    * Returns a set method matching the property name.
444    */

445   public static Method JavaDoc getGetMethod(BeanInfo JavaDoc info, String JavaDoc propertyName)
446   {
447     PropertyDescriptor JavaDoc []pds = info.getPropertyDescriptors();
448
449     for (int i = 0; i < pds.length; i++) {
450       if (pds[i].getName().equals(propertyName) &&
451           pds[i].getReadMethod() != null) {
452     if (! Modifier.isPublic(pds[i].getReadMethod().getDeclaringClass().getModifiers())) {
453       try {
454         pds[i].getReadMethod().setAccessible(true);
455       } catch (Throwable JavaDoc e) {
456         continue;
457       }
458     }
459     
460         return pds[i].getReadMethod();
461     }
462     }
463
464     return getGetMethod(info.getBeanDescriptor().getBeanClass(), propertyName);
465   }
466
467   /**
468    * Returns a get method matching the property name.
469    */

470   public static Method JavaDoc getGetMethod(Class JavaDoc cl, String JavaDoc propertyName)
471   {
472     Method JavaDoc method = getGetMethod(cl, propertyName, false);
473
474     if (method != null)
475       return method;
476     
477     return getGetMethod(cl, propertyName, true);
478   }
479
480   /**
481    * Returns a get method matching the property name.
482    */

483   public static Method JavaDoc getGetMethod(Class JavaDoc cl,
484                                     String JavaDoc propertyName,
485                                     boolean ignoreCase)
486   {
487     String JavaDoc getName = "get" + propertyNameToMethodName(propertyName);
488     String JavaDoc isName = "is" + propertyNameToMethodName(propertyName);
489
490     for (Class JavaDoc ptrCl = cl; ptrCl != null; ptrCl = ptrCl.getSuperclass()) {
491       Method JavaDoc method = getGetMethod(ptrCl.getDeclaredMethods(), getName,
492                                    isName, ignoreCase);
493
494       if (method != null)
495         return method;
496
497       Class JavaDoc []interfaces = ptrCl.getInterfaces();
498       for (int i = 0; i < interfaces.length; i++) {
499     method = getGetMethod(interfaces[i].getDeclaredMethods(),
500                   getName, isName, ignoreCase);
501
502     if (method != null)
503       return method;
504       }
505     }
506
507     return null;
508   }
509
510   /**
511    * Finds the matching set method
512    *
513    * @param method the methods for the class
514    * @param setName the method name
515    */

516   private static Method JavaDoc getGetMethod(Method JavaDoc []methods,
517                                      String JavaDoc getName,
518                                      String JavaDoc isName,
519                                      boolean ignoreCase)
520   {
521     for (int i = 0; i < methods.length; i++) {
522       Method JavaDoc method = methods[i];
523
524       // The method must be public
525
if (! Modifier.isPublic(method.getModifiers()))
526         continue;
527
528       // It must be in a public class or interface
529
if (! Modifier.isPublic(method.getDeclaringClass().getModifiers()))
530         continue;
531
532       // It must have no parameters
533
if (method.getParameterTypes().length != 0)
534         continue;
535       
536       // It must not return void
537
if (method.getReturnType().equals(void.class))
538         continue;
539
540       // If it matches the get name, it's the right method
541
else if (! ignoreCase && methods[i].getName().equals(getName))
542         return methods[i];
543       
544       // If it matches the get name, it's the right method
545
else if (ignoreCase && methods[i].getName().equalsIgnoreCase(getName))
546         return methods[i];
547
548       // The is methods must return boolean
549
else if (! methods[i].getReturnType().equals(boolean.class))
550         continue;
551       
552       // If it matches the is name, it must return boolean
553
else if (! ignoreCase && methods[i].getName().equals(isName))
554         return methods[i];
555       
556       // If it matches the is name, it must return boolean
557
else if (ignoreCase && methods[i].getName().equalsIgnoreCase(isName))
558         return methods[i];
559     }
560
561     return null;
562   }
563
564   /**
565    * Converts a user's property name to a bean method name.
566    *
567    * @param propertyName the user property name
568    * @return the equivalent bean method name
569    */

570   public static String JavaDoc propertyNameToMethodName(String JavaDoc propertyName)
571   {
572     char ch = propertyName.charAt(0);
573     if (Character.isLowerCase(ch))
574       propertyName = Character.toUpperCase(ch) + propertyName.substring(1);
575
576     return propertyName;
577   }
578
579   /**
580    * Converts a user's property name to a bean method name.
581    *
582    * @param methodName the method name
583    * @return the equivalent property name
584    */

585   public static String JavaDoc methodNameToPropertyName(BeanInfo JavaDoc info,
586                                                 String JavaDoc methodName)
587   {
588     PropertyDescriptor JavaDoc []pds = info.getPropertyDescriptors();
589
590     for (int i = 0; i < pds.length; i++) {
591       if (pds[i].getReadMethod() != null &&
592           pds[i].getReadMethod().getName().equals(methodName))
593         return pds[i].getName();
594       if (pds[i].getWriteMethod() != null &&
595           pds[i].getWriteMethod().getName().equals(methodName))
596         return pds[i].getName();
597     }
598
599     return methodNameToPropertyName(methodName);
600   }
601
602   /**
603    * Converts a user's property name to a bean method name.
604    *
605    * @param methodName the method name
606    * @return the equivalent property name
607    */

608   public static String JavaDoc methodNameToPropertyName(String JavaDoc methodName)
609   {
610     if (methodName.startsWith("get"))
611       methodName = methodName.substring(3);
612     else if (methodName.startsWith("set"))
613       methodName = methodName.substring(3);
614     else if (methodName.startsWith("is"))
615       methodName = methodName.substring(2);
616
617     if (methodName.length() == 0)
618       return null;
619
620     char ch = methodName.charAt(0);
621     if (Character.isUpperCase(ch) &&
622         (methodName.length() == 1 ||
623          ! Character.isUpperCase(methodName.charAt(1)))) {
624       methodName = Character.toLowerCase(ch) + methodName.substring(1);
625     }
626
627     return methodName;
628   }
629 }
630
Popular Tags