/*
 * 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.brooklyn.entity.webapp.jboss;

import static java.lang.String.format;

import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.entity.webapp.JavaWebAppSshDriver;
import org.apache.brooklyn.util.text.Identifiers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.net.Networking;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.ssh.BashCommands;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;

import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;

/**
 * @deprecated since 1.0.0; JBoss 7 is EOF
 */
@Deprecated
public class JBoss7SshDriver extends JavaWebAppSshDriver implements JBoss7Driver {

    private static final Logger LOG = LoggerFactory.getLogger(JBoss7SshDriver.class);

    // TODO more configurability of config files, java memory, etc

    public static final String SERVER_TYPE = "standalone";
    public static final String CONFIG_FILE = "standalone-brooklyn.xml";
    public static final String KEYSTORE_FILE = ".keystore";
    public static final String MANAGEMENT_REALM = "ManagementRealm";

    public JBoss7SshDriver(JBoss7ServerImpl entity, SshMachineLocation machine) {
        super(entity, machine);
    }

    @Override
    public JBoss7ServerImpl getEntity() {
        return (JBoss7ServerImpl) super.getEntity();
    }

    @Override
    public String getSslKeystoreFile() {
        return Os.mergePathsUnix(getRunDir(), SERVER_TYPE, "configuration", KEYSTORE_FILE);
    }
    
    protected String getTemplateConfigurationUrl() {
        return entity.getConfig(JBoss7Server.TEMPLATE_CONFIGURATION_URL);
    }

    @Override
    protected String getLogFileLocation() {
        return Os.mergePathsUnix(getRunDir(), SERVER_TYPE, "log/server.log");
    }

    @Override
    protected String getDeploySubdir() {
        return Os.mergePathsUnix(SERVER_TYPE, "deployments");
    }

    private Integer getManagementHttpPort() {
        return entity.getAttribute(JBoss7Server.MANAGEMENT_HTTP_PORT);
    }

    private Integer getManagementHttpsPort() {
        return entity.getAttribute(JBoss7Server.MANAGEMENT_HTTPS_PORT);
    }

    private Integer getManagementNativePort() {
        return entity.getAttribute(JBoss7Server.MANAGEMENT_NATIVE_PORT);
    }

    private String getManagementUsername() {
        return entity.getConfig(JBoss7Server.MANAGEMENT_USER);
    }

    private String getManagementPassword() {
        return entity.getConfig(JBoss7Server.MANAGEMENT_PASSWORD);
    }

    @Override
    public void prepare() {
        resolver = Entities.newDownloader(this);
        setExpandedInstallDir(Os.mergePaths(getInstallDir(), resolver.getUnpackedDirectoryName(format("jboss-as-%s", getVersion()))));
    }

    @Override
    public boolean installJava() {
        /*
         * JBoss only works on Java 7 or lower, see here: https://developer.jboss.org/message/808212
         */
        return checkForAndInstallJava("1.7");
    }

