View Javadoc

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