All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lordofthejars.nosqlunit.mongodb.ManagedMongoDbLifecycleManager Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package com.lordofthejars.nosqlunit.mongodb;

import static com.lordofthejars.nosqlunit.core.IOUtils.deleteDir;

import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lordofthejars.nosqlunit.core.AbstractLifecycleManager;
import com.lordofthejars.nosqlunit.core.CommandLineExecutor;
import com.lordofthejars.nosqlunit.core.OperatingSystem;
import com.lordofthejars.nosqlunit.core.OperatingSystemResolver;
import com.lordofthejars.nosqlunit.core.OsNameSystemPropertyOperatingSystemResolver;
import com.lordofthejars.nosqlunit.env.SystemEnvironmentVariables;

public class ManagedMongoDbLifecycleManager extends AbstractLifecycleManager {

	private static final Logger LOGGER = LoggerFactory.getLogger(ManagedMongoDbLifecycleManager.class);
	public ManagedMongoDbLifecycleManager() {
		super();
	}
	
	private static final String LOCALHOST = "localhost";

	protected static final String CONFIG_SERVER_ENABLED = "--configsvr";
	protected static final String SHARD_SERVER_ENABLED = "--shardsvr";
	protected static final String JOURNALING_ENABLED = "--journal";
	protected static final String NONE_JOURNALING_ENABLED = "--nojournal";
	protected static final String LOGPATH_ARGUMENT_NAME = "--logpath";
	protected static final String DBPATH_ARGUMENT_NAME = "--dbpath";
	protected static final String REPLICA_SET_ARGUMENT_NAME = "--replSet";
	protected static final String PORT_ARGUMENT_NAME= "--port";
	protected static final String DEFAULT_MONGO_LOGPATH = "logpath";
	protected static final String DEFAULT_MONGO_DBPATH = "mongo-dbpath";
	protected static final String DEFAULT_MONGO_TARGET_PATH = "target"
			+ File.separatorChar + "mongo-temp";
	protected static final String DEFAULT_MONGO_REPLICA_SET_NAME = "";
	protected static final boolean DEFAULT_MONGO_SHARD_SERVER = false;
	protected static final boolean DEFAULT_MONGO_CONFIG_SERVER = false;

	protected static final String MONGODB_BINARY_DIRECTORY = "bin";

	protected static final String MONGODB_EXECUTABLE_X = "mongod";
	protected static final String MONGODB_EXECUTABLE_W = "mongod.exe";
	protected static final int DEFAULT_PORT = 27017;

	private String mongodPath = SystemEnvironmentVariables.getEnvironmentOrPropertyVariable("MONGO_HOME");
	private int port = DEFAULT_PORT;
	
	private String targetPath = DEFAULT_MONGO_TARGET_PATH;
	private String dbRelativePath = DEFAULT_MONGO_DBPATH;
	private String logRelativePath = DEFAULT_MONGO_LOGPATH;
	private String replicaSetName = DEFAULT_MONGO_REPLICA_SET_NAME;
	
	private boolean shardServer = DEFAULT_MONGO_SHARD_SERVER;
	private boolean configServer = DEFAULT_MONGO_CONFIG_SERVER;
	private boolean journaling = false;
	
	private Map extraCommandArguments = new HashMap();
	private List singleCommandArguments = new ArrayList();

	private CommandLineExecutor commandLineExecutor = new CommandLineExecutor();
	private OperatingSystemResolver operatingSystemResolver = new OsNameSystemPropertyOperatingSystemResolver();
	private MongoDbLowLevelOps mongoDbLowLevelOps = MongoDbLowLevelOpsFactory.getSingletonInstance();

	private ProcessRunnable processRunnable;
	
	@Override
	public String getHost() {
		return LOCALHOST;
	}

	@Override
	public int getPort() {
		return this.port;
	}

