1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.tomcat.util;
19
20 import java.io.File;
21 import java.io.FilenameFilter;
22 import java.io.IOException;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.net.InetAddress;
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.net.UnknownHostException;
29 import java.util.Hashtable;
30 import java.util.StringTokenizer;
31 import java.util.Vector;
32
33 // Depends: JDK1.1
34
35 /**
36 * Utils for introspection and reflection
37 */
38 public final class IntrospectionUtils {
39
40
41 private static org.apache.juli.logging.Log log=
42 org.apache.juli.logging.LogFactory.getLog( IntrospectionUtils.class );
43
44 /**
45 * Call execute() - any ant-like task should work
46 */
47 public static void execute(Object proxy, String method) throws Exception {
48 Method executeM = null;
49 Class c = proxy.getClass();
50 Class params[] = new Class[0];
51 // params[0]=args.getClass();
52 executeM = findMethod(c, method, params);
53 if (executeM == null) {
54 throw new RuntimeException("No execute in " + proxy.getClass());
55 }
56 executeM.invoke(proxy, (Object[]) null);//new Object[] { args });
57 }
58
59 /**
60 * Call void setAttribute( String ,Object )
61 */
62 public static void setAttribute(Object proxy, String n, Object v)
63 throws Exception {
64 if (proxy instanceof AttributeHolder) {
65 ((AttributeHolder) proxy).setAttribute(n, v);
66 return;
67 }
68
69 Method executeM = null;
70 Class c = proxy.getClass();
71 Class params[] = new Class[2];
72 params[0] = String.class;
73 params[1] = Object.class;
74 executeM = findMethod(c, "setAttribute", params);
75 if (executeM == null) {
76 if (log.isDebugEnabled())
77 log.debug("No setAttribute in " + proxy.getClass());
78 return;
79 }
80 if (false)
81 if (log.isDebugEnabled())
82 log.debug("Setting " + n + "=" + v + " in " + proxy);
83 executeM.invoke(proxy, new Object[] { n, v });
84 return;
85 }
86
87 /**
88 * Call void getAttribute( String )
89 */
90 public static Object getAttribute(Object proxy, String n) throws Exception {
91 Method executeM = null;
92 Class c = proxy.getClass();
93 Class params[] = new Class[1];
94 params[0] = String.class;
95 executeM = findMethod(c, "getAttribute", params);
96 if (executeM == null) {
97 if (log.isDebugEnabled())
98 log.debug("No getAttribute in " + proxy.getClass());
99 return null;
100 }
101 return executeM.invoke(proxy, new Object[] { n });
102 }
103
104 /**
105 * Construct a URLClassLoader. Will compile and work in JDK1.1 too.
106 */
107 public static ClassLoader getURLClassLoader(URL urls[], ClassLoader parent) {
108 try {
109 Class urlCL = Class.forName("java.net.URLClassLoader");
110 Class paramT[] = new Class[2];
111 paramT[0] = urls.getClass();
112 paramT[1] = ClassLoader.class;
113 Method m = findMethod(urlCL, "newInstance", paramT);
114 if (m == null)
115 return null;
116
117 ClassLoader cl = (ClassLoader) m.invoke(urlCL, new Object[] { urls,
118 parent });
119 return cl;
120 } catch (ClassNotFoundException ex) {
121 // jdk1.1
122 return null;
123 } catch (Exception ex) {
124 ex.printStackTrace();
125 return null;
126 }
127 }
128
129 public static String guessInstall(String installSysProp,
130 String homeSysProp, String jarName) {
131 return guessInstall(installSysProp, homeSysProp, jarName, null);
132 }
133
134 /**
135 * Guess a product install/home by analyzing the class path. It works for
136 * product using the pattern: lib/executable.jar or if executable.jar is
137 * included in classpath by a shell script. ( java -jar also works )
138 *
139 * Insures both "install" and "home" System properties are set. If either or
140 * both System properties are unset, "install" and "home" will be set to the
141 * same value. This value will be the other System property that is set, or
142 * the guessed value if neither is set.
143 */
144 public static String guessInstall(String installSysProp,
145 String homeSysProp, String jarName, String classFile) {
146 String install = null;
147 String home = null;
148
149 if (installSysProp != null)
150 install = System.getProperty(installSysProp);
151
152 if (homeSysProp != null)
153 home = System.getProperty(homeSysProp);
154
155 if (install != null) {
156 if (home == null)
157 System.getProperties().put(homeSysProp, install);
158 return install;
159 }
160
161 // Find the directory where jarName.jar is located
162
163 String cpath = System.getProperty("java.class.path");
164 String pathSep = System.getProperty("path.separator");
165 StringTokenizer st = new StringTokenizer(cpath, pathSep);
166 while (st.hasMoreTokens()) {
167 String path = st.nextToken();
168 // log( "path " + path );
169 if (path.endsWith(jarName)) {
170 home = path.substring(0, path.length() - jarName.length());
171 try {
172 if ("".equals(home)) {
173 home = new File("./").getCanonicalPath();
174 } else if (home.endsWith(File.separator)) {
175 home = home.substring(0, home.length() - 1);
176 }
177 File f = new File(home);
178 String parentDir = f.getParent();
179 if (parentDir == null)
180 parentDir = home; // unix style
181 File f1 = new File(parentDir);
182 install = f1.getCanonicalPath();
183 if (installSysProp != null)
184 System.getProperties().put(installSysProp, install);
185 if (home == null && homeSysProp != null)
186 System.getProperties().put(homeSysProp, install);
187 return install;
188 } catch (Exception ex) {
189 ex.printStackTrace();
190 }
191 } else {
192 String fname = path + (path.endsWith("/") ? "" : "/")
193 + classFile;
194 if (new File(fname).exists()) {
195 try {
196 File f = new File(path);
197 String parentDir = f.getParent();
198 if (parentDir == null)
199 parentDir = path; // unix style
200 File f1 = new File(parentDir);
201 install = f1.getCanonicalPath();
202 if (installSysProp != null)
203 System.getProperties().put(installSysProp, install);
204 if (home == null && homeSysProp != null)
205 System.getProperties().put(homeSysProp, install);
206 return install;
207 } catch (Exception ex) {
208 ex.printStackTrace();
209 }
210 }
211 }
212 }
213
214 // if install directory can't be found, use home as the default
215 if (home != null) {
216 System.getProperties().put(installSysProp, home);
217 return home;
218 }
219
220 return null;
221 }
222
223 /**
224 * Debug method, display the classpath
225 */
226 public static void displayClassPath(String msg, URL[] cp) {
227 if (log.isDebugEnabled()) {
228 log.debug(msg);
229 for (int i = 0; i < cp.length; i++) {
230 log.debug(cp[i].getFile());
231 }
232 }
233 }
234
235 public static String PATH_SEPARATOR = System.getProperty("path.separator");
236
237 /**
238 * Adds classpath entries from a vector of URL's to the "tc_path_add" System
239 * property. This System property lists the classpath entries common to web
240 * applications. This System property is currently used by Jasper when its
241 * JSP servlet compiles the Java file for a JSP.
242 */
243 public static String classPathAdd(URL urls[], String cp) {
244 if (urls == null)
245 return cp;
246
247 for (int i = 0; i < urls.length; i++) {
248 if (cp != null)
249 cp += PATH_SEPARATOR + urls[i].getFile();
250 else
251 cp = urls[i].getFile();
252 }
253 return cp;
254 }
255
256 /**
257 * Find a method with the right name If found, call the method ( if param is
258 * int or boolean we'll convert value to the right type before) - that means
259 * you can have setDebug(1).
260 */
261 public static boolean setProperty(Object o, String name, String value) {
262 if (dbg > 1)
263 d("setProperty(" + o.getClass() + " " + name + "=" + value + ")");
264
265 String setter = "set" + capitalize(name);
266
267 try {
268 Method methods[] = findMethods(o.getClass());
269 Method setPropertyMethodVoid = null;
270 Method setPropertyMethodBool = null;
271
272 // First, the ideal case - a setFoo( String ) method
273 for (int i = 0; i < methods.length; i++) {
274 Class paramT[] = methods[i].getParameterTypes();
275 if (setter.equals(methods[i].getName()) && paramT.length == 1
276 && "java.lang.String".equals(paramT[0].getName())) {
277
278 methods[i].invoke(o, new Object[] { value });
279 return true;
280 }
281 }
282
283 // Try a setFoo ( int ) or ( boolean )
284 for (int i = 0; i < methods.length; i++) {
285 boolean ok = true;
286 if (setter.equals(methods[i].getName())
287 && methods[i].getParameterTypes().length == 1) {
288
289 // match - find the type and invoke it
290 Class paramType = methods[i].getParameterTypes()[0];
291 Object params[] = new Object[1];
292
293 // Try a setFoo ( int )
294 if ("java.lang.Integer".equals(paramType.getName())
295 || "int".equals(paramType.getName())) {
296 try {
297 params[0] = new Integer(value);
298 } catch (NumberFormatException ex) {
299 ok = false;
300 }
301 // Try a setFoo ( long )
302 }else if ("java.lang.Long".equals(paramType.getName())
303 || "long".equals(paramType.getName())) {
304 try {
305 params[0] = new Long(value);
306 } catch (NumberFormatException ex) {
307 ok = false;
308 }
309
310 // Try a setFoo ( boolean )
311 } else if ("java.lang.Boolean".equals(paramType.getName())
312 || "boolean".equals(paramType.getName())) {
313 params[0] = new Boolean(value);
314
315 // Try a setFoo ( InetAddress )
316 } else if ("java.net.InetAddress".equals(paramType
317 .getName())) {
318 try {
319 params[0] = InetAddress.getByName(value);
320 } catch (UnknownHostException exc) {
321 d("Unable to resolve host name:" + value);
322 ok = false;
323 }
324
325 // Unknown type
326 } else {
327 d("Unknown type " + paramType.getName());
328 }
329
330 if (ok) {
331 methods[i].invoke(o, params);
332 return true;
333 }
334 }
335
336 // save "setProperty" for later
337 if ("setProperty".equals(methods[i].getName())) {
338 if (methods[i].getReturnType()==Boolean.TYPE){
339 setPropertyMethodBool = methods[i];
340 }else {
341 setPropertyMethodVoid = methods[i];
342 }
343
344 }
345 }
346
347 // Ok, no setXXX found, try a setProperty("name", "value")
348 if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
349 Object params[] = new Object[2];
350 params[0] = name;
351 params[1] = value;
352 if (setPropertyMethodBool != null) {
353 try {
354 return (Boolean) setPropertyMethodBool.invoke(o, params);
355 }catch (IllegalArgumentException biae) {
356 //the boolean method had the wrong
357 //parameter types. lets try the other
358 if (setPropertyMethodVoid!=null) {
359 setPropertyMethodVoid.invoke(o, params);
360 return true;
361 }else {
362 throw biae;
363 }
364 }
365 } else {
366 setPropertyMethodVoid.invoke(o, params);
367 return true;
368 }
369 }
370
371 } catch (IllegalArgumentException ex2) {
372 log.warn("IAE " + o + " " + name + " " + value, ex2);
373 } catch (SecurityException ex1) {
374 if (dbg > 0)
375 d("SecurityException for " + o.getClass() + " " + name + "="
376 + value + ")");
377 if (dbg > 1)
378 ex1.printStackTrace();
379 } catch (IllegalAccessException iae) {
380 if (dbg > 0)
381 d("IllegalAccessException for " + o.getClass() + " " + name
382 + "=" + value + ")");
383 if (dbg > 1)
384 iae.printStackTrace();
385 } catch (InvocationTargetException ie) {
386 if (dbg > 0)
387 d("InvocationTargetException for " + o.getClass() + " " + name
388 + "=" + value + ")");
389 if (dbg > 1)
390 ie.printStackTrace();
391 }
392 return false;
393 }
394
395 public static Object getProperty(Object o, String name) {
396 String getter = "get" + capitalize(name);
397 String isGetter = "is" + capitalize(name);
398
399 try {
400 Method methods[] = findMethods(o.getClass());
401 Method getPropertyMethod = null;
402
403 // First, the ideal case - a getFoo() method
404 for (int i = 0; i < methods.length; i++) {
405 Class paramT[] = methods[i].getParameterTypes();
406 if (getter.equals(methods[i].getName()) && paramT.length == 0) {
407 return methods[i].invoke(o, (Object[]) null);
408 }
409 if (isGetter.equals(methods[i].getName()) && paramT.length == 0) {
410 return methods[i].invoke(o, (Object[]) null);
411 }
412
413 if ("getProperty".equals(methods[i].getName())) {
414 getPropertyMethod = methods[i];
415 }
416 }
417
418 // Ok, no setXXX found, try a getProperty("name")
419 if (getPropertyMethod != null) {
420 Object params[] = new Object[1];
421 params[0] = name;
422 return getPropertyMethod.invoke(o, params);
423 }
424
425 } catch (IllegalArgumentException ex2) {
426 log.warn("IAE " + o + " " + name, ex2);
427 } catch (SecurityException ex1) {
428 if (dbg > 0)
429 d("SecurityException for " + o.getClass() + " " + name + ")");
430 if (dbg > 1)
431 ex1.printStackTrace();
432 } catch (IllegalAccessException iae) {
433 if (dbg > 0)
434 d("IllegalAccessException for " + o.getClass() + " " + name
435 + ")");
436 if (dbg > 1)
437 iae.printStackTrace();
438 } catch (InvocationTargetException ie) {
439 if (dbg > 0)
440 d("InvocationTargetException for " + o.getClass() + " " + name
441 + ")");
442 if (dbg > 1)
443 ie.printStackTrace();
444 }
445 return null;
446 }
447
448 /**
449 */
450 public static void setProperty(Object o, String name) {
451 String setter = "set" + capitalize(name);
452 try {
453 Method methods[] = findMethods(o.getClass());
454 Method setPropertyMethod = null;
455 // find setFoo() method
456 for (int i = 0; i < methods.length; i++) {
457 Class paramT[] = methods[i].getParameterTypes();
458 if (setter.equals(methods[i].getName()) && paramT.length == 0) {
459 methods[i].invoke(o, new Object[] {});
460 return;
461 }
462 }
463 } catch (Exception ex1) {
464 if (dbg > 0)
465 d("Exception for " + o.getClass() + " " + name);
466 if (dbg > 1)
467 ex1.printStackTrace();
468 }
469 }
470
471 /**
472 * Replace ${NAME} with the property value
473 *
474 * @deprecated Use the explicit method
475 */
476 public static String replaceProperties(String value, Object getter) {
477 if (getter instanceof Hashtable)
478 return replaceProperties(value, (Hashtable) getter, null);
479
480 if (getter instanceof PropertySource) {
481 PropertySource src[] = new PropertySource[] { (PropertySource) getter };
482 return replaceProperties(value, null, src);
483 }
484 return value;
485 }
486
487 /**
488 * Replace ${NAME} with the property value
489 */
490 public static String replaceProperties(String value, Hashtable staticProp,
491 PropertySource dynamicProp[]) {
492 StringBuffer sb = new StringBuffer();
493 int prev = 0;
494 // assert value!=nil
495 int pos;
496 while ((pos = value.indexOf("$", prev)) >= 0) {
497 if (pos > 0) {
498 sb.append(value.substring(prev, pos));
499 }
500 if (pos == (value.length() - 1)) {
501 sb.append('$');
502 prev = pos + 1;
503 } else if (value.charAt(pos + 1) != '{') {
504 sb.append('$');
505 prev = pos + 1; // XXX
506 } else {
507 int endName = value.indexOf('}', pos);
508 if (endName < 0) {
509 sb.append(value.substring(pos));
510 prev = value.length();
511 continue;
512 }
513 String n = value.substring(pos + 2, endName);
514 String v = null;
515 if (staticProp != null) {
516 v = (String) ((Hashtable) staticProp).get(n);
517 }
518 if (v == null && dynamicProp != null) {
519 for (int i = 0; i < dynamicProp.length; i++) {
520 v = dynamicProp[i].getProperty(n);
521 if (v != null) {
522 break;
523 }
524 }
525 }
526 if (v == null)
527 v = "${" + n + "}";
528
529 sb.append(v);
530 prev = endName + 1;
531 }
532 }
533 if (prev < value.length())
534 sb.append(value.substring(prev));
535 return sb.toString();
536 }
537
538 /**
539 * Reverse of Introspector.decapitalize
540 */
541 public static String capitalize(String name) {
542 if (name == null || name.length() == 0) {
543 return name;
544 }
545 char chars[] = name.toCharArray();
546 chars[0] = Character.toUpperCase(chars[0]);
547 return new String(chars);
548 }
549
550 public static String unCapitalize(String name) {
551 if (name == null || name.length() == 0) {
552 return name;
553 }
554 char chars[] = name.toCharArray();
555 chars[0] = Character.toLowerCase(chars[0]);
556 return new String(chars);
557 }
558
559 // -------------------- Class path tools --------------------
560
561 /**
562 * Add all the jar files in a dir to the classpath, represented as a Vector
563 * of URLs.
564 */
565 public static void addToClassPath(Vector cpV, String dir) {
566 try {
567 String cpComp[] = getFilesByExt(dir, ".jar");
568 if (cpComp != null) {
569 int jarCount = cpComp.length;
570 for (int i = 0; i < jarCount; i++) {
571 URL url = getURL(dir, cpComp[i]);
572 if (url != null)
573 cpV.addElement(url);
574 }
575 }
576 } catch (Exception ex) {
577 ex.printStackTrace();
578 }
579 }
580
581 public static void addToolsJar(Vector v) {
582 try {
583 // Add tools.jar in any case
584 File f = new File(System.getProperty("java.home")
585 + "/../lib/tools.jar");
586
587 if (!f.exists()) {
588 // On some systems java.home gets set to the root of jdk.
589 // That's a bug, but we can work around and be nice.
590 f = new File(System.getProperty("java.home") + "/lib/tools.jar");
591 if (f.exists()) {
592 if (log.isDebugEnabled())
593 log.debug("Detected strange java.home value "
594 + System.getProperty("java.home")
595 + ", it should point to jre");
596 }
597 }
598 URL url = new URL("file", "", f.getAbsolutePath());
599
600 v.addElement(url);
601 } catch (MalformedURLException ex) {
602 ex.printStackTrace();
603 }
604 }
605
606 /**
607 * Return all files with a given extension in a dir
608 */
609 public static String[] getFilesByExt(String ld, String ext) {
610 File dir = new File(ld);
611 String[] names = null;
612 final String lext = ext;
613 if (dir.isDirectory()) {
614 names = dir.list(new FilenameFilter() {
615 public boolean accept(File d, String name) {
616 if (name.endsWith(lext)) {
617 return true;
618 }
619 return false;
620 }
621 });
622 }
623 return names;
624 }
625
626 /**
627 * Construct a file url from a file, using a base dir
628 */
629 public static URL getURL(String base, String file) {
630 try {
631 File baseF = new File(base);
632 File f = new File(baseF, file);
633 String path = f.getCanonicalPath();
634 if (f.isDirectory()) {
635 path += "/";
636 }
637 if (!f.exists())
638 return null;
639 return new URL("file", "", path);
640 } catch (Exception ex) {
641 ex.printStackTrace();
642 return null;
643 }
644 }
645
646 /**
647 * Add elements from the classpath <i>cp </i> to a Vector <i>jars </i> as
648 * file URLs (We use Vector for JDK 1.1 compat).
649 * <p>
650 *
651 * @param jars The jar list
652 * @param cp a String classpath of directory or jar file elements
653 * separated by path.separator delimiters.
654 * @throws IOException If an I/O error occurs
655 * @throws MalformedURLException Doh ;)
656 */
657 public static void addJarsFromClassPath(Vector jars, String cp)
658 throws IOException, MalformedURLException {
659 String sep = System.getProperty("path.separator");
660 String token;
661 StringTokenizer st;
662 if (cp != null) {
663 st = new StringTokenizer(cp, sep);
664 while (st.hasMoreTokens()) {
665 File f = new File(st.nextToken());
666 String path = f.getCanonicalPath();
667 if (f.isDirectory()) {
668 path += "/";
669 }
670 URL url = new URL("file", "", path);
671 if (!jars.contains(url)) {
672 jars.addElement(url);
673 }
674 }
675 }
676 }
677
678 /**
679 * Return a URL[] that can be used to construct a class loader
680 */
681 public static URL[] getClassPath(Vector v) {
682 URL[] urls = new URL[v.size()];
683 for (int i = 0; i < v.size(); i++) {
684 urls[i] = (URL) v.elementAt(i);
685 }
686 return urls;
687 }
688
689 /**
690 * Construct a URL classpath from files in a directory, a cpath property,
691 * and tools.jar.
692 */
693 public static URL[] getClassPath(String dir, String cpath,
694 String cpathProp, boolean addTools) throws IOException,
695 MalformedURLException {
696 Vector jarsV = new Vector();
697 if (dir != null) {
698 // Add dir/classes first, if it exists
699 URL url = getURL(dir, "classes");
700 if (url != null)
701 jarsV.addElement(url);
702 addToClassPath(jarsV, dir);
703 }
704
705 if (cpath != null)
706 addJarsFromClassPath(jarsV, cpath);
707
708 if (cpathProp != null) {
709 String cpath1 = System.getProperty(cpathProp);
710 addJarsFromClassPath(jarsV, cpath1);
711 }
712
713 if (addTools)
714 addToolsJar(jarsV);
715
716 return getClassPath(jarsV);
717 }
718
719 // -------------------- Mapping command line params to setters
720
721 public static boolean processArgs(Object proxy, String args[])
722 throws Exception {
723 String args0[] = null;
724 if (null != findMethod(proxy.getClass(), "getOptions1", new Class[] {})) {
725 args0 = (String[]) callMethod0(proxy, "getOptions1");
726 }
727
728 if (args0 == null) {
729 //args0=findVoidSetters(proxy.getClass());
730 args0 = findBooleanSetters(proxy.getClass());
731 }
732 Hashtable h = null;
733 if (null != findMethod(proxy.getClass(), "getOptionAliases",
734 new Class[] {})) {
735 h = (Hashtable) callMethod0(proxy, "getOptionAliases");
736 }
737 return processArgs(proxy, args, args0, null, h);
738 }
739
740 public static boolean processArgs(Object proxy, String args[],
741 String args0[], String args1[], Hashtable aliases) throws Exception {
742 for (int i = 0; i < args.length; i++) {
743 String arg = args[i];
744 if (arg.startsWith("-"))
745 arg = arg.substring(1);
746 if (aliases != null && aliases.get(arg) != null)
747 arg = (String) aliases.get(arg);
748
749 if (args0 != null) {
750 boolean set = false;
751 for (int j = 0; j < args0.length; j++) {
752 if (args0[j].equalsIgnoreCase(arg)) {
753 setProperty(proxy, args0[j], "true");
754 set = true;
755 break;
756 }
757 }
758 if (set)
759 continue;
760 }
761 if (args1 != null) {
762 for (int j = 0; j < args1.length; j++) {
763 if (args1[j].equalsIgnoreCase(arg)) {
764 i++;
765 if (i >= args.length)
766 return false;
767 setProperty(proxy, arg, args[i]);
768 break;
769 }
770 }
771 } else {
772 // if args1 is not specified,assume all other options have param
773 i++;
774 if (i >= args.length)
775 return false;
776 setProperty(proxy, arg, args[i]);
777 }
778
779 }
780 return true;
781 }
782
783 // -------------------- other utils --------------------
784 public static void clear() {
785 objectMethods.clear();
786 }
787
788 public static String[] findVoidSetters(Class c) {
789 Method m[] = findMethods(c);
790 if (m == null)
791 return null;
792 Vector v = new Vector();
793 for (int i = 0; i < m.length; i++) {
794 if (m[i].getName().startsWith("set")
795 && m[i].getParameterTypes().length == 0) {
796 String arg = m[i].getName().substring(3);
797 v.addElement(unCapitalize(arg));
798 }
799 }
800 String s[] = new String[v.size()];
801 for (int i = 0; i < s.length; i++) {
802 s[i] = (String) v.elementAt(i);
803 }
804 return s;
805 }
806
807 public static String[] findBooleanSetters(Class c) {
808 Method m[] = findMethods(c);
809 if (m == null)
810 return null;
811 Vector v = new Vector();
812 for (int i = 0; i < m.length; i++) {
813 if (m[i].getName().startsWith("set")
814 && m[i].getParameterTypes().length == 1
815 && "boolean".equalsIgnoreCase(m[i].getParameterTypes()[0]
816 .getName())) {
817 String arg = m[i].getName().substring(3);
818 v.addElement(unCapitalize(arg));
819 }
820 }
821 String s[] = new String[v.size()];
822 for (int i = 0; i < s.length; i++) {
823 s[i] = (String) v.elementAt(i);
824 }
825 return s;
826 }
827
828 static Hashtable objectMethods = new Hashtable();
829
830 public static Method[] findMethods(Class c) {
831 Method methods[] = (Method[]) objectMethods.get(c);
832 if (methods != null)
833 return methods;
834
835 methods = c.getMethods();
836 objectMethods.put(c, methods);
837 return methods;
838 }
839
840 public static Method findMethod(Class c, String name, Class params[]) {
841 Method methods[] = findMethods(c);
842 if (methods == null)
843 return null;
844 for (int i = 0; i < methods.length; i++) {
845 if (methods[i].getName().equals(name)) {
846 Class methodParams[] = methods[i].getParameterTypes();
847 if (methodParams == null)
848 if (params == null || params.length == 0)
849 return methods[i];
850 if (params == null)
851 if (methodParams == null || methodParams.length == 0)
852 return methods[i];
853 if (params.length != methodParams.length)
854 continue;
855 boolean found = true;
856 for (int j = 0; j < params.length; j++) {
857 if (params[j] != methodParams[j]) {
858 found = false;
859 break;
860 }
861 }
862 if (found)
863 return methods[i];
864 }
865 }
866 return null;
867 }
868
869 /** Test if the object implements a particular
870 * method
871 */
872 public static boolean hasHook(Object obj, String methodN) {
873 try {
874 Method myMethods[] = findMethods(obj.getClass());
875 for (int i = 0; i < myMethods.length; i++) {
876 if (methodN.equals(myMethods[i].getName())) {
877 // check if it's overriden
878 Class declaring = myMethods[i].getDeclaringClass();
879 Class parentOfDeclaring = declaring.getSuperclass();
880 // this works only if the base class doesn't extend
881 // another class.
882
883 // if the method is declared in a top level class
884 // like BaseInterceptor parent is Object, otherwise
885 // parent is BaseInterceptor or an intermediate class
886 if (!"java.lang.Object".equals(parentOfDeclaring.getName())) {
887 return true;
888 }
889 }
890 }
891 } catch (Exception ex) {
892 ex.printStackTrace();
893 }
894 return false;
895 }
896
897 public static void callMain(Class c, String args[]) throws Exception {
898 Class p[] = new Class[1];
899 p[0] = args.getClass();
900 Method m = c.getMethod("main", p);
901 m.invoke(c, new Object[] { args });
902 }
903
904 public static Object callMethod1(Object target, String methodN,
905 Object param1, String typeParam1, ClassLoader cl) throws Exception {
906 if (target == null || param1 == null) {
907 d("Assert: Illegal params " + target + " " + param1);
908 }
909 if (dbg > 0)
910 d("callMethod1 " + target.getClass().getName() + " "
911 + param1.getClass().getName() + " " + typeParam1);
912
913 Class params[] = new Class[1];
914 if (typeParam1 == null)
915 params[0] = param1.getClass();
916 else
917 params[0] = cl.loadClass(typeParam1);
918 Method m = findMethod(target.getClass(), methodN, params);
919 if (m == null)
920 throw new NoSuchMethodException(target.getClass().getName() + " "
921 + methodN);
922 return m.invoke(target, new Object[] { param1 });
923 }
924
925 public static Object callMethod0(Object target, String methodN)
926 throws Exception {
927 if (target == null) {
928 d("Assert: Illegal params " + target);
929 return null;
930 }
931 if (dbg > 0)
932 d("callMethod0 " + target.getClass().getName() + "." + methodN);
933
934 Class params[] = new Class[0];
935 Method m = findMethod(target.getClass(), methodN, params);
936 if (m == null)
937 throw new NoSuchMethodException(target.getClass().getName() + " "
938 + methodN);
939 return m.invoke(target, emptyArray);
940 }
941
942 static Object[] emptyArray = new Object[] {};
943
944 public static Object callMethodN(Object target, String methodN,
945 Object params[], Class typeParams[]) throws Exception {
946 Method m = null;
947 m = findMethod(target.getClass(), methodN, typeParams);
948 if (m == null) {
949 d("Can't find method " + methodN + " in " + target + " CLASS "
950 + target.getClass());
951 return null;
952 }
953 Object o = m.invoke(target, params);
954
955 if (dbg > 0) {
956 // debug
957 StringBuffer sb = new StringBuffer();
958 sb.append("" + target.getClass().getName() + "." + methodN + "( ");
959 for (int i = 0; i < params.length; i++) {
960 if (i > 0)
961 sb.append(", ");
962 sb.append(params[i]);
963 }
964 sb.append(")");
965 d(sb.toString());
966 }
967 return o;
968 }
969
970 public static Object convert(String object, Class paramType) {
971 Object result = null;
972 if ("java.lang.String".equals(paramType.getName())) {
973 result = object;
974 } else if ("java.lang.Integer".equals(paramType.getName())
975 || "int".equals(paramType.getName())) {
976 try {
977 result = new Integer(object);
978 } catch (NumberFormatException ex) {
979 }
980 // Try a setFoo ( boolean )
981 } else if ("java.lang.Boolean".equals(paramType.getName())
982 || "boolean".equals(paramType.getName())) {
983 result = new Boolean(object);
984
985 // Try a setFoo ( InetAddress )
986 } else if ("java.net.InetAddress".equals(paramType
987 .getName())) {
988 try {
989 result = InetAddress.getByName(object);
990 } catch (UnknownHostException exc) {
991 d("Unable to resolve host name:" + object);
992 }
993
994 // Unknown type
995 } else {
996 d("Unknown type " + paramType.getName());
997 }
998 if (result == null) {
999 throw new IllegalArgumentException("Can't convert argument: " + object);
1000 }
1001 return result;
1002 }
1003
1004 // -------------------- Get property --------------------
1005 // This provides a layer of abstraction
1006
1007 public static interface PropertySource {
1008
1009 public String getProperty(String key);
1010
1011 }
1012
1013 public static interface AttributeHolder {
1014
1015 public void setAttribute(String key, Object o);
1016
1017 }
1018
1019 // debug --------------------
1020 static final int dbg = 0;
1021
1022 static void d(String s) {
1023 if (log.isDebugEnabled())
1024 log.debug("IntrospectionUtils: " + s);
1025 }
1026 }