/*
 * Copyright (c) 2007, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.v3.server;

import com.sun.enterprise.module.bootstrap.StartupContext;
import com.sun.enterprise.util.SystemPropertyConstants;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.inject.Inject;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.kernel.KernelLoggerInfo;
import org.jvnet.hk2.annotations.Service;

/**
 * This class is responsible for setting up Common Class Loader. As the
 * name suggests, Common Class Loader is common to all deployed applications.
 * Common Class Loader is responsible for loading classes from
 * following URLs (the order is strictly maintained):
 * lib/*.jar:domain_dir/lib/classes:domain_dir/lib/*.jar:DERBY_DRIVERS.
 * Please note that domain_dir/lib/classes comes before domain_dir/lib/*.jar,
 * just like WEB-INF/classes is searched first before WEB-INF/lib/*.jar.
 * DERBY_DRIVERS are added to this class loader, because GlassFish ships with Derby database by default
 * and it makes them available to users by default. Earlier, they used to be available to applications via
 * launcher classloader, but now they are available via this class loader (see issue 13612 for more details on this).
 *
 * It applies a special rule while handling jars in install_root/lib.
 * In order to maintain file layout compatibility (see  issue #9526),
 * we add jars like javaee.jar and appserv-rt.jar which need to be excluded
 * from runtime classloaders in the server side, as they are already available via
 * PublicAPIClassLoader. So, before we add any jar from install_root/lib,
 * we look at their manifest entry and skip the ones that have an entry
 * GlassFish-ServerExcluded: true
 *
 * @author Sanjeeb.Sahoo@Sun.COM
 */
@Service
public class CommonClassLoaderServiceImpl implements PostConstruct {
    /**
     * The common classloader.
     */
    private ClassLoader commonClassLoader;

    @Inject
    APIClassLoaderServiceImpl acls;

    @Inject
    ServerEnvironment env;

    final static Logger logger = KernelLoggerInfo.getLogger();
    private ClassLoader APIClassLoader;
    private String commonClassPath = "";

    private static final String SERVER_EXCLUDED_ATTR_NAME = "GlassFish-ServerExcluded";

    @Override
    public void postConstruct() {
        APIClassLoader = acls.getAPIClassLoader();
        assert (APIClassLoader != null);
        createCommonClassLoader();
    }

    private void createCommonClassLoader() {
        List<File> cpElements = new ArrayList<>();
        File domainDir = env.getDomainRoot();
        // I am forced to use System.getProperty, as there is no API that makes
        // the installRoot available. Sad, but true. Check dev forum on this.
        final String installRoot = System.getProperty(
            SystemPropertyConstants.INSTALL_ROOT_PROPERTY);

        // See https://glassfish.dev.java.net/issues/show_bug.cgi?id=5872
        // In case of embedded GF, we may not have an installRoot.
        if (installRoot!=null) {
            File installDir = new File(installRoot);
            File installLibPath = new File(installDir, "lib");
            if (installLibPath.isDirectory()) {
                Collections.addAll(cpElements,
                    installLibPath.listFiles(new CompiletimeJarFileFilter()));
            }
        } else {
            logger.logp(Level.WARNING, "CommonClassLoaderServiceImpl",
                "createCommonClassLoader",
                KernelLoggerInfo.systemPropertyNull,
                SystemPropertyConstants.INSTALL_ROOT_PROPERTY);
        }
        File domainClassesDir = new File(domainDir, "lib/classes/"); // NOI18N
        if (domainClassesDir.exists()) {
            cpElements.add(domainClassesDir);
        }
        final File domainLib = new File(domainDir, "lib/"); // NOI18N
        if (domainLib.isDirectory()) {
            Collections.addAll(cpElements,
                domainLib.listFiles(new JarFileFilter()));
        }
        // See issue https://glassfish.dev.java.net/issues/show_bug.cgi?id=13612
        // We no longer add derby jars to launcher class loader, we add them to common class loader instead.
        cpElements.addAll(findDerbyClient());
        List<URL> urls = new ArrayList<>();
        StringBuilder cp = new StringBuilder();
        for (File f : cpElements) {
            try {
                urls.add(f.toURI().toURL());
                if (cp.length() > 0) {
                    cp.append(File.pathSeparator);
                }
                cp.append(f.getAbsolutePath());
            } catch (MalformedURLException e) {
                logger.log(Level.WARNING, KernelLoggerInfo.invalidClassPathEntry,
                    new Object[] {f, e});
            }
        }
        commonClassPath = cp.toString();
        if (!urls.isEmpty()) {
            // Skip creation of an unnecessary classloader in the hierarchy,
            // when all it would have done was to delegate up.
            commonClassLoader = new URLClassLoader(
                urls.toArray(new URL[urls.size()]), APIClassLoader);
        } else {
            logger.logp(Level.FINE, "CommonClassLoaderManager",
                "Skipping creation of CommonClassLoader " +
                    "as there are no libraries available",
                    "urls = {0}", new Object[]{urls});
        }
    }

