org.ngrinder.infra.AgentConfig.java Source code

Java tutorial

Introduction

Here is the source code for org.ngrinder.infra.AgentConfig.java

Source

/* 
 * Licensed 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.ngrinder.infra;

import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.joran.spi.JoranException;
import net.grinder.util.NetworkUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.ngrinder.common.constants.AgentConstants;
import org.ngrinder.common.constants.CommonConstants;
import org.ngrinder.common.constants.MonitorConstants;
import org.ngrinder.common.util.PropertiesKeyMapper;
import org.ngrinder.common.util.PropertiesWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Set;

import static net.grinder.util.NetworkUtils.DEFAULT_LOCAL_HOST_ADDRESS;
import static org.apache.commons.lang.StringUtils.trimToEmpty;
import static org.ngrinder.common.util.ExceptionUtils.processException;
import static org.ngrinder.common.util.NoOp.noOp;
import static org.ngrinder.common.util.Preconditions.checkNotNull;

/**
 * Spring component which is responsible to get the nGrinder config which is stored
 * ${NGRINDER_AGENT_HOME}.
 *
 * @author JunHo Yoon
 * @since 3.0
 */
public class AgentConfig implements AgentConstants, MonitorConstants, CommonConstants {
    private static final String NGRINDER_DEFAULT_FOLDER = ".ngrinder_agent";
    private static final Logger LOGGER = LoggerFactory.getLogger("agent config");

    protected AgentHome home = null;

    private PropertiesWrapper agentProperties;
    private PropertiesWrapper monitorProperties;
    private PropertiesWrapper commonProperties;
    private PropertiesWrapper internalProperties;

    private PropertiesKeyMapper internalPropertyMapper = PropertiesKeyMapper.create("internal-properties.map");
    private PropertiesKeyMapper agentPropertyMapper = PropertiesKeyMapper.create("agent-properties.map");
    private PropertiesKeyMapper monitorPropertyMapper = PropertiesKeyMapper.create("monitor-properties.map");
    private PropertiesKeyMapper commonPropertyMapper = PropertiesKeyMapper.create("common-properties.map");

    /**
     * Initialize.
     *
     * @return initialized AgentConfig
     */
    public AgentConfig init() {
        home = resolveHome();
        copyDefaultConfigurationFiles();
        loadProperties();
        loadInternalProperties();
        configureLogging();
        return this;
    }

    private void copyDefaultConfigurationFiles() {
        checkNotNull(home);
        final File agentConfig = home.getFile("agent.conf");
        File newAgentConfig = new File(getCurrentDirectory(), "__agent.conf");
        if (agentConfig.exists()) {
            if (System.getProperty(CommonConstants.PROP_OVERWRITE_CONFIG) != null) {
                LOGGER.info("Overwrite the existing agent.conf with __agent.conf");
            } else if (newAgentConfig.exists()) {
                LOGGER.warn("The agent configuration file '{}' already exists.", agentConfig.getAbsolutePath());
                LOGGER.warn("If you want to use the '{}' file", newAgentConfig.getAbsolutePath());
                LOGGER.warn("Please run agent with -o option");
                return;
            }
        }
        if (newAgentConfig.exists()) {
            home.copyFileTo(newAgentConfig, "agent.conf");
            agentConfig.setLastModified(newAgentConfig.lastModified());
        } else {
            try {
                home.writeFileTo(loadResource("/agent.conf"), "agent.conf");
            } catch (IOException e) {
                throw processException(e);
            }
        }
    }

    protected void loadProperties() {
        checkNotNull(home);
        Properties properties = home.getProperties("agent.conf");
        properties.put("NGRINDER_AGENT_HOME", home.getDirectory().getAbsolutePath());
        properties.putAll(System.getProperties());
        agentProperties = new PropertiesWrapper(properties, agentPropertyMapper);
        monitorProperties = new PropertiesWrapper(properties, monitorPropertyMapper);
        commonProperties = new PropertiesWrapper(properties, commonPropertyMapper);
    }