    @Override
    public void install() {
        List<String> urls = resolver.getTargets();
        String saveAs = resolver.getFilename();

        List<String> installCommands = new LinkedList<String>();
        installCommands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs));
        installCommands.add(BashCommands.INSTALL_TAR);
        installCommands.add("tar xzfv " + saveAs);

        newScript(INSTALLING)
                // don't set vars yet -- it resolves dependencies (e.g. DB) which we don't want until we start
                .environmentVariablesReset()
                .body.append(installCommands)
                .execute();

        // The jboss-modules.jar that comes with jBoss 7.1.1 is of version 1.1.1.GA. However, this has issue on initialisation.
        // Hopefully, version 1.1.5.GA fixes the init issue. However, as jBoss 7.1.1 is EOF, we need to download and replace
        // this jar before starting up the server
        // see: https://stackoverflow.com/questions/48403832/javax-xml-parsers-factoryconfigurationerror-running-jboss-as-7-1-with-java-7-upd
        String installDir = getExpandedInstallDir();
        List<String> fixBugCommands = new LinkedList<String>();
        fixBugCommands.add(BashCommands.INSTALL_WGET);
        fixBugCommands.add(format("rm %s/jboss-modules.jar", installDir));
        fixBugCommands.add(format("wget http://repo1.maven.org/maven2/org/jboss/modules/jboss-modules/1.1.5.GA/jboss-modules-1.1.5.GA.jar -O %s/jboss-modules.jar", installDir));

        newScript("fix JBoss 7.1.1 init bug")
                // don't set vars yet -- it resolves dependencies (e.g. DB) which we don't want until we start
                .environmentVariablesReset()
                .body.append(fixBugCommands)
                .execute();
    }

    /**
     * AS7 config notes and TODOs:
     * We're using the http management interface on port managementPort
     * We're not using any JMX.
     * - AS 7 simply doesn't boot with Sun JMX enabled (https://issues.jboss.org/browse/JBAS-7427)
     * - 7.1 onwards uses Remoting 3, which we haven't configured
     * - We have generic support for jmxmp, which one could configure
     * We're completely disabling security on the management interface.
     * - In the future we probably want to use the as7/bin/add-user.sh script using config keys for user and password
     * - Or we could create our own security realm and use that.
     * We disable the root welcome page, since we can't deploy our own root otherwise
     * We bind all interfaces to entity.hostname, rather than 127.0.0.1.
     */
    @Override
    public void customize() {
        // Check that a password was set for the management user
        Preconditions.checkState(Strings.isNonBlank(getManagementUsername()), "User for management realm required");
        String managementPassword = getManagementPassword();
        if (Strings.isBlank(managementPassword)) {
            LOG.debug(this+" has no password specified for "+JBoss7Server.MANAGEMENT_PASSWORD.getName()+"; using a random string");
            entity.config().set(JBoss7Server.MANAGEMENT_PASSWORD, Identifiers.makeRandomPassword(8));
        }
        String hashedPassword = hashPassword(getManagementUsername(), getManagementPassword(), MANAGEMENT_REALM);

        // Check that ports are all configured
        Map<String,Integer> ports = MutableMap.<String,Integer>builder()
                .put("managementHttpPort", getManagementHttpPort()) 
                .put("managementHttpsPort", getManagementHttpsPort())
                .put("managementNativePort", getManagementNativePort())
                .build();
        if (isProtocolEnabled("HTTP")) {
            ports.put("httpPort", getHttpPort());
        }
        if (isProtocolEnabled("HTTPS")) {
            ports.put("httpsPort", getHttpsPort());
        }
        Networking.checkPortsValid(ports);

        // Check hostname is defined
        String hostname = entity.getAttribute(SoftwareProcess.HOSTNAME);
        Preconditions.checkNotNull(hostname, "AS 7 entity must set hostname otherwise server will only be visible on localhost");

        // Copy the install files to the run-dir and add the management user
        newScript(CUSTOMIZING)
                // don't set vars yet -- it resolves dependencies (e.g. DB) which we don't want until we start
                .environmentVariablesReset()
                .body.append(
                        format("cp -r %s/%s . || exit $!", getExpandedInstallDir(), SERVER_TYPE),
                        format("echo -e '\n%s=%s' >> %s/%s/configuration/mgmt-users.properties",
                                getManagementUsername(), hashedPassword, getRunDir(), SERVER_TYPE)
                    )
                .execute();

        // Copy the keystore across, if there is one
        if (isProtocolEnabled("HTTPS")) {
            String keystoreUrl = Preconditions.checkNotNull(getSslKeystoreUrl(), "keystore URL must be specified if using HTTPS for "+entity);
            String destinationSslKeystoreFile = getSslKeystoreFile();
            InputStream keystoreStream = resource.getResourceFromUrl(keystoreUrl);
            getMachine().copyTo(keystoreStream, destinationSslKeystoreFile);
        }

        // Copy the configuration file across
        String destinationConfigFile = Os.mergePathsUnix(getRunDir(), SERVER_TYPE, "configuration", CONFIG_FILE);
        copyTemplate(getTemplateConfigurationUrl(), destinationConfigFile);

        // Copy the initial wars to the deploys directory
        getEntity().deployInitialWars();
    }

    @Override
    public void launch() {
        entity.sensors().set(JBoss7Server.PID_FILE, Os.mergePathsUnix(getRunDir(), PID_FILENAME));

        // We wait for evidence of JBoss running because, using SshCliTool,
        // we saw the ssh session return before the JBoss process was fully running
        // so the process failed to start.
        newScript(MutableMap.of(USE_PID_FILE, false), LAUNCHING)
                .body.append(
                        "export LAUNCH_JBOSS_IN_BACKGROUND=true",
                        format("export JBOSS_HOME=%s", getExpandedInstallDir()),
                        format("export JBOSS_PIDFILE=%s/%s", getRunDir(), PID_FILENAME),
                        "mv "+getRunDir()+"/console "+getRunDir()+"/console-$(date +\"%Y%m%d.%H%M.%S\") || true",
                        format("%s/bin/%s.sh ", getExpandedInstallDir(), SERVER_TYPE) +
                                format("--server-config %s ", CONFIG_FILE) +
                                format("-Djboss.server.base.dir=%s/%s ", getRunDir(), SERVER_TYPE) +
                                format("\"-Djboss.server.base.url=file://%s/%s\" ", getRunDir(), SERVER_TYPE) +
                                "-Djava.net.preferIPv4Stack=true " +
                                "-Djava.net.preferIPv6Addresses=false " +
                                format(" >> %s/console 2>&1 </dev/null &", getRunDir()),
                        BashCommands.waitForFileContents("console", "starting", Duration.TEN_SECONDS, false)
                    )
                .execute();
    }

    @Override
    public boolean isRunning() {
        return newScript(MutableMap.of(USE_PID_FILE, true), CHECK_RUNNING).execute() == 0;
    }

    @Override
    public void stop() {
        newScript(MutableMap.of(USE_PID_FILE, true), STOPPING).environmentVariablesReset().execute();
    }

    @Override
    public void kill() {
        newScript(MutableMap.of(USE_PID_FILE, true), KILLING).execute();
    }

    @Override
    protected List<String> getCustomJavaConfigOptions() {
        return MutableList.<String>builder()
                .addAll(super.getCustomJavaConfigOptions())
                .add("-Xms200m")
                .add("-Xmx800m")
                .add("-XX:MaxPermSize=400m")
                .build();
    }

    /**
     * Creates a hash of a username, password and security realm that is suitable for use
     * with AS7 and Wildfire.
     * <p/>
     * Although AS7 has an <code>add-user.sh</code> script it is unsuitable for use in
     * non-interactive modes. (See AS7-5061 for details.) Versions 7.1.2+ (EAP) accept
     * a <code>--silent</code> flag. When this entity is updated past 7.1.1 we should
     * probably use that instead.
     * <p/>
     * This method mirrors AS7 and Wildfire's method of hashing user's passwords. Refer
     * to its class <code>UsernamePasswordHashUtil.generateHashedURP</code> for their
     * implementation.
     *
     * @see <a href="https://issues.jboss.org/browse/AS7-5061">AS7-5061</a>
     * @see <a href="https://github.com/jboss-remoting/jboss-sasl/blob/master/src/main/java/org/jboss/sasl/util/UsernamePasswordHashUtil.java">
     *     UsernamePasswordHashUtil.generateHashedURP</a>
     * @return <code>HEX(MD5(username ':' realm ':' password))</code>
     */
    public static String hashPassword(String username, String password, String realm) {
        String concat = username + ":" + realm + ":" + password;
        byte[] hashed = Hashing.md5().hashString(concat, Charsets.UTF_8).asBytes();
        return BaseEncoding.base16().lowerCase().encode(hashed);
    }
}
