package net.sourceforge.groboutils.codecoverage.v2;

import java.util.Hashtable;

public class ArrayClassLoader extends ClassLoader
{
    //----------------------------
    // Public data
    


    //----------------------------
    // Private data
    
    private Hashtable m_classList = new Hashtable();
    private Hashtable m_classCache = new Hashtable();
    
    //----------------------------
    // constructors
    
    /**
     * Default constructor
     */
    public ArrayClassLoader()
    {
        // do nothing
    }
    
    
    //----------------------------
    // Public methods
    
    
    /**
     * Add a new class to the internal list.
     */
    public void addClass( String name, byte[] bytecode )
    {
        if (name == null || bytecode == null)
        {
            throw new IllegalArgumentException("no null args");
        }
        this.m_classList.put( name, bytecode );
    }
    

    // inherited from ClassLoader
    /**
     * @exception ClassNotFoundException thrown if the given class name
     *      could not be found, or if there was a problem loading the
     *      bytecode for the class.
     */
    public Class loadClass( String name, boolean resolve )
            throws ClassNotFoundException
    {
        Class c;
        
        if (name == null)
        {
            throw new IllegalArgumentException("classname is null");
        }
        
        c = (Class)this.m_classCache.get( name );
        if (c == null)
        {
            byte bytecode[] = getBytecode( name );
            if (bytecode == null)
            {
                c = findSystemClass( name );
            }
            else
            {
                try
                {
                    c = defineClass( name, bytecode, 0, bytecode.length );
                    this.m_classCache.put( name, c );
                }
                catch (Exception ex2)
                {
                    // something wrong with the class format
                    throw new ClassNotFoundException(
                        "Bad class format for class "+name );
                }
            }
        }
        if (resolve)
        {
            resolveClass( c );
        }
        return c;
    }
    
    //----------------------------
    // Protected methods
    
    
    /**
     * Retrieves the internal bytecode for the given class.  If not known,
     * then <tt>null</tt> is returned.
     *
     * @param className a non-null class name.
     */
    protected byte[] getBytecode( String className )
    {
        byte bytecode[] = (byte[])this.m_classList.get( className );
        return bytecode;
    }
    
    
    //----------------------------
    // Private methods
}