	@Override
	public void doStart() throws Throwable {
		
		LOGGER.info("Starting {} MongoDb instance.", mongodPath);
		
		File dbPath = ensureDbPathDoesNotExitsAndReturnCompositePath();

		if (dbPath.mkdirs()) {
			startMongoDBAsADaemon();
			boolean isServerUp = assertThatConnectionToMongoDbIsPossible();

			if (!isServerUp) {
				throw new IllegalStateException(
						"Couldn't establish a connection with "
								+ this.mongodPath
								+ " server at /127.0.0.1:"+port);
			}

		} else {
			throw new IllegalStateException("Db Path " + dbPath
					+ " could not be created.");
		}
		
		LOGGER.info("Started {} MongoDb instance.", mongodPath);
	}

	@Override
	public void doStop() {
		
		LOGGER.info("Stopping {} MongoDb instance.", mongodPath);
		
		try {
			if(this.processRunnable != null) {
				this.processRunnable.destroyProcess();
			}
		} finally {
			ensureDbPathDoesNotExitsAndReturnCompositePath();
		}
		
		LOGGER.info("Stopped {} MongoDb instance.", mongodPath);
	}


	private List startMongoDBAsADaemon() throws InterruptedException {
        CountDownLatch processIsReady = new CountDownLatch(1);
        processRunnable = new ProcessRunnable(processIsReady);
        Thread thread = new Thread(processRunnable);
        thread.start();
        processIsReady.await();
        return processRunnable.consoleOutput;
	}


	private List buildOperationSystemProgramAndArguments() {

		List programAndArguments = new ArrayList();

		programAndArguments.add(getExecutablePath());
		
		if(isReplicaSetNameSet()) {
			programAndArguments.add(REPLICA_SET_ARGUMENT_NAME);
			programAndArguments.add(this.replicaSetName);
		}

		programAndArguments.add(DBPATH_ARGUMENT_NAME);
		programAndArguments.add(dbRelativePath);
		programAndArguments.add(PORT_ARGUMENT_NAME);
		programAndArguments.add(Integer.toString(port));
		programAndArguments.add(LOGPATH_ARGUMENT_NAME);
		programAndArguments.add(logRelativePath);
		programAndArguments.add(journalingArgument());
		
		if(isShardServerConfigured()) {
			programAndArguments.add(SHARD_SERVER_ENABLED);
		}
		
		if(isConfigServerConfigured()) {
			programAndArguments.add(CONFIG_SERVER_ENABLED);
		}
		
		for (String argument : this.singleCommandArguments) {
			programAndArguments.add(argument);
		}

		for (String argumentName : this.extraCommandArguments.keySet()) {
			programAndArguments.add(argumentName);
			programAndArguments.add(this.extraCommandArguments
					.get(argumentName));
		}

		return programAndArguments;

	}

	private boolean isConfigServerConfigured() {
		return this.configServer;
	}

	private boolean isShardServerConfigured() {
		return this.shardServer;
	}

	public boolean isReplicaSetNameSet() {
		return this.replicaSetName != DEFAULT_MONGO_REPLICA_SET_NAME;
	}

	private String getExecutablePath() {
		return this.mongodPath + File.separatorChar + MONGODB_BINARY_DIRECTORY
				+ File.separatorChar + mongoExecutable();
	}

	private String mongoExecutable() {
		OperatingSystem operatingSystem = this.operatingSystemResolver
				.currentOperatingSystem();

		switch (operatingSystem.getFamily()) {
		case WINDOWS:
			return MONGODB_EXECUTABLE_W;
		default:
			return MONGODB_EXECUTABLE_X;
		}

	}

	private boolean assertThatConnectionToMongoDbIsPossible()
			throws InterruptedException, UnknownHostException {
		return this.mongoDbLowLevelOps.assertThatConnectionIsPossible(LOCALHOST, port);
	}

	private File ensureDbPathDoesNotExitsAndReturnCompositePath() {
		File dbPath = new File(targetPath + File.separatorChar + dbRelativePath);
		if (dbPath.exists()) {
			deleteDir(dbPath);
		}
		return dbPath;
	}

