/*
 * Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.loader;

import com.sun.appserv.server.util.PreprocessorUtil;
import com.sun.enterprise.util.CULoggerInfo;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.enterprise.security.integration.DDPermissionsLoader;
import com.sun.enterprise.security.integration.PermsHolder;
import org.glassfish.api.deployment.DeploymentContext;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.security.SecureClassLoader;
import java.security.cert.Certificate;
import java.security.Permissions;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.security.PermissionCollection;
import org.glassfish.api.deployment.InstrumentableClassLoader;
import org.glassfish.hk2.api.PreDestroy;

/**
 * Class loader used by the ejbs of an application or stand alone module.
 *
 * This class loader also keeps cache of not found classes and resources.
 * </xmp>
 *
 * @author Nazrul Islam
 * @author Kenneth Saks
 * @author Sivakumar Thyagarajan
 * @since  JDK 1.4
 */
public class ASURLClassLoader
        extends URLClassLoader
        implements JasperAdapter, InstrumentableClassLoader, PreDestroy, DDPermissionsLoader {

    /*
       NOTE: various variables are 'final' to enjoy the JVM thread visibility guaranteed for 'final'.
       These variables cannot be nulled out because of this, but the contents are cleared (for Map/Vector).
       This is actually a hidden benefit, because there are places in the code where these variables
       are being used but they could be nulled out while being used.
       Another benefit is that there is no synchronization needed to get the Map/Vector/List itself.
    */

    /** logger for this class */
    private static final Logger _logger=CULoggerInfo.getLogger();

    /*
       list of url entries of this class loader. Using LinkedHashSet instead of original ArrayList
       for faster search.
    */
    private final Set<URLEntry> urlSet = Collections.synchronizedSet(new LinkedHashSet<URLEntry>());

    /** cache of not found resources */
    private final Map<String,String> notFoundResources   = new ConcurrentHashMap<String,String>();

    /** cache of not found classes */
    private final Map<String,String> notFoundClasses     = new ConcurrentHashMap<String,String>();

    /**
        State flag to track whether this instance has been shut off.

        Note: 'volatile' *does not by itself eliminate a race condition* similar to null-check idiom bug.
    */
    private volatile boolean doneCalled = false;

    /**
        snapshot of classloader state at the time done was called.
        <p>
        Must be 'volatile'; not all access is within 'synchronized' eg it is used in toString().
    */
    private volatile String doneSnapshot;

    /** streams opened by this loader */
    private final Vector<SentinelInputStream> streams = new Vector<SentinelInputStream>();

    private final ArrayList<ClassFileTransformer> transformers = new ArrayList<ClassFileTransformer>(1);

    private final static StringManager sm =
        StringManager.getManager(ASURLClassLoader.class);

    //holder for declared and ee permissions
    private PermsHolder permissionsHolder;

    /**
     * Constructor.
     */
    public ASURLClassLoader() {
        super(new URL[0]);

        permissionsHolder = new PermsHolder();

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE,
                        "ClassLoader: " + this + " is getting created.");
        }
    }

    /**
     * Constructor.
     *
     * @param    parent    parent class loader
     */
    public ASURLClassLoader(ClassLoader parent) {
        super(new URL[0], parent);
        permissionsHolder = new PermsHolder();
    }

    public boolean isDone() {
        // method need not by 'synchronized' because 'doneCalled' is 'volatile'.
        return doneCalled;
    }


    @Override
    public void preDestroy() {
        done();
    }


    /**
     * This method should be called to free up the resources.
     * It helps garbage collection.
     *
     * Must be synchronized for:
         (a) visibility of variables
         (b) race condition while checking 'doneCalled'
         (c) only one caller should close the zip files,
         (d) done should occur only once and set the flag when done.
         (e) shoudl not return 'true' when a previous thread might still
         be in the process of executing the method.
     */
    public void done() {
        // This works because 'doneCalled' is 'volatile'
        if( doneCalled ) {
            return;
        }

        // the above optimized check for 'doneCalled=true' is a race condition.
        // The lock must now be acquired, and 'doneCalled' rechecked.
        synchronized(this) {
            if( doneCalled ) {
                return;
            }

            // Capture the fact that the classloader is now effectively disabled.
            // First create a snapshot of our state.  This should be called
            // before setting doneCalled = true.
            doneSnapshot = "ASURLClassLoader.done() called ON " + this.toString()
                + "\n AT " + new Date() +
                " \n BY :" + Arrays.toString(Thread.currentThread().getStackTrace());

            // Presumably OK to set this flag now while the rest of the cleanup proceeeds,
            // because we've taken the snapshot.
            doneCalled = true;

            // closes the jar handles and sets the url entries to null
            for (URLEntry u : this.urlSet) {
                if (u.zip != null) {
                    try {
                        u.zip.reallyClose();
                    } catch (IOException ioe) {
                        _logger.log(Level.INFO,
                                CULoggerInfo.getString(CULoggerInfo.exceptionClosingURLEntry, u.source),
                                ioe);
                    }
                }
                if (u.table != null) {
                    u.table.clear();
                    u.table = null;
                }
                u = null;
            }

            closeOpenStreams();

            // clears out the tables
            // Clear all values.  Because fields are 'final' (for thread safety), cannot null them
            this.urlSet.clear();
            if (this.notFoundResources != null) { this.notFoundResources.clear(); }
            if (this.notFoundClasses != null)   { this.notFoundClasses.clear();   }
        }
    }


    /**
     * Adds a URL to the search list, based on the specified File.
     * <p>
     * This variant of the method makes sure that the URL is valid, in particular
     * encoding special characters (such as blanks) in the file path.
     * @param file the File to use in creating the URL
     * @throws IOException in case of errors converting the file to a URL
     */
    public void appendURL(File file) throws IOException {
        try {
            appendURL(file.toURI().toURL());
        } catch (MalformedURLException mue) {
            _logger.log(Level.SEVERE,
                    CULoggerInfo.getString(CULoggerInfo.badUrlEntry, file.toURI()),
                    mue);

            IOException ioe = new IOException();
            ioe.initCause(mue);
            throw ioe;
        }
    }


    /**
     * Appends the specified URL to the list of URLs to search for
     * classes and resources.
     *
     * @param url the URL to be added to the search path of URLs
     */
    public void addURL(URL url) {
        appendURL(url);
    }


    /**
     * Add a url to the list of urls we search for a class's bytecodes.
     *
     * @param    url    url to be added
     */
    public synchronized void appendURL(URL url) {

        try {
            if (url == null) {
                _logger.log(Level.INFO, CULoggerInfo.missingURLEntry);
                return;
            }

            URLEntry entry = new URLEntry(url);

            if ( !urlSet.contains(entry) ) {
                // adds the url entry to the list
                this.urlSet.add(entry);

                if (entry.isJar) {
                    // checks the manifest if a jar
                    checkManifest(entry.zip, entry.file);
                }
            } else {
                _logger.log(Level.FINE,
                    "[ASURLClassLoader] Ignoring duplicate URL: " + url);
                /*
                 *Clean up the unused entry or it could hold open a jar file.
                 */
                if (entry.zip != null) {
                    try {
                        entry.zip.reallyClose();
                    } catch (IOException ioe) {
                        _logger.log(Level.INFO,
                                CULoggerInfo.getString(CULoggerInfo.exceptionClosingDupUrlEntry, url),
                                ioe);
                    }
                }
            }

            // clears the "not found" cache since we are adding a new url
            clearNotFoundCaches();

        } catch (IOException ioe) {

            _logger.log(Level.SEVERE,
                    CULoggerInfo.getString(CULoggerInfo.badUrlEntry, url),
                    ioe);
        }
    }

    /**
     * Returns the urls of this class loader.
     *
     * Method is 'synchronized' to avoid the  thread-unsafe null-check idiom idiom, also
     * protects the caller from simultaneous changes while iterating,
     * by returning a URL[] (copy) rather than the original.  Also protects against
     * changes to 'urlSet' while iterating over it.
     *
     * @return    the urls of this class loader or an empty array
     */
    public synchronized URL[] getURLs() {

        URL[] url  = null;

        int i=0;
        if (this.urlSet != null) {
            url  = new URL[this.urlSet.size()];

            for (URLEntry urlEntry : urlSet) {
                url[i++] = (urlEntry).source;
            }
        } else {
            url = new URL[0];
        }

        return url;
    }

    /**
     * Returns all the "file" protocol resources of this ASURLClassLoader,
     * concatenated to a classpath string.
     *
     * Notice that this method is called by the setClassPath() method of
     * org.apache.catalina.loader.WebappLoader, since this ASURLClassLoader does
     * not extend off of URLClassLoader.
     *
     * @return Classpath string containing all the "file" protocol resources
     * of this ASURLClassLoader
     */
    public String getClasspath() {

        StringBuffer strBuf = null;

        URL[] urls = getURLs();
        if (urls != null) {
            for (int i=0; i<urls.length; i++) {
                if (urls[i].getProtocol().equals("file")) {
                    if (strBuf == null) {
                        strBuf = new StringBuffer();
                    }
                    if (i > 0) {
                        strBuf.append(File.pathSeparator);
                    }
                    strBuf.append(urls[i].getFile());
                }
            }
        }

        return (strBuf != null) ? strBuf.toString() : null;
    }

    /**
     *Refreshes the memory of the class loader.  This involves clearing the
     *not-found cahces and recreating the hash tables for the URLEntries that
     *record the files accessible for each.
     *<p>
     *Code that creates an ASURLClassLoader and then adds files to a directory
     *that is in the loader's classpath should invoke this method after the new
     *file(s) have been added in order to update the class loader's data
     *structures which optimize class and resource searches.
     *@throws IOException in case of errors refreshing the cache
     */
    public synchronized void refresh() throws IOException {
        clearNotFoundCaches();
//        for (URLEntry entry : urlSet) {
//            entry.cacheItems();
//        }
    }

    public void addTransformer(ClassFileTransformer transformer) {
        transformers.add(transformer);
    }

    /**
     * Create a new instance of a sibling classloader
     * @return a new instance of a class loader that has the same visibility
     *  as this class loader
     */
    public ClassLoader copy() {
        final ASURLClassLoader copyFrom = this;
        DelegatingClassLoader newCl = (DelegatingClassLoader)AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                // privileged code goes here, for example:
                return new DelegatingClassLoader(copyFrom);
            }
        });
        return newCl;
    }

    /**
     *Erases the memory of classes and resources that have been searched for
     *but not found.
     */
     private void clearNotFoundCaches() {
        this.notFoundResources.clear();
        this.notFoundClasses.clear();
    }

    /**
     * Internal implementation of find resource.
     *
     * @param    res    url resource entry
     * @param    name   name of the resource
     */
    private URL findResource0(final URLEntry res,
                              final String name) {

        Object result =
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {

                if (res.isJar) {

                    try {
                        JarEntry jarEntry = res.zip.getJarEntry(name);
                        if (jarEntry != null) {
                            /*
                             *Use a custom URL with a special stream handler to
                             *prevent the JDK's JarURLConnection caching from
                             *locking the jar file until JVM exit.
                             */
                            InternalURLStreamHandler handler = new InternalURLStreamHandler(res, name);

                            // Create a new sub URL from the resource URL (i.e. res.source). To avoid double encoding
                            // (see https://glassfish.dev.java.net/issues/show_bug.cgi?id=13045)
                            // use URL constructor instead of first creating a URI and then calling toURL().
                            // If the resource URL is not properly encoded, that's not our problem.
                            // Whoever has supplied the resource URL is at fault.
                            URL ret = new URL("jar", null /* host */, -1 /* port */, res.source + "!/" + name, handler);
                            handler.tieUrl(ret);
                            return ret;
                        }

                    } catch (Throwable thr) {
                        _logger.log(Level.INFO, CULoggerInfo.exceptionInASURLClassLoader, thr);
                    }
                } else { // directory
                    try {
                        File resourceFile =
                            new File(res.file.getCanonicalPath()
                                        + File.separator + name);

                        if (resourceFile.exists()) {
                            // If we make it this far,
                            // the resource is in the directory.
                            return  resourceFile.toURL();
                        }

                    } catch (IOException e) {
                        _logger.log(Level.INFO, CULoggerInfo.exceptionInASURLClassLoader, e);
                    }
                }

                return null;

            } // End for -- each URL in classpath.
        });

        return (URL) result;
    }

    public URL findResource(String name) {

        // quick quick that relies on 'doneCalled' being 'volatile'
        if( doneCalled ) {
            _logger.log(Level.WARNING,
                    CULoggerInfo.getString(CULoggerInfo.findResourceAfterDone, name, this.toString()),
                    new Throwable());
            return null;
        }

        // This code is dubious, because it iterates over items that could
        // be changing via another thread.   It appears that since 'urlSet' cannot shrink
        // that the iteration at least won't go out of bounds.  And it's probably OK
        // if more than one thread adds the same resource to 'notFoundResources'.
        //
        // HOWEVER, there is still a race condition from the check for 'doneCalled' above.
        // That's OK for 'notFoundResources', but it could lead to an ArrayIndexOutOfBounds
        // excpetion for 'urlSet', should the set be cleared while looping.

        // resource is in the not found list
        String nf = (String) notFoundResources.get(name);
        if (nf != null && nf.equals(name) ) {
            return null;
        }

        synchronized(this) {
            for (final URLEntry u : this.urlSet) {

                if (!u.hasItem(name)) {
                    continue;
                }

                final URL url = findResource0(u, name);
                if (url != null) return url;
            }
        }

        // add resource to the not found list
        notFoundResources.put(name, name);

        return null;
    }

    /**
     * Returns an enumeration of java.net.URL objects
     * representing all the resources with the given name.
     *
     * This method is synchronized to avoid (a) race condition checking 'doneCalled',
     * (b) changes to contents or length of 'resourcesList' and/or 'notFoundResources' while iterating
     * over them, (c) thread visibility to all of the above.
     */
    public synchronized Enumeration<URL>
    findResources(String name) throws IOException {
        if( doneCalled ) {
            _logger.log(Level.WARNING, CULoggerInfo.doneAlreadyCalled,
                        new Object[] { name, doneSnapshot });
            // return an empty enumeration instead of null. See issue #13096
            return Collections.enumeration(Collections.EMPTY_LIST);
        }
        List<URL> resourcesList = new ArrayList<URL>();

        // resource is in the not found list
        final String nf = (String) notFoundResources.get(name);
        if (nf != null && nf.equals(name) ) {
            return (new Vector(resourcesList)).elements();
        }

        for (Iterator<URLEntry> iter = this.urlSet.iterator(); iter.hasNext();) {
            final URLEntry urlEntry = iter.next();
            final URL url = findResource0(urlEntry, name);
            if (url != null) {
                resourcesList.add(url);
            }
        }

        if (resourcesList.size() == 0) {
            // add resource to the not found list
            notFoundResources.put(name, name);
        }

        return (new Vector(resourcesList)).elements();
    }



    /**
     * Checks the manifest of the given jar file.
     *
     * @param    jar    the jar file that may contain manifest class path
     * @param    file   file pointer to the jar
     *
     * @throws   IOException   if an i/o error
     */
    private void checkManifest(JarFile jar, File file) throws IOException {

        if ( (jar == null) || (file == null) ) return;

        Manifest man = jar.getManifest();
        if (man == null) return;

        synchronized (this) {
            String cp = man.getMainAttributes().getValue(
                                        Attributes.Name.CLASS_PATH);
            if (cp == null) return;

            StringTokenizer st = new StringTokenizer(cp, " ");

            while (st.hasMoreTokens()) {
                final String entry = st.nextToken();

                final File newFile = new File(file.getParentFile(), entry);

                // add to class path of this class loader
                try {
                    appendURL(newFile);
                } catch (MalformedURLException ex) {
                    _logger.log(Level.SEVERE, CULoggerInfo.exceptionInASURLClassLoader, ex);
                }
            }
        }
    }

    /**
     * Internal implementation of load class.
     *
     * @param    res        url resource entry
     * @param    entryName  name of the class
     */
    private byte[] loadClassData0(final URLEntry res, final String entryName) {

        Object result =
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                InputStream classStream = null;
                try {

                    if (res.isJar) { // It is a jarfile..
                        JarFile zip = res.zip;
                        JarEntry entry = zip.getJarEntry(entryName);
                        if (entry != null) {
                            classStream = zip.getInputStream(entry);
                            byte[] classData = getClassData(classStream);
                            res.setProtectionDomain(ASURLClassLoader.this, entry.getCertificates());
                            return classData;
                        }
                    } else { // Its a directory....
                        File classFile = new File (res.file,
                                    entryName.replace('/', File.separatorChar));

                        if (classFile.exists()) {
                            try {
                                classStream = new FileInputStream(classFile);
                                byte[] classData = getClassData(classStream);
                                res.setProtectionDomain(ASURLClassLoader.this, null);
                                return classData;
                            } finally {
                                /*
                                 *Close the stream only if this is a directory.  The stream for
                                 *a jar/zip file was opened elsewhere and should remain open after this
                                 *method completes.
                                 */
                                if (classStream != null) {
                                    try {
                                        classStream.close();
                                    } catch (IOException closeIOE) {
                                        _logger.log(Level.INFO, "loader.excep_in_asurlclassloader", closeIOE);
                                    }
                                }
                            }
                        }
                    }
                } catch (IOException ioe) {
                    _logger.log(Level.INFO, CULoggerInfo.exceptionInASURLClassLoader, ioe);
                }
                return null;
            }
        });
        return (byte[]) result;
    }

    @Override
    public void addEEPermissions(PermissionCollection eePc)
        throws SecurityException {
        // sm on
        if (System.getSecurityManager() != null) {
            System.getSecurityManager().checkSecurityAccess(
                    DDPermissionsLoader.SET_EE_POLICY);

            permissionsHolder.setEEPermissions(eePc);
        }
    }

    @Override
    public void addDeclaredPermissions(PermissionCollection declaredPc
            ) throws SecurityException {

        if (System.getSecurityManager() != null) {
            System.getSecurityManager().checkSecurityAccess(
                    DDPermissionsLoader.SET_EE_POLICY);

            permissionsHolder.setDeclaredPermissions(declaredPc);
        }

    }



    @Override
    protected PermissionCollection getPermissions(CodeSource codeSource) {

        PermissionCollection cachedPc =
            permissionsHolder.getCachedPerms(codeSource);
        if (cachedPc != null)
            return cachedPc;

        return permissionsHolder.getPermissions(
                codeSource, super.getPermissions(codeSource));
    }



    /** THREAD SAFETY: what happens when more than one thread requests the same class
        and thus works on the same classData?  Or defines the same package?  Maybe
        the same work just gets done twice, and that's all.
        CAUTION: this method might be overriden, and subclasses must be cautious (also)
        about thread safety.
     */
    protected Class findClass(String name) throws ClassNotFoundException {
        ClassData classData = findClassData(name);
        // Instruments the classes if the profiler's enabled
        if (PreprocessorUtil.isPreprocessorEnabled()) {
            // search thru the JARs for a file of the form java/lang/Object.class
            final String entryName = name.replace('.', '/') + ".class";
            classData.setClassBytes(PreprocessorUtil.processClass(entryName, classData.getClassBytes()));
        }

        // Define package information if necessary
        int lastPackageSep = name.lastIndexOf('.');
        if ( lastPackageSep != -1 ) {
            String packageName = name.substring(0, lastPackageSep);
            if( getPackage(packageName) == null ) {
                try {

                    // There's a small chance that one of our parents
                    // could define the same package after getPackage
                    // returns null but before we call definePackage,
                    // since the parent classloader instances
                    // are not locked.  So, just catch the exception
                    // that is thrown in that case and ignore it.
                    //
                    // It's unclear where we would get the info to
                    // set all spec and impl data for the package,
                    // so just use null.  This is consistent will the
                    // JDK code that does the same.
                    definePackage(packageName, null, null, null,
                                  null, null, null, null);
                } catch(IllegalArgumentException iae) {
                    // duplicate attempt to define same package.
                    // safe to ignore.
                    _logger.log(Level.FINE, "duplicate package " +
                        "definition attempt for " + packageName, iae);
                }
            }
        }

        // Loop though the transformers here!!
        try {
            final ArrayList<ClassFileTransformer> xformers = (ArrayList<ClassFileTransformer>) transformers.clone();
            for ( final ClassFileTransformer transformer : xformers) {

                // see javadocs of transform().
                // It expects class name as java/lang/Object
                // as opposed to java.lang.Object
                final String internalClassName = name.replace('.','/');
                final byte[] transformedBytes = transformer.transform(this, internalClassName, null,
                        classData.pd, classData.getClassBytes());
                if(transformedBytes!=null){ // null indicates no transformation
                    _logger.log(Level.INFO, CULoggerInfo.actuallyTransformed, name);
                    classData.setClassBytes(transformedBytes);
                }
            }
        } catch (IllegalClassFormatException icfEx) {
            throw new ClassNotFoundException(icfEx.toString(), icfEx);
        }
        Class clazz = null;
        try {
            byte[] bytes = classData.getClassBytes();
            clazz = defineClass(name, bytes, 0, bytes.length, classData.pd);
            return clazz;
        } catch (UnsupportedClassVersionError ucve) {
             throw new UnsupportedClassVersionError(
                 sm.getString("ejbClassLoader.unsupportedVersion", name,
                              System.getProperty("java.version")));
        }
    }

    /**
     * This method is responsible for locating the url from the class bytes
     * have to be read and reading the bytes. It does not actually define
     * the Class object.
     * <p>
     * To preclude a race condition on checking 'doneCalled', as well as transient errors
     * if done() is called while running, this method is 'synchronized'.

     * @param name class name in java.lang.Object format
     * @return class bytes as well protection domain information
     * @throws ClassNotFoundException
     */
    protected synchronized ClassData findClassData(String name) throws ClassNotFoundException {

        if( doneCalled ) {
            _logger.log(Level.WARNING,
                    CULoggerInfo.getString(CULoggerInfo.findClassAfterDone, name, this.toString()),
                    new Throwable());
            throw new ClassNotFoundException(name);
        }

        String nf = (String) notFoundClasses.get(name);
        if (nf != null && nf.equals(name) ) {
            throw new ClassNotFoundException(name);
        }

        // search thru the JARs for a file of the form java/lang/Object.class
        String entryName = name.replace('.', '/') + ".class";

        for (URLEntry u : this.urlSet) {
            if (!u.hasItem(entryName)) {
                continue;
            }

            byte[] result = loadClassData0(u, entryName);
            if (result != null) {
                if (System.getSecurityManager() == null)
                    return new ClassData(result, u.pd);
                else {
                    //recreate the pd to include the declared permissions
                    CodeSource cs = u.pd.getCodeSource();
                    PermissionCollection pc = this.getPermissions(cs);
                    ProtectionDomain pdWithPemissions =
                        new ProtectionDomain(u.pd.getCodeSource(), pc, u.pd.getClassLoader(), u.pd.getPrincipals());
                    return new ClassData(result, pdWithPemissions);
                }
            }
        }

        // add to the not found classes list
        notFoundClasses.put(name, name);

        throw new ClassNotFoundException(name);
    }

    /**
     * Returns the byte array from the given input stream.
     *
     * @param    istream    input stream to the class or resource
     *
     * @throws   IOException  if an i/o error
     */
    private byte[] getClassData(InputStream istream) throws IOException {

        BufferedInputStream bstream = new BufferedInputStream(istream);
        byte[] buf = new byte[4096];
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        int num = 0;
        try {
            while( (num = bstream.read(buf)) != -1) {
                bout.write(buf, 0, num);
            }
        } finally {
            if (bstream != null) {
                try {
                    bstream.close();
                } catch (IOException closeIOE) {
                    ASURLClassLoader._logger.log(Level.INFO,
                            CULoggerInfo.exceptionInASURLClassLoader, closeIOE);
                }
            }
        }

        return bout.toByteArray();
    }


    protected String getClassLoaderName() {
        return "ASURLClassLoader";
    }

    /**
     * Returns a string representation of this class loader.
     *
     * @return   a string representation of this class loader
     */
    public String toString() {

        StringBuffer buffer = new StringBuffer();

        buffer.append(getClassLoaderName() + " : \n");
        if( doneCalled ) {
            buffer.append("doneCalled = true" + "\n");
            String snapshot = doneSnapshot; // MUST use temp for thread safety; could go null after checking
            if( snapshot != null ) {
                buffer.append("doneSnapshot = " + snapshot);
            }
        } else {
            buffer.append("urlSet = " + this.urlSet + "\n");
            buffer.append("doneCalled = false " + "\n");
        }
        buffer.append(" Parent -> " + getParent() + "\n");

        return buffer.toString();
    }

    public InputStream getResourceAsStream(final String name) {
        InputStream stream = super.getResourceAsStream(name);
        /*
         *Make sure not to wrap the stream if it already is a wrapper.
         */
        if (stream != null) {
            if (! (stream instanceof SentinelInputStream)) {
                stream = new SentinelInputStream(stream);
            }
        }
        return stream;
    }

    /**
     * The JarFile objects loaded in the classloader may get exposed to the
     * application code (e.g. EJBs) through calls of
     * ((JarURLConnection) getResource().openConnection()).getJarFile().
     *
     * This class protects the jar file from being closed by such an application.
     *
     * @author fkieviet
     */
    private static final class ProtectedJarFile extends JarFile {
        /**
         * Constructor
         *
         * @param file File
         * @throws IOException from parent
         */
        public ProtectedJarFile(File file) throws IOException {
            super(file);
        }

        /**
         * Do nothing
         *
         * @see java.util.zip.ZipFile#close()
         *
         * Byron sez:  I wonder what's going on here?!?  This looks quite weird.
         * Why not just get rid of both reallyClose() and close() and finalize()
         * -- and just rely on the superclass?
         * At any rate I am not messing with it today, 1/9/2013.  Mainly because
         * maybe close() is called outside and we do NOT want it to really close?
         * Here is what happens at finalize time:
         * 1. ASURLClassLoader$ProtectedJarFile.finalize()
         * 2. java.util.zip.ZipFile.finalize()
         * 3. ASURLClassLoader$ProtectedJarFile.close()
         * 4. dumps a WARNING log message
         * 5. reallyClose()
         * 6. java.util.zip.ZipFile.close()
         * I
         */
        public void close() {
            // do nothing
        }

        /**
         * Really close the jar file
         *
         * @throws IOException from parent
         */
        public void reallyClose() throws IOException {
            super.close();
        }

        /**
         * @see java.lang.Object#finalize()
         */
        @Deprecated(since = "6.1.0", forRemoval = true)
        protected void finalize() throws IOException {
            try {
                super.finalize();
                reallyClose();
            } catch (Throwable t) {
                throw new IOException(t);
            }
        }
    }

    /**
     * URL entry - keeps track of the url resources.
     */
    protected static final class URLEntry {
        /** the url, ensure thread visibility by making it 'final' */
        final URL source;

        /** file of the url,
            ensure thread visibility by making it 'volatile' */
        volatile File file       = null;

        /** jar file if url is a jar else null,
            ensure thread visibility by making it 'volatile'  */
        volatile ProtectedJarFile zip     = null;

        /** true if url is a jar,
            ensure thread visibility by making it 'volatile'  */
        volatile boolean isJar  = false;

        /** ensure thread visibility by making it 'volatile'  */
        volatile Hashtable<String,String> table = null;

        /** ProtectionDomain with signers if jar is signed,
            ensure thread visibility by making it 'volatile'  */
        volatile ProtectionDomain pd = null;

        URLEntry(URL url) throws IOException {
            source = url;
            init();
        }

        void init() throws IOException {
            try {
                file    = new File(source.toURI());
                isJar  = file.isFile();

                if (isJar) {
                    zip = new ProtectedJarFile(file);
                }

                table = new Hashtable<String,String>();
//                cacheItems();
            } catch (URISyntaxException use) {
                IOException ioe= new IOException();
                ioe.initCause(use);
                throw ioe;
            }
        }

        private void fillTable(File f, Hashtable t, String parent) throws IOException {

            String localName = (parent.equals("")) ? "" : parent + "/";

            File[] children = f.listFiles();
            for (int i = 0; i < children.length; i++) {
                processFile(children[i],  t, localName);
            }
        }

        /**
         *Adds a file (or, if a directory, the directory's contents) to the table
         *of files this loader knows about.
         *<p>
         *Invokes fillTable for subdirectories which in turn invokes processFile
         *recursively.
         *@param fileToProcess the File to be processed
         *@param t the Hashtable that holds the files the loader knows about
         *@param parentLocalName prefix to be used for the full path; should be
         *non-empty only for recursive invocations
         *@throws IOException in case of errors working with the fileToProcess
         */
        private void processFile(File fileToProcess, Hashtable t, String parentLocalName) throws IOException {
            String key = parentLocalName + fileToProcess.getName();
            if (fileToProcess.isFile()) {
                t.put(key, key);
            } else if (fileToProcess.isDirectory()) {
                fillTable(fileToProcess, t, key);
            }
        }


        boolean hasItem(String item) {
            // in the case of ejbc stub compilation, asurlclassloader is created before stubs
            // gets generated, thus we need to return true for this case.
            if (table.size() == 0) {
                return true;
            }

            /*
             *Even with the previous special handling, a file could be created
             *in a directory after the loader was created and its table of
             *URLEntry names populated.  So check the table first and, if
             *the target item is not there and this URLEntry is for a directory, look for
             *the file.  If the file is now present but was not when the loader
             *was created, add an entry for the file in the table.
             */
            boolean result = false;
            String target = item;
            // special handling
            if (item.startsWith("./")) {
                target = item.substring(2, item.length());
            }

            result = table.containsKey(target);
            if ( ! result && ! isJar) {
                /*
                 *If the file exists now then it has been added to the directory since the
                 *loader was created.  Add it to the table of files we
                 *know about.
                 */
                File targetFile = privilegedCheckForFile(target);
                if (targetFile != null) {
                    try {
                        processFile(targetFile, table, "");
                        result = true;
                    } catch (IOException ioe) {
                        _logger.log(Level.SEVERE,
                                CULoggerInfo.getString(CULoggerInfo.exceptionProcessingFile, target, file.getAbsolutePath()),
                                ioe);
                        return false;
                    }
                }
            }
            return result;
        }

        /**
         *Returns a File object for the requested path within the URLEntry.
         *<p>
         *Runs privileged because user code could trigger invocations of this
         *method.
         *@param targetPath the relative path to look for
         *@return File object for the requested file; null if it does not exist or
         *in case of error
         */
        private File privilegedCheckForFile(final String targetPath) {
            /*
             *Check for the file existence with privs, because this code can
             *be invoked from user code which may not otherwise have access
             *to the directories of interest.
             */
            try {
                File result = (File) AccessController.doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws Exception {

                            File targetFile = new File(file, targetPath);
                            if ( ! targetFile.exists()) {
                                targetFile = null;
                            }
                            return targetFile;
                        }
                    });

                return result;

            } catch (PrivilegedActionException pae) {
                /*
                 *Log any exception and return false.
                 */
                _logger.log(Level.SEVERE,
                        CULoggerInfo.getString(CULoggerInfo.exceptionCheckingFile, targetPath, file.getAbsolutePath()),
                        pae.getCause());
                return null;
            }
        }

          /**
           * Sets ProtectionDomain with CodeSource including Signers in
           * Entry for use in call to defineClass.
           * @param signers the array of signer certs or null
           */
         public void setProtectionDomain (ClassLoader ejbClassLoader, Certificate[] signers) throws MalformedURLException {
             if (pd == null) {
                 pd = new ProtectionDomain(new CodeSource(file.toURL(),signers),null, ejbClassLoader, null );
             }
         }

        public String toString() {
            return "URLEntry : " + source.toString();
        }

        /**
         * Returns true if two URL entries has equal URLs.
         *
         * @param  obj   URLEntry to compare against
         * @return       true if both entry has equal URL
         */
        public boolean equals(Object obj) {

            boolean tf = false;

            if (obj instanceof URLEntry) {
                URLEntry e = (URLEntry) obj;
                try {
                              //try comparing URIs
                              if (source.toURI().equals(e.source.toURI())) {
                                  tf = true;
                              }
                          } catch (URISyntaxException e1) {
                    // We should never get here, because we call init() in the constructor and
                    // init() would have thrown an exception if the URL could not be converted to a valid URI.
                    assert(false);
                    throw new RuntimeException(e1);
                }
            }

            return tf;
        }

        /**
         * Since equals is overridden, we need to override hashCode as well.
         */
        public int hashCode() {
            try {
                          return source.toURI().hashCode();
                      } catch (URISyntaxException e) {
                // We should never get here, because we call init() in the constructor and
                // init() would have thrown an exception if the URL could not be converted to a valid URI.
                assert(false);
                throw new RuntimeException(e);
            }
        }

    }

    /**
     *Returns the vector of open streams; creates it if needed.
     *@return Vector<SentinelInputStream> holding open streams
     */
    private Vector<SentinelInputStream> getStreams() {
        return streams;
    }

    /**
     *Closes any streams that remain open, logging a warning for each.
     *<p>
     *This method should be invoked when the loader will no longer be used
     *and the app will no longer explicitly close any streams it may have opened.
     * Must be synchnronized to (a) avoid race condition checking 'streams'.
     */
    private synchronized void closeOpenStreams() {
        if (streams != null) {

            SentinelInputStream[] toClose = streams.toArray(new SentinelInputStream[streams.size()]);
            for (SentinelInputStream s : toClose) {
                try {
                    s.closeWithWarning();
                } catch (IOException ioe) {
                    _logger.log(Level.WARNING, CULoggerInfo.exceptionClosingStream, ioe);
                }
            }
            streams.clear();
        }
    }

    /**
     * Wraps all InputStreams returned by this class loader to report when
     * a finalizer is run before the stream has been closed.  This helps
     * to identify where locked files could arise.
     * @author vtsyganok
     * @author tjquinn
     */
    protected final class SentinelInputStream extends FilterInputStream {
        private volatile boolean closed = false;
        private final Throwable throwable;

        /**
         * Constructs new FilteredInputStream which reports InputStreams not closed properly.
         * When the garbage collector runs the finalizer.  If the stream is still open this class will
         * report a stack trace showing where the stream was opened.
         *
         * @param in - InputStream to be wrapped
         */
        protected SentinelInputStream(final InputStream in) {
            super(in);
            throwable = new Throwable();
            getStreams().add(this);
        }

        /**
         * Closes underlying input stream.
         */
        public void close() throws IOException {
            _close();
        }

        /**
         * Invoked by Garbage Collector. If underlying InputStream was not closed properly,
         * the stack trace of the constructor will be logged!
         *
         * 'closed' is 'volatile', but it's a race condition to check it and how this code
         * relates to _close() is unclear.
         */
        protected void finalize() throws Throwable {
            if (!closed && this.in != null){
                try {
                    in.close();
                }
                catch (IOException ignored){
                    //Cannot do anything here.
                }
                //Well, give them a stack trace!
                report();
            }
            super.finalize();
        }

        private synchronized void _close() throws IOException {
            if ( closed ) {
                return;
            }
            // race condition with above check, but should have no harmful effects

            closed = true;
            getStreams().remove(this);
            super.close();
        }

        private void closeWithWarning() throws IOException {
            _close();
            report();
        }

        /**
         * Report "left-overs"!
         */
        private void report(){
            _logger.log(Level.WARNING, CULoggerInfo.inputStreamFinalized, this.throwable);
        }
    }
    /**
     * To properly close streams obtained through URL.getResource().getStream():
     * this opens the input stream on a JarFile that is already open as part
     * of the classloader, and returns a sentinel stream on it.
     *
     * @author fkieviet
     */
    private class InternalJarURLConnection extends JarURLConnection {
        private final URLEntry mRes;
        private final String mName;

        /**
         * Constructor
         *
         * @param url the URL that is a stream for
         * @param res URLEntry
         * @param name String
         * @throws MalformedURLException from super class
         */
        public InternalJarURLConnection(URL url, URLEntry res, String name)
            throws MalformedURLException {
            super(url);
            mRes = res;
            mName = name;
        }

        /**
         * @see java.net.JarURLConnection#getJarFile()
         */
        public JarFile getJarFile() throws IOException {
            return mRes.zip;
        }

        /**
         * @see java.net.URLConnection#connect()
         */
        public void connect() throws IOException {
            // Nothing
        }

        /**
         * @see java.net.URLConnection#getInputStream()
         */
        public InputStream getInputStream() throws IOException {
            // When there is no entry name specified (this can happen for url like jar:file:///tmp/foo.jar!/),
            // we must throw an IOException as that's the behavior of JarURLConnection as well.
            if ("".equals(mName)) {
                throw new IOException("no entry name specified");
            }
            ZipEntry entry = mRes.zip.getEntry(mName);
            if (entry == null) {
                throw new IOException("no entry called " + mName + " found in " + mRes.source);
            }
            return new SentinelInputStream(mRes.zip.getInputStream(entry));
        }
    }

    /**
     * To properly close streams obtained through URL.getResource().getStream():
     * an instance of this class is instantiated for each and every URL object
     * created by this classloader. It provides a custom JarURLConnection
     * (InternalJarURLConnection) so that the stream can be obtained from an already
     * open jar file.
     *
     * @author fkieviet
     */
    private class InternalURLStreamHandler extends URLStreamHandler {
        /** must be 'volatile' for thread visibility */
        private volatile URL   mURL;
        private final URLEntry mRes;

        /**
         * Constructor
         *
         * @param res URLEntry
         * @param name String
         */
        public InternalURLStreamHandler(URLEntry res, String name) {
            mRes = res;
        }

        /**
         * @see java.net.URLStreamHandler#openConnection(java.net.URL)
         */
        protected URLConnection openConnection(final URL u) throws IOException {
            String path = u.getPath();
            int separator = path.lastIndexOf('!');
            assert(separator != -1); // we deal with jar urls only
            try {
                URI jarFileURI = new URI(path.substring(0, separator));
                if (!jarFileURI.equals(mRes.file.toURI())) {
                    throw new IOException("Cannot open a foreign URL; this.url=" + mURL
                        + "; foreign.url=" + u);
                }
                String entryName = path.substring(separator+1);
                if (entryName != null) {
                    assert (entryName.startsWith("/"));
                    entryName = entryName.substring(1);
                }
                return new InternalJarURLConnection(u, mRes, entryName);
            } catch (URISyntaxException e) {
                throw new IOException(e);
            }
        }

        /**
         * Ties the URL that this handler is associated with to the handler, so
         * that it can be asserted that somehow no other URLs are mangled in (this
         * is theoretically impossible)
         *
         * @param url URL
         */
        public void tieUrl(URL url) {
            // is it OK to call this twice and whack the variable a second time?
            if ( mURL != null )
            {
                throw new IllegalStateException("Setting the URL more than once not allowed" );
            }
            mURL = url;
        }
    }

    /**
     * This class is used as return value of findClassIntenal method  to return
     * both class bytes and protection domain.
     */
    private static final class ClassData {
        // Byron Sez: making classBytes volatile is pointless.  That just makes
        // the reference to the array volatile.  The byte contents are NOT volatile
        // I solved this low-level FB issue by:
        // 1. don't use the field directly outside of this inner class
        // 2. add a getter/setter
        // 3. make both the setter and getter synchronized.

        private byte[] classBytes;

        /** must be 'final' to ensure thread visibility */
        private final ProtectionDomain pd;

        ClassData(byte[] classBytes, ProtectionDomain pd) {
            this.classBytes = classBytes;
            this.pd = pd;
        }
        private synchronized byte[] getClassBytes() {
            return classBytes;
        }

        private synchronized void setClassBytes(byte[] newBytes) {
            classBytes = newBytes;
        }

    }

    /**
     * This class loader only provides a new class loading namespace
     * so that persistence provider can load classes in that separate
     * namespace while scanning annotations.
     * This class loader delegates all stream handling (i.e. reading
     * actual class/resource data) operations to the application class loader.
     * It only defines the Class using the byte codes.
     * Motivation behind this class is discussed at
     * https://glassfish.dev.java.net/issues/show_bug.cgi?id=237.
     */
    private static final class DelegatingClassLoader extends SecureClassLoader {

        /**
         * The application class loader which is used to read class data.
         * Made 'final' to ensure thread visibility.
         */
        private final ASURLClassLoader delegate;

        /**
         * Create a new instance.
         * @param applicationCL  is the original class loader associated
         * with this application. The new class loader uses it to delegate
         * stream handling operations. The new class loader also uses
         * applicationCL's parent as its own parent.
         */
        DelegatingClassLoader(ASURLClassLoader applicationCL) {
            super(applicationCL.getParent()); // normal class loading delegation
            this.delegate = applicationCL;
        }

        /**
         * This method uses the delegate to use class bytes and then defines
         * the class using this class loader
         */
        protected Class findClass(String name) throws ClassNotFoundException {
            ClassData classData = delegate.findClassData(name);
            // Define package information if necessary
            int lastPackageSep = name.lastIndexOf('.');
            if ( lastPackageSep != -1 ) {
                String packageName = name.substring(0, lastPackageSep);
                if( getPackage(packageName) == null ) {
                    try {
                        // There's a small chance that one of our parents
                        // could define the same package after getPackage
                        // returns null but before we call definePackage,
                        // since the parent classloader instances
                        // are not locked.  So, just catch the exception
                        // that is thrown in that case and ignore it.
                        //
                        // It's unclear where we would get the info to
                        // set all spec and impl data for the package,
                        // so just use null.  This is consistent will the
                        // JDK code that does the same.
                        definePackage(packageName, null, null, null,
                                      null, null, null, null);
                    } catch(IllegalArgumentException iae) {
                        // duplicate attempt to define same package.
                        // safe to ignore.
                        _logger.log(Level.FINE, "duplicate package " +
                            "definition attempt for " + packageName, iae);
                    }
                }
            }
            Class clazz = null;
            try {
                final byte[] bytes = classData.getClassBytes();
                clazz = defineClass(name, bytes, 0, bytes.length, classData.pd);
                return clazz;
            } catch (UnsupportedClassVersionError ucve) {
                 throw new UnsupportedClassVersionError(
                     sm.getString("ejbClassLoader.unsupportedVersion", name,
                                  System.getProperty("java.version")));
            }
        }

        protected URL findResource(String name) {
            return delegate.findResource(name);
        }

        protected Enumeration<URL> findResources(String name) throws IOException {
            return delegate.findResources(name);
        }

    }
}

