org.rhq.modules.plugins.wildfly10.BaseProcessDiscovery.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.modules.plugins.wildfly10.BaseProcessDiscovery.java

Source

/*
 * RHQ Management Platform
 * Copyright (C) 2005-2014 Red Hat, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

package org.rhq.modules.plugins.wildfly10;

import static org.rhq.core.util.StringUtil.arrayToString;
import static org.rhq.core.util.StringUtil.isNotBlank;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ManualAddFacet;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.core.pluginapi.util.CommandLineOption;
import org.rhq.core.pluginapi.util.FileUtils;
import org.rhq.core.pluginapi.util.JavaCommandLine;
import org.rhq.core.pluginapi.util.ServerStartScriptDiscoveryUtility;
import org.rhq.core.pluginapi.util.StartScriptConfiguration;
import org.rhq.core.system.ProcessInfo;
import org.rhq.modules.plugins.wildfly10.helper.HostConfiguration;
import org.rhq.modules.plugins.wildfly10.helper.HostPort;
import org.rhq.modules.plugins.wildfly10.helper.ServerPluginConfiguration;
import org.rhq.modules.plugins.wildfly10.json.Operation;
import org.rhq.modules.plugins.wildfly10.json.ReadAttribute;
import org.rhq.modules.plugins.wildfly10.json.Result;

/**
 * Abstract base discovery component for the two server types - "JBossAS7 Host Controller" and
 * "JBossAS7 Standalone Server".
 */