    public ClassLoader getCommonClassLoader() {
        return commonClassLoader != null ? commonClassLoader : APIClassLoader;
    }

    public String getCommonClassPath() {
        return commonClassPath;
    }

    private List<File> findDerbyClient() {
        final String DERBY_HOME_PROP = "AS_DERBY_INSTALL";
        StartupContext startupContext = env.getStartupContext();
        Properties arguments = null;

        if (startupContext != null) {
            arguments = startupContext.getArguments();
        }

        String derbyHome = null;

        if (arguments != null) {
            derbyHome = arguments.getProperty(DERBY_HOME_PROP,
                System.getProperty(DERBY_HOME_PROP));
        }

        File derbyLib = null;
        if (derbyHome != null) {
            derbyLib = new File(derbyHome, "lib");
        }
        if (derbyLib == null || !derbyLib.exists()) {
            // maybe the jdk...
            if (System.getProperty("java.version").compareTo("1.6") > 0) {
                File jdkHome = new File(System.getProperty("java.home"));
                derbyLib = new File(jdkHome, "../db/lib");
            }
        }
        if (!derbyLib.exists()) {
            logger.info(KernelLoggerInfo.cantFindDerby);
            return Collections.EMPTY_LIST;
        }

        return Arrays.asList(derbyLib.listFiles(new FilenameFilter(){
            @Override
            public boolean accept(File dir, String name) {
                // Include only files having .jar extn and exclude all localisation jars, because they are
                // already mentioned in the Class-Path header of the main jars
                return (name.endsWith(".jar") && !name.startsWith("derbyLocale_"));
            }
        }));
    }

    private static class JarFileFilter implements FilenameFilter {
        private final String JAR_EXT = ".jar"; // NOI18N

        @Override
        public boolean accept(File dir, String name) {
            return name.endsWith(JAR_EXT);
        }
    }

    private static class CompiletimeJarFileFilter extends JarFileFilter {
        /*
         * See https://glassfish.dev.java.net/issues/show_bug.cgi?id=9526
         */
        @Override
        public boolean accept(File dir, String name)
        {
            if (super.accept(dir, name)) {
                File file = new File(dir, name);
                JarFile jar = null;
                try
                {
                    jar = new JarFile(file);
                    Manifest manifest = jar.getManifest();
                    if (manifest != null) {
                        String exclude = manifest.getMainAttributes().
                            getValue(SERVER_EXCLUDED_ATTR_NAME);
                        if (exclude != null && exclude.equalsIgnoreCase("true")) {
                            return false;
                        }
                    }
                }
                catch (IOException e)
                {
                    logger.log(Level.WARNING, KernelLoggerInfo.exceptionProcessingJAR,
                        new Object[] {file.getAbsolutePath(), e});
                } finally {
                    try
                    {
                        if (jar != null) {
                            jar.close();
                        }
                    }
                    catch (IOException e)
                    {
                        // ignore
                    }
                }
                return true;
            }
            return false;
        }
    }
}
