com.lordofthejars.nosqlunit.redis.ManagedRedisLifecycleManager Maven / Gradle / Ivy
package com.lordofthejars.nosqlunit.redis;
import static com.lordofthejars.nosqlunit.core.IOUtils.deleteDir;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
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.OperatingSystemFamily;
import com.lordofthejars.nosqlunit.core.OperatingSystemResolver;
import com.lordofthejars.nosqlunit.core.OsNameSystemPropertyOperatingSystemResolver;
import com.lordofthejars.nosqlunit.env.SystemEnvironmentVariables;
public class ManagedRedisLifecycleManager extends AbstractLifecycleManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ManagedRedis.class);
Process pwd;
private static final String LOCALHOST = "127.0.0.1";
public static final int DEFAULT_PORT = 6379;
private static final int NO_MASTER_PORT = -1;
protected static final String DEFAULT_REDIS_TARGET_PATH = "target" + File.separatorChar + "redis-temp";
protected static final String REDIS_BINARY_DIRECTORY = "src";
protected static final String REDIS_EXECUTABLE_X = "redis-server";
protected static final String SLAVE_OF_ARGUMENT = "--slaveof";
private String targetPath = DEFAULT_REDIS_TARGET_PATH;
private String redisPath = SystemEnvironmentVariables.getEnvironmentOrPropertyVariable("REDIS_HOME");
private String configurationFilepath = null;
private int port = DEFAULT_PORT;
private String masterHost;
private int masterPort = NO_MASTER_PORT;
private Map extraCommandArguments = new HashMap();
private List singleCommandArguments = new ArrayList();
private CommandLineExecutor commandLineExecutor = new CommandLineExecutor();
private OperatingSystemResolver operatingSystemResolver = new OsNameSystemPropertyOperatingSystemResolver();
public ManagedRedisLifecycleManager() {
super();
}
@Override
public String getHost() {
return LOCALHOST;
}
@Override
public int getPort() {
return port;
}
@Override
public void doStart() throws Throwable {
LOGGER.info("Starting {} Redis instance.", redisPath);
if (isWindowsSystem()) {
throw new IllegalArgumentException(
"Windows System is not supported, because there is no official Redis server for Windows.");
}
File targetPathDirectory = ensureTargetPathDoesNotExitsAndReturnCompositePath();
if (targetPathDirectory.mkdirs()) {
startRedisAsDaemon();
} else {
throw new IllegalStateException("Target Path " + targetPathDirectory + " could not be created.");
}
LOGGER.info("Started {} Redis instance.", redisPath);
}
private void startRedisAsDaemon() throws AssertionError {
final CountDownLatch startupLatch = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run() {
try {
startRedisProcess();
startupLatch.countDown();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}).start();
try {
startupLatch.await(5, SECONDS);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
private boolean isWindowsSystem() {
return this.operatingSystemResolver.currentOperatingSystem().getFamily() == OperatingSystemFamily.WINDOWS;
}
private List startRedisProcess() throws InterruptedException {
try {
pwd = startProcess();
pwd.waitFor();
if (pwd.exitValue() != 0) {
List consoleOutput = getConsoleOutput(pwd);
throw new IllegalStateException("Redis [" + redisPath + " at port " + port
+ "] could not be started. Next console message was thrown: " + consoleOutput);
}
return null;
} catch (IOException e) {
throw new IllegalStateException("Redis [" + redisPath + " at port " + port
+ "] could not be started. Next console message was thrown: " + e.getMessage());
}
}
private File ensureTargetPathDoesNotExitsAndReturnCompositePath() {
File dbPath = new File(targetPath);
if (dbPath.exists()) {
deleteDir(dbPath);
}
return dbPath;
}
private Process startProcess() throws IOException {
return this.commandLineExecutor.startProcessInDirectoryAndArguments(targetPath,
buildOperationSystemProgramAndArguments());
}
private List getConsoleOutput(Process pwd) throws IOException {
return this.commandLineExecutor.getConsoleOutput(pwd);
}
private List buildOperationSystemProgramAndArguments() {
List programAndArguments = new ArrayList();
programAndArguments.add(getExecutablePath());
addConfigurationPath(programAndArguments);
addSlaveOfParameter(programAndArguments);
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 String getExecutablePath() {
return this.redisPath + File.separatorChar + REDIS_BINARY_DIRECTORY + File.separatorChar + redisExecutable();
}
private String redisExecutable() {
OperatingSystem operatingSystem = this.operatingSystemResolver.currentOperatingSystem();
switch (operatingSystem.getFamily()) {
case WINDOWS:
throw new IllegalArgumentException(
"Windows System is not supported, because there is no official Redis server for Windows.");
default:
return REDIS_EXECUTABLE_X;
}
}
private List addSlaveOfParameter(List programAndArguments) {
if(isMasterDefined()) {
programAndArguments.add(SLAVE_OF_ARGUMENT+" "+this.masterHost+" "+Integer.toString(this.masterPort));
}
return programAndArguments;
}
private List addConfigurationPath(List programAndArguments) {
if (this.configurationFilepath != null) {
programAndArguments.add(this.configurationFilepath);
}
return programAndArguments;
}
@Override
public void doStop() {
LOGGER.info("Stopping {} Redis instance.", redisPath);
try {
stopRedis();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
} finally {
ensureTargetPathDoesNotExitsAndReturnCompositePath();
}
LOGGER.info("Stopped {} Redis instance.", redisPath);
}
private void stopRedis() throws InterruptedException {
if (isProcessAlive()) {
pwd.destroy();
TimeUnit.SECONDS.sleep(2);
}
}
private boolean isProcessAlive() {
return pwd != null;
}
private boolean isMasterDefined() {
return this.masterHost != null && this.masterPort != NO_MASTER_PORT;
}
public void setTargetPath(String targetPath) {
this.targetPath = targetPath;
}
public void setPort(int port) {
this.port = port;
}
public void setRedisPath(String redisPath) {
this.redisPath = redisPath;
}
public void setMasterHost(String host) {
this.masterHost = host;
}
public void setMasterPort(int port) {
this.masterPort = port;
}
public void addExtraCommandLineArgument(String argumentName, String argumentValue) {
this.extraCommandArguments.put(argumentName, argumentValue);
}
public void addSingleCommandLineArgument(String argument) {
this.singleCommandArguments.add(argument);
}
public String getRedisPath() {
return redisPath;
}
public void setConfigurationFilepath(String configurationFilepath) {
this.configurationFilepath = configurationFilepath;
}
public void setOperatingSystemResolver(OperatingSystemResolver operatingSystemResolver) {
this.operatingSystemResolver = operatingSystemResolver;
}
public void setCommandLineExecutor(CommandLineExecutor commandLineExecutor) {
this.commandLineExecutor = commandLineExecutor;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy