/**
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.axis2.classloader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/**
 * @version $Rev$ $Date$
 */
public class UrlResourceFinder implements ResourceFinder {
    private final Object lock = new Object();
    private final LinkedHashSet<URL> urls = new LinkedHashSet<URL>();
    private final LinkedHashMap<URL,ResourceLocation> classPath = new LinkedHashMap<URL,ResourceLocation>();
    private final LinkedHashSet<File> watchedFiles = new LinkedHashSet<File>();

    private boolean destroyed = false;

    public UrlResourceFinder() {
    }

    public UrlResourceFinder(URL[] urls) {
        addUrls(urls);
    }

    public void destroy() {
        synchronized (lock) {
            if (destroyed) {
                return;
            }
            destroyed = true;
            urls.clear();
            for (ResourceLocation resourceLocation : classPath.values()) {
                resourceLocation.close();
            }
            classPath.clear();
        }
    }

    public ResourceHandle getResource(String resourceName) {
        synchronized (lock) {
            if (destroyed) {
                return null;
            }
            for (Map.Entry<URL, ResourceLocation> entry : getClassPath().entrySet()) {
                ResourceLocation resourceLocation = entry.getValue();
                ResourceHandle resourceHandle = resourceLocation.getResourceHandle(resourceName);
                if (resourceHandle != null && !resourceHandle.isDirectory()) {
                    return resourceHandle;
                }
            }
        }
        return null;
    }

    public URL findResource(String resourceName) {
        synchronized (lock) {
            if (destroyed) {
                return null;
            }
            for (Map.Entry<URL, ResourceLocation> entry : getClassPath().entrySet()) {
                ResourceLocation resourceLocation = entry.getValue();
                ResourceHandle resourceHandle = resourceLocation.getResourceHandle(resourceName);
                if (resourceHandle != null) {
                    return resourceHandle.getUrl();
                }
            }
        }
        return null;
    }

    public Enumeration findResources(String resourceName) {
        synchronized (lock) {
            return new ResourceEnumeration(new ArrayList<ResourceLocation>(getClassPath().values()), resourceName);
        }
    }

    public void addUrl(URL url) {
        addUrls(Collections.singletonList(url));
    }

    public URL[] getUrls() {
        synchronized (lock) {
            return urls.toArray(new URL[urls.size()]);
        }
    }

    /**
     * Adds an array of urls to the end of this class loader.
     * @param urls the URLs to add
     */
    protected void addUrls(URL[] urls) {
        addUrls(Arrays.asList(urls));
    }

    /**
     * Adds a list of urls to the end of this class loader.
     * @param urls the URLs to add
     */
    protected void addUrls(List<URL> urls) {
        synchronized (lock) {
            if (destroyed) {
                throw new IllegalStateException("UrlResourceFinder has been destroyed");
            }

            boolean shouldRebuild = this.urls.addAll(urls);
            if (shouldRebuild) {
                rebuildClassPath();
            }
        }
    }

    private LinkedHashMap<URL, ResourceLocation> getClassPath() {
        assert Thread.holdsLock(lock): "This method can only be called while holding the lock";

        for (File file : watchedFiles) {
            if (file.canRead()) {
                rebuildClassPath();
                break;
            }
        }

        return classPath;
    }

    /**
     * Rebuilds the entire class path.  This class is called when new URLs are added or one of the watched files
     * becomes readable.  This method will not open jar files again, but will add any new entries not alredy open
     * to the class path.  If any file based url is does not exist, we will watch for that file to appear.
     */
    private void rebuildClassPath() {
        assert Thread.holdsLock(lock): "This method can only be called while holding the lock";

        // copy all of the existing locations into a temp map and clear the class path
        Map<URL,ResourceLocation> existingJarFiles = new LinkedHashMap<URL,ResourceLocation>(classPath);
        classPath.clear();

        LinkedList<URL> locationStack = new LinkedList<URL>(urls);
        try {
            while (!locationStack.isEmpty()) {
                URL url = locationStack.removeFirst();

                // Skip any duplicate urls in the classpath
                if (classPath.containsKey(url)) {
                    continue;
                }

                // Check is this URL has already been opened
                ResourceLocation resourceLocation = existingJarFiles.remove(url);

                // If not opened, cache the url and wrap it with a resource location
                if (resourceLocation == null) {
                    try {
                        File file = cacheUrl(url);
                        resourceLocation = createResourceLocation(url, file);
                    } catch (FileNotFoundException e) {
                        // if this is a file URL, the file doesn't exist yet... watch to see if it appears later
                        if ("file".equals(url.getProtocol())) {
                            File file = new File(url.getPath());
                            watchedFiles.add(file);
                            continue;

                        }
                    } catch (IOException ignored) {
                        // can't seem to open the file... this is most likely a bad jar file
                        // so don't keep a watch out for it because that would require lots of checking
                        // Dain: We may want to review this decision later
                        continue;
                    } catch (UnsupportedOperationException ex) {
                        // the protocol for the JAR file's URL is not supported.  This can occur when
                        // the jar file is embedded in an EAR or CAR file.  Proceed but log the message.
                        System.out.println("The protocol for the JAR file's URL is not supported" + ex);
                        continue;
                    }
                }

                // add the jar to our class path
                classPath.put(resourceLocation.getCodeSource(), resourceLocation);

                // push the manifest classpath on the stack (make sure to maintain the order)
                List<URL> manifestClassPath = getManifestClassPath(resourceLocation);
                locationStack.addAll(0, manifestClassPath);
            }
        } catch (Error e) {
            destroy();
            throw e;
        }

        for (ResourceLocation resourceLocation : existingJarFiles.values()) {
            resourceLocation.close();
        }
    }

    protected File cacheUrl(URL url) throws IOException {
        if (!"file".equals(url.getProtocol())) {
            // download the jar
            throw new UnsupportedOperationException("Only local file jars are supported " + url);
        }

        File file = new File(url.getPath());
        if (!file.exists()) {
            throw new FileNotFoundException(file.getAbsolutePath());
        }
        if (!file.canRead()) {
            throw new IOException("File is not readable: " + file.getAbsolutePath());
        }
        return file;
    }

    protected ResourceLocation createResourceLocation(URL codeSource, File cacheFile) throws IOException {
        if (!cacheFile.exists()) {
            throw new FileNotFoundException(cacheFile.getAbsolutePath());
        }
        if (!cacheFile.canRead()) {
            throw new IOException("File is not readable: " + cacheFile.getAbsolutePath());
        }

        ResourceLocation resourceLocation;
        if (cacheFile.isDirectory()) {
            // DirectoryResourceLocation will only return "file" URLs within this directory
            // do not user the DirectoryResourceLocation for non file based urls
            resourceLocation = new DirectoryResourceLocation(cacheFile);
        } else {
            resourceLocation = new JarResourceLocation(codeSource, cacheFile);
        }
        return resourceLocation;
    }

    private List<URL> getManifestClassPath(ResourceLocation resourceLocation) {
        try {
            // get the manifest, if possible
            Manifest manifest = resourceLocation.getManifest();
            if (manifest == null) {
                // some locations don't have a manifest
                return Collections.EMPTY_LIST;
            }

            // get the class-path attribute, if possible
            String manifestClassPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
            if (manifestClassPath == null) {
                return Collections.EMPTY_LIST;
            }

            // build the urls...
            // the class-path attribute is space delimited
            URL codeSource = resourceLocation.getCodeSource();
            LinkedList<URL> classPathUrls = new LinkedList<URL>();
            for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
                String entry = tokenizer.nextToken();
                try {
                    // the class path entry is relative to the resource location code source
                    URL entryUrl = new URL(codeSource, entry);
                    classPathUrls.addLast(entryUrl);
                } catch (MalformedURLException ignored) {
                    // most likely a poorly named entry
                }
            }
            return classPathUrls;
        } catch (IOException ignored) {
            // error opening the manifest
            return Collections.EMPTY_LIST;
        }
    }
}
