ServerCommand.java
package emissary.command;
import emissary.client.EmissaryResponse;
import emissary.command.converter.ModeConverter;
import emissary.command.converter.ProjectBaseConverter;
import emissary.directory.EmissaryNode;
import emissary.server.EmissaryServer;
import emissary.server.api.Pause;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Set;
import static emissary.directory.EmissaryNode.STRICT_STARTUP_MODE;
@Command(description = "Start an Emissary jetty server", subcommands = {HelpCommand.class})
public class ServerCommand extends ServiceCommand {
private static final Logger LOG = LoggerFactory.getLogger(ServerCommand.class);
public static final String COMMAND_NAME = "server";
public static final int DEFAULT_PORT = 8001;
@Option(names = {"-m", "--mode"}, description = "mode: standalone or cluster\nDefault: ${DEFAULT-VALUE}", converter = ModeConverter.class,
defaultValue = "standalone")
private EmissaryNode.Mode mode;
@Option(names = "--staticDir", description = "path to static assets, loaded from classpath otherwise", converter = ProjectBaseConverter.class)
private Path staticDir;
@Option(names = {"-a", "--agents"}, description = "number of mobile agents (default is based on memory)\nDefault: ${DEFAULT-VALUE}")
private int agents;
@Option(names = {"--dumpJettyBeans"}, description = "dump all the jetty beans that loaded\nDefault: ${DEFAULT-VALUE}")
private boolean dumpJettyBeans = false;
@Option(names = {"--strict"}, description = "If one Place fails to start, shut down the entire server\nDefault: ${DEFAULT-VALUE}")
private boolean strictMode = false;
@Override
public String getCommandName() {
return COMMAND_NAME;
}
@Override
public int getDefaultPort() {
return DEFAULT_PORT;
}
public EmissaryNode.Mode getMode() {
return mode;
}
public Path getStaticDir() {
return staticDir;
}
public int getAgents() {
return agents;
}
public boolean shouldDumpJettyBeans() {
return dumpJettyBeans;
}
/**
* If strictMode is set to true, the server will shut down if a Place fails to start
*
* @return strictMode
*/
public boolean shouldStrictMode() {
return strictMode;
}
@Override
public void setupCommand() {
setupHttp();
reinitLogback();
setupServer();
}
public void setupServer() {
String flavorMode;
if (getFlavor() == null) {
flavorMode = getMode().toString();
} else {
flavorMode = getMode().toString() + "," + getFlavor();
}
if (shouldStrictMode()) {
System.setProperty(STRICT_STARTUP_MODE, "true");
}
// Must maintain insertion order
Set<String> flavorSet = new LinkedHashSet<>();
for (String f : flavorMode.split(",")) {
flavorSet.add(f.toUpperCase(Locale.getDefault()));
}
if (flavorSet.contains("STANDALONE") && flavorSet.contains("CLUSTER")) {
throw new IllegalArgumentException("Can not run a server in both STANDALONE and CLUSTER");
} else {
overrideFlavor(String.join(",", flavorSet));
}
}
@Override
protected void startService() {
LOG.info("Running Emissary Server");
EmissaryServer.init(this).startServer();
}
@Override
protected void pauseService() {
setServerState(Pause.PAUSE);
}
@Override
protected void unpauseService() {
setServerState(Pause.UNPAUSE);
}
protected void setServerState(String state) {
LOG.debug("Setting state to {} for EmissaryServer", state);
EmissaryResponse response = performPost("/api/" + state);
if (response.getStatus() != 200) {
LOG.error("Setting Emissary server state to {} failed -- {}", state, response.getContentString());
} else {
LOG.info("Setting Emissary server state to {} successful", state);
}
}
}