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

import org.apache.openejb.ClassLoaderUtil;
import org.apache.openejb.NoSuchApplicationException;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.UndeployException;
import org.apache.openejb.assembler.classic.*;
import org.apache.openejb.config.AppModule;
import org.apache.openejb.config.ConfigurationFactory;
import org.apache.openejb.config.DeploymentLoader;
import org.apache.openejb.config.DeploymentModule;
import org.apache.openejb.config.WebModule;
import org.apache.openejb.config.sys.AdditionalDeployments;
import org.apache.openejb.config.sys.Deployments;
import org.apache.openejb.config.sys.JaxbOpenejb;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.IO;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.loader.provisining.ProvisioningResolver;
import org.apache.openejb.util.JavaSecurityManagers;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;

import javax.ejb.Lock;
import javax.ejb.Remote;
import javax.ejb.Singleton;
import javax.ejb.TransactionManagement;
import javax.enterprise.inject.Alternative;
import javax.validation.ValidationException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import static javax.ejb.LockType.READ;
import static javax.ejb.TransactionManagementType.BEAN;
import static org.apache.openejb.config.ConfigurationFactory.ADDITIONAL_DEPLOYMENTS;
import static org.apache.openejb.loader.ProvisioningUtil.realLocation;

@SuppressWarnings("EjbProhibitedPackageUsageInspection")
@Singleton(name = "openejb/Deployer")
@Lock(READ)
@Remote(Deployer.class)
@TransactionManagement(BEAN)
@Alternative
public class DeployerEjb implements Deployer {
    private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB, DeployerEjb.class);

    public static final String OPENEJB_DEPLOYER_FORCED_APP_ID_PROP = "openejb.deployer.forced.appId";

    public static final String OPENEJB_DEPLOYER_HOST = "openejb.deployer.host";

    public static final String OPENEJB_USE_BINARIES = "openejb.deployer.binaries.use";
    public static final String OPENEJB_PATH_BINARIES = "openejb.deployer.binaries.path";
    public static final String OPENEJB_VALUE_BINARIES = "openejb.deployer.binaries.value";

    public static final String OPENEJB_APP_AUTODEPLOY = "openejb.app.autodeploy";
    public static final ThreadLocal<Boolean> AUTO_DEPLOY = new ThreadLocal<>();

    private static final File uniqueFile;
    private static final boolean oldWarDeployer = "old".equalsIgnoreCase(SystemInstance.get().getOptions().get("openejb.deployer.war", "new"));
    private static final String OPENEJB_DEPLOYER_SAVE_DEPLOYMENTS = "openejb.deployer.save-deployments";
    private static final boolean SAVE_DEPLOYMENTS = SystemInstance.get().getOptions().get(OPENEJB_DEPLOYER_SAVE_DEPLOYMENTS, false);

    static {
        final String uniqueName = "OpenEJB-" + new BigInteger(128, new SecureRandom()).toString(Character.MAX_RADIX);
        final String tempDir = JavaSecurityManagers.getSystemProperty("java.io.tmpdir");
        File unique;
        try {
            unique = new File(tempDir, uniqueName).getCanonicalFile();
            if (!unique.createNewFile()) {
                throw new IOException("Failed to create file in temp: " + unique);
            }
        } catch (final IOException e) {
            // same trying in work directory
            unique = new File(SystemInstance.get().getBase().getDirectory(), "work");
            if (unique.exists()) {
                try {
                    unique = new File(unique, uniqueName).getCanonicalFile();
                    if (!unique.createNewFile()) {
                        throw new IOException("Failed to create file in work: " + unique);
                    }
                } catch (final IOException e1) {
                    throw new OpenEJBRuntimeException(e);
                }
            } else {
                throw new OpenEJBRuntimeException("cannot create unique file, please set java.io.tmpdir to a writable folder or create work folder", e);
            }
        }
        uniqueFile = unique;
        uniqueFile.deleteOnExit();
    }


    private final DeploymentLoader deploymentLoader;
    private final Assembler assembler;

    public DeployerEjb() {
        deploymentLoader = new DeploymentLoader();
        assembler = (Assembler) SystemInstance.get().getComponent(org.apache.openejb.spi.Assembler.class);
    }

    @Override
    public String getUniqueFile() {
        return uniqueFile.getAbsolutePath();
    }

    @Override
    public Collection<AppInfo> getDeployedApps() {
        return assembler.getDeployedApplications();
    }

    @Override
    public AppInfo deploy(final String location) throws OpenEJBException {
        return deploy(location, null);
    }

    @Override
    public AppInfo deploy(final Properties properties) throws OpenEJBException {
        return deploy(null, properties);
    }

    @Override
    public AppInfo deploy(final String inLocation, Properties properties) throws OpenEJBException {
        String rawLocation = inLocation;
        if (rawLocation == null && properties == null) {
            throw new NullPointerException("location and properties are null");
        }
        if (rawLocation == null) {
            rawLocation = properties.getProperty(FILENAME);
        }
        if (properties == null) {
            properties = new Properties();
        }

        AppModule appModule = null;

        final File file;
        if ("true".equalsIgnoreCase(properties.getProperty(OPENEJB_USE_BINARIES, "false"))) {
            file = copyBinaries(properties);
        } else {
            file = new File(realLocation(rawLocation).iterator().next());
        }

        final boolean autoDeploy = Boolean.parseBoolean(properties.getProperty(OPENEJB_APP_AUTODEPLOY, "false"));
        final String host = properties.getProperty(OPENEJB_DEPLOYER_HOST, null);

        if (WebAppDeployer.Helper.isWebApp(file) && !oldWarDeployer) {
            AUTO_DEPLOY.set(autoDeploy);
            try {
                final AppInfo appInfo = SystemInstance.get().getComponent(WebAppDeployer.class)
                        .deploy(host, contextRoot(properties, file.getAbsolutePath()), file);
                if (appInfo != null) {
                    saveIfNeeded(properties, file, appInfo);
                    return appInfo;
                }
                throw new OpenEJBException("can't deploy " + file.getAbsolutePath());
            } finally {
                AUTO_DEPLOY.remove();
            }
        }

        AppInfo appInfo = null;

        try {
            appModule = deploymentLoader.load(file, null);

            // Add any alternate deployment descriptors to the modules
            final Map<String, DeploymentModule> modules = new TreeMap<>();
            for (final DeploymentModule module : appModule.getEjbModules()) {
                modules.put(module.getModuleId(), module);
            }
            for (final DeploymentModule module : appModule.getClientModules()) {
                modules.put(module.getModuleId(), module);
            }
            for (final WebModule module : appModule.getWebModules()) {
                final String contextRoot = contextRoot(properties, module.getJarLocation());
                if (contextRoot != null) {
                    module.setContextRoot(contextRoot);
                    module.setHost(host);
                }
                modules.put(module.getModuleId(), module);
            }
            for (final DeploymentModule module : appModule.getConnectorModules()) {
                modules.put(module.getModuleId(), module);
            }

            for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
                String name = (String) entry.getKey();
                if (name.startsWith(ALT_DD + "/")) {
                    name = name.substring(ALT_DD.length() + 1);

                    final DeploymentModule module;
                    final int slash = name.indexOf('/');
                    if (slash > 0) {
                        final String moduleId = name.substring(0, slash);
                        name = name.substring(slash + 1);
                        module = modules.get(moduleId);
                    } else {
                        module = appModule;
                    }

                    if (module != null) {
                        final String value = (String) entry.getValue();
                        final File dd = new File(value);
                        if (dd.canRead()) {
                            module.getAltDDs().put(name, dd.toURI().toURL());
                        } else {
                            module.getAltDDs().put(name, value);
                        }
                    }
                }
            }

            final OpenEjbConfiguration configuration = new OpenEjbConfiguration();
            configuration.containerSystem = new ContainerSystemInfo();
            configuration.facilities = new FacilitiesInfo();

            final ConfigurationFactory configurationFactory = new ConfigurationFactory(false, configuration);
            appInfo = configurationFactory.configureApplication(appModule);
            appInfo.autoDeploy = autoDeploy;

            if (properties != null && properties.containsKey(OPENEJB_DEPLOYER_FORCED_APP_ID_PROP)) {
                appInfo.appId = properties.getProperty(OPENEJB_DEPLOYER_FORCED_APP_ID_PROP);
            }

            if (!appInfo.webApps.isEmpty()) {
                appInfo.properties.setProperty("tomcat.unpackWar", "false");
            }

            // create any resources and containers defined in the application itself
            if (!appInfo.webApps.isEmpty()) {
                appInfo.properties.setProperty("tomcat.unpackWar", "false");
            }

            final ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
            final ClassLoader appClassLoader = assembler.createAppClassLoader(appInfo);
            try {
                Thread.currentThread().setContextClassLoader(appClassLoader);

                for (final ResourceInfo resource : configuration.facilities.resources) {
                    assembler.createResource(resource);
                }

                for (final ContainerInfo container : configuration.containerSystem.containers) {
                    assembler.createContainer(container);
                }

            } finally {
                Thread.currentThread().setContextClassLoader(oldCl);
            }

            assembler.createApplication(appInfo, appClassLoader);

            saveIfNeeded(properties, file, appInfo);

            return appInfo;

        } catch (final Throwable e) {
            // destroy the class loader for the failed application
            if (appModule != null) {
                ClassLoaderUtil.destroyClassLoader(appModule.getJarLocation());
            }

            if (null != appInfo) {
                ClassLoaderUtil.destroyClassLoader(appInfo.appId, appInfo.path);
            }

            LOGGER.error("Can't deploy " + inLocation, e);

            if (e instanceof ValidationException) {
                throw (ValidationException) e;
            }

            final Throwable ex;
            final DeploymentExceptionManager dem = SystemInstance.get().getComponent(DeploymentExceptionManager.class);
            if (dem != null) {
                if (dem.hasDeploymentFailed()) {
                    ex = dem.getLastException();
                } else {
                    ex = e;
                }
                if (appInfo != null) {
                    dem.clearLastException(appInfo);
                }
            } else {
                ex = e;
            }

            if (ex instanceof OpenEJBException) {
                if (ex.getCause() instanceof ValidationException) {
                    throw (ValidationException) ex.getCause();
                }
                throw (OpenEJBException) ex;
            }
            throw new OpenEJBException(ex);
        }
    }

    private void saveIfNeeded(final Properties properties, final File file, final AppInfo appInfo) {
        if ((SAVE_DEPLOYMENTS && null == properties.getProperty(OPENEJB_DEPLOYER_SAVE_DEPLOYMENTS))
            || "true".equalsIgnoreCase(properties.getProperty(OPENEJB_DEPLOYER_SAVE_DEPLOYMENTS, "false"))) {
            appInfo.properties.setProperty("save-deployment","true");
            saveDeployment(file, true);
        }
    }

    private synchronized File copyBinaries(final Properties props) throws OpenEJBException {
        final File dump = ProvisioningResolver.cacheFile(props.getProperty(OPENEJB_PATH_BINARIES, "dump.war"));
        if (dump.exists()) {
            Files.delete(dump);
            final String name = dump.getName();
            if (name.endsWith("ar") && name.length() > 4) {
                final File exploded = new File(dump.getParentFile(), name.substring(0, name.length() - 4));
                if (exploded.exists()) {
                    Files.delete(exploded);
                }
            }
        }
        try {
            IO.copy(byte[].class.cast(props.get(OPENEJB_VALUE_BINARIES)), dump);
        } catch (final IOException e) {
            throw new OpenEJBException(e);
        }
        return dump;
    }

    private synchronized void saveDeployment(final File file, final boolean add) {
        final Deployments deps = new Deployments();
        if (file.isDirectory()) {
            deps.setDir(file.getAbsolutePath());
        } else {
            deps.setFile(file.getAbsolutePath());
        }

        File config;
        try {
            config = SystemInstance.get().getBase().getFile(ADDITIONAL_DEPLOYMENTS, false);
        } catch (final IOException e) {
            config = null;
        }
        if (config == null || !config.getParentFile().exists()) {
            LOGGER.info("Cannot save the added app because the conf folder does not exist, it will not be present on a restart");
            return;
        }

        // dump it
        OutputStream os = null;
        try {
            final AdditionalDeployments additionalDeployments;
            if (config.exists() && config.length() > 0) {
                final InputStream fis = IO.read(config);
                try {
                    additionalDeployments = JaxbOpenejb.unmarshal(AdditionalDeployments.class, fis);
                } finally {
                    IO.close(fis);
                }
            } else {
                additionalDeployments = new AdditionalDeployments();
            }

            if (add) {
                if (!additionalDeployments.getDeployments().contains(deps)) {
                    additionalDeployments.getDeployments().add(deps);
                }
            } else {
                final Iterator<Deployments> it = additionalDeployments.getDeployments().iterator();
                while (it.hasNext()) {
                    final Deployments current = it.next();
                    if (deps.getDir() != null && deps.getDir().equals(current.getDir())) {
                        it.remove();
                        break;
                    } else if (deps.getFile() != null && deps.getFile().equals(current.getFile())) {
                        it.remove();
                        break;
                    } else { // exploded dirs
                        final String jar = deps.getFile();
                        if (jar != null && jar.length() > 3) {
                            final String substring = jar.substring(0, jar.length() - 4);
                            if (substring.equals(current.getDir()) || substring.equals(current.getFile())) {
                                it.remove();
                                break;
                            }
                        } else {
                            final String jarC = current.getFile();
                            if (jarC != null && jarC.length() > 3) {
                                final String substring = jarC.substring(0, jarC.length() - 4);
                                if (substring.equals(deps.getDir()) || substring.equals(deps.getFile())) {
                                    it.remove();
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            os = IO.write(config);
            JaxbOpenejb.marshal(AdditionalDeployments.class, additionalDeployments, os);
        } catch (final Exception e) {
            LOGGER.error("cannot save the added app, will not be present next time you'll start", e);
        } finally {
            IO.close(os);
        }
    }

    @Override
    public void undeploy(final String moduleId) throws UndeployException, NoSuchApplicationException {
        AppInfo appInfo = assembler.getAppInfo(moduleId);
        if (appInfo == null) {
            appInfo = assembler.getAppInfo(realLocation(moduleId).iterator().next());
            if (appInfo == null) {
                appInfo = assembler.getAppInfo(new File(moduleId).getAbsolutePath());
                if (appInfo == null) {
                    appInfo = assembler.getAppInfo(new File(realLocation(moduleId).iterator().next()).getAbsolutePath());
                }
            }
        }
        if (appInfo != null) {
            try {
                assembler.destroyApplication(appInfo);
            } finally {
                if (appInfo.properties.containsKey("save-deployment")) {
                    saveDeployment(new File(moduleId), false);
                }
            }
        } else {
            throw new NoSuchApplicationException(moduleId);
        }
    }

    private String contextRoot(final Properties properties, final String jarPath) {
        return properties.getProperty("webapp." + jarPath + ".context-root");
    }

    @Override
    public void reload(final String moduleId) {
        for (final AppInfo info : assembler.getDeployedApplications()) {
            if (info.path.equals(moduleId)) {
                reload(info);
                break;
            }
        }
    }

    private void reload(final AppInfo info) {

        if (info.webAppAlone) {
            final WebAppDeployer component = SystemInstance.get().getComponent(WebAppDeployer.class);

            if (null != component) {
                component.reload(info.path);
                return;
            }
        }

            try {
                assembler.destroyApplication(info);
                assembler.createApplication(info);
            } catch (final Exception e) {
                throw new OpenEJBRuntimeException(e);
            }
        }
    }
