* @param args The command-line arguments provided to this program.
*/
public static void main(String[] args)
{
// Define the arguments that may be provided to the server.
BooleanArgument checkStartability = null;
BooleanArgument quietMode = null;
IntegerArgument timeout = null;
BooleanArgument windowsNetStart = null;
BooleanArgument displayUsage = null;
BooleanArgument fullVersion = null;
BooleanArgument noDetach = null;
BooleanArgument systemInfo = null;
BooleanArgument useLastKnownGoodConfig = null;
StringArgument configClass = null;
StringArgument configFile = null;
// Create the command-line argument parser for use with this program.
Message toolDescription = DirectoryServer.toolDescription;
ArgumentParser argParser =
new ArgumentParser("org.nasutekds.server.core.DirectoryServer",
toolDescription, false);
// Initialize all the command-line argument types and register them with the
// parser.
try
{
configClass = new StringArgument("configclass", 'C', "configClass",
true, false, true,
INFO_CONFIGCLASS_PLACEHOLDER.get(),
ConfigFileHandler.class.getName(), null,
INFO_DSCORE_DESCRIPTION_CONFIG_CLASS
.get());
configClass.setHidden(true);
argParser.addArgument(configClass);
configFile = new StringArgument("configfile", 'f', "configFile",
true, false, true,
INFO_CONFIGFILE_PLACEHOLDER.get(), null,
null,
INFO_DSCORE_DESCRIPTION_CONFIG_FILE
.get());
configFile.setHidden(true);
argParser.addArgument(configFile);
checkStartability = new BooleanArgument("checkstartability", null,
"checkStartability",
INFO_DSCORE_DESCRIPTION_CHECK_STARTABILITY.get());
checkStartability.setHidden(true);
argParser.addArgument(checkStartability);
windowsNetStart = new BooleanArgument("windowsnetstart", null,
"windowsNetStart",
INFO_DSCORE_DESCRIPTION_WINDOWS_NET_START.get());
windowsNetStart.setHidden(true);
argParser.addArgument(windowsNetStart);
fullVersion = new BooleanArgument("fullversion", 'F', "fullVersion",
INFO_DSCORE_DESCRIPTION_FULLVERSION
.get());
fullVersion.setHidden(true);
argParser.addArgument(fullVersion);
systemInfo = new BooleanArgument("systeminfo", 's', "systemInfo",
INFO_DSCORE_DESCRIPTION_SYSINFO.get());
argParser.addArgument(systemInfo);
useLastKnownGoodConfig =
new BooleanArgument("lastknowngoodconfig", 'L',
"useLastKnownGoodConfig",
INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG.get());
argParser.addArgument(useLastKnownGoodConfig);
noDetach = new BooleanArgument("nodetach", 'N', "nodetach",
INFO_DSCORE_DESCRIPTION_NODETACH.get());
argParser.addArgument(noDetach);
quietMode = new BooleanArgument("quiet", 'Q', "quiet",
INFO_DESCRIPTION_QUIET.get());
argParser.addArgument(quietMode);
// Not used in this class, but required by the start-ds script
// (see issue #3814)
timeout = new IntegerArgument("timeout", 't', "timeout", true, false,
true, INFO_SECONDS_PLACEHOLDER.get(),
DEFAULT_TIMEOUT,
null, true, 0, false,
0, INFO_DSCORE_DESCRIPTION_TIMEOUT.get());
argParser.addArgument(timeout);
displayUsage = new BooleanArgument("help", 'H', "help",
INFO_DSCORE_DESCRIPTION_USAGE.get());
argParser.addArgument(displayUsage);
argParser.setUsageArgument(displayUsage);
}
catch (ArgumentException ae)
{
Message message = ERR_DSCORE_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
System.err.println(message);
System.exit(1);
}
// Parse the command-line arguments provided to this program.
try
{
argParser.parseArguments(args);
}
catch (ArgumentException ae)
{
Message message = ERR_DSCORE_ERROR_PARSING_ARGS.get(ae.getMessage());
System.err.println(message);
System.err.println(argParser.getUsage());
System.exit(1);
}
// If we should just display usage information, then print it and exit.
if (checkStartability.isPresent())
{
// This option should only be used if a PID file already exists in the
// server logs directory, and we need to check which of the following
// conditions best describes the current usage:
// - We're trying to start the server, but it's already running. The
// attempt to start the server should fail, and the server process will
// exit with a result code of 98.
// - We're trying to start the server and it's not already running. We
// won't start it in this invocation, but the script used to get to this
// point should go ahead and overwrite the PID file and retry the
// startup process. The server process will exit with a result code of
// 99.
// - We're not trying to start the server, but instead are trying to do
// something else like display the version number. In that case, we
// don't need to write the PID file at all and can just execute the
// intended command. If that command was successful, then we'll have an
// exit code of NOTHING_TO_DO (0). Otherwise, it will have an exit code
// that is something other than NOTHING_TO_DO, SERVER_ALREADY_STARTED,
// START_AS_DETACH, START_AS_NON_DETACH, START_AS_WINDOWS_SERVICE,
// START_AS_DETACH_QUIET, START_AS_NON_DETACH_QUIET to indicate that a
// problem occurred.
if (argParser.usageOrVersionDisplayed())
{
// We're just trying to display usage, and that's already been done so
// exit with a code of zero.
System.exit(NOTHING_TO_DO);
}
else if (fullVersion.isPresent() || systemInfo.isPresent())
{
// We're not really trying to start, so rebuild the argument list
// without the "--checkStartability" argument and try again. Exit with
// whatever that exits with.
LinkedList<String> newArgList = new LinkedList<String>();
for (String arg : args)
{
if (! arg.equalsIgnoreCase("--checkstartability"))
{
newArgList.add(arg);
}
}
String[] newArgs = new String[newArgList.size()];
newArgList.toArray(newArgs);
main(newArgs);
System.exit(NOTHING_TO_DO);
}
else
{
System.exit(checkStartability(argParser));
}
}
else if (argParser.usageOrVersionDisplayed())
{
System.exit(0);
}
else if (fullVersion.isPresent())
{
printFullVersionInformation();
return;
}
else if (systemInfo.isPresent())
{
RuntimeInformation.printInfo();
return;
}
else if (noDetach.isPresent() && timeout.isPresent()) {
Message message = ERR_DSCORE_ERROR_NODETACH_TIMEOUT.get();
System.err.println(message);
System.err.println(argParser.getUsage());
System.exit(1);
}
// At this point, we know that we're going to try to start the server.
// Attempt to grab an exclusive lock for the Directory Server process.
String lockFile = LockFileManager.getServerLockFileName();
try
{
StringBuilder failureReason = new StringBuilder();
if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
{
Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile,
String.valueOf(failureReason));
System.err.println(message);
System.exit(1);
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile,
stackTraceToSingleLineString(e));
System.err.println(message);
System.exit(1);
}
serverLocked = true;
// Configure the JVM to delete the PID file on exit, if it exists.
boolean pidFileMarkedForDeletion = false;
boolean startingFileMarkedForDeletion = false;
try
{
String pidFilePath;
String startingFilePath;
String serverRoot = System.getenv(ENV_VAR_INSTALL_ROOT);
File instanceRoot = DirectoryEnvironmentConfig
.getInstanceRootFromServerRoot(new File(serverRoot));
if (instanceRoot == null)
{
pidFilePath = "logs/server.pid";
startingFilePath = "logs/server.starting";
}
else
{
pidFilePath = instanceRoot.getAbsolutePath() + File.separator + "logs"
+ File.separator + "server.pid";
startingFilePath = instanceRoot.getAbsolutePath() + File.separator
+ "logs" + File.separator + "server.starting";
}
File pidFile = new File(pidFilePath);
if (pidFile.exists())
{
pidFile.deleteOnExit();
pidFileMarkedForDeletion = true;
}
File startingFile = new File(startingFilePath);
if (startingFile.exists())
{
startingFile.deleteOnExit();
startingFileMarkedForDeletion = true;
}
} catch (Exception e) {}
// Redirect standard output and standard error to the server.out file. If
// the server hasn't detached from the terminal, then also continue writing
// to the original standard output and standard error. Also, configure the
// JVM to delete the PID and server.starting files on exit, if they exist.
PrintStream serverOutStream;
try
{
// We need to figure out where to put the file. See if the server root
// is available as an environment variable and if so then use it.
// Otherwise, try to figure it out from the location of the config file.
String serverRoot = System.getenv(ENV_VAR_INSTALL_ROOT);
if (serverRoot == null)
{
serverRoot = new File(configFile.getValue()).getParentFile().
getParentFile().getAbsolutePath();
}
if (serverRoot == null)
{
System.err.println("WARNING: Unable to determine server root in " +
"order to redirect standard output and standard " +
"error.");
}
else
{
File instanceRoot = DirectoryEnvironmentConfig
.getInstanceRootFromServerRoot(new File(serverRoot));
File logDir = new File(instanceRoot.getAbsolutePath() + File.separator
+ "logs");
if (logDir.exists())
{
FileOutputStream fos =
new FileOutputStream(new File(logDir, "server.out"), true);
serverOutStream = new PrintStream(fos);
if (noDetach.isPresent())
{
if (! quietMode.isPresent())
{
MultiOutputStream multiStream =
new MultiOutputStream(System.out, serverOutStream);
serverOutStream = new PrintStream(multiStream);
}
}
System.setOut(serverOutStream);
System.setErr(serverOutStream);
if (! pidFileMarkedForDeletion)
{
File f = new File(logDir, "server.pid");
if (f.exists())
{
f.deleteOnExit();
}
}
if (! startingFileMarkedForDeletion)
{
File f = new File(logDir, "server.starting");
if (f.exists())
{
f.deleteOnExit();
}
}
}
else
{
System.err.println("WARNING: Unable to redirect standard output " +
"and standard error because the logs directory " +
logDir.getAbsolutePath() + " does not exist.");
}
}
}
catch (Exception e)
{
System.err.println("WARNING: Unable to redirect standard output and " +
"standard error: " + stackTraceToSingleLineString(e));
}
// Install the default loggers so the startup messages
// will be printed.
TextErrorLogPublisher startupErrorLogPublisher = null;
TextDebugLogPublisher startupDebugLogPublisher = null;
startupErrorLogPublisher =
TextErrorLogPublisher.getStartupTextErrorPublisher(
new TextWriter.STDOUT());
ErrorLogger.addErrorLogPublisher(startupErrorLogPublisher);
startupDebugLogPublisher =
TextDebugLogPublisher.getStartupTextDebugPublisher(
new TextWriter.STDOUT());
DebugLogger.addDebugLogPublisher(startupDebugLogPublisher);
// Create an environment configuration for the server and populate a number
// of appropriate properties.
DirectoryEnvironmentConfig environmentConfig =
new DirectoryEnvironmentConfig();
try
{
environmentConfig.setProperty(PROPERTY_CONFIG_CLASS,
configClass.getValue());
environmentConfig.setProperty(PROPERTY_CONFIG_FILE,
configFile.getValue());
environmentConfig.setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG,
String.valueOf(useLastKnownGoodConfig.isPresent()));
}
catch (Exception e)
{
// This shouldn't happen. For the methods we are using, the exception is
// just a guard against making changes with the server running.