/*
 * 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.openejb.util.classloader;

import org.apache.openejb.core.ParentClassLoaderFinder;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.JavaSecurityManagers;

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;

// TODO: look SM usage, find a better name
public class URLClassLoaderFirst extends URLClassLoader {

    // log4j is optional, moreover it will likely not work if not skipped and loaded by a temp classloader
    private static final boolean SKIP_LOG4J = "true".equals(SystemInstance.get().getProperty("openejb.skip.log4j", "true")) && skipLib("org.apache.log4j.Logger");
    private static final boolean SKIP_MYFACES = "true".equals(SystemInstance.get().getProperty("openejb.skip.myfaces", "true")) && skipLib("org.apache.myfaces.spi.FactoryFinderProvider");
    private static final boolean SKIP_HSQLDB = skipLib("org.hsqldb.lib.HsqlTimer");
    // commons-net is only in tomee-plus
    private static final boolean SKIP_COMMONS_NET = skipLib("org.apache.commons.net.pop3.POP3Client");

    // first skip container APIs if not in the jaxrs or plus version
    private static final boolean SKIP_JAXWS = skipLib("org.apache.cxf.jaxws.support.JaxWsImplementorInfo");
    private static final boolean SKIP_JMS = skipLib("org.apache.activemq.broker.BrokerFactory");
    private static final boolean EMBEDDED = "true".equals(SystemInstance.get().getProperty("openejb.embedded"));

    // - will not match anything, that's the desired default behavior
    public static final Collection<String> FORCED_SKIP = new ArrayList<>();
    public static final Collection<String> FORCED_LOAD = new ArrayList<>();
    public static final Collection<String> FILTERABLE_RESOURCES = new ArrayList<>();

    static {
        reloadConfig();
        ClassLoader.registerAsParallelCapable();
    }

    public static final String SLF4J_BINDER_CLASS = "org/slf4j/impl/StaticLoggerBinder.class";
    private static final URL SLF4J_CONTAINER = URLClassLoaderFirst.class.getClassLoader().getResource(SLF4J_BINDER_CLASS);
    private static final String CLASS_EXT = ".class";
    public static final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader();
    private static final boolean ALLOW_OPEN_EJB_SYSTEM_LOADING = !Boolean.getBoolean("openejb.classloader.first.disallow-system-loading");

    public static void reloadConfig() {
        list(FORCED_SKIP, "openejb.classloader.forced-skip", null);
        list(FORCED_LOAD, "openejb.classloader.forced-load", null);
        list(FILTERABLE_RESOURCES, "openejb.classloader.filterable-resources",
                "META-INF/services/javax.validation.spi.ValidationProvider," +
                "META-INF/services/javax.ws.rs.client.ClientBuilder," +
                "META-INF/services/javax.json.spi.JsonProvider," +
                "META-INF/services/javax.cache.spi.CachingProvider," +
                "META-INF/javamail.default.providers,META-INF/javamail.default.address.map," +
                "META-INF/javamail.charset.map,META-INF/mailcap," +
                SLF4J_BINDER_CLASS);
    }

    private static void list(final Collection<String> list, final String key, final String def) {
        list.clear();

        final String s = SystemInstance.get().getOptions().get(key, def);
        if (s != null && !s.trim().isEmpty()) {
            list.addAll(Arrays.asList(s.trim().split(",")));
        }
    }

    private static boolean skipLib(final String includedClass) {
        try {
            URLClassLoaderFirst.class.getClassLoader().loadClass(includedClass);
            return "true".equalsIgnoreCase(JavaSecurityManagers.getSystemProperty(includedClass + ".skip", "true"));
        } catch (final ClassNotFoundException e) {
            return false;
        }
    }

    private final ClassLoader system;

    public URLClassLoaderFirst(final URL[] urls, final ClassLoader parent) {
        super(urls, parent);
        system = ClassLoader.getSystemClassLoader();
    }

    @Override
    public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // already loaded?
            Class<?> clazz = findLoadedClass(name);
            if (clazz != null) {
                if (resolve) {
                    resolveClass(clazz);
                }
                return clazz;
            }

            // JSE classes?
            if (canBeLoadedFromSystem(name)) {
                try {
                    clazz = system.loadClass(name);
                    if (clazz != null) {
                        if (resolve) {
                            resolveClass(clazz);
                        }
                        return clazz;
                    }
                } catch (final NoClassDefFoundError | ClassNotFoundException ignored) {
                    // no-op
                }
            }

            // look for it in this classloader
            final boolean ok = !(shouldSkip(name) || shouldDelegateToTheContainer(this, name));
            if (ok) {
                clazz = loadInternal(name, resolve);
                if (clazz != null) {
                    return clazz;
                }
            }

            // finally delegate
            clazz = loadFromParent(name, resolve);
            if (clazz != null) {
                return clazz;
            }

            if (!ok) {
                clazz = loadInternal(name, resolve);
                if (clazz != null) {
                    return clazz;
                }
            }

            throw new ClassNotFoundException(name);
        }
    }

    public static boolean shouldDelegateToTheContainer(final ClassLoader loader, final String name) {
        return shouldSkipJsf(loader, name) || shouldSkipSlf4j(loader, name);
    }

    private Class<?> loadFromParent(final String name, final boolean resolve) {
        ClassLoader parent = getParent();
        if (parent == null) {
            parent = system;
        }
        try {
            final Class<?> clazz = Class.forName(name, false, parent);
            if (clazz != null) {
                if (resolve) {
                    resolveClass(clazz);
                }
                return clazz;
            }
        } catch (final ClassNotFoundException ignored) {
            // no-op
        }
        return null;
    }

    public Class<?> findAlreadyLoadedClass(final String name) {
        return super.findLoadedClass(name);
    }

    public Class<?> loadInternal(final String name, final boolean resolve) {
        try {
            final Class<?> clazz = findClass(name);
            if (clazz != null) {
                if (resolve) {
                    resolveClass(clazz);
                }
                return clazz;
            }
        } catch (final ClassNotFoundException ignored) {
            // no-op
        }
        return null;
    }

    // we skip webapp enrichment jars since we want to load them from the webapp or lib
    // Note: this is not a real limitation since it is first fail it will be done later
    public static boolean canBeLoadedFromSystem(final String name) {
        return ALLOW_OPEN_EJB_SYSTEM_LOADING && (!name.startsWith("org.apache.openejb.") || !isWebAppEnrichment(name.substring("org.apache.openejb.".length())));
    }

    // making all these call inline if far more costly than factorizing packages
    //
    // /!\ please check org.apache.openejb.persistence.PersistenceUnitInfoImpl.isServerClass() too
    // when updating this method
    public static boolean shouldSkip(final String name) {
        if (name == null) { // can happen with rest servlet definition or errors
            return false;
        }

        for (final String prefix : FORCED_SKIP) {
            if (name.startsWith(prefix)) {
                return true;
            }
        }
        for (final String prefix : FORCED_LOAD) {
            if (name.startsWith(prefix)) {
                return false;
            }
        }

        if (name.startsWith("java.")) {
            return true;
        }
        if (name.startsWith("javax.faces.")) {
            return false;
        }
        if (name.startsWith("javax.mail.")) {
            return false;
        }
        if (name.startsWith("javax.") || name.startsWith("jakarta.")) {
            return isInServer(name);
        }
        if (name.startsWith("sun.")) {
            return isInJvm(name);
        }

        // can be provided in the webapp
        if (name.startsWith("javax.servlet.jsp.jstl")) {
            return false;
        }

        if (name.startsWith("org.")) {
            final String org = name.substring("org.".length());

            if (org.startsWith("apache.")) {
                final String apache = org.substring("apache.".length());

                // the following block is classes which enrich webapp classloader
                if (apache.startsWith("webbeans.jsf")) {
                    return false;
                }
                if (apache.startsWith("tomee.mojarra.")) {
                    return false;
                }

                // here we find server classes
                if (apache.startsWith("bval.")) {
                    return true;
                }
                if (apache.startsWith("openjpa.")) {
                    return true;
                }
                if (apache.startsWith("xbean.")) {
                    return !apache.substring("xbean.".length()).startsWith("spring");
                }
                if (apache.startsWith("geronimo.")) {
                    return true;
                }
                if (apache.startsWith("coyote.")) {
                    return true;
                }
                if (apache.startsWith("webbeans.")) {
                    return true;
                }
                if (apache.startsWith("log4j.") && SKIP_LOG4J) {
                    return true;
                }
                if (apache.startsWith("catalina.")) {
                    return true;
                }
                if (apache.startsWith("jasper.")) {
                    return true;
                }
                if (apache.startsWith("tomcat.")) {
                    return true;
                }
                if (apache.startsWith("el.")) {
                    return true;
                }
                // if (apache.startsWith("jsp")) return true; // precompiled jsp have to be loaded from the webapp
                if (apache.startsWith("naming.")) {
                    return true;
                }
                if (apache.startsWith("taglibs.standard.")) {
                    return true;
                }

                if (apache.startsWith("openejb.")) { // skip all excepted webapp enrichment artifacts
                    return !isWebAppEnrichment(apache.substring("openejb.".length()));
                }

                if (apache.startsWith("commons.")) {
                    final String commons = apache.substring("commons.".length());

                    // don't stop on commons package since we don't bring all commons
                    if (commons.startsWith("beanutils.")) {
                        return isInServer(name);
                    }
                    if (commons.startsWith("cli.")) {
                        return true;
                    }
                    if (commons.startsWith("codec.")) {
                        return true;
                    }
                    if (commons.startsWith("collections.")) {
                        return true;
                    }
                    if (commons.startsWith("dbcp.")) {
                        return true;
                    }
                    if (commons.startsWith("dbcp2.")) {
                        return true;
                    }
                    if (commons.startsWith("digester.")) {
                        return true;
                    }
                    if (commons.startsWith("jocl.")) {
                        return true;
                    }
                    if (commons.startsWith("lang.")) { // openjpa
                        return true;
                    }
                    if (commons.startsWith("lang3.")) {  // us
                        return true;
                    }
                    if (commons.startsWith("logging.")) {
                        return false;
                    }
                    if (commons.startsWith("pool.")) {
                        return true;
                    }
                    if (commons.startsWith("pool2.")) {
                        return true;
                    }
                    if (commons.startsWith("net.") && SKIP_COMMONS_NET) {
                        return true;
                    }

                    return false;
                }

                if (SKIP_MYFACES && apache.startsWith("myfaces.")) {
                    // we bring only myfaces-impl (+api but that's javax)
                    // mainly inspired from a comparison with tomahawk packages
                    final String myfaces = name.substring("myfaces.".length());
                    if (myfaces.startsWith("shared.")) {
                        return true;
                    }
                    if (myfaces.startsWith("ee.")) {
                        return true;
                    }
                    if (myfaces.startsWith("lifecycle.")) {
                        return true;
                    }
                    if (myfaces.startsWith("context.")) {
                        return true;
                    }
                    if (myfaces.startsWith("logging.")) {
                        return true;
                    }
                    // tomahawk uses component.html package
                    if (myfaces.startsWith("component.visit.") || myfaces.equals("component.ComponentResourceContainer")) {
                        return true;
                    }
                    if (myfaces.startsWith("application.")) {
                        return true;
                    }
                    if (myfaces.startsWith("config.")) {
                        return true;
                    }
                    if (myfaces.startsWith("event.")) {
                        return true;
                    }

                    if (myfaces.startsWith("resource.")) {
                        return true;
                    }
                    if (myfaces.startsWith("el.")) {
                        return true;
                    }
                    if (myfaces.startsWith("spi.")) {
                        return true;
                    }
                    if (myfaces.startsWith("convert.")) {
                        return true;
                    }
                    if (myfaces.startsWith("debug.")) {
                        return true;
                    }
                    if (myfaces.startsWith("util.")) {
                        return true;
                    }
                    if (myfaces.startsWith("view.")) {
                        return true;
                    }
                    if (myfaces.equals("convert.ConverterUtils")) {
                        return true;
                    }

                    if (myfaces.startsWith("renderkit.")) {
                        final String renderkit = myfaces.substring("renderkit.".length());
                        if (renderkit.startsWith("html.Html")) {
                            return true;
                        }
                        final char firstNextletter = renderkit.charAt(0);
                        if (Character.isUpperCase(firstNextletter)) {
                            return true;
                        }
                        return false;
                    }

                    if (myfaces.startsWith("taglib.")) {
                        final String taglib = myfaces.substring("taglib.".length());
                        if (taglib.startsWith("html.Html")) {
                            return true;
                        }
                        if (taglib.startsWith("core.")) {
                            return true;
                        }
                        return false;
                    }

                    if (myfaces.startsWith("webapp.")) {
                        final String webapp = myfaces.substring("webapp.".length());
                        if (webapp.startsWith("Faces")) {
                            return true;
                        }
                        if (webapp.startsWith("Jsp")) {
                            return true;
                        }
                        if (webapp.startsWith("Startup")) {
                            return true;
                        }
                        if (webapp.equals("AbstractFacesInitializer")) {
                            return true;
                        }
                        if (webapp.equals("MyFacesServlet")) {
                            return true;
                        }
                        if (webapp.equals("ManagedBeanDestroyerListener")) {
                            return true;
                        }
                        if (webapp.equals("WebConfigParamsLogger")) {
                            return true;
                        }
                        return false;
                    }

                    return false;
                }

                if (apache.startsWith("activemq.")) {
                    return SKIP_JMS && isInServer(name);
                }

                return false;
            }

            // other org packages
            if (org.startsWith("hsqldb.") && SKIP_HSQLDB) {
                return true;
            }
            if (org.startsWith("codehaus.swizzle.")) {
                final String swizzle = org.substring("codehaus.swizzle.".length());
                if (swizzle.startsWith("stream.")) {
                    return true;
                }
                if (swizzle.startsWith("rss.")) {
                    return true;
                }
                if (swizzle.startsWith("Grep.class") || swizzle.startsWith("Lexer.class")) {
                    return true;
                }
                return false;
            }
            if (org.startsWith("w3c.dom.") || org.startsWith("xml.sax.")) {
                return isInJvm(name);
            }
            if (org.startsWith("eclipse.jdt.")) {
                return true;
            }

            // let an app use its own slf4j impl (so its own api too)
            // if (org.startsWith("slf4j")) return true;

            return false;
        }

        // other packages
        if (name.startsWith("com.")) {
            final String sub = name.substring("com.".length());
            if (sub.startsWith("sun.")) {
                return !name.startsWith("sun.mail.") && isInJvm(name);
            }
            if (sub.startsWith("oracle.")) {
                return true;
            }
        }
        if (name.startsWith("jdk.")) {
            return true;
        }

        if (name.startsWith("serp.bytecode.")) {
            return true;
        }

        return false;
    }

    private static boolean isInJvm(final String name) {
        return SYSTEM_CLASS_LOADER.getResource(name.replace('.', '/') + CLASS_EXT) != null;
    }

    private static boolean isInServer(final String name) {
        if (name.startsWith("javax.")) {
            final String sub = name.substring("javax.".length());
            if (sub.startsWith("jws.")) {
                return SKIP_JAXWS || EMBEDDED;
            }
            if (sub.startsWith("jms.")) {
                return SKIP_JMS || EMBEDDED;
            }
        }
        if (name.startsWith("jakarta.")) {
            final String sub = name.substring("jakarta.".length());
            if (sub.startsWith("jws.")) {
                return SKIP_JAXWS || EMBEDDED;
            }
            if (sub.startsWith("jms.")) {
                return SKIP_JMS || EMBEDDED;
            }
        }
        return ParentClassLoaderFinder.Helper.get().getResource(name.replace('.', '/') + ".class") != null;
    }

    public static boolean shouldSkipJsf(final ClassLoader loader, final String name) {
        if (!name.startsWith("javax.faces.")) {
            return false;
        }

        // using annotation to test to avoid to load more classes with deps
        final String testClass;
        // these test classes have to be jsf 2.x AND 1.x otherwise we force JSF 2
        if ("javax.faces.webapp.FacesServlet".equals(name)) {
            testClass = "javax.faces.FactoryFinder";
        } else {
            testClass = "javax.faces.webapp.FacesServlet";
        }

        final String classname = testClass.replace('.', '/') + ".class";
        try {
            final Enumeration<URL> resources = loader.getResources(classname);
            final Collection<URL> thisJSf = Collections.list(resources);
            return thisJSf.isEmpty() || thisJSf.size() <= 1;
        } catch (final IOException e) {
            return true;
        }

    }

    // in org.apache.openejb.
    private static boolean isWebAppEnrichment(final String openejb) {
        return openejb.startsWith("hibernate.") || openejb.startsWith("jpa.integration.")
            || openejb.startsWith("toplink.") || openejb.startsWith("eclipselink.")
            || openejb.startsWith("arquillian.");
    }

    @Override
    public Enumeration<URL> getResources(final String name) throws IOException {
        return URLClassLoaderFirst.filterResources(name, super.getResources(name));
    }

    public static boolean isFilterableResource(final String name) {
        // currently bean validation, Slf4j, myfaces (because of enrichment)
        return name != null
            && (FILTERABLE_RESOURCES.contains(name) || name.startsWith("META-INF/services/org.apache.myfaces.spi"));
    }

    public static boolean shouldSkipSlf4j(final ClassLoader loader, final String name) {
        if (name == null || !name.startsWith("org.slf4j.")) {
            return false;
        }

        try { // using getResource here just returns randomly the container one so we need getResources
            final Enumeration<URL> resources = loader.getResources(SLF4J_BINDER_CLASS);
            while (resources.hasMoreElements()) {
                final URL resource = resources.nextElement();
                if (!resource.equals(SLF4J_CONTAINER)) {
                    // applicative slf4j
                    return false;
                }
            }
        } catch (final Throwable e) {
            // no-op
        }

        return true;
    }

    // useful method for SPI
    public static Enumeration<URL> filterResources(final String name, final Enumeration<URL> result) {
        if (isFilterableResource(name)) {
            final Collection<URL> values = Collections.list(result);
            if (values.size() > 1) {
                // remove openejb one
                final URL url = URLClassLoaderFirst.class.getResource("/" + name);
                if (url != null) {
                    values.remove(url);
                }
            }
            return Collections.enumeration(values);
        }
        return result;
    }
}
