/*
 * Copyright (c) 1997, 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 java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import jakarta.inject.Inject;
import jakarta.inject.Named;

import org.glassfish.api.FutureProvider;
import org.glassfish.api.StartupRunLevel;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.api.event.Events;
import org.glassfish.deployment.common.DeploymentException;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.api.PreDestroy;
import org.glassfish.hk2.runlevel.RunLevel;
import org.glassfish.internal.api.ServerContext;
import org.jvnet.hk2.annotations.Service;

import com.sun.appserv.server.LifecycleListener;
import com.sun.appserv.server.ServerLifecycleException;
import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerTags;
import com.sun.enterprise.util.Result;

/**
 * Support class to assist in firing LifecycleEvent notifications to
 * registered LifecycleListeners.
 */
@Service
@RunLevel(StartupRunLevel.VAL)
public class LifecycleModuleService implements PreDestroy, PostConstruct, EventListener, FutureProvider<Result<Thread>>{

    @Inject
    ServerContext context;

    @Inject
    Applications apps;

    @Inject
    Events events;

    @Inject @Named( ServerEnvironment.DEFAULT_INSTANCE_NAME)
    Server server;

    @Inject
    private ConfigBeansUtilities configBeansUtilities;

    /**
     * The set of registered LifecycleListeners for event notifications.
     */
    private ArrayList listeners = new ArrayList();

    List<Future<Result<Thread>>> futures = new ArrayList();

    public void postConstruct() {
        events.register(this);
        try {
            onInitialization();
        } catch (Exception e) {
            addExceptionToFuture(e);
        }
    }

    public void preDestroy() {
        try {
            onTermination();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public List<Future<Result<Thread>>> getFutures() {
        return futures;
    }

    public void event(Event event) {
        try {
            if (event.is(EventTypes.SERVER_STARTUP)) {
                onStartup();
            } else if (event.is(EventTypes.SERVER_READY)) {
                onReady();
            } else if (event.is(EventTypes.PREPARE_SHUTDOWN)) {
                onShutdown();
            }
        } catch (Exception e) {
            throw new DeploymentException(e);
        }
    }

    private void onInitialization() throws ServerLifecycleException {
        List<Application> applications = apps.getApplications();
        List<Application> lcms = new ArrayList<Application>();;
        for (Application app : applications) {
            if (Boolean.valueOf(app.getDeployProperties().getProperty
                (ServerTags.IS_LIFECYCLE))) {
                lcms.add(app);
            }
        }

        HashSet listenerSet = new HashSet();
        for (Application next : lcms) {
            Properties props = next.getDeployProperties();
            String enabled = next.getEnabled();
            if ( isEnabled(next.getName(), enabled) ) {
                String strOrder = (String)props.remove(
                    ServerTags.LOAD_ORDER);

                int order = Integer.MAX_VALUE;
                if (strOrder != null && strOrder.length() > 0) {
                    try {
                        order = Integer.parseInt(strOrder);
                    } catch(NumberFormatException nfe) {
                        nfe.printStackTrace();
                    }
                }

                String className = (String)props.remove(
                    ServerTags.CLASS_NAME);
                ServerLifecycleModule slcm =
                    new ServerLifecycleModule(context,
                                next.getName(), className);

                slcm.setLoadOrder(order);

                String classpath = (String)props.remove(
                    ServerTags.CLASSPATH);
                slcm.setClasspath(classpath);

                String isFailureFatal = (String)props.remove(
                    ServerTags.IS_FAILURE_FATAL);
                slcm.setIsFatal(Boolean.valueOf(isFailureFatal));

                props.remove(ServerTags.IS_LIFECYCLE);
                props.remove(ServerTags.OBJECT_TYPE);

                for (String propName : props.stringPropertyNames()) {
                    slcm.setProperty(propName, props.getProperty(propName));
                }

                LifecycleListener listener = slcm.loadServerLifecycle();
                listenerSet.add(slcm);
            }
        }
        sortModules(listenerSet);

        initialize();
    }

    /**
     * Returns true if life cycle module is enabled in the application
     * level and in the application ref level.
     *
     * @return  true if life cycle module is enabled
     */
    private boolean isEnabled(String name, String enabled) {

        // true if enabled in both lifecyle module and in the ref
        return (Boolean.valueOf(enabled) &&
            Boolean.valueOf(configBeansUtilities.getEnabled(
                server.getName(), name)));
    }

    private void resetClassLoader(final ClassLoader c) {
         // set the common class loader as the thread context class loader
        java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction() {
                public Object run() {
                    Thread.currentThread().setContextClassLoader(c);
                    return null;
                }
            }
        );
    }

    private void sortModules(HashSet listenerSet) {
        // FIXME: use a better sorting algo
        for(Iterator iter = listenerSet.iterator(); iter.hasNext();) {
            ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
            int order = next.getLoadOrder();
            int i=0;
            for(;i<this.listeners.size();i++) {
                if(((ServerLifecycleModule)listeners.get(i)).getLoadOrder() > order) {
                    break;
                }
            }
            this.listeners.add(i,next);
        }
    }

    private void initialize()
                            throws ServerLifecycleException {

        if (listeners.isEmpty())
            return;

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for(Iterator iter = listeners.iterator(); iter.hasNext();) {
            ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
            next.onInitialization();
        }
        // set it back
        resetClassLoader(cl);
    }

    private void onStartup() throws ServerLifecycleException {

        if (listeners.isEmpty())
            return;

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for(Iterator iter = listeners.iterator(); iter.hasNext();) {
            ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
            next.onStartup();
        }
        // set it back
        resetClassLoader(cl);
    }

    private void onReady() throws ServerLifecycleException {

        if (listeners.isEmpty())
            return;

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for(Iterator iter = listeners.iterator(); iter.hasNext();) {
            ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
            next.onReady();
        }
        // set it back
        resetClassLoader(cl);
    }

    private void onShutdown() throws ServerLifecycleException {

        if (listeners.isEmpty())
            return;

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for(Iterator iter = listeners.iterator(); iter.hasNext();) {
            ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
            next.onShutdown();
        }
        // set it back
        resetClassLoader(cl);
    }

    private void onTermination() throws ServerLifecycleException {

        if (listeners.isEmpty())
            return;

        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for(Iterator iter = listeners.iterator(); iter.hasNext();) {
            ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
            next.onTermination();
        }
        // set it back
        resetClassLoader(cl);
    }

    private Future<Result<Thread>> addExceptionToFuture(Throwable t) {
        Future<Result<Thread>> future = new LifecycleModuleFuture();
        ((LifecycleModuleFuture)future).setResult(new Result<Thread>(t));
        futures.add(future);
        return future;
    }

    public static final class LifecycleModuleFuture implements Future<Result<Thread>> {
        Result<Thread> result;
        CountDownLatch latch = new CountDownLatch(1);

        public void setResult(Result<Thread> result) {
            this.result = result;
            latch.countDown();
        }

        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            return false;
        }

        @Override
        public boolean isCancelled() {
            return false;
        }

        @Override
        public boolean isDone() {
            return latch.getCount() == 0;
        }

        @Override
        public Result<Thread> get() throws InterruptedException {
            latch.await();
            return result;
        }

        @Override
        public Result<Thread> get(long timeout, TimeUnit unit) throws InterruptedException {
            latch.await(timeout, unit);
            return result;
        }
    }
}