    protected void loadInternalProperties() {
        InputStream inputStream = null;
        Properties properties = new Properties();
        try {
            inputStream = AgentConfig.class.getResourceAsStream("/internal.properties");
            properties.load(inputStream);
            internalProperties = new PropertiesWrapper(properties, internalPropertyMapper);
        } catch (IOException e) {
            LOGGER.error("Error while load internal.properties", e);
            internalProperties = new PropertiesWrapper(properties, internalPropertyMapper);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }

    public String loadResource(String name) throws IOException {
        InputStream inputStream = null;
        try {
            inputStream = AgentConfig.class.getResourceAsStream(name);
            if (inputStream != null) {
                return IOUtils.toString(inputStream);
            } else {
                return "";
            }
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }

    private void configureLogging() {
        File logDirectory = getHome().getLogDirectory();
        String level = "INFO";
        if (getCommonProperties().getPropertyBoolean(PROP_COMMON_VERBOSE)) {
            level = "TRACE";
        }
        if (isSilentMode()) {
            level = "ERROR";
        }
        final Context context = (Context) LoggerFactory.getILoggerFactory();
        final JoranConfigurator configurator = new JoranConfigurator();
        configurator.setContext(context);
        context.putProperty("LOG_LEVEL", level);
        context.putProperty("LOG_DIRECTORY", logDirectory.getAbsolutePath());
        try {
            configurator.doConfigure(getClass().getResource("/logback-agent.xml"));
        } catch (JoranException e) {
            LOGGER.error("Error while configuring logger", e);
        }
    }

    /**
     * Save the agent pid.
     *
     * @param agentPid  agent pid
     * @param startMode startMode
     */
    public void saveAgentPidProperties(String agentPid, String startMode) {
        checkNotNull(home);
        Properties properties = home.getProperties("pid");
        if ("agent".equalsIgnoreCase(startMode)) {
            properties.put("agent.pid", agentPid);
        } else {
            properties.put("monitor.pid", agentPid);
        }
        home.saveProperties("pid", properties);
    }

    /**
     * Update agent pid file.
     *
     * @param startMode startMode
     */
    public void updateAgentPidProperties(String startMode) {
        checkNotNull(home);
        Properties properties = home.getProperties("pid");
        Set<String> names = properties.stringPropertyNames();
        if (names.size() > 1) {
            properties.remove(startMode + ".pid");
            home.saveProperties("pid", properties);
        } else if (names.contains(startMode + ".pid")) {
            removeAgentPidProperties();
        }
    }

    /**
     * Get the agent pid in the form of string.
     *
     * @param startMode agent or monitor
     * @return pid
     */
    public String getAgentPidProperties(String startMode) {
        checkNotNull(home);
        Properties properties = home.getProperties("pid");
        if ("agent".equalsIgnoreCase(startMode)) {
            return (String) properties.get("agent.pid");
        } else {
            return (String) properties.get("monitor.pid");
        }
    }

    /**
     * Remove agent pid properties.
     */
    public void removeAgentPidProperties() {
        checkNotNull(home);
        File file = home.getFile("pid");
        FileUtils.deleteQuietly(file);
    }

    /**
     * Resolve NGrinder agent home path.
     *
     * @return resolved {@link AgentHome}
     */
    protected AgentHome resolveHome() {
        String userHomeFromEnv = trimToEmpty(System.getenv("NGRINDER_AGENT_HOME"));
        //printLog("    System Environment:  NGRINDER_AGENT_HOME={}", userHomeFromEnv);
        String userHomeFromProperty = trimToEmpty(System.getProperty("ngrinder.agent.home"));
        //printLog("    Java System Property:  ngrinder.agent.home={}", userHomeFromEnv);
        if (StringUtils.isNotEmpty(userHomeFromEnv) && !StringUtils.equals(userHomeFromEnv, userHomeFromProperty)) {
            printLog("The path to ngrinder agent home is ambiguous:");
            printLog("    '{}' is accepted.", userHomeFromProperty);
        }

        String userHome = StringUtils.defaultIfEmpty(userHomeFromProperty, userHomeFromEnv);
        if (StringUtils.isEmpty(userHome)) {
            userHome = System.getProperty("user.home") + File.separator + NGRINDER_DEFAULT_FOLDER;
        } else if (StringUtils.startsWith(userHome, "~" + File.separator)) {
            userHome = System.getProperty("user.home") + File.separator + userHome.substring(2);
        } else if (StringUtils.startsWith(userHome, "." + File.separator)) {
            userHome = System.getProperty("user.dir") + File.separator + userHome.substring(2);
        }

        userHome = FilenameUtils.normalize(userHome);
        printLog("NGRINDER_AGENT_HOME : {}", userHome);
        File homeDirectory = new File(userHome);
        try {
            if (homeDirectory.mkdirs()) {
                noOp();
            }
            if (!homeDirectory.canWrite()) {
                throw processException("home directory " + userHome + " is not writable.");
            }
        } catch (Exception e) {
            throw processException("Error while resolve the home directory.", e);
        }
        return new AgentHome(homeDirectory);
    }

    private void printLog(String template, Object... var) {
        if (!isSilentMode()) {
            LOGGER.info(template, var);
        }
    }

    /**
     * If there is test mode property in system.properties.. return true
     *
     * @return true is test mode
     */

    public boolean isDevMode() {
        return getCommonProperties().getPropertyBoolean(PROP_COMMON_DEV_MODE);
    }

    public AgentHome getHome() {
        return this.home;
    }

    /**
     * Get agent properties.
     *
     * @return agent properties
     */
    public PropertiesWrapper getAgentProperties() {
        return checkNotNull(agentProperties);
    }

    /**
     * Get monitor properties.
     *
     * @return monitor properties
     */
    public PropertiesWrapper getMonitorProperties() {
        return checkNotNull(monitorProperties);
    }

    /**
     * Get internal properties.
     *
     * @return internalProperties
     */
    public PropertiesWrapper getInternalProperties() {
        return internalProperties;
    }

    public File getCurrentDirectory() {
        return new File(System.getProperty("user.dir"));
    }

    public String getMonitorBindingIP() {
        return getMonitorProperties().getProperty(PROP_MONITOR_BINDING_IP);
    }

    public String getControllerIP() {
        return getAgentProperties().getProperty(PROP_AGENT_CONTROLLER_HOST, DEFAULT_LOCAL_HOST_ADDRESS);
    }

    public void setControllerHost(String host) {
        getAgentProperties().addProperty(PROP_AGENT_CONTROLLER_HOST, host);
    }

    public int getControllerPort() {
        return getAgentProperties().getPropertyInt(PROP_AGENT_CONTROLLER_PORT);
    }

    public String getRegion() {
        return getAgentProperties().getProperty(PROP_AGENT_REGION);
    }

    public String getAgentHostID() {
        return getAgentProperties().getProperty(PROP_AGENT_HOST_ID, NetworkUtils.DEFAULT_LOCAL_HOST_NAME);
    }

    public boolean isServerMode() {
        return getAgentProperties().getPropertyBoolean(PROP_AGENT_SERVER_MODE);
    }

    public boolean isSilentMode() {
        final PropertiesWrapper properties = getCommonProperties();
        if (properties == null) {
            return Boolean.getBoolean(System.getProperty(PROP_COMMON_SILENT_MODE, "false"));
        } else {
            return properties.getPropertyBoolean(PROP_COMMON_SILENT_MODE);
        }
    }

    public PropertiesWrapper getCommonProperties() {
        return commonProperties;
    }

    public static class NullAgentConfig extends AgentConfig {
        public int counter = 0;
        private int controllerPort = 0;

        public NullAgentConfig(int i) {
            counter = i;
            home = resolveHome();
            loadProperties();
            loadInternalProperties();
        }

        public int getControllerPort() {
            return (this.controllerPort == 0) ? super.getControllerPort() : this.controllerPort;
        }

        public void setControllerPort(int controllerPort) {
            this.controllerPort = controllerPort;
        }

        public boolean isSilentMode() {
            return true;
        }

        @Override
        protected AgentHome resolveHome() {
            AgentHome resolveHome = super.resolveHome();
            File directory = new File(resolveHome.getDirectory(), "tmp_" + String.valueOf(counter));
            resolveHome = new AgentHome(directory);
            try {
                FileUtils.forceDeleteOnExit(directory);
            } catch (IOException e) {
                noOp();
            }
            return resolveHome;
        }
    }
}