/*
 * Copyright 1999-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.misc;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.net.URL;
import java.net.MalformedURLException;
import sun.net.www.ParseUtil;

/**
 * <p>
 * This class checks dependent extensions a particular jar file may have
 * declared through its manifest attributes.
 * </p>
 * Jar file declared dependent extensions through the extension-list
 * attribute. The extension-list contains a list of keys used to
 * fetch the other attributes describing the required extension.
 * If key is the extension key declared in the extension-list
 * attribute, the following describing attribute can be found in
 * the manifest :
 * key-Extension-Name:  (Specification package name)
 * key-Specification-Version: (Specification-Version)
 * key-Implementation-Version: (Implementation-Version)
 * key-Implementation-Vendor-Id: (Imlementation-Vendor-Id)
 * key-Implementation-Version: (Implementation version)
 * key-Implementation-URL: (URL to download the requested extension)
 * <p>
 * This class also maintain versioning consistency of installed
 * extensions dependencies declared in jar file manifest.
 * </p>
 * @author  Jerome Dochez
 */
public class ExtensionDependency {

    /* Callbak interfaces to delegate installation of missing extensions */
    private static Vector providers;

    /**
     * <p>
     * Register an ExtensionInstallationProvider. The provider is responsible
     * for handling the installation (upgrade) of any missing extensions.
     * </p>
     * @param eip ExtensionInstallationProvider implementation
     */
    public synchronized static void addExtensionInstallationProvider
        (ExtensionInstallationProvider eip)
    {
        if (providers == null) {
            providers = new Vector();
        }
        providers.add(eip);
    }

    /**
     * <p>
     * Unregister a previously installed installation provider
     * </p>
     */
    public synchronized  static void removeExtensionInstallationProvider
        (ExtensionInstallationProvider eip)
    {
        providers.remove(eip);
    }

    /**
     * <p>
     * Checks the dependencies of the jar file on installed extension.
     * </p>
     * @param jarFile containing the attriutes declaring the dependencies
     */
    public static boolean checkExtensionsDependencies(JarFile jar)
    {
        if (providers == null) {
            // no need to bother, nobody is registered to install missing
            // extensions
            return true;
        }

        try {
            ExtensionDependency extDep = new ExtensionDependency();
            return extDep.checkExtensions(jar);
        } catch (ExtensionInstallationException e) {
            debug(e.getMessage());
        }
        return false;
    }

    /*
     * Check for all declared required extensions in the jar file
     * manifest.
     */
    protected boolean checkExtensions(JarFile jar)
        throws ExtensionInstallationException
    {
        Manifest man;
        try {
            man = jar.getManifest();
        } catch (IOException e) {
            return false;
        }

        if (man == null) {
            // The applet does not define a manifest file, so
            // we just assume all dependencies are satisfied.
            return true;
        }

        boolean result = true;
        Attributes attr = man.getMainAttributes();
        if (attr != null) {
            // Let's get the list of declared dependencies
            String value = attr.getValue(Name.EXTENSION_LIST);
            if (value != null) {
                StringTokenizer st = new StringTokenizer(value);
                // Iterate over all declared dependencies
                while (st.hasMoreTokens()) {
                    String extensionName = st.nextToken();
                    debug("The file " + jar.getName() +
                          " appears to depend on " + extensionName);
                    // Sanity Check
                    String extName = extensionName + "-" +
                        Name.EXTENSION_NAME.toString();
                    if (attr.getValue(extName) == null) {
                        debug("The jar file " + jar.getName() +
                              " appers to depend on "
                              + extensionName + " but does not define the " +
                              extName + " attribute in its manifest ");

                    } else {
                        if (!checkExtension(extensionName, attr)) {
                            debug("Failed installing " + extensionName);
                            result = false;
                        }
                    }
                }
            } else {
                debug("No dependencies for " + jar.getName());
            }
        }
        return result;
    }


    /*
     * <p>
     * Check that a particular dependency on an extension is satisfied.
     * </p>
     * @param extensionName is the key used for the attributes in the manifest
     * @param attr is the attributes of the manifest file
     *
     * @return true if the dependency is satisfied by the installed extensions
     */
    protected synchronized boolean checkExtension(final String extensionName,
                                     final Attributes attr)
        throws ExtensionInstallationException
    {
        debug("Checking extension " + extensionName);
        if (checkExtensionAgainstInstalled(extensionName, attr))
            return true;

        debug("Extension not currently installed ");
        ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
        return installExtension(reqInfo, null);
    }

    /*
     * <p>
     * Check if a particular extension is part of the currently installed
     * extensions.
     * </p>
     * @param extensionName is the key for the attributes in the manifest
     * @param attr is the attributes of the manifest
     *
     * @return true if the requested extension is already installed
     */
    boolean checkExtensionAgainstInstalled(String extensionName,
                                           Attributes attr)
        throws ExtensionInstallationException
    {
        File fExtension = checkExtensionExists(extensionName);

        if (fExtension != null) {
        // Extension already installed, just check against this one
            try {
                if (checkExtensionAgainst(extensionName, attr, fExtension))
                    return true;
            } catch (FileNotFoundException e) {
                debugException(e);
            } catch (IOException e) {
                debugException(e);
            }
            return false;

        } else {
        // Not sure if extension is already installed, so check all the
        // installed extension jar files to see if we get a match

            File[] installedExts;

            try {
            // Get the list of installed extension jar files so we can
            // compare the installed versus the requested extension
                installedExts = getInstalledExtensions();
            } catch(IOException e) {
                debugException(e);
                return false;
            }

            for (int i=0;i<installedExts.length;i++) {
                try {
                    if (checkExtensionAgainst(extensionName, attr, installedExts[i]))
                        return true;
                } catch (FileNotFoundException e) {
                    debugException(e);
                } catch (IOException e) {
                    debugException(e);
                    // let's continue with the next installed extension
                }
            }
        }
        return false;
    }

    /*
     * <p>
     * Check if the requested extension described by the attributes
     * in the manifest under the key extensionName is compatible with
     * the jar file.
     * </p>
     *
     * @param extensionName key in the attibute list
     * @param attr manifest file attributes
     * @param file installed extension jar file to compare the requested
     * extension against.
     */
    protected boolean checkExtensionAgainst(String extensionName,
                                            Attributes attr,
                                            final File file)
        throws IOException,
               FileNotFoundException,
               ExtensionInstallationException
    {

        debug("Checking extension " + extensionName +
              " against " + file.getName());

        // Load the jar file ...
        Manifest man;
        try {
            man = (Manifest) AccessController.doPrivileged
                (
                 new PrivilegedExceptionAction() {
                     public Object run()
                            throws IOException, FileNotFoundException {
                         if (!file.exists())
                             throw new FileNotFoundException(file.getName());
                         JarFile jarFile =  new JarFile(file);
                         return jarFile.getManifest();
                     }
                 });
        } catch(PrivilegedActionException e) {
            if (e.getException() instanceof FileNotFoundException)
                throw (FileNotFoundException) e.getException();
            throw (IOException) e.getException();
        }

        // Construct the extension information object
        ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
        debug("Requested Extension : " + reqInfo);

        int isCompatible = ExtensionInfo.INCOMPATIBLE;
        ExtensionInfo instInfo = null;

        if (man != null) {
            Attributes instAttr = man.getMainAttributes();
            if (instAttr != null) {
                instInfo = new ExtensionInfo(null, instAttr);
                debug("Extension Installed " + instInfo);
                isCompatible = instInfo.isCompatibleWith(reqInfo);
                switch(isCompatible) {
                case ExtensionInfo.COMPATIBLE:
                    debug("Extensions are compatible");
                    return true;

                case ExtensionInfo.INCOMPATIBLE:
                    debug("Extensions are incompatible");
                    return false;

                default:
                    // everything else
                    debug("Extensions require an upgrade or vendor switch");
                    return installExtension(reqInfo, instInfo);

                }
            }
        }
        return false;
    }

    /*
     * <p>
     * An required extension is missing, if an ExtensionInstallationProvider is
     * registered, delegate the installation of that particular extension to it.
     * </p>
     *
     * @param reqInfo Missing extension information
     * @param instInfo Older installed version information
     *
     * @return true if the installation is successful
     */
    protected boolean installExtension(ExtensionInfo reqInfo,
                                       ExtensionInfo instInfo)
        throws ExtensionInstallationException
    {

        Vector currentProviders;
        synchronized(providers) {
            currentProviders = (Vector) providers.clone();
        }
        for (Enumeration e=currentProviders.elements();e.hasMoreElements();) {
            ExtensionInstallationProvider eip =
                (ExtensionInstallationProvider) e.nextElement();

            if (eip!=null) {
                // delegate the installation to the provider
                if (eip.installExtension(reqInfo, instInfo)) {
                    debug(reqInfo.name + " installation successful");
                    Launcher.ExtClassLoader cl = (Launcher.ExtClassLoader)
                        Launcher.getLauncher().getClassLoader().getParent();
                    addNewExtensionsToClassLoader(cl);
                    return true;
                }
            }
        }
        // We have tried all of our providers, noone could install this
        // extension, we just return failure at this point
        debug(reqInfo.name + " installation failed");
        return false;
    }

