/*
 * 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.deployment;

import org.apache.axiom.attachments.utils.IOUtils;
import org.apache.axis2.classloader.BeanInfoCache;
import org.apache.axis2.classloader.BeanInfoCachingClassLoader;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class DeploymentClassLoader extends URLClassLoader implements BeanInfoCachingClassLoader {
    // List of URL's
    private URL[] urls = null;

    // List of jar files inside the jars in the original url
    private List embedded_jars;

    private boolean isChildFirstClassLoading;

    private final BeanInfoCache beanInfoCache = new BeanInfoCache();
    
    /**
     * DeploymentClassLoader is extended from URLClassLoader. The constructor
     * does not override the super constructor, but takes in an addition list of
     * jar files inside /lib directory.
     *
     * @param urls   <code>URL</code>s
     * @param parent parent classloader <code>ClassLoader</code>
     */
    public DeploymentClassLoader(URL[] urls,
                                 List embedded_jars,
                                 ClassLoader parent,
                                 boolean isChildFirstClassLoading) {
        super(urls, parent);
        this.urls = urls;
        this.embedded_jars = embedded_jars;
        this.isChildFirstClassLoading = isChildFirstClassLoading;
    }

    /**
     * Finds and loads the class with the specified name from the URL search
     * path. Any URLs referring to JAR files are loaded and opened as needed
     * until the class is found.
     *
     * @param name the name of the class
     * @return the resulting class
     * @exception ClassNotFoundException if the class could not be found
     */
    protected Class findClass(String name) throws ClassNotFoundException {
        Class clazz;
        try {
            clazz = super.findClass(name);
        } catch (ClassNotFoundException e) {
            byte raw[] = null;
            try {
                String completeFileName = name;
                /**
                 * Replacing org.apache. -> org/apache/...
                 */
                completeFileName = completeFileName.replace('.', '/').concat(".class");
                raw = getBytes(completeFileName);
            } catch (Exception ex) {
                // Fall through
            }
            if (raw == null) {
                throw new ClassNotFoundException("Class Not found : " + name);
            }
            clazz = defineClass(name, raw, 0, raw.length);
        }
        return clazz;
    }


    /**
     * Finds the resource with the specified name on the URL search path.
     *
     * @param resource the name of the resource
     * @return a <code>URL</code> for the resource, or <code>null</code>
     * if the resource could not be found.
     */
    public URL findResource(String resource) {
        URL url = super.findResource(resource);
        if (url == null) {
            for (int i = 0; embedded_jars != null && i < embedded_jars.size(); i++) {
                String libjar_name = (String) embedded_jars.get(i);
                try {
                    InputStream in = getJarAsStream(libjar_name);
                    ZipInputStream zin = new ZipInputStream(in);
                    ZipEntry entry;
                    String entryName;
                    while ((entry = zin.getNextEntry()) != null) {
                        entryName = entry.getName();
                        if (entryName != null &&
                                entryName.endsWith(resource)) {
                            byte[] raw = IOUtils.getStreamAsByteArray(zin);
                            return new URL("jar", "", -1, urls[0] + "!/" + libjar_name + "!/" + entryName,
                                    new ByteUrlStreamHandler(raw));
                        }
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return url;
    }

    /**
     * Returns an Enumeration of URLs representing all of the resources
     * on the URL search path having the specified name.
     *
     * @param resource the resource name
     * @exception IOException if an I/O exception occurs
     * @return an <code>Enumeration</code> of <code>URL</code>s
     */
    public Enumeration findResources(String resource) throws IOException {
        ArrayList resources = new ArrayList();
        Enumeration e = super.findResources(resource);
        while (e.hasMoreElements()) {
            resources.add(e.nextElement());
        }
        for (int i = 0; embedded_jars != null && i < embedded_jars.size(); i++) {
            String libjar_name = (String) embedded_jars.get(i);
            try {
            InputStream in = getJarAsStream(libjar_name);
            ZipInputStream zin = new ZipInputStream(in);
            ZipEntry entry;
            String entryName;
                while ((entry = zin.getNextEntry()) != null) {
                    entryName = entry.getName();
                    if (entryName != null &&
                            entryName.endsWith(resource)) {
                        byte[] raw = IOUtils.getStreamAsByteArray(zin);
                        resources.add(new URL("jar", "", -1, urls[0] + "!/" + libjar_name + "!/" + entryName,
                                new ByteUrlStreamHandler(raw)));
                    }
                }
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
        return Collections.enumeration(resources);
    }

    /**
     * Access the jars file (/lib) one by one , then for each one create a <code>ZipInputStream</code>
     * and check to see whether there is any entry eith given name. if it is found then
     * return the byte array for that
     *
     * @param resource <code>String</code>  Name of the file to be found
     * @return byte[]
     * @throws java.io.IOException <code>Exception</code>
     */
    private byte[] getBytes(String resource) throws Exception {
        for (int i = 0; embedded_jars != null && i < embedded_jars.size(); i++) {
            String libjar_name = (String) embedded_jars.get(i);
            InputStream in = getJarAsStream(libjar_name);
            byte[] bytes = getBytes(in, resource);
            if(bytes != null) {
                return bytes;
            }
        }
        return null;
    }

    /**
     * Get a specific entry's content as a byte array
     * 
     * @param in
     * @param resource
     * @return
     * @throws Exception
     */
    private byte[] getBytes(InputStream in, String resource) throws Exception {
        ZipInputStream zin = new ZipInputStream(in);
        ZipEntry entry;
        String entryName;
        while ((entry = zin.getNextEntry()) != null) {
            entryName = entry.getName();
            if (entryName != null &&
                    entryName.endsWith(resource)) {
                byte[] raw = IOUtils.getStreamAsByteArray(zin);
                zin.close();
                return raw;
            }
        }
        return null;
    }

    /**
     * Get the specified embedded jar from the main jar 
     *
     * @param libjar_name
     * @return
     * @throws Exception
     */
    private InputStream getJarAsStream(String libjar_name) throws Exception {
        return new ByteArrayInputStream(getBytes(urls[0].openStream(), libjar_name));
    }

    public static class ByteUrlStreamHandler extends URLStreamHandler {
        private byte[] bytes;

        public ByteUrlStreamHandler(byte[] bytes) {
            this.bytes = bytes;
        }

        protected URLConnection openConnection(URL u) throws IOException {
            return new ByteURLConnection(u, bytes);
        }
    }

    public static class ByteURLConnection extends URLConnection {
        protected byte[] bytes;

        public ByteURLConnection(URL url, byte[] bytes) {
            super(url);
            this.bytes = bytes;
        }

        public void connect() {
        }

        public InputStream getInputStream() {
            return new ByteArrayInputStream(bytes);
        }
    }

    public InputStream getResourceAsStream(String name) {
        URL url = findResource(name);
        if(url == null) {
            url = getResource(name);
        }
        if(url!=null){
            try {
                return url.openStream();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        Class c = null;
        if (!isChildFirstClassLoading) {
            c = super.loadClass(name, resolve);
        } else {
            c = findLoadedClass(name);
            if (c == null) {
                try {
                    c = findClass(name);
                } catch (Exception e) {
                    c = super.loadClass(name, resolve);
                }
            }
        }
        return c;
    }

    public boolean isChildFirstClassLoading() {
        return isChildFirstClassLoading;
    }

    public void setChildFirstClassLoading(boolean childFirstClassLoading) {
        isChildFirstClassLoading = childFirstClassLoading;
    }

    public final BeanInfoCache getBeanInfoCache() {
        return beanInfoCache;
    }
}
