1 33 34 package bsh; 35 36 import java.net.*; 37 import java.util.*; 38 import java.io.IOException ; 39 import java.io.*; 40 import java.lang.reflect.Method ; 41 import java.lang.reflect.Modifier ; 42 43 59 80 public class BshClassManager 81 { 82 83 private static Object NOVALUE = new Object (); 84 88 private Interpreter declaringInterpreter; 89 90 93 protected ClassLoader externalClassLoader; 94 95 100 protected transient Hashtable absoluteClassCache = new Hashtable(); 101 106 protected transient Hashtable absoluteNonClasses = new Hashtable(); 107 108 113 protected transient Hashtable resolvedObjectMethods = new Hashtable(); 114 protected transient Hashtable resolvedStaticMethods = new Hashtable(); 115 116 protected transient Hashtable definingClasses = new Hashtable(); 117 protected transient Hashtable definingClassesBaseNames = new Hashtable(); 118 119 126 public static BshClassManager createClassManager( Interpreter interpreter ) 127 { 128 BshClassManager manager; 129 130 if ( Capabilities.classExists("java.lang.ref.WeakReference") 132 && Capabilities.classExists("java.util.HashMap") 133 && Capabilities.classExists("bsh.classpath.ClassManagerImpl") 134 ) 135 try { 136 Class clas = Class.forName( "bsh.classpath.ClassManagerImpl" ); 139 manager = (BshClassManager)clas.newInstance(); 140 } catch ( Exception e ) { 141 throw new InterpreterError("Error loading classmanager: "+e); 142 } 143 else 144 manager = new BshClassManager(); 145 146 if ( interpreter == null ) 147 interpreter = new Interpreter(); 148 manager.declaringInterpreter = interpreter; 149 return manager; 150 } 151 152 public boolean classExists( String name ) { 153 return ( classForName( name ) != null ); 154 } 155 156 164 public Class classForName( String name ) 165 { 166 if ( isClassBeingDefined( name ) ) 167 throw new InterpreterError( 168 "Attempting to load class in the process of being defined: " 169 +name ); 170 171 Class clas = null; 172 try { 173 clas = plainClassForName( name ); 174 } catch ( ClassNotFoundException e ) { } 175 176 if ( clas == null ) 178 clas = loadSourceClass( name ); 179 180 return clas; 181 } 182 183 protected Class loadSourceClass( String name ) 185 { 186 String fileName = "/"+name.replace('.','/')+".java"; 187 InputStream in = getResourceAsStream( fileName ); 188 if ( in == null ) 189 return null; 190 191 try { 192 System.out.println("Loading class from source file: "+fileName); 193 declaringInterpreter.eval( new InputStreamReader(in) ); 194 } catch ( EvalError e ) { 195 System.err.println( e ); 197 } 198 try { 199 return plainClassForName( name ); 200 } catch ( ClassNotFoundException e ) { 201 System.err.println("Class not found in source file: "+name ); 202 return null; 203 } 204 } 205 206 220 public Class plainClassForName( String name ) 221 throws ClassNotFoundException 222 { 223 Class c = null; 224 225 try { 226 if ( externalClassLoader != null ) 227 c = externalClassLoader.loadClass( name ); 228 else 229 c = Class.forName( name ); 230 231 cacheClassInfo( name, c ); 232 233 243 } catch ( NoClassDefFoundError e ) { 244 throw noClassDefFound( name, e ); 245 } 246 247 return c; 248 } 249 250 254 public URL getResource( String path ) 255 { 256 URL url = null; 257 if ( externalClassLoader != null ) 258 { 259 url = externalClassLoader.getResource( path.substring(1) ); 261 } 262 if ( url == null ) 263 url = Interpreter.class.getResource( path ); 264 265 return url; 266 } 267 271 public InputStream getResourceAsStream( String path ) 272 { 273 InputStream in = null; 274 if ( externalClassLoader != null ) 275 { 276 in = externalClassLoader.getResourceAsStream( path.substring(1) ); 278 } 279 if ( in == null ) 280 in = Interpreter.class.getResourceAsStream( path ); 281 282 return in; 283 } 284 285 292 public void cacheClassInfo( String name, Class value ) { 293 if ( value != null ) 294 absoluteClassCache.put( name, value ); 295 else 296 absoluteNonClasses.put( name, NOVALUE ); 297 } 298 299 305 public void cacheResolvedMethod( 306 Class clas, Class [] types, Method method ) 307 { 308 if ( Interpreter.DEBUG ) 309 Interpreter.debug( 310 "cacheResolvedMethod putting: " + clas +" "+ method ); 311 312 SignatureKey sk = new SignatureKey( clas, method.getName(), types ); 313 if ( Modifier.isStatic( method.getModifiers() ) ) 314 resolvedStaticMethods.put( sk, method ); 315 else 316 resolvedObjectMethods.put( sk, method ); 317 } 318 319 324 protected Method getResolvedMethod( 325 Class clas, String methodName, Class [] types, boolean onlyStatic ) 326 { 327 SignatureKey sk = new SignatureKey( clas, methodName, types ); 328 329 Method method = (Method )resolvedStaticMethods.get( sk ); 332 if ( method == null && !onlyStatic) 333 method = (Method )resolvedObjectMethods.get( sk ); 334 335 if ( Interpreter.DEBUG ) 336 { 337 if ( method == null ) 338 Interpreter.debug( 339 "getResolvedMethod cache MISS: " + clas +" - "+methodName ); 340 else 341 Interpreter.debug( 342 "getResolvedMethod cache HIT: " + clas +" - " +method ); 343 } 344 return method; 345 } 346 347 351 protected void clearCaches() 352 { 353 absoluteNonClasses = new Hashtable(); 354 absoluteClassCache = new Hashtable(); 355 resolvedObjectMethods = new Hashtable(); 356 resolvedStaticMethods = new Hashtable(); 357 } 358 359 370 public void setClassLoader( ClassLoader externalCL ) 371 { 372 externalClassLoader = externalCL; 373 classLoaderChanged(); 374 } 375 376 public void addClassPath( URL path ) 377 throws IOException { 378 } 379 380 383 public void reset() { 384 clearCaches(); 385 } 386 387 391 public void setClassPath( URL [] cp ) 392 throws UtilEvalError 393 { 394 throw cmUnavailable(); 395 } 396 397 403 public void reloadAllClasses() throws UtilEvalError { 404 throw cmUnavailable(); 405 } 406 407 412 public void reloadClasses( String [] classNames ) 413 throws UtilEvalError 414 { 415 throw cmUnavailable(); 416 } 417 418 424 public void reloadPackage( String pack ) 425 throws UtilEvalError 426 { 427 throw cmUnavailable(); 428 } 429 430 437 438 442 protected void doSuperImport() 443 throws UtilEvalError 444 { 445 throw cmUnavailable(); 446 } 447 448 451 protected boolean hasSuperImport() 452 { 453 return false; 454 } 455 456 460 protected String getClassNameByUnqName( String name ) 461 throws UtilEvalError 462 { 463 throw cmUnavailable(); 464 } 465 466 public void addListener( Listener l ) { } 467 468 public void removeListener( Listener l ) { } 469 470 public void dump( PrintWriter pw ) { 471 pw.println("BshClassManager: no class manager."); 472 } 473 474 478 487 protected void definingClass( String className ) { 488 String baseName = Name.suffix(className,1); 489 int i = baseName.indexOf("$"); 490 if ( i != -1 ) 491 baseName = baseName.substring(i+1); 492 String cur = (String )definingClassesBaseNames.get( baseName ); 493 if ( cur != null ) 494 throw new InterpreterError("Defining class problem: "+className 495 +": BeanShell cannot yet simultaneously define two or more " 496 +"dependant classes of the same name. Attempt to define: " 497 + className +" while defining: "+cur 498 ); 499 definingClasses.put( className, NOVALUE ); 500 definingClassesBaseNames.put( baseName, className ); 501 } 502 503 protected boolean isClassBeingDefined( String className ) { 504 return definingClasses.get( className ) != null; 505 } 506 507 511 protected String getClassBeingDefined( String className ) { 512 String baseName = Name.suffix(className,1); 513 return (String )definingClassesBaseNames.get( baseName ); 514 } 515 516 520 protected void doneDefiningClass( String className ) { 521 String baseName = Name.suffix(className,1); 522 definingClasses.remove( className ); 523 definingClassesBaseNames.remove( baseName ); 524 } 525 526 530 public Class defineClass( String name, byte [] code ) 531 { 532 throw new InterpreterError("Can't create class ("+name 533 +") without class manager package."); 534 559 } 560 561 protected void classLoaderChanged() { } 562 563 567 protected static Error noClassDefFound( String className, Error e ) { 568 return new NoClassDefFoundError ( 569 "A class required by class: "+className +" could not be loaded:\n" 570 +e.toString() ); 571 } 572 573 protected static UtilEvalError cmUnavailable() { 574 return new Capabilities.Unavailable( 575 "ClassLoading features unavailable."); 576 } 577 578 public static interface Listener 579 { 580 public void classLoaderChanged(); 581 } 582 583 588 598 static class SignatureKey 599 { 600 Class clas; 601 Class [] types; 602 String methodName; 603 int hashCode = 0; 604 605 SignatureKey( Class clas, String methodName, Class [] types ) { 606 this.clas = clas; 607 this.methodName = methodName; 608 this.types = types; 609 } 610 611 public int hashCode() 612 { 613 if ( hashCode == 0 ) 614 { 615 hashCode = clas.hashCode() * methodName.hashCode(); 616 if ( types == null ) return hashCode; 618 for( int i =0; i < types.length; i++ ) { 619 int hc = types[i] == null ? 21 : types[i].hashCode(); 620 hashCode = hashCode*(i+1) + hc; 621 } 622 } 623 return hashCode; 624 } 625 626 public boolean equals( Object o ) { 627 SignatureKey target = (SignatureKey)o; 628 if ( types == null ) 629 return target.types == null; 630 if ( clas != target.clas ) 631 return false; 632 if ( !methodName.equals( target.methodName ) ) 633 return false; 634 if ( types.length != target.types.length ) 635 return false; 636 for( int i =0; i< types.length; i++ ) 637 { 638 if ( types[i]==null ) 639 { 640 if ( !(target.types[i]==null) ) 641 return false; 642 } else 643 if ( !types[i].equals( target.types[i] ) ) 644 return false; 645 } 646 647 return true; 648 } 649 } 650 } 651 | Popular Tags |