2013-11-19 13:53:36 +00:00
|
|
|
// Generated by CoffeeScript 1.6.3
|
|
|
|
|
/*
|
|
|
|
|
Rules Server
|
|
|
|
|
============
|
2013-11-20 14:41:41 +00:00
|
|
|
>This is the main module that is used to run the whole server:
|
|
|
|
|
>
|
|
|
|
|
> node server [log_type http_port]
|
|
|
|
|
>
|
|
|
|
|
>Valid `log_type`'s are:
|
|
|
|
|
>
|
|
|
|
|
>- `0`: standard I/O output (default)
|
|
|
|
|
>- `1`: log file (server.log)
|
|
|
|
|
>- `2`: silent
|
|
|
|
|
>
|
|
|
|
|
>`http_port` can be set to use another port, than defined in the
|
|
|
|
|
>[config](config.html) file, to listen to, e.g. used by the test suite.
|
|
|
|
|
>
|
|
|
|
|
>---
|
2013-11-19 13:53:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function() {
|
2013-11-19 17:13:38 +00:00
|
|
|
'use strict';
|
2013-11-20 14:41:41 +00:00
|
|
|
/* Grab all required modules*/
|
|
|
|
|
|
|
|
|
|
var adminCmds, args, conf, db, engine, handleAdminCommands, http_listener, init, log, mm, path, procCmds, shutDown;
|
2013-11-19 13:53:36 +00:00
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
path = require('path');
|
2013-11-19 13:53:36 +00:00
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
log = require('./logging');
|
|
|
|
|
|
|
|
|
|
conf = require('./config');
|
|
|
|
|
|
|
|
|
|
db = require('./db_interface');
|
|
|
|
|
|
|
|
|
|
engine = require('./engine');
|
|
|
|
|
|
|
|
|
|
http_listener = require('./http_listener');
|
|
|
|
|
|
|
|
|
|
mm = require('./module_manager');
|
|
|
|
|
|
|
|
|
|
args = {};
|
|
|
|
|
|
|
|
|
|
procCmds = {};
|
|
|
|
|
|
|
|
|
|
/* Prepare the admin commands that are issued via HTTP requests.*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
adminCmds = {
|
|
|
|
|
'loadrules': mm.loadRulesFromFS,
|
|
|
|
|
'loadaction': mm.loadActionModuleFromFS,
|
|
|
|
|
'loadactions': mm.loadActionModulesFromFS,
|
|
|
|
|
'loadevent': mm.loadEventModuleFromFS,
|
|
|
|
|
'loadevents': mm.loadEventModulesFromFS,
|
|
|
|
|
'loadusers': http_listener.loadUsers,
|
|
|
|
|
'shutdown': shutDown
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Error handling of the express port listener requires special attention,
|
|
|
|
|
thus we have to catch the process error, which is issued if
|
|
|
|
|
the port is already in use.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process.on('uncaughtException', function(err) {
|
|
|
|
|
switch (err.errno) {
|
|
|
|
|
case 'EADDRINUSE':
|
|
|
|
|
err.addInfo = 'http_port already in use, shutting down!';
|
|
|
|
|
log.error('RS', err);
|
|
|
|
|
shutDown();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
log.error(err);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
## Initialize the Server
|
|
|
|
|
This function is invoked right after the module is loaded and starts the server.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
init = function() {
|
|
|
|
|
log.print('RS', 'STARTING SERVER');
|
2013-11-20 14:41:41 +00:00
|
|
|
/* Check whether the config file is ready, which is required to start the server.*/
|
|
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
if (!conf.isReady()) {
|
|
|
|
|
log.error('RS', 'Config file not ready!');
|
2013-11-20 14:41:41 +00:00
|
|
|
process.exit();
|
2013-11-19 17:13:38 +00:00
|
|
|
}
|
|
|
|
|
/* Fetch the `log_type` argument and post a log about which log type is used.*/
|
|
|
|
|
|
|
|
|
|
if (process.argv.length > 2) {
|
|
|
|
|
args.logType = parseInt(process.argv[2]) || 0;
|
|
|
|
|
switch (args.logType) {
|
|
|
|
|
case 0:
|
|
|
|
|
log.print('RS', 'Log type set to standard I/O output');
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
log.print('RS', 'Log type set to file output');
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
log.print('RS', 'Log type set to silent');
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
log.print('RS', 'Unknown log type, using standard I/O');
|
|
|
|
|
}
|
|
|
|
|
log(args);
|
|
|
|
|
} else {
|
|
|
|
|
log.print('RS', 'No log method argument provided, using standard I/O');
|
|
|
|
|
}
|
|
|
|
|
/* Fetch the `http_port` argument*/
|
|
|
|
|
|
|
|
|
|
if (process.argv.length > 3) {
|
|
|
|
|
args.http_port = parseInt(process.argv[3]);
|
|
|
|
|
} else {
|
|
|
|
|
log.print('RS', 'No HTTP port passed, using standard port from config file');
|
|
|
|
|
}
|
|
|
|
|
db(args);
|
2013-11-20 14:41:41 +00:00
|
|
|
/* We only proceed with the initialization if the DB is ready*/
|
|
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
return db.isConnected(function(err, result) {
|
|
|
|
|
if (!err) {
|
2013-11-20 14:41:41 +00:00
|
|
|
/* Initialize all required modules with the args object.*/
|
|
|
|
|
|
|
|
|
|
log.print('RS', 'Initialzing engine');
|
|
|
|
|
engine(args);
|
|
|
|
|
log.print('RS', 'Initialzing http listener');
|
|
|
|
|
http_listener(args);
|
|
|
|
|
log.print('RS', 'Initialzing module manager');
|
|
|
|
|
mm(args);
|
|
|
|
|
log.print('RS', 'Initialzing DB');
|
|
|
|
|
/* Distribute handlers between modules to link the application.*/
|
|
|
|
|
|
|
|
|
|
log.print('RS', 'Passing handlers to engine');
|
|
|
|
|
engine.addDBLinkAndLoadActionsAndRules(db);
|
|
|
|
|
log.print('RS', 'Passing handlers to http listener');
|
|
|
|
|
http_listener.addHandlers(db, handleAdminCommands, engine.pushEvent);
|
|
|
|
|
log.print('RS', 'Passing handlers to module manager');
|
|
|
|
|
return mm.addHandlers(db, engine.loadActionModule, engine.addRule);
|
2013-11-19 17:13:38 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2013-11-19 13:53:36 +00:00
|
|
|
/*
|
2013-11-19 17:13:38 +00:00
|
|
|
admin commands handler receives all command arguments and an answerHandler
|
|
|
|
|
object that eases response handling to the HTTP request issuer.
|
2013-11-19 13:53:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
handleAdminCommands = function(args, answHandler) {
|
|
|
|
|
var fAnsw, _name;
|
|
|
|
|
if (args && args.cmd) {
|
|
|
|
|
if (typeof adminCmds[_name = args.cmd] === "function") {
|
|
|
|
|
adminCmds[_name](args, answHandler);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log.print('RS', 'No command in request');
|
|
|
|
|
}
|
2013-11-20 14:41:41 +00:00
|
|
|
/*
|
|
|
|
|
The fAnsw function receives an answerHandler object as an argument when called
|
|
|
|
|
and returns an anonymous function
|
|
|
|
|
*/
|
|
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
fAnsw = function(ah) {
|
2013-11-20 14:41:41 +00:00
|
|
|
/*
|
|
|
|
|
The anonymous function checks whether the answerHandler was already used to
|
|
|
|
|
issue an answer, if no answer was provided we answer with an error message
|
|
|
|
|
*/
|
|
|
|
|
|
2013-11-19 17:13:38 +00:00
|
|
|
return function() {
|
|
|
|
|
if (!ah.isAnswered()) {
|
2013-11-20 14:41:41 +00:00
|
|
|
return ah.answerError('Not handled...');
|
2013-11-19 17:13:38 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
2013-11-20 14:41:41 +00:00
|
|
|
/*
|
|
|
|
|
Delayed function call of the anonymous function that checks the answer handler
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return setTimeout(fAnsw(answHandler), 2000);
|
2013-11-19 17:13:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Shuts down the server.
|
|
|
|
|
@param {Object} args
|
|
|
|
|
@param {Object} answHandler
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shutDown = function(args, answHandler) {
|
|
|
|
|
if (answHandler != null) {
|
|
|
|
|
answHandler.answerSuccess('Goodbye!');
|
|
|
|
|
}
|
|
|
|
|
log.print('RS', 'Received shut down command!');
|
|
|
|
|
if (engine != null) {
|
|
|
|
|
engine.shutDown();
|
|
|
|
|
}
|
|
|
|
|
return http_listener != null ? http_listener.shutDown() : void 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
## Process Commands
|
|
|
|
|
|
|
|
|
|
When the server is run as a child process, this function handles messages
|
|
|
|
|
from the parent process (e.g. the testing suite)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process.on('message', function(cmd) {
|
|
|
|
|
return typeof procCmds[cmd] === "function" ? procCmds[cmd]() : void 0;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
The die command redirects to the shutDown function.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
procCmds.die = shutDown;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*Start initialization*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
init();
|
|
|
|
|
|
2013-11-19 13:53:36 +00:00
|
|
|
}).call(this);
|