/*
 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.misc;

/**
 * Provides utility functions related to URLClassLoaders or subclasses of it.
 *
 *                  W  A  R  N  I  N  G
 *
 * This class uses undocumented, unpublished, private data structures inside
 * java.net.URLClassLoader and sun.misc.URLClassPath.  Use with extreme caution.
 *
 * @author      tjquinn
 */


import java.io.IOException;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarFile;

public class ClassLoaderUtil {

    /**
     * Releases resources held by a URLClassLoader. A new classloader must
     * be created before the underlying resources can be accessed again.
     * @param classLoader the instance of URLClassLoader (or a subclass)
     */
    public static void releaseLoader(URLClassLoader classLoader) {
        releaseLoader(classLoader, null);
    }

    /**
     * Releases resources held by a URLClassLoader.  Notably, close the jars
     * opened by the loader. Initializes and updates the List of
     * jars that have been successfully closed.
     * <p>
     * @param classLoader the instance of URLClassLoader (or a subclass)
     * @param jarsClosed a List of Strings that will contain the names of jars
     *  successfully closed; can be null if the caller does not need the information returned
     * @return a List of IOExceptions reporting jars that failed to close; null
     * indicates that an error other than an IOException occurred attempting to
     * release the loader; empty indicates a successful release; non-empty
     * indicates at least one error attempting to close an open jar.
     */
    public static List<IOException> releaseLoader(URLClassLoader classLoader, List<String> jarsClosed) {

        List<IOException> ioExceptions = new LinkedList<IOException>();

        try {
            /* Records all IOExceptions thrown while closing jar files. */

            if (jarsClosed != null) {
                jarsClosed.clear();
            }

            URLClassPath ucp = SharedSecrets.getJavaNetAccess()
                                                .getURLClassPath(classLoader);
            ArrayList<?> loaders = ucp.loaders;
            Stack<?> urls = ucp.urls;
            HashMap<?,?> lmap = ucp.lmap;

            /*
             *The urls variable in the URLClassPath object holds URLs that have not yet
             *been used to resolve a resource or load a class and, therefore, do
             *not yet have a loader associated with them.  Clear the stack so any
             *future requests that might incorrectly reach the loader cannot be
             *resolved and cannot open a jar file after we think we've closed
             *them all.
             */
            synchronized(urls) {
                urls.clear();
            }

            /*
             *Also clear the map of URLs to loaders so the class loader cannot use
             *previously-opened jar files - they are about to be closed.
             */
            synchronized(lmap) {
                lmap.clear();
            }

            /*
             *The URLClassPath object's path variable records the list of all URLs that are on
             *the URLClassPath's class path.  Leave that unchanged.  This might
             *help someone trying to debug why a released class loader is still used.
             *Because the stack and lmap are now clear, code that incorrectly uses a
             *the released class loader will trigger an exception if the
             *class or resource would have been resolved by the class
             *loader (and no other) if it had not been released.
             *
             *The list of URLs might provide some hints to the person as to where
             *in the code the class loader was set up, which might in turn suggest
             *where in the code the class loader needs to stop being used.
             *The URLClassPath does not use the path variable to open new jar
             *files - it uses the urls Stack for that - so leaving the path variable
             *will not by itself allow the class loader to continue handling requests.
             */

            /*
             *For each loader, close the jar file associated with that loader.
             *
             *The URLClassPath's use of loaders is sync-ed on the entire URLClassPath
             *object.
             */
            synchronized (ucp) {
                for (Object o : loaders) {
                    if (o != null) {
                        /*
                         *If the loader is a JarLoader inner class and its jarFile
                         *field is non-null then try to close that jar file.  Add
                         *it to the list of closed files if successful.
                         */
                        if (o instanceof URLClassPath.JarLoader) {
                                URLClassPath.JarLoader jl = (URLClassPath.JarLoader)o;
                                JarFile jarFile = jl.getJarFile();
                                try {
                                    if (jarFile != null) {
                                        jarFile.close();
                                        if (jarsClosed != null) {
                                            jarsClosed.add(jarFile.getName());
                                        }
                                    }
                                } catch (IOException ioe) {
                                    /*
                                     *Wrap the IOException to identify which jar
                                     *could not be closed and add it to the list
                                     *of IOExceptions to be returned to the caller.
                                     */
                                    String jarFileName = (jarFile == null) ? "filename not available":jarFile.getName();
                                    String msg = "Error closing JAR file: " + jarFileName;
                                    IOException newIOE = new IOException(msg);
                                    newIOE.initCause(ioe);
                                    ioExceptions.add(newIOE);
                                }
                        }
                    }
                }
                /*
                 *Now clear the loaders ArrayList.
                 */
                loaders.clear();
            }
        } catch (Throwable t) {
            throw new RuntimeException (t);
        }
        return ioExceptions;
    }
}
