/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * Copyright 2005-2007 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.
 */

package com.sun.faces.facelets.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * @author Jacob Hookom
 * @author Roland Huss
 * @author Ales Justin (ales.justin@jboss.org)
 */
public final class Classpath {

    // discard any urls that begin with rar: and sar:
    // or end with their counterparts
    // as these should not be looked at for JSF related content.
    private static final String [] PREFIXES_TO_EXCLUDE = {
        "rar:",
        "sar:"
    };
    private static final String [] EXTENSIONS_TO_EXCLUDE = {
        ".rar",
        ".sar"
    };

    /**
     *
     */
    public Classpath() {
        super();
    }

    public static URL[] search(String prefix, String suffix)
          throws IOException {
        return search(Thread.currentThread().getContextClassLoader(), prefix,
                      suffix);
    }

    public static URL[] search(ClassLoader cl, String prefix, String suffix)
          throws IOException {
        Enumeration[] e = new Enumeration[]{
              cl.getResources(prefix),
              cl.getResources(prefix + "MANIFEST.MF")
        };
        Set all = new LinkedHashSet();
        URL url;
        URLConnection conn;
        JarFile jarFile = null;
        for (int i = 0, s = e.length; i < s; ++i) {
            while (e[i].hasMoreElements()) {
                url = (URL) e[i].nextElement();
                // Defensive programming.  Due to issue 13045 this collection
                // can contain URLs that have their spaces incorrectly escaped
                // by having %20 replaced with %2520.  This quick conditional 
                // check catches this particular case and averts it.
                String str = url.getPath();
                if (-1 != str.indexOf("%2520")) {
                    str = url.toExternalForm();
                    str = str.replace("%2520", "%20");
                    url = new URL(str);
                }
                conn = url.openConnection();
                conn.setUseCaches(false);
                conn.setDefaultUseCaches(false);
                try {
					if (conn instanceof JarURLConnection) {
					    jarFile = ((JarURLConnection) conn).getJarFile();
					} else {
					    jarFile = getAlternativeJarFile(url);
					}
					if (jarFile != null) {
					    searchJar(cl, all, jarFile, prefix, suffix);
					} else {
					    boolean searchDone =
					          searchDir(all, new File(URLDecoder.decode(url.getFile(), "UTF-8")), suffix);
					    if (!searchDone) {
					        searchFromURL(all, prefix, suffix, url);
					    }
					}
				} finally {
					if (jarFile != null) {
						try {
							jarFile.close();
						} catch (Exception ex) {
							// do nothing
						}
					}
				}
            }
        }
        URL[] urlArray = (URL[]) all.toArray(new URL[all.size()]);
        return urlArray;
    }

    private static boolean searchDir(Set result, File file, String suffix)
          throws IOException {
        if (file.exists() && file.isDirectory()) {
            File[] fc = file.listFiles();
            String path;
            URL src;
            // protect against Windows JDK bugs for listFiles -
            // if it's null (even though it shouldn't be) return false
            if (fc == null) return false;

            for (int i = 0; i < fc.length; i++) {
                path = fc[i].getAbsolutePath();
                if (fc[i].isDirectory()) {
                    searchDir(result, fc[i], suffix);
                } else if (path.endsWith(suffix)) {
                    // result.add(new URL("file:/" + path));
                    result.add(fc[i].toURL());
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Search from URL. Fall back on prefix tokens if not able to read from
     * original url param.
     *
     * @param result the result urls
     * @param prefix the current prefix
     * @param suffix the suffix to match
     * @param url    the current url to start search
     *
     * @throws IOException for any error
     */
    private static void searchFromURL(Set result, String prefix, String suffix,
                                      URL url) throws IOException {
        boolean done = false;
        InputStream is = getInputStream(url);
        if (is != null) {
            ZipInputStream zis;
            if (is instanceof ZipInputStream) {
                zis = (ZipInputStream) is;
            } else {
                zis = new ZipInputStream(is);
            }
            try {
                ZipEntry entry = zis.getNextEntry();
                // initial entry should not be null
                // if we assume this is some inner jar
                done = (entry != null);
                while (entry != null) {
                    String entryName = entry.getName();
                    if (entryName.endsWith(suffix)) {
                        String urlString = url.toExternalForm();
                        result.add(new URL(urlString + entryName));
                    }
                    entry = zis.getNextEntry();
                }
            } finally {
                zis.close();
            }
        }
        if (!done && prefix.length() > 0) {
            // we add '/' at the end since join adds it as well
            String urlString = url.toExternalForm() + "/";
            String[] split = prefix.split("/");
            prefix = join(split, true);
            String end = join(split, false);
            int p = urlString.lastIndexOf(end);
            urlString = urlString.substring(0, p);
            for (String cur : PREFIXES_TO_EXCLUDE) {
                if (urlString.startsWith(cur)) {
                    return;
                }
            }
            url = new URL(urlString);
            searchFromURL(result, prefix, suffix, url);
        }
    }

    /**
     * Join tokens, exlude last if param equals true.
     *
     * @param tokens      the tokens
     * @param excludeLast do we exclude last token
     *
     * @return joined tokens
     */
    private static String join(String[] tokens, boolean excludeLast) {
        StringBuffer join = new StringBuffer();
        for (int i = 0; i < tokens.length - (excludeLast ? 1 : 0); i++) {
            join.append(tokens[i]).append("/");
        }
        return join.toString();
    }

    /**
     * Open input stream from url. Ignore any errors.
     *
     * @param url the url to open
     *
     * @return input stream or null if not possible
     */
    private static InputStream getInputStream(URL url) {
        try {
            return url.openStream();
        } catch (Throwable t) {
            return null;
        }
    }

    /**
     * For URLs to JARs that do not use JarURLConnection - allowed by the servlet
     * spec - attempt to produce a JarFile object all the same. Known servlet
     * engines that function like this include Weblogic and OC4J. This is not a
     * full solution, since an unpacked WAR or EAR will not have JAR "files" as
     * such.
     */
    private static JarFile getAlternativeJarFile(URL url) throws IOException {
        String urlFile = url.getFile();
        return getAlternativeJarFile(urlFile);
    }
    
    static JarFile getAlternativeJarFile(String urlFile) throws IOException {
        JarFile result = null;
        // Trim off any suffix - which is prefixed by "!/" on Weblogic
        int bangSlash = urlFile.indexOf("!/");
        // Try the less safe "!", used on OC4J
        int bang = urlFile.indexOf('!');
        int separatorIndex = -1;
        
        // if either are found, take the first one.
        if (-1 != bangSlash || -1 != bang) {
            if (bangSlash < bang) {
                separatorIndex = bangSlash;
            } else {
                separatorIndex = bang;
            }
        }

        if (separatorIndex != -1) {
            String jarFileUrl = urlFile.substring(0, separatorIndex);
            // And trim off any "file:" prefix.
            if (jarFileUrl.startsWith("file:")) {
                jarFileUrl = jarFileUrl.substring("file:".length());
                jarFileUrl = URLDecoder.decode(jarFileUrl, "UTF-8");
            }
            boolean foundExclusion = false;
            for (int i = 0; i < PREFIXES_TO_EXCLUDE.length; i++) {
                if (jarFileUrl.startsWith(PREFIXES_TO_EXCLUDE[i]) ||
                    jarFileUrl.endsWith(EXTENSIONS_TO_EXCLUDE[i])) {
                    foundExclusion = true;
                    break;
                }
            }
            if (!foundExclusion) {
                result = new JarFile(jarFileUrl);
            }

            return result;
        }
        return null;
    }

    private static void searchJar(ClassLoader cl, Set result, JarFile file,
                                  String prefix, String suffix)
          throws IOException {
        Enumeration e = file.entries();
        JarEntry entry;
        String name;
        while (e.hasMoreElements()) {
            try {
                entry = (JarEntry) e.nextElement();
            } catch (Throwable t) {
                continue;
            }
            name = entry.getName();
            if (name.startsWith(prefix) && name.endsWith(suffix)) {
                Enumeration e2 = cl.getResources(name);
                while (e2.hasMoreElements()) {
					result.add(e2.nextElement());
				}
			}
		}
	}

}