public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent, ManualAddFacet {
    private static final Log LOG = LogFactory.getLog(BaseProcessDiscovery.class);

    private static final String JBOSS_EAP_PREFIX = "jboss-eap-";
    private static final String WILDFLY_PREFIX = "wildfly-";

    private static final String LOCAL_RESOURCE_KEY_PREFIX = "hostConfig: ";
    private static final String REMOTE_RESOURCE_KEY_PREFIX = "hostPort: ";

    private static final String HOME_DIR_SYSPROP = "jboss.home.dir";

    private static final String RHQADMIN = "rhqadmin";
    private static final String RHQADMIN_ENCRYPTED = "35c160c1f841a889d4cda53f0bfc94b6";

    private static final boolean OS_IS_WINDOWS = (File.separatorChar == '\\');

    // The list of environment vars that the AS7 start script will use if they are set.
    private static final Set<String> START_SCRIPT_ENV_VAR_NAMES = new LinkedHashSet<String>();
    static {
        START_SCRIPT_ENV_VAR_NAMES.addAll(Arrays.asList( //
                "RUN_CONF", //
                "STANDALONE_CONF", //
                "DOMAIN_CONF", //
                "MAX_FD", //
                "PROFILER", //
                "JAVA_HOME", //
                "JAVA", //
                "PRESERVE_JAVA_OPTS", //
                "PROCESS_CONTROLLER_JAVA_OPTS", //
                "HOST_CONTROLLER_JAVA_OPTS", //
                "JAVAC_JAR", //
                "JBOSS_HOME", //
                "JBOSS_MODULES_SYSTEM_PKGS", //
                "JBOSS_MODULEPATH", //
                "JBOSS_BASE_DIR", //
                "JBOSS_LOG_DIR", //
                "JBOSS_CONFIG_DIR", //
                "JBOSS_PIDFILE", //
                "LAUNCH_JBOSS_IN_BACKGROUND" //
        ));

        // If OS is Windows, add env vars that are only used by the batch files.
        if (OS_IS_WINDOWS) {
            START_SCRIPT_ENV_VAR_NAMES.add("ECHO");
            START_SCRIPT_ENV_VAR_NAMES.add("NOPAUSE");
        }
    }

    // e.g.: -mp /opt/jboss-as-7.1.1.Final/modules
    //       --pc-address 127.0.0.1
    //       --pc-port 52624
    //       -default-jvm /usr/java/jdk1.6.0_30/jre/bin/java
    //       -Djboss.home.dir=/opt/jboss-as-7.1.1.Final
    private static final Set<CommandLineOption> START_SCRIPT_OPTION_EXCLUDES = new HashSet<CommandLineOption>();
    static {
        START_SCRIPT_OPTION_EXCLUDES.add(new CommandLineOption("mp", null));
        START_SCRIPT_OPTION_EXCLUDES.add(new CommandLineOption(null, "pc-address"));
        START_SCRIPT_OPTION_EXCLUDES.add(new CommandLineOption(null, "pc-port"));
        START_SCRIPT_OPTION_EXCLUDES.add(new CommandLineOption("default-jvm", null));
        START_SCRIPT_OPTION_EXCLUDES.add(new CommandLineOption("Djboss.home.dir", null));
    }

    private static final Pattern SPACE_PATTERN = Pattern.compile("\\s+");

    // Auto-discover running AS7 instances.
    @Override
    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext discoveryContext)
            throws Exception {
        Set<DiscoveredResourceDetails> discoveredResources = new HashSet<DiscoveredResourceDetails>();

        List<ProcessScanResult> processScanResults = discoveryContext.getAutoDiscoveredProcesses();
        for (ProcessScanResult processScanResult : processScanResults) {
            try {
                ProcessInfo process = processScanResult.getProcessInfo();
                AS7CommandLine commandLine = new AS7CommandLine(process);
                DiscoveredResourceDetails details = buildResourceDetails(discoveryContext, process, commandLine);
                if (details != null) {
                    discoveredResources.add(details);
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Discovered new " + discoveryContext.getResourceType().getName() + " Resource (key=["
                            + details.getResourceKey() + "], name=[" + details.getResourceName() + "], version=["
                            + details.getResourceVersion() + "]).");
                }
            } catch (RuntimeException e) {
                // Only barf a stack trace for runtime exceptions.
                LOG.error("Discovery of a " + discoveryContext.getResourceType().getName() + " Resource failed for "
                        + processScanResult.getProcessInfo() + ".", e);
            } catch (Exception e) {
                LOG.error("Discovery of a " + discoveryContext.getResourceType().getName() + " Resource failed for "
                        + processScanResult.getProcessInfo() + " - cause: " + e);
            }
        }

        return discoveredResources;
    }

    protected DiscoveredResourceDetails buildResourceDetails(ResourceDiscoveryContext discoveryContext,
            ProcessInfo process, AS7CommandLine commandLine) throws Exception {
        Configuration pluginConfig = discoveryContext.getDefaultPluginConfiguration();
        ServerPluginConfiguration serverPluginConfig = new ServerPluginConfiguration(pluginConfig);

        File homeDir = getHomeDir(process, commandLine);
        serverPluginConfig.setHomeDir(homeDir);

        File baseDir = getBaseDir(process, commandLine, homeDir);
        serverPluginConfig.setBaseDir(baseDir);

        File configDir = getConfigDir(process, commandLine, baseDir);
        serverPluginConfig.setConfigDir(configDir);

        File hostXmlFile = getHostXmlFile(commandLine, configDir);
        if (!hostXmlFile.exists()) {
            throw new Exception(
                    "Server configuration file not found at the expected location (" + hostXmlFile + ").");
        }

        // This is a "hidden" plugin config prop, i.e. it is intentionally not defined in the plugin descriptor.
        serverPluginConfig.setHostConfigFile(hostXmlFile);

        // This method must be called before getHostConfiguration() can be called.
        HostConfiguration hostConfig = loadHostConfiguration(hostXmlFile);

        File logDir = getLogDir(process, commandLine, baseDir);
        serverPluginConfig.setLogDir(logDir);

        File logFile = getLogFile(logDir);
        initLogEventSourcesConfigProp(logFile.getPath(), pluginConfig);

        HostPort managementHostPort = hostConfig.getManagementHostPort(commandLine, getMode());
        if ("0.0.0.0".equals(managementHostPort.host)) {
            LOG.debug("Discovered management host set to 0.0.0.0, falling back to 127.0.0.1");
            serverPluginConfig.setHostname("127.0.0.1");
        } else {
            serverPluginConfig.setHostname(managementHostPort.host);
        }
        serverPluginConfig.setPort(managementHostPort.port);
        serverPluginConfig.setSecure(managementHostPort.isSecure);
        serverPluginConfig.setNativeLocalAuth(hostConfig.isNativeLocalOnly());
        pluginConfig.setSimpleValue("realm", hostConfig.getManagementSecurityRealm());
        String apiVersion = hostConfig.getDomainApiVersion();
        JBossProductType productType = JBossProductType.determineJBossProductType(homeDir, apiVersion);
        if (productType == null) {
            // Allows skipping AS7/EAP6 based products
            return null;
        }
        serverPluginConfig.setProductType(productType);
        pluginConfig.setSimpleValue("expectedRuntimeProductName", productType.PRODUCT_NAME);
        pluginConfig.setSimpleValue("hostXmlFileName", getHostXmlFileName(commandLine));

        ProcessInfo agentProcess = discoveryContext.getSystemInformation().getThisProcess();
        setStartScriptPluginConfigProps(process, commandLine, pluginConfig, agentProcess);
        setUserAndPasswordPluginConfigProps(serverPluginConfig, hostConfig);

        String key = createKeyForLocalResource(serverPluginConfig);
        HostPort hostPort = hostConfig.getDomainControllerHostPort(commandLine);
        String name = buildDefaultResourceName(hostPort, managementHostPort, productType, hostConfig.getHostName());
        String description = buildDefaultResourceDescription(hostPort, productType);
        String version = getVersion(homeDir, productType);

        return new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, version, description,
                pluginConfig, process);
    }

    protected HostConfiguration loadHostConfiguration(File hostXmlFile) throws Exception {
        try {
            return new HostConfiguration(hostXmlFile);
        } catch (Exception e) {
            throw new Exception("Failed to load host configuration from [" + hostXmlFile + "].", e);
        }
    }

    protected File getHomeDir(ProcessInfo processInfo, JavaCommandLine javaCommandLine) {
        String home = javaCommandLine.getSystemProperties().get(HOME_DIR_SYSPROP);
        File homeDir = new File(home);
        if (!homeDir.isAbsolute()) {
            if (processInfo.priorSnaphot().getExecutable() == null) {
                throw new RuntimeException(HOME_DIR_SYSPROP + " for AS7 process " + processInfo
                        + " is a relative path, and the RHQ Agent process does not have permission to resolve it.");
            }
            String cwd = processInfo.priorSnaphot().getExecutable().getCwd();
            homeDir = new File(cwd, home);
        }

        return new File(FileUtils.getCanonicalPath(homeDir.getPath()));
    }

    private void setStartScriptPluginConfigProps(ProcessInfo process, AS7CommandLine commandLine,
            Configuration pluginConfig, ProcessInfo agentProcess) {
        StartScriptConfiguration startScriptConfig = new StartScriptConfiguration(pluginConfig);
        ProcessInfo parentProcess = getPotentialStartScriptProcess(process);

        File startScript = ServerStartScriptDiscoveryUtility.getStartScript(parentProcess);
        if (startScript == null) {
            // The parent process is not a script - fallback to the default value (e.g. "bin/standalone.sh").
            String startScriptFileName = getMode().getStartScriptFileName();
            startScript = new File("bin", startScriptFileName);
        }
        if (!startScript.exists()) {
            if (!startScript.isAbsolute()) {
                File homeDir = new File(pluginConfig.getSimpleValue("homeDir"));
                File startScriptAbsolute = new File(homeDir, startScript.getPath());
                if (!startScriptAbsolute.exists()) {
                    LOG.warn("Failed to find start script file for AS7 server with command line [" + commandLine
                            + "] - defaulting 'startScripFile' plugin config prop to [" + startScript + "].");
                }
            }
        }
        startScriptConfig.setStartScript(startScript);

        String startScriptPrefix = ServerStartScriptDiscoveryUtility.getStartScriptPrefix(process, agentProcess);
        startScriptConfig.setStartScriptPrefix(startScriptPrefix);

        Map<String, String> startScriptEnv = ServerStartScriptDiscoveryUtility.getStartScriptEnv(process,
                parentProcess, START_SCRIPT_ENV_VAR_NAMES);
        startScriptConfig.setStartScriptEnv(startScriptEnv);

        List<String> startScriptArgs = ServerStartScriptDiscoveryUtility.getStartScriptArgs(parentProcess,
                commandLine.getAppServerArguments(), START_SCRIPT_OPTION_EXCLUDES);
        startScriptConfig.setStartScriptArgs(startScriptArgs);
    }

    protected abstract ProcessInfo getPotentialStartScriptProcess(ProcessInfo process);

    private void setUserAndPasswordPluginConfigProps(ServerPluginConfiguration serverPluginConfig,
            HostConfiguration hostConfig) {
        Properties mgmtUsers = getManagementUsers(hostConfig, serverPluginConfig);
        String user;
        String password;
        if (!mgmtUsers.isEmpty()) {
            if (mgmtUsers.containsKey(RHQADMIN)) {
                user = RHQADMIN;
                String encryptedPassword = mgmtUsers.getProperty(user);
                if (RHQADMIN_ENCRYPTED.equals(encryptedPassword)) {
                    // If the password is "rhqadmin" encrypted, set the "password" prop to "rhqadmin".
                    password = RHQADMIN;
                } else {
                    password = null;
                }
            } else {
                // No "rhqadmin" user is defined - just grab an arbitrary user.
                user = (String) mgmtUsers.keySet().iterator().next();
                // Note, we don't set the "password" prop, since the password we've read from mgmt-users.properties is
                // encrypted, and we need to return an unencrypted value.
                password = null;
            }
        } else {
            // Either no users are defined, or we failed to read the mgmt-users.properties file - default both user and
            // password to "rhqadmin", so that if the end user runs the "createRhqUser" operation, their conn props will
            // already be ready to go.
            user = RHQADMIN;
            password = RHQADMIN;
        }
        serverPluginConfig.setUser(user);
        serverPluginConfig.setPassword(password);
    }

    protected File getBaseDir(ProcessInfo process, JavaCommandLine javaCommandLine, File homeDir) {
        String baseDirString = javaCommandLine.getSystemProperties().get(getBaseDirSystemPropertyName());
        File baseDir;
        if (baseDirString != null) {
            baseDir = new File(baseDirString);
            if (!baseDir.isAbsolute()) {
                if (process.priorSnaphot().getExecutable() == null) {
                    baseDir = new File(homeDir, baseDirString);
                    if (!baseDir.exists()) {
                        throw new RuntimeException(getBaseDirSystemPropertyName() + " for AS7 process " + process
                                + " is a relative path, and the RHQ Agent process does not have permission to resolve it.");
                    }
                } else {
                    String cwd = process.priorSnaphot().getExecutable().getCwd();
                    baseDir = new File(cwd, baseDirString);
                    if (!baseDir.exists()) {
                        baseDir = new File(homeDir, baseDirString);
                    }
                }
            }
            baseDir = new File(FileUtils.getCanonicalPath(baseDir.getPath()));
        } else {
            baseDir = new File(homeDir, getDefaultBaseDirName());
        }
        return baseDir;
    }

    protected File getConfigDir(ProcessInfo process, JavaCommandLine javaCommandLine, File baseDir) {
        String configDirString = javaCommandLine.getSystemProperties().get(getConfigDirSystemPropertyName());
        File configDir;
        if (configDirString != null) {
            configDir = new File(configDirString);
            if (!configDir.isAbsolute()) {
                if (process.priorSnaphot().getExecutable() == null) {
                    throw new RuntimeException(getConfigDirSystemPropertyName() + " for AS7 process " + process
                            + " is a relative path, and the RHQ Agent process does not have permission to resolve it.");
                }
                String cwd = process.priorSnaphot().getExecutable().getCwd();
                configDir = new File(cwd, configDirString);
            }
            configDir = new File(FileUtils.getCanonicalPath(configDir.getPath()));
        } else {
            configDir = new File(baseDir, getDefaultConfigDirName());
        }
        return configDir;
    }

    protected File getLogDir(ProcessInfo process, AS7CommandLine commandLine, File baseDir) {
        String logDirString = commandLine.getSystemProperties().get(getLogDirSystemPropertyName());
        File logDir;
        if (logDirString != null) {
            logDir = new File(logDirString);
            if (!logDir.isAbsolute()) {
                if (process.priorSnaphot().getExecutable() == null) {
                    throw new RuntimeException(getLogDirSystemPropertyName() + " for AS7 process " + process
                            + " is a relative path, and the RHQ Agent process does not have permission to resolve it.");
                }
                String cwd = process.priorSnaphot().getExecutable().getCwd();
                logDir = new File(cwd, logDirString);
            }
            logDir = new File(FileUtils.getCanonicalPath(logDir.getPath()));
        } else {
            logDir = new File(baseDir, getDefaultLogDirName());
        }
        return logDir;
    }

    // Returns the name of the host config xml file (domain controller) or server config xml file (standalone server),
    // e.g. "standalone.xml" or "host.xml".
    protected String getHostXmlFileName(AS7CommandLine commandLine) {
        AS7Mode mode = getMode();
        String optionValue = commandLine.getClassOption(mode.getHostConfigFileNameOption());
        if (optionValue == null) {
            optionValue = commandLine.getSystemProperties().get(mode.getDefaultHostConfigSystemPropertyName());
        }
        return (optionValue != null) ? optionValue : mode.getDefaultHostConfigFileName();
    }

    // Returns the host config xml file (domain controller) or server config xml file (standalone server).
    protected File getHostXmlFile(AS7CommandLine commandLine, File configDir) {
        return new File(configDir, getHostXmlFileName(commandLine));
    }

    protected String getDefaultConfigDirName() {
        return "configuration";
    }

    protected String getDefaultLogDirName() {
        return "log";
    }

    protected abstract AS7Mode getMode();

    protected File getLogFile(File logDir) {
        return new File(logDir, getLogFileName());
    }

    protected abstract String getBaseDirSystemPropertyName();

    protected abstract String getConfigDirSystemPropertyName();

    protected abstract String getLogDirSystemPropertyName();

    protected abstract String getDefaultBaseDirName();

    protected abstract String getLogFileName();

    protected abstract String buildDefaultResourceName(HostPort hostPort, HostPort managementHostPort,
            JBossProductType productType, String serverName);

    protected abstract String buildDefaultResourceDescription(HostPort hostPort, JBossProductType productType);

    /**
     * Deprecated due to changes requiring a server name to build resource name. If no name
     * is provided then the information is omitted from the resource name.
     *
     *  Please see [BZ 1080552] for more details.
     */
    @Deprecated
    protected String buildDefaultResourceName(HostPort hostPort, HostPort managementHostPort,
            JBossProductType productType) {
        return buildDefaultResourceName(hostPort, managementHostPort, productType, null);
    }

    // Manually add a (remote) AS7 instance.
    @Override
    public DiscoveredResourceDetails discoverResource(Configuration pluginConfig, ResourceDiscoveryContext context)
            throws InvalidPluginConfigurationException {
        ServerPluginConfiguration serverPluginConfig = new ServerPluginConfiguration(pluginConfig);

        String hostname = serverPluginConfig.getHostname();
        Integer port = serverPluginConfig.getPort();
        String user = serverPluginConfig.getUser();

        if (hostname == null || port == null) {
            throw new InvalidPluginConfigurationException("Hostname and port must both be set.");
        }

        ProductInfo productInfo = new ProductInfo(ASConnectionParams.createFrom(serverPluginConfig))
                .getFromRemote();
        JBossProductType productType = productInfo.getProductType();

        if (productType == null) {
            throw new InvalidPluginConfigurationException("Can not connect to [" + hostname + ":" + port
                    + "] as user [" + user + "]. Did you provide the correct credentials?");
        }

        HostPort hostPort = new HostPort(false);
        HostPort managementHostPort = new HostPort(false);
        managementHostPort.host = hostname;
        managementHostPort.port = port;
        String key = createKeyForRemoteResource(hostname + ":" + port);
        String name = buildDefaultResourceName(hostPort, managementHostPort, productType, null);
        //FIXME this is inconsistent with how the version looks like when autodiscovered
        String version = productInfo.getProductVersion();
        String description = buildDefaultResourceDescription(hostPort, productType);

        pluginConfig.put(new PropertySimple("manuallyAdded", true));
        pluginConfig.put(new PropertySimple("productType", productType.name()));
        pluginConfig.setSimpleValue("expectedRuntimeProductName", productType.PRODUCT_NAME);

        DiscoveredResourceDetails detail = new DiscoveredResourceDetails(context.getResourceType(), key, name,
                version, description, pluginConfig, null);

        return detail;
    }

    private String createKeyForRemoteResource(String hostPort) {
        return REMOTE_RESOURCE_KEY_PREFIX + hostPort;
    }

    private String createKeyForLocalResource(ServerPluginConfiguration serverPluginConfiguration) {
        // Canonicalize the config path, so it's consistent no matter how it's entered.
        // This prevents two servers with different forms of the same config path, but
        // that are actually the same server, from ending up in inventory.
        try {
            return LOCAL_RESOURCE_KEY_PREFIX + serverPluginConfiguration.getHostConfigFile().getCanonicalPath();
        } catch (IOException e) {
            throw new RuntimeException(
                    "Unexpected IOException while converting host config file path to its canonical form", e);
        }
    }

    private <T> T getServerAttribute(ASConnection connection, String attributeName) {
        Operation op = new ReadAttribute(null, attributeName);
        Result res = connection.execute(op);
        if (!res.isSuccess()) {
            throw new InvalidPluginConfigurationException("Could not connect to remote server ["
                    + res.getFailureDescription() + "]. Did you enable management?");
        }
        @SuppressWarnings("unchecked")
        T result = (T) res.getResult();
        return result;
    }

    // never returns null
    private Properties getManagementUsers(HostConfiguration hostConfig, ServerPluginConfiguration pluginConfig) {
        String realm = hostConfig.getManagementSecurityRealm();
        File mgmUsersPropsFile = hostConfig.getSecurityPropertyFile(pluginConfig, realm);

        Properties props = new Properties();

        if (!mgmUsersPropsFile.exists()) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Management user properties file not found at [" + mgmUsersPropsFile + "].");
            }
            return props;
        }

        if (!mgmUsersPropsFile.canRead()) {
            // BZ 1118061 Log only at debug because JBoss EAP's users, groups, and roles configuration files
            // are read/write by owner only. Meaning that the jbossadmin user owns these files and the
            // jbossonadmin user may not have permission to read these files.
            if (LOG.isDebugEnabled()) {
                LOG.debug("Management user properties at [" + mgmUsersPropsFile + "] is not readable.");
            }
            return props;
        }

        FileInputStream inputStream;
        try {
            inputStream = new FileInputStream(mgmUsersPropsFile);
        } catch (FileNotFoundException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Management user properties file not found at [" + mgmUsersPropsFile + "].");
            }
            return props;
        }

        try {
            props.load(inputStream);
        } catch (IOException e) {
            LOG.error("Failed to parse management users properties file at [" + mgmUsersPropsFile + "]: "
                    + e.getMessage());
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                LOG.error("Failed to close management users properties file at [" + mgmUsersPropsFile + "]: "
                        + e.getMessage());
            }
        }

        return props;
    }

    private void initLogEventSourcesConfigProp(String fileName, Configuration pluginConfiguration) {
        PropertyList logEventSources = pluginConfiguration
                .getList(LogFileEventResourceComponentHelper.LOG_EVENT_SOURCES_CONFIG_PROP);

        if (logEventSources == null)
            return;

        File serverLogFile = new File(fileName);

        if (serverLogFile.exists() && !serverLogFile.isDirectory()) {
            PropertyMap serverLogEventSource = new PropertyMap("logEventSource");
            serverLogEventSource.put(new PropertySimple(
                    LogFileEventResourceComponentHelper.LogEventSourcePropertyNames.LOG_FILE_PATH, serverLogFile));
            serverLogEventSource.put(new PropertySimple(
                    LogFileEventResourceComponentHelper.LogEventSourcePropertyNames.ENABLED, Boolean.FALSE));
            logEventSources.add(serverLogEventSource);
        }
    }

    private String getVersion(File homeDir, JBossProductType productType) {
        // Products should have a version.txt file at root dir
        File versionFile = new File(homeDir, "version.txt");
        String version = getProductVersionInFile(versionFile, " - Version ", productType);
        if (version == null) {
            // No version.txt file. Try modules/system/layers/base/org/jboss/as/product/slot/dir/META-INF/MANIFEST.MF
            String layeredProductManifestFilePath = arrayToString(
                    new String[] { "modules", "system", "layers", "base", "org", "jboss", "as", "product",
                            productType.SHORT_NAME.toLowerCase(), "dir", "META-INF", "MANIFEST.MF" },
                    File.separatorChar);
            File productManifest = new File(homeDir, layeredProductManifestFilePath);
            version = getProductVersionInFile(productManifest, "JBoss-Product-Release-Version: ", productType);
            if (version == null) {
                // Try modules/org/jboss/as/product/slot/dir/META-INF/MANIFEST.MF
                String productManifestFilePath = arrayToString(
                        new String[] { "modules", "org", "jboss", "as", "product",
                                productType.SHORT_NAME.toLowerCase(), "dir", "META-INF", "MANIFEST.MF" },
                        File.separatorChar);
                productManifest = new File(homeDir, productManifestFilePath);
                version = getProductVersionInFile(productManifest, "JBoss-Product-Release-Version: ", productType);
            }
        }
        if (version == null) {
            // Fallback
            version = determineServerVersionFromHomeDir(homeDir);
        }
        return version;
    }

    private String getProductVersionInFile(File file, String versionPrefix, JBossProductType productType) {
        if (!file.exists() || file.isDirectory()) {
            return null;
        }
        try {
            String versionLine = FileUtils.findString(file.getAbsolutePath(), versionPrefix);
            if (isNotBlank(versionLine)) {
                return productType.SHORT_NAME + " "
                        + versionLine.substring(versionLine.lastIndexOf(versionPrefix) + versionPrefix.length());
            }
        } catch (IOException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Could not read file " + file.getAbsolutePath(), e);
            }
        }
        return null;
    }

    protected String determineServerVersionFromHomeDir(File homeDir) {
        String version;
        String homeDirName = homeDir.getName();
        if (homeDirName.startsWith(WILDFLY_PREFIX)) {
            version = homeDirName.substring(WILDFLY_PREFIX.length());
        } else if (homeDirName.startsWith(JBOSS_EAP_PREFIX)) {
            version = homeDirName.substring(JBOSS_EAP_PREFIX.length());
        } else if (homeDirName.indexOf('-') >= 0) {
            version = homeDirName.substring(homeDirName.lastIndexOf('-') + 1);
        } else {
            version = "";
        }
        return version;
    }

    private class ProductInfo {
        private ASConnectionParams asConnectionParams;
        private String productVersion;
        private JBossProductType productType;
        private String releaseVersion;
        private String releaseCodeName;
        private boolean fromRemote = false;

        public ProductInfo(ASConnectionParams asConnectionParams) {
            this.asConnectionParams = asConnectionParams;
        }

        public String getProductVersion() {
            return productVersion;
        }

        public JBossProductType getProductType() {
            return productType;
        }

        public ProductInfo getFromRemote() {
            ASConnection connection = new ASConnection(asConnectionParams);
            try {
                String productName = getServerAttribute(connection, "product-name");
                if ((productName != null) && !productName.isEmpty()) {
                    productType = JBossProductType.getValueByProductName(productName);
                }
                releaseVersion = getServerAttribute(connection, "release-version");
                releaseCodeName = getServerAttribute(connection, "release-codename");
                productVersion = getServerAttribute(connection, "product-version");
                if (productVersion == null) {
                    productVersion = releaseVersion;
                }
                fromRemote = true;
            } catch (InvalidPluginConfigurationException e) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Could not get the product info from [" + asConnectionParams.getHost() + ":"
                            + asConnectionParams.getPort() + "] - probably a connection failure");
                }
            } finally {
                connection.shutdown();
            }
            return this;
        }

        @Override
        public String toString() {
            return "ProductInfo{" + "hostname='" + asConnectionParams.getHost() + '\'' + ", port="
                    + asConnectionParams.getPort() + ", productVersion='" + productVersion + '\''
                    + ", productType='" + productType + '\'' + ", releaseVersion='" + releaseVersion + '\''
                    + ", releaseCodeName='" + releaseCodeName + '\'' + ", fromRemote=" + fromRemote + '}';
        }
    }

}