Source: server/index.js

//Imports
var util         = require( "util" ),
    path         = require( "path" ),
    EventEmitter = require( "events" ).EventEmitter,
    Interface    = require( "./interface.js" );

/**
 *
 * @access public
 * @constructor
 * @since 0.6.0
 * @type {Server}
 */
function Server( ftpdjs, options ) {
    this.ftpdjs  = ftpdjs;
    this.id      = options.id;
    this.options = options;
    //Check if the interface path have been defined or not
    if ( undefined === this.getOptions().interfacePath ) {
        //Add the default interface path
        this.getOptions().interfacePath = [ "./interfaces" ];
    }
    this.interfaces   = [];
    this.closeIndex   = 0;
    this.setupCounter = 0;
    EventEmitter.call( this );
}

util.inherits( Server, EventEmitter );

/**
 *
 * This callback will get invoked when the server have finished setting up all of the interfaces it wished to utilize
 *
 * @callback Server~finishSetup
 * @since 0.6.0
 */

/**
 *
 * This function will be invoked by the application when the server instance have been successfully stored
 * in the application's main class. Use this to start and listen the interfaces needed.
 *
 * Setup Process
 * - Setup User Manager
 * - Setup All Interfaces
 *
 * @access public
 * @param {Server~finishSetup} callback the callback to invoke when finished
 * @since 0.6.0
 */
Server.prototype.setup = function ( callback ) {
    //Get the array of available interface configurations
    var interfaceConfigurations = this.getOptions().interfaces || [],
        that                    = this;
    this.getFtpdjs().log( this.getBaseMessage() + ": Setting up" );

    function setupCallback( theInterface ) {
        that.getInterfaces().push( theInterface );
        that.setupCounter++;
        if ( that.setupCounter === that.getOptions().interfaces.length ) {
            that.emit( "state", "setup" );
            that.getFtpdjs().log( that.getBaseMessage() + ": Finished setting up" );
            if ( undefined !== callback ) {
                try {
                    callback();
                } catch ( e ) {

                }
            }
        }
    }

    //Loop through all of the interface configurations
    for ( var i = 0; i < interfaceConfigurations.length; i++ ) {
        var interfaceOptions = interfaceConfigurations[ i ],
            type             = interfaceOptions.type;
        interfaceOptions.id  = that.getID() + i;
        if ( undefined === interfaceOptions.type ) {
            var theInterface = new Interface( this, interfaceOptions );
            theInterface.setup( setupCallback );
        } else {
            this.getInterfaceFile( type, function ( path ) {
                if ( undefined !== path ) {
                    var interfaceModule = require( path ),
                        theInterface    = new interfaceModule( this, interfaceOptions );
                    theInterface.setup( setupCallback );
                }
            } );
        }
    }
};

/**
 *
 * @callback Server~finishClose
 * @since 0.6.0
 */

/**
 *
 * This method is used to close all of the interfaces the server is currently utilizing
 *
 * @access public
 * @param {Supervisor~finishClose} callback the callback to invoke upon completed closure of the interfaces
 * @since 0.6.0
 */
Server.prototype.close = function ( callback ) {
    //Check if we've been through all of the interfaces or if there even is interface in use
    if ( this.getInterfaces().length === (this.closeIndex) || 0 == this.getInterfaces().length ) {
        //Invoke the callback as there's nothing more to close
        this.interfaces = [];
        this.getFtpdjs().log( this.getBaseMessage() + ": Closed" );
        try {
            callback();
        } catch ( e ) {

        }
        return;
    }
    //Get the next interface and increment the interface close counter
    var serverInterface = this.getInterfaces()[ this.closeIndex++ ],
        //Setup a this reference as we can't use this within a callback
        that            = this;

    try {
        //Close the interface
        serverInterface.close( function () {
            //Continue to the next interface
            that.close( callback );
        } )
    } catch ( exception ) {
        //@TODO Error Handling
    }
};

/**
 *
 * This callback will be invoked when the server finished looking for the wanted interface class
 *
 * @callback Server~interfaceFile
 * @param {string|undefined} interfacePath this will be the full path if the class was found otherwise it'll be
 *     undefined
 * @since 0.6.0
 */

/**
 *
 * This function is used to search for the wanted interface class in the interfaces paths provided by the server's
 * options
 *
 * @param {string} name the name of the interface
 * @param {Server~interfaceFile} callback the callback to invoke when finished looking for the class
 * @param {int} index the current path index. Use this if you want to ignore the paths defined before index
 */
Server.prototype.getInterfaceFile = function ( name, callback, index ) {
    index = index || 0;
    try {
        var interfacePath = path.join( this.getOptions().interfacePath[ index ], type + ".js" ),
            that          = this;
        fs.exists( interfacePath, function ( exists ) {
            if ( !exists ) {
                that.getInterfaceFile( type, callback, index + 1 );
            } else {
                callback( interfacePath );
            }
        } )
    } catch ( e ) {
        callback( undefined );
    }
};

/**
 *
 * @access public
 * @returns {ftpdjs} the ftpdjs instance using the server
 * @since 0.6.0
 */
Server.prototype.getFtpdjs = function () {
    return this.ftpdjs;
};

/**
 *
 * This function is used to get the id of the server
 *
 * @access public
 * @returns {string} the id of the server
 * @since 0.6.0
 */
Server.prototype.getID = function () {
    return this.id;
};

/**
 *
 * This function is used to get the server's options
 *
 * @access public
 * @returns {Object} the server's options
 * @since 0.6.0
 */
Server.prototype.getOptions = function () {
    return this.options;
};

/**
 *
 * This function is used to get the array of interfaces the server is utilizing
 *
 * @access public
 * @returns {Array} the initialized interfaces
 * @since 0.6.0
 */
Server.prototype.getInterfaces = function () {
    return this.interfaces;
};

/**
 *
 * This function is used to tell wether or not all of the interfaces the server have to utilize have been setup
 *
 * @access public
 * @returns {boolean} wether or not all of the interfaces have been setup
 * @since 0.6.0
 */
Server.prototype.isSetup = function () {
    return this.getInterfaces().length === this.setupCounter;
};

/**
 *
 * This function is used to get the base logging message for the server
 *
 * @access public
 * @returns {string} the base log message
 * @since 0.6.o
 */
Server.prototype.getBaseMessage = function () {
    return "[Server " + this.getID() + "]";
};

Server.prototype.getUserManager = function(){
    return this.userManager;
}

/**
 *
 * @access public
 * @type {Server}
 * @since 0.6.0
 */
module.exports = Server;