bsh.classpath
Class ClassManagerImpl

java.lang.Object
  |
  +--bsh.BshClassManager
        |
        +--bsh.classpath.ClassManagerImpl

public class ClassManagerImpl
extends BshClassManager

        Manage all classloading in BeanShell.
        Allows classpath extension and class file reloading.

        This class holds the implementation of the BshClassManager so that it
        can be separated from the core package.

        This class currently relies on 1.2 for BshClassLoader and weak references.
        Is there a workaround for weak refs?  If so we could make this work
        with 1.1 by supplying our own classloader code...

        See "http://www.beanshell.org/manual/classloading.html" for details
        on the bsh classloader architecture.

        Bsh has a multi-tiered class loading architecture.  No class loader is
        used unless/until the classpath is modified or a class is reloaded.

        Note: we may need some synchronization in here

        Note on jdk1.2 dependency:

        We are forced to use weak references here to accomodate all of the
        fleeting namespace listeners.  (NameSpaces must be informed if the class
        space changes so that they can un-cache names).  I had the interesting
        thought that a way around this would be to implement BeanShell's own
        garbage collector...  Then I came to my senses and said - screw it,
        class re-loading will require 1.2.
        


Nested Class Summary
 
Nested classes inherited from class bsh.BshClassManager
BshClassManager.Listener
 
Field Summary
private  BshClassPath baseClassPath
          The classpath of the base loader.
private  BshClassLoader baseLoader
          This handles extension / modification of the base classpath The loader to use where no mapping of reloaded classes exists.
private  BshClassPath fullClassPath
          This is the full blown classpath including baseClassPath (extensions), user path, and java bootstrap path (rt.jar) This is lazily constructed and further (and more importantly) lazily intialized in components because mapping the full path could be expensive.
private  java.util.Vector listeners
           
private  java.util.Map loaderMap
          Map by classname of loaders to use for reloaded classes
private  java.lang.ref.ReferenceQueue refQueue
           
 
Fields inherited from class bsh.BshClassManager
absoluteClassCache, absoluteNonClasses
 
Constructor Summary
ClassManagerImpl()
          Used by BshClassManager singleton constructor
 
Method Summary
 void addClassPath(java.net.URL path)
           
 void addListener(BshClassManager.Listener l)
           
protected  void classLoaderChanged()
          Clear global class cache and notify namespaces to clear their class caches.
 void doSuperImport()
          Support for "import *;" Hide details in here as opposed to NameSpace.
 void dump(java.io.PrintWriter i)
           
 java.lang.ClassLoader getBaseLoader()
           
 java.lang.Class getClassForName(java.lang.String name)
           
 java.lang.String getClassNameByUnqName(java.lang.String name)
          Return the name or null if none is found, Throw an ClassPathException containing detail if name is ambigous.
 BshClassPath getClassPath()
          Get the full blown classpath.
 java.lang.ClassLoader getLoaderForClass(java.lang.String name)
           
 java.lang.Class getPlainClassForName(java.lang.String name)
          Delegate for bottom level implementation of Class.forName().
private  void initBaseLoader()
          init the baseLoader from the baseClassPath
 void reloadAllClasses()
          Overlay the entire path with a new class loader.
 void reloadClasses(java.lang.String[] classNames)
          Reloading classes means creating a new classloader and using it whenever we are asked for classes in the appropriate space.
 void reloadPackage(java.lang.String pack)
          Reload all classes in the specified package: e.g.
 void removeListener(BshClassManager.Listener l)
           
 void reset()
          Clear all loaders and start over.
 void setClassPath(java.net.URL[] cp)
          Set a new base classpath and create a new base classloader.
 
Methods inherited from class bsh.BshClassManager
addCMListener, cacheClassInfo, classExists, classForName, clearCaches, getClassManager, plainClassForName, setClassLoader
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

baseClassPath

private BshClassPath baseClassPath
The classpath of the base loader. Initially empty. This grows as paths are added or is reset when the classpath is explicitly set. This could also be called the "extension" class path, but is not strictly confined to added path (could be set arbitrarily by setClassPath())


fullClassPath

private BshClassPath fullClassPath
This is the full blown classpath including baseClassPath (extensions), user path, and java bootstrap path (rt.jar) This is lazily constructed and further (and more importantly) lazily intialized in components because mapping the full path could be expensive. The full class path is a composite of: baseClassPath (user extension) : userClassPath : bootClassPath in that order.


listeners

private java.util.Vector listeners

refQueue

private java.lang.ref.ReferenceQueue refQueue

baseLoader

private BshClassLoader baseLoader
This handles extension / modification of the base classpath The loader to use where no mapping of reloaded classes exists. The baseLoader is initially null meaning no class loader is used.


loaderMap

private java.util.Map loaderMap
Map by classname of loaders to use for reloaded classes

Constructor Detail

ClassManagerImpl

public ClassManagerImpl()
Used by BshClassManager singleton constructor

Method Detail

getClassForName

public java.lang.Class getClassForName(java.lang.String name)
Specified by:
getClassForName in class BshClassManager
Returns:
the class or null
See Also:
BshClassManager.classForName( String )

getPlainClassForName

public java.lang.Class getPlainClassForName(java.lang.String name)
                                     throws java.lang.ClassNotFoundException
Delegate for bottom level implementation of Class.forName(). This is here solely to provide for Java version specific features. In this case - the Thread getContextClassLoader() which is required to get bsh to see user classpath when it's installed in the lib/ext directory.

Specified by:
getPlainClassForName in class BshClassManager
java.lang.ClassNotFoundException
See Also:
BshClassManager.plainClassForName()

getBaseLoader

public java.lang.ClassLoader getBaseLoader()
Specified by:
getBaseLoader in class BshClassManager

getLoaderForClass

public java.lang.ClassLoader getLoaderForClass(java.lang.String name)
Specified by:
getLoaderForClass in class BshClassManager

addClassPath

public void addClassPath(java.net.URL path)
                  throws java.io.IOException
Specified by:
addClassPath in class BshClassManager
java.io.IOException

reset

public void reset()
Clear all loaders and start over. No class loading.

Specified by:
reset in class BshClassManager

setClassPath

public void setClassPath(java.net.URL[] cp)
Set a new base classpath and create a new base classloader. This means all types change.

Specified by:
setClassPath in class BshClassManager

reloadAllClasses

public void reloadAllClasses()
                      throws ClassPathException
Overlay the entire path with a new class loader. Set the base path to the user path + base path. No point in including the boot class path (can't reload thos).

Specified by:
reloadAllClasses in class BshClassManager
ClassPathException

initBaseLoader

private void initBaseLoader()
init the baseLoader from the baseClassPath


reloadClasses

public void reloadClasses(java.lang.String[] classNames)
                   throws ClassPathException
Reloading classes means creating a new classloader and using it whenever we are asked for classes in the appropriate space. For this we use a DiscreteFilesClassLoader

Specified by:
reloadClasses in class BshClassManager
ClassPathException

reloadPackage

public void reloadPackage(java.lang.String pack)
                   throws ClassPathException
Reload all classes in the specified package: e.g. "com.sun.tools" The special package name "" can be used to refer to unpackaged classes.

Specified by:
reloadPackage in class BshClassManager
ClassPathException

getClassPath

public BshClassPath getClassPath()
                          throws ClassPathException
Get the full blown classpath.

ClassPathException

doSuperImport

public void doSuperImport()
                   throws EvalError
Support for "import *;" Hide details in here as opposed to NameSpace.

Specified by:
doSuperImport in class BshClassManager
EvalError

getClassNameByUnqName

public java.lang.String getClassNameByUnqName(java.lang.String name)
                                       throws ClassPathException
Return the name or null if none is found, Throw an ClassPathException containing detail if name is ambigous.

Specified by:
getClassNameByUnqName in class BshClassManager
ClassPathException

addListener

public void addListener(BshClassManager.Listener l)
Specified by:
addListener in class BshClassManager

removeListener

public void removeListener(BshClassManager.Listener l)
Specified by:
removeListener in class BshClassManager

classLoaderChanged

protected void classLoaderChanged()
Clear global class cache and notify namespaces to clear their class caches. The listener list is implemented with weak references so that we will not keep every namespace in existence forever.

Specified by:
classLoaderChanged in class BshClassManager

dump

public void dump(java.io.PrintWriter i)
Specified by:
dump in class BshClassManager