    /**
     * <p>
     * Checks if the extension, that is specified in the extension-list in
     * the applet jar manifest, is already installed (i.e. exists in the
     * extension directory).
     * </p>
     *
     * @param extensionName extension name in the extension-list
     *
     * @return the extension if it exists in the extension directory
     */
    private File checkExtensionExists(String extensionName) {
        // Function added to fix bug 4504166
        final String extName = extensionName;
        final String[] fileExt = {".jar", ".zip"};

        return (File) AccessController.doPrivileged
            (new PrivilegedAction() {
                public Object run() {
                    try {
                        File fExtension;
                        File[] dirs = getExtDirs();

                        // Search the extension directories for the extension that is specified
                        // in the attribute extension-list in the applet jar manifest
                        for (int i=0;i<dirs.length;i++) {
                            for (int j=0;j<fileExt.length;j++) {
                                if (extName.toLowerCase().endsWith(fileExt[j])) {
                                    fExtension = new File(dirs[i], extName);
                                } else {
                                    fExtension = new File(dirs[i], extName+fileExt[j]);
                                }
                                debug("checkExtensionExists:fileName " + fExtension.getName());
                                if (fExtension.exists()) {
                                    return fExtension;
                                }
                            }
                        }
                        return null;

                    } catch(Exception e) {
                         debugException(e);
                         return null;
                    }
                }
            });
    }

    /**
     * <p>
     * @return the java.ext.dirs property as a list of directory
     * </p>
     */
    private static File[] getExtDirs() {
        String s = java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction("java.ext.dirs"));

        File[] dirs;
        if (s != null) {
            StringTokenizer st =
                new StringTokenizer(s, File.pathSeparator);
            int count = st.countTokens();
            debug("getExtDirs count " + count);
            dirs = new File[count];
            for (int i = 0; i < count; i++) {
                dirs[i] = new File(st.nextToken());
                debug("getExtDirs dirs["+i+"] "+ dirs[i]);
            }
        } else {
            dirs = new File[0];
            debug("getExtDirs dirs " + dirs);
        }
        debug("getExtDirs dirs.length " + dirs.length);
        return dirs;
    }

    /*
     * <p>
     * Scan the directories and return all files installed in those
     * </p>
     * @param dirs list of directories to scan
     *
     * @return the list of files installed in all the directories
     */
    private static File[] getExtFiles(File[] dirs) throws IOException {
        Vector urls = new Vector();
        for (int i = 0; i < dirs.length; i++) {
            String[] files = dirs[i].list(new JarFilter());
            if (files != null) {
                debug("getExtFiles files.length " + files.length);
                for (int j = 0; j < files.length; j++) {
                    File f = new File(dirs[i], files[j]);
                    urls.add(f);
                    debug("getExtFiles f["+j+"] "+ f);
                }
            }
        }
        File[] ua = new File[urls.size()];
        urls.copyInto(ua);
        debug("getExtFiles ua.length " + ua.length);
        return ua;
    }

    /*
     * <p>
     * @return the list of installed extensions jar files
     * </p>
     */
    private File[] getInstalledExtensions() throws IOException {
        return (File[]) AccessController.doPrivileged
            (
             new PrivilegedAction() {
                 public Object run() {
                     try {
                         return getExtFiles(getExtDirs());
                     } catch(IOException e) {
                         debug("Cannot get list of installed extensions");
                         debugException(e);
                         return new URL[0];
                     }
                 }
            });
    }

    /*
     * <p>
     * Add the newly installed jar file to the extension class loader.
     * </p>
     *
     * @param cl the current installed extension class loader
     *
     * @return true if successful
     */
    private Boolean addNewExtensionsToClassLoader(Launcher.ExtClassLoader cl) {
        try {
            File[] installedExts = getInstalledExtensions();
            for (int i=0;i<installedExts.length;i++) {
                final File instFile = installedExts[i];
                URL instURL = AccessController.doPrivileged(
                    new PrivilegedAction<URL>() {
                        public URL run() {
                            try {
                                return ParseUtil.fileToEncodedURL(instFile);
                            } catch (MalformedURLException e) {
                                debugException(e);
                                return null;
                            }
                        }
                    });
                if (instURL != null) {
                    URL[] urls = cl.getURLs();
                    boolean found=false;
                    for (int j = 0; j<urls.length; j++) {
                        debug("URL["+j+"] is " + urls[j] + " looking for "+
                                           instURL);
                        if (urls[j].toString().compareToIgnoreCase(
                                    instURL.toString())==0) {
                            found=true;
                            debug("Found !");
                        }
                    }
                    if (!found) {
                        debug("Not Found ! adding to the classloader " +
                              instURL);
                        cl.addExtURL(instURL);
                    }
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            // let's continue with the next installed extension
        }
        return Boolean.TRUE;
    }

    // True to display all debug and trace messages
    static final boolean DEBUG = false;

    private static void debug(String s) {
        if (DEBUG) {
            System.err.println(s);
        }
    }

    private void debugException(Throwable e) {
        if (DEBUG) {
            e.printStackTrace();
        }
    }

}