	public void setDbRelativePath(String dbRelativePath) {
		this.dbRelativePath = dbRelativePath;
	}

	public void setLogRelativePath(String logRelativePath) {
		this.logRelativePath = logRelativePath;
	}

	public void setMongodPath(String mongodPath) {
		this.mongodPath = mongodPath;
	}

	public void setReplicaSetName(String replicaSetName) {
		this.replicaSetName = replicaSetName;
	}
	
	public void setTargetPath(String targetPath) {
		this.targetPath = targetPath;
	}

	public void addExtraCommandLineArgument(String argumentName,
			String argumentValue) {
		this.extraCommandArguments.put(argumentName, argumentValue);
	}

	public void addSingleCommandLineArgument(String argument) {
		this.singleCommandArguments.add(argument);
	}

	public void setPort(int port) {
		this.port = port;
	}
	
	public void setJournaling(boolean journaling) {
		this.journaling = journaling;
	}
	
	public void setShardServer(boolean shardServer) {
		this.shardServer = shardServer;
	}
	
	public void setConfigServer(boolean configServer) {
		this.configServer = configServer;
	}
	
	protected String getMongodPath() {
		return mongodPath;
	}

	protected void setCommandLineExecutor(
			CommandLineExecutor commandLineExecutor) {
		this.commandLineExecutor = commandLineExecutor;
	}

	protected void setOperatingSystemResolver(
			OperatingSystemResolver operatingSystemResolver) {
		this.operatingSystemResolver = operatingSystemResolver;
	}

	protected void setMongoDbLowLevelOps(MongoDbLowLevelOps mongoDbLowLevelOps) {
		this.mongoDbLowLevelOps = mongoDbLowLevelOps;
	}

	protected String journalingArgument() {
		return this.journaling ? JOURNALING_ENABLED : NONE_JOURNALING_ENABLED;
	}

	public String getReplicaSetName() {
		return replicaSetName;
	}
	
    public class ProcessRunnable implements Runnable {

        private CountDownLatch processIsReady;
        private List consoleOutput;

        private Process process;
        
        public ProcessRunnable(CountDownLatch processIsReady) {
            this.processIsReady = processIsReady;
        }

        @Override
        public void run() {
            try {
            	process = startProcess();
                //consoleOutput = getConsoleOutput(process);
            } catch (IOException e) {
                throw prepareException(e);
            } finally {
                processIsReady.countDown();
            }

            try {
            	process.waitFor();
                if (process.exitValue() != 0) {
                    LOGGER.info(
                            "Mongodb ["
                                    + mongodPath
                                    + DBPATH_ARGUMENT_NAME
                                    + dbRelativePath
                                    + PORT_ARGUMENT_NAME
                                    + port
                                    + LOGPATH_ARGUMENT_NAME
                                    + logRelativePath
                                    + "] console output is: "
                                    + consoleOutput);
                }
            } catch (InterruptedException ie) {
                throw prepareException(ie);
            }

        }

        public void destroyProcess() {
        	if(this.process != null) {
        		this.process.destroy();
        	}
        }
        
        private IllegalStateException prepareException(Exception e) {
            return new IllegalStateException(
                    "Mongodb ["
                            + mongodPath
                            + DBPATH_ARGUMENT_NAME
                            + dbRelativePath
                            + PORT_ARGUMENT_NAME
                            + port
                            + LOGPATH_ARGUMENT_NAME
                            + logRelativePath
                            + "] could not be started. Next console message was thrown: "
                            + e.getMessage());
        }
        
        private Process startProcess() throws IOException {
    		return commandLineExecutor.startProcessInDirectoryAndArguments(
    				targetPath, buildOperationSystemProgramAndArguments());
    	}
        
        private List getConsoleOutput(Process pwd) throws IOException {
    		return commandLineExecutor.getConsoleOutput(pwd);
    	}
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy