package mykeynote.server;
import java.io.File;
import java.io.IOException;
import java.io.FileNotFoundException;
import mykeynote.exceptions.configuration.ConfigurationUnacceptableValue;
import mykeynote.exceptions.configuration.MissingConfigOptionException;
import mykeynote.exceptions.configuration.UniqueFileException;
import mykeynote.exceptions.report.ReportFileCreationException;
import mykeynote.exceptions.report.ReportNotInitializedException;
import mykeynote.server.configuration.Configuration;
import mykeynote.server.nonpersistent.Server;
import mykeynote.server.persistent.PersistentServer;
/**
* This is the main class of the server package. This file can be executed in order
* to bring the servers (and all that is needed) up and running.
* @author Orlin Gueorguiev
*/
public class Main{
private static Report report;
private static Configuration config;
//private static KeyNoteThread kn;
private static final Shutdown sh = new Shutdown();
private static File configFile;
// Servers
private static Server server;
private static PersistentServer pserver;
private static boolean isDeamonized = false;
/**
* Just the main class. It is intended to be used from the command line.<br>
* If you are interested in running the servers from a running java vm, use
* {@link #main(File)}.
* @param args
* @throws UniqueFileException
* @throws ConfigurationUnacceptableValue
* @throws ReportFileCreationException
* @throws MissingConfigOptionException
*/
public static void main(String[] args) {
//checking if the arguments are acceptable
cmdOptions(args);
//Adding the shutdown hook, needed for the shutdown
Runtime.getRuntime().addShutdownHook(sh);
//creating the configuration (by reading the provided configuration file)
try {
initiateConfiguration();
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
} catch (ReportNotInitializedException e) {
e.printStackTrace();
System.exit(1);
} catch (MissingConfigOptionException e) {
e.printStackTrace();
System.exit(1);
} catch (ReportFileCreationException e) {
e.printStackTrace();
System.exit(1);
} catch (ConfigurationUnacceptableValue e) {
e.printStackTrace();
System.exit(1);
} catch (UniqueFileException e) {
e.printStackTrace();
System.exit(1);
}
sh.setConfiguration(config);
sh.setReport(report);
//report the running configuration
report.reportServerLog(config.getEnviroment());
//initiate the keynote program
//initiateKN();
//starting the servers
try {
initiateServers();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
//started = true;
doNothing();
try {
finilize();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
/**
* This method waits one second and then looks if the servers are still started.
* It can be used to force the servers to run until the program is stopped.
*/
private static void doNothing(){
while(started){
//do nothing so that the servers can run
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//nothing to be done
}
}
}
/**
* This is the alternative to the {@link #main(String[])} method, which can be
* used from a java vm.
* @param configuration The file where the configuration resides.
* @throws FileNotFoundException This exception indicates that the configuration file
* or any other needed file could not be found.
* @throws IOException An IOException
* @throws ReportNotInitializedException This error indicates that the report was not
* initialized when it was needed. This condition should never occur.
* @throws UniqueFileException
* @throws ConfigurationUnacceptableValue
* @throws ReportFileCreationException
* @throws MissingConfigOptionException
*/
public static void main(File configuration) throws FileNotFoundException, IOException, ReportNotInitializedException, MissingConfigOptionException, ReportFileCreationException, ConfigurationUnacceptableValue, UniqueFileException{
//setting the "args" options
isDeamonized = true;
configFile = configuration;
//creating the configuration (by reading the provided configuration file)
initiateConfiguration();
//initiate the keynote program
//initiateKN();
//starting the servers
initiateServers();;
}
/**
* Parsing the command line options.
* @param args The command line options.
*/
private static void cmdOptions(String[] args){
/* our server takes only 1 to 3 arguments, see usage() */
if (args.length < 1 || args.length > 3){
System.err.println(usage());
System.exit(1);
}
//only --help or -h is allowed
if (args.length == 1){
if((args[0].compareTo("--help")==0) || (args[0].compareTo("-h") == 0)){
System.out.println(usage());
System.exit(0);
}
}
/* the third argument can be only daemon */
if (args.length == 3){
if((args[3].compareTo("daemon") == 0)){
demonize();
} else {
System.err.println("The third argument can only be daemon");
//System.err.println(usage());
System.exit(1);
}
}
if((args[0].compareTo("--configFile")!= 0)){
System.err.println(usage());
System.exit(1);
}
configFile = new File(args[1]);
}
/**
* This method initiates the needed servers.
* @throws IOException
*/
private static void initiateServers() throws IOException{
started = true;
if(config.getUseServer()){
//report.reportDebugLog("server", "Strarting the ");
server = new Server(config, report);
server.start();
}
if(config.getUsePServer()){
pserver = new PersistentServer(config, report);
pserver.start();
}
}
/**
* This method is used to initiate the configuration part,
* such as reading the configuration file.
* @throws IOException
* @throws FileNotFoundException
* @throws ReportNotInitializedException
* @throws UniqueFileException
* @throws ConfigurationUnacceptableValue
* @throws ReportFileCreationException
* @throws MissingConfigOptionException
*/
private static void initiateConfiguration() throws FileNotFoundException, IOException, ReportNotInitializedException, MissingConfigOptionException, ReportFileCreationException, ConfigurationUnacceptableValue, UniqueFileException{
config = new Configuration(configFile, !isDeamonized);
config.readConfigFile();
report = config.getReport();
if(!config.getReportToConsole()){
if(!isDeamonized){
demonize();
}
}
}
/**
* Shows the command line options for using this program
* @return Command line usage options
*/
private static String usage() {
return "Possible options are:\n"
+ "-h|--help:\t\tShows this help menu and exits\n" + ""
+ "--configFile <path>:\tSet the path to the config file\n"
+ "daemon:\t\tMakes the server work as a daemon\n";
}
private static void demonize(){
if(!isDeamonized)
try{
System.in.close();
} catch(IOException e){
System.err.println("Error while demonizing server, exiting!");
System.exit(1);
}
System.err.close();
System.out.close();
System.setErr(null);
System.setIn(null);
System.setOut(null);
}
public static void endItMan(int out){
System.runFinalization();
System.exit(out);
}
private static boolean started = false;
/**
* A getter for the status of the server part.
* @return Returns <b>true</b> when all specified servers (persistent and non
* persistent) are started. Returns <b>false</b> if the servers are not started
* or if the servers should be shut down.
*/
public static boolean getStarted(){
return started;
}
/**
* A setter for the started boolean, which shows if the servers are running.
* @param started Set <b>true</b> when all servers are running. Set to
* false <b>false</b> when the servers are being shut down.
*/
public static synchronized void setStarted(boolean start){
started = start;
}
@Deprecated
public static Report getReport(){
return report;
}
/**
* This method is used to finalize the program when this is needed.
* @throws IOException
*/
public static void finilize() throws IOException{
finilizeServers();
config.finalizeConfiguration();
}
private static void finilizeServers(){
finilizeServer();
finilizePServer();
}
private static void finilizePServer(){
if(config.getUsePServer()){
pserver.close();
}
}
private static void finilizeServer(){
if(config.getUseServer()){
server.close();
}
}
}