001         package com.croftsoft.core.lang.classloader;
002    
003         /*********************************************************************
004         * <P>
005         * Assumes that Java 1.1 is being used and classes are cached as the
006         * default behavior as part of the defineClass() method.
007         * <P>
008         * This should be upgraded when the switch is made from Java 1.1 to
009         * Java 1.2.
010         * <P>
011         * <B>
012         * References
013         * </B>
014         * Scott Oaks, <U>Java Security</U>, O'Reilly, 1998.
015         * <P>
016         * @version
017         *   1998-05-25
018         * @author
019         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
020         *********************************************************************/
021    
022         public abstract class  CustomClassLoader extends ClassLoader
023         //////////////////////////////////////////////////////////////////////
024         //////////////////////////////////////////////////////////////////////
025         {
026    
027         /*********************************************************************
028         * Parses the package name out of a full class name.
029         * Returns the empty string ("") if the class is not in a package.
030         *********************************************************************/
031         public static String  parsePackageName ( String  className )
032         //////////////////////////////////////////////////////////////////////
033         {
034           String  packageName = "";
035           int  i = className.lastIndexOf ( '.' );
036           if ( i > -1 ) packageName = className.substring ( 0, i );
037           return packageName;
038         }
039    
040         /*********************************************************************
041         * Returns the Class of the given name.
042         * <P>
043         * Calls loadClassData() if the class was not previously loaded and
044         *   is not a system class.
045         *********************************************************************/
046         public Class  loadClass ( String  name,  boolean resolve )
047         //////////////////////////////////////////////////////////////////////
048         // See Ch. 3, "Java Class Loaders", "Implementing a Class Loader",
049         // pp44-45.
050         //////////////////////////////////////////////////////////////////////
051         {
052           // Step 1 -- Check for a previously loaded class
053           Class  c = findLoadedClass ( name );
054           if ( c != null ) return c;
055    
056           // Step 2 -- Check to make sure that we can access this class
057           String  packageName = null;
058           SecurityManager  securityManager = System.getSecurityManager ( );
059           if ( securityManager != null )
060           {
061             packageName = parsePackageName ( name );
062    // What if in "default" package?
063             securityManager.checkPackageAccess ( packageName );
064           }
065    
066           // Step 3 -- Check for system class first
067           try
068           {
069             c = findSystemClass ( name );
070             if ( c != null ) return c;
071           }
072           catch ( ClassNotFoundException  ex ) { }
073    
074           // Step 4 -- Check to make sure that we can define this class
075           if ( securityManager != null )
076           {
077             securityManager.checkPackageDefinition ( packageName );
078           }
079    
080           // Step 5 -- Read in the class file
081           byte [ ]  data = loadClassData ( name );
082           if ( data == null ) return null;
083    
084           // Step 6 and 7 -- Define the class from the data;
085           // this also passes the data through the bytecode verifier
086           c = defineClass ( name, data, 0, data.length );
087    
088           // Step 8 -- Resolve the internal references of the class
089           if ( resolve ) resolveClass ( c );
090    
091           return c;
092         }
093    
094         /*********************************************************************
095         * Implement to load the raw bytecode from an external source.
096         * @return
097         *   May return null on failure.
098         *********************************************************************/
099    // Better to thrown an exception than to return null.
100         protected abstract byte [ ]  loadClassData ( String  name );
101    
102         /*********************************************************************
103         * Calls getSystemResource(name).
104         *********************************************************************/
105    /*
106         public URL  getResource ( String  name )
107         //////////////////////////////////////////////////////////////////////
108         {
109           return getSystemResource ( name );
110         }
111    */
112    
113         /*********************************************************************
114         * Calls getSystemResourceAsStream(name).
115         *********************************************************************/
116    /*
117         public InputStream  getResourceAsStream ( String  name )
118         //////////////////////////////////////////////////////////////////////
119         {
120           return getSystemResourceAsStream ( name );
121         }
122    */
123    
124         //////////////////////////////////////////////////////////////////////
125         //////////////////////////////////////////////////////////////////////
126         }