package org.apache.maven.j2ee;

/* ====================================================================
 *   Copyright 2001-2004 The Apache Software Foundation.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * ====================================================================
 */

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;

/**
 * A {@link ClassLoader} that loads classes from a {@link WarFile}
 *
 * @author <a href="mailto:dion@multitask.com.au">dIon Gillard</a>
 * @version $Id$
 */
public class WarClassLoader extends URLClassLoader
{
    /** temp files created by classloader */
    private List tempFiles = new ArrayList();
    /** war file to be used for class loading */
    private WarFile war;
    
    /**
     * Creates a new instance of WarClassLoader
     * 
     * @param war a {@link WarFile}
     * @throws IOException when an I/O error occurs extracting the jars from the
     *         war
     * @throws MalformedURLException if the jar: URL is not supported on the
     *         underlying platform
     */
    public WarClassLoader(WarFile war) throws IOException, MalformedURLException
    {
        super (new URL[0]);
        this.war = war;
        addURLs();
    }
    
    /**
     * Creates a new instance of WarClassLoader with the provided parent 
     * classloader as the one to delegate to if classes can't be found
     * 
     * @param war a {@link WarFile}
     * @param classloader a {@link ClassLoader} to delegate to.
     * @throws IOException when an I/O error occurs extracting the jars from
     *      the war
     * @throws MalformedURLException if the jar: URL is not supported on the
     *      underlying platform
     */
    public WarClassLoader(WarFile war, ClassLoader classloader) throws
        IOException, MalformedURLException
    {
        super(new URL[0], classloader);
        this.war = war;
        addURLs();
    }
    
    /**
     * Add WEB-INF/classes and WEB-INF/lib/*.jar as extra classpath URLs
     * 
     * @throws IOException when an I/O error occurs extracting the jars from
     *      the war
     * @throws MalformedURLException if the jar: URL is not supported on the
     *      underlying platform
     */
    private void addURLs() throws IOException, MalformedURLException
    {
        File warFile = new File(war.getName());
        URL webInfClasses = new URL("jar:" + warFile.toURL() + "!/"
            + "WEB-INF/classes/");
        addURL(webInfClasses);
        Set jars = war.getLibEntries();
        JarEntry entry = null;
        for (Iterator jarEntries = jars.iterator(); jarEntries.hasNext();)
        {
            entry = (JarEntry) jarEntries.next();
            File jar = war.extract(entry);
            tempFiles.add(jar);
            jar.deleteOnExit();
            addURL(new URL("jar:" + jar.toURL() + "!/"));
        }
    }
}
