<commit_before>/*///////////////////////////////////////////////////////////////////////////

 For Best results use the an 'app-config.json' file. This File should be
 located in the same directory as this file. If you choose not to use it
 then your application must run out of the same directory as this file
 and you entry point must be a file named 'start.js' located in this
 directory.

 'app-config.json' allows you to configure following properties for your
 application:

"applicationName:" <name of the application>
 "applicationDirectory": <set this to the directory you application lives in>
 "appEntry": <set this to the name of the 'js' file that is your entry point>

 "pullPort": <set this to the port for a pull requests> - defaults to 8000

 // The key and cert files are only necessary if you want to listen for a pull
 // request securely. If they are omitted and HTTP server is start instead. Beware
 // as someone could be snooping and then start sending your servers pull requests
 "pullKey": <path to a ssh key file for the HTTPS Server>
 "pullCert": <path to a ssh cert file for the HTTPS Server>
 "pullCa": <array of paths to the certificate authority files> (optional)
 "pullPassphrase" : <string - phrase that the certificate was generated with> (optional if certificate was not generated with a passphrase)

 // This is a secret key that is configured here and passed in via a webhook in
 // response to a pull request. This is to prevent unauthorized requests from causing
 // pulls. If no pull secret is configure then all pull request are valid
 "pullSecret": <secret phrase>

 "pullBranch": <git branch to use for the pull>

 // In theory you can put an cloud vendor specific params in here. You just have to have support in cloud.js for them.
 // Curently AWS is the only cloud platform supported
 // Put your AWS config params in here. Example:
 "accessKeyId": "XXXXXXXXXXXXXXXXXXXX",
 "secretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 "region": "us-east-1"

 "sudo": <Mac and Linux only, should we prefix all shell commands with sudo?> - defaults to no sudo

 // To Trigger a pull and restart

 *////////////////////////////////////////////////////////////////////////////

(function (){
    var fs = require ('fs');
    var exec = require('child_process').exec;
    var path = require('path');
    var url = require('url');
    var qs = require ('querystring');
    var config_file, config, error, pull_error = "";
    var package_json, package_copy, parsed_package, parsed_copy;
    var restart = true;
    var need_restart = false;
    var http = require('http');
    var https = require('https');
    // This an abstraction layer for different cloud services
    // all AWS specific code or other cloud vendor stuff should go in here
    var cloud = require ("./cloud.js");
    var updating_on = false;
    var sudo;
    var instance_data;

    // post a command out
    function post (url, body, port, secure, path, cb){
        var qs = require('querystring');
        body = qs.stringify (body);
        var options = {
            host: url,
            port: port,
            path: path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': body.length
            },
            rejectUnauthorized:false // add this so if someone uses a local certificate on the machine the post will still go through
        };

        var server = (secure) ? https : http;
        var req = server.request(options, function(res) {
            var result = "";
            //console.log('STATUS: ' + res.statusCode);
            //console.log('HEADERS: ' + JSON.stringify(res.headers) + '\n');
            res.setEncoding('utf8');
            res.on('data', function (chunk) {result += chunk;});
            res.on('end', function (){
                cb (null, result);
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
            cb (e.message);
        });

        // write data to request body
        req.write(body);
        req.end();
    }

    // pull the latest source
    function pull(cb, master, req){
        pull_error = "";
        function _pull (cb){
            console.log ("\nPulling the latest code from remote repository");
            // get the latest code
            var child = exec (sudo + "git pull", function (err, std, ster){
                if (err){
                    console.log ("	Error pulling reposititory. Error" + ster);
                    pull_error += "\nError pulling reposititory. Error" + ster;
                }
                else{console.log ("	" + std);}
                cb && cb ();
            });
        }
        // only pull the latest if in the cloud. For local development don't do anything. The developer must manually pull
        if (cloud.isCloud ()){
            restart = (master || master === false);
            need_restart = false;
            if (!master){
                _pull (function (){
                    if (need_restart){
                        process.exit(0);
                    }
                    cb && cb ();
                });
            }
            else { // else we are the master so find all the other AWS instances to pull from
                // get other instances that our are same type and already running
                var secure = (req.href.search ("https://") !== -1);
                var instances = cloud.getInstances (function (instances){
                    instances && instances.forEach (function (instance){
                        if (instance.dns && instance.id !== cloud.getInstanceId ()){ // don't signal ourselves
                            post (instance.dns, req,body, config.pullPort, secure, url.format (req.query));
                        }
                    });
                    // now pull and restart ourselves
                    _pull (function (){
                        if (need_restart){
                            process.exit(0);
                        }
                        cb && cb ();
                    });
                });
            }
        }
        else {cb && cb ();}
    }
    // check if any NPM dependencies changed
    function checkNodeDependencies (cb){
        // read in our files
        console.log ("\nChecking for Node version changes");
        try { package_copy = fs.readFileSync ("package.copy");}
        catch (e) { package_copy = null;}
        try {package_json = fs.readFileSync ("package.json");}
        catch (e) { package_json = null;}
        parsed_package = (package_json) ? JSON.parse (package_json) : null;
        parsed_copy = (package_copy) ? JSON.parse (package_copy) : null;
        // see if our node versions match
        if (parsed_package && parsed_package.node_version){
            var version = parsed_package.node_version.replace ('v', "");
            var node_version = process.version.replace ('v', "");
            if (version !== node_version){
                console.log ("	Upgrading Node");
                console.log ("		current version:" + node_version);
                console.log ("		requested version:" + version);
                // upgrade node using 'n'
                var child = exec (sudo + "n " + version, function (err, std, ster){
                    if (err){
                        console.log ("		Node upgrade failed. Error:" + ster);
                        pull_error += "\nNode upgrade failed. Error:" + ster;
                    }
                    else{
                        console.log ("		Node upgrade success, restarting");
                        if (restart){ process.exit (0); }// exit so we get restarted
                        else { need_restart = true;}
                    }
                    cb & cb ();
                });
            }
            else{
                console.log ("  Node is up to date");
                console.log ("      current version:" + node_version);
                cb & cb ();
            }
        }
        else{
            console.log ("	Current Node version is:" + node_version);
            cb & cb ();
        }
    }

    // check for any node module changes and reinstall the associated packages.
    // NPM doesn't do a good job of keeping track. So keep a copy of the last successful
    // update and compare it. Find ones that have changed and delete them and the
    // re-install.
    function checkNPMDependencies (cb){
        function deleteRecursiveSync(itemPath) {
            if (fs.existsSync(itemPath)){
                if (fs.existsSync(itemPath) && fs.statSync(itemPath).isDirectory()) {
                    fs.readdirSync(itemPath).forEach(function(childItemName) {
                        deleteRecursiveSync(path.join(itemPath, childItemName));
                    });
                    fs.rmdirSync(itemPath);
                } else {
                    fs.unlinkSync(itemPath);
                }
            }
        }
        console.log ("\nChecking for Node Module dependency changes");
        if (!package_json){
            console.log ("WARNING Your Application has no 'package.json' . It is highly" +
                " recommended that you use one to manage your NPM dependencies");
        }
        else{ // delete the module that have changed and re-install with new versions
            if (!package_copy || package_copy.toString() !== package_json.toString ()){
                console.log ("	NPM depency changes detected");
                if (parsed_package && parsed_package.dependencies){
                    for (var package_name in parsed_package.dependencies){
                        var copy_version = (parsed_copy && parsed_copy.dependencies) ? parsed_copy.dependencies[package_name] : "";
                        if (copy_version !== parsed_package.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                if (parsed_copy && parsed_copy.dependencies){
                    for (package_name in parsed_copy.dependencies){
                        copy_version = (parsed_package && parsed_package.dependencies) ? parsed_package.dependencies[package_name] : "";
                        if (copy_version !== parsed_copy.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                var child = exec (sudo + "npm install -d", function (err, std, ster){
                    if (err){
                        console.log ("	Error installing Node` modules. Error:" + ster);
                        pull_error += "\nError installing Node` modules. Error:" + ster;
                    }
                    else{
                        console.log ("	Sucessfully update Node Modules: " + std);
                        fs.writeFileSync ("package.copy", package_json);
                    }
                    cb && cb ();
                });
            }
            else{
                console.log ("  No node module changes detected");
                cb && cb ();
            }
        }
    }
    // start the application
    function startApp (){
        var appEntry = config.appEntry || "start.js";
        console.log ("\nSTARTING APPLICATION CALLING: " + appEntry);
        require ('./' + appEntry);
    }

    /////////////////// CODE EXECUTION STARTS HERE ///////////////////////////
    console.log ("********** Node-Deploy Started *********");
    var date = new Date ();
    console.log (date.toString ());

    try {config_file = fs.readFileSync (".app-config.json");}
    catch (err){ error = err;}

    if (config_file){
        try {config = JSON.parse (config_file);}
        catch (err){ error = err;}
    }

    if (!config) {
        console.log ("	'app-config.json' is missing or invalid: Error:" + error);
        console.log ("	Continuing on with defaults");
        config = {};
    }
    // if nor configured this does nothing
    sudo = (config.sudo) ? "sudo " : "";

    // init the cloud code
    cloud.init (config, function (){
        instance_data = cloud.getInstanceData ();
        console.log ("\nGetting Cloud Data")
        console.log ("  Instance ID:" + cloud.getInstanceId ());
        console.log ("  Instance Data:%j", instance_data);

        // see if updating should be on or off
        if (instance_data && instance_data.deploy === true){
            updating_on = true;
        }

        // change directory to the app working directory. Default to the current directory
        var workingDirectory = config.applicationDirectory || process.cwd();
        console.log ("\nWorking Directory is:" + process.cwd());
        process.chdir (workingDirectory);
        console.log ("\nSetting Working Directory to:" + process.cwd());

        // determine if we are in the could or not and set an environment variable
        // in case other code needs to know this
        console.log ("\nServer in cloud: " + cloud.isCloud ());
        process.env['CLOUD'] = cloud.isCloud ();
        process.env['INSTANCE_ID'] = cloud.getInstanceId ();
        process.env['INSTANCE_DATA'] = cloud.getInstanceData ();

        function checkAndUpdateEnvironment (master){
            if (updating_on){
                // get the latest code
                pull (function (){
                    // check for dependency changes
                    checkNodeDependencies (function (){
                        checkNPMDependencies (function (){
                            startApp ();
                        });
                    });
                }, master);
            }
        }
        checkAndUpdateEnvironment (false);

        // create a server to listen for pull requests
        function handleRequests (req, res){
            function parseURL (req){
                var url_in = url.parse(req.url,true);
                req.query = url_in.query;
                req.href = url_in.href;
            }
            function bodyParser (req, res, func){
                if (req.method == 'POST') {
                    var body = '';
                    req.on('data', function (data) {
                        body += data;
                        if (body.length > 524488) { // limit the most data someone can send to 1/2 a meg
                            request.connection.destroy();
                        }
                    });
                    req.on('end', function () {
                        req.body = qs.parse(body);
                        if (func){func (req, res);}
                    });
                }
            }
            if (req.url.search ("/pull") !== -1){ // handle a command to pull
                var valid_request = true;
                parseURL (req);
                if (config.pullSecret){
                    valid_request = (req.query.secret == config.pullSecret) ? true : false;
                }
                if (valid_request){
                    bodyParser (req, res, function (){
                        var listensTo = (instance_data && instance_data.listensTo) ? instance_data.listensTo : "";
                        if (req.body.ref.search (listensTo) !== -1){
                            pull (function (){
                                res.writeHead(200, {'Content-Type': 'text/plain'});
                                if (pull_error){ res.end("Pull Accepted. There were Errors:" + pull_error); }
                                else {res.end("Pull Accepted"); }
                                var date = new Date ();
                                console.log ("\nPull Command, master:" + req.query.master + " @" + date.toString ());
                                console.log ("	body:%j", req.body);
                                if (pull_error){
                                    console.log ("	There were Errors:%j", pull_error);
                                }
                            }, req.query.master, req);
                        }
                        else{
                            console.log ("\nIgnoring Pull Request, wrong branch. \n\tListening for: " + config.branch +
                                "\n\t Recieved:" + body.ref);
                        }
                    });
                }
                else{
                    res.res.writeHead(200, {'Content-Type': 'text/plain'});
                    res.end("Pull Not Authorized");
                    console.log ("\nPull Not Authorized @" + date.toString ());
                    console.log ("	Secret passed in:" + !!params.secret);
                    console.log ("	Secret required:" + !!config.pullSecret);
                    console.log ("	Secrets Match:" + (config.pullSecret === params.secret));
                }
            }
            else{
                res.res.writeHead(404, {'Content-Type': 'text/plain'});
                res.end("Not Found");
            }
        }
        if (updating_on){
            var http_port = (config.pullPort || 8000), key, cert, options;
            if (config.pullKey && config.pullCert){
                try {key = fs.readFileSync (config.pullKey);}
                catch (err) {key = null;}
                try {cert = fs.readFileSync (config.pullCert);}
                catch (err) {cert = null;}
                if (key && cert) {
                    options = {key:key, cert:cert,
                    ciphers: 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH',
                    honorCipherOrder: true
                    };
                }
                if (options && config.pullPassphrase){
                    options.passphrase = config.pullPassphrase;
                }
                if (options && config.pullCa && config.pullCa.length){
                    var ca = [];
                    config.pullCa.forEach (function (_ca){
                        try {__ca = fs.readFileSync (_ca, {encoding: "aascii"});}
                        catch (err) {__ca = null;}
                        if (__ca){ ca.push (__ca);}
                    });
                    if (ca.length){
                        options.ca = ca;
                    }
                }
            }
            if (key && cert){
                console.log ("\nHTTPS Pull Server Started. Listening on Port:" + http_port);
                https.createServer (options, handleRequests).listen (http_port);
            }
            else{
                console.log ("\nWARNING cert and key not specified or invalid. Falling back to HTTP");
                console.log ("HTTP Pull Server Started. Listening on Port:" + http_port);
                http.createServer (handleRequests).listen (http_port);
            }
        }
    });
 })();
<commit_msg>Initial<commit_after>/*///////////////////////////////////////////////////////////////////////////

 For Best results use the an 'app-config.json' file. This File should be
 located in the same directory as this file. If you choose not to use it
 then your application must run out of the same directory as this file
 and you entry point must be a file named 'start.js' located in this
 directory.

 'app-config.json' allows you to configure following properties for your
 application:

"applicationName:" <name of the application>
 "applicationDirectory": <set this to the directory you application lives in>
 "appEntry": <set this to the name of the 'js' file that is your entry point>

 "pullPort": <set this to the port for a pull requests> - defaults to 8000

 // The key and cert files are only necessary if you want to listen for a pull
 // request securely. If they are omitted and HTTP server is start instead. Beware
 // as someone could be snooping and then start sending your servers pull requests
 "pullKey": <path to a ssh key file for the HTTPS Server>
 "pullCert": <path to a ssh cert file for the HTTPS Server>
 "pullCa": <array of paths to the certificate authority files> (optional)
 "pullPassphrase" : <string - phrase that the certificate was generated with> (optional if certificate was not generated with a passphrase)

 // This is a secret key that is configured here and passed in via a webhook in
 // response to a pull request. This is to prevent unauthorized requests from causing
 // pulls. If no pull secret is configure then all pull request are valid
 "pullSecret": <secret phrase>

 "pullBranch": <git branch to use for the pull>

 // In theory you can put an cloud vendor specific params in here. You just have to have support in cloud.js for them.
 // Curently AWS is the only cloud platform supported
 // Put your AWS config params in here. Example:
 "accessKeyId": "XXXXXXXXXXXXXXXXXXXX",
 "secretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 "region": "us-east-1"

 "sudo": <Mac and Linux only, should we prefix all shell commands with sudo?> - defaults to no sudo

 // To Trigger a pull and restart

 *////////////////////////////////////////////////////////////////////////////

(function (){
    var fs = require ('fs');
    var exec = require('child_process').exec;
    var path = require('path');
    var url = require('url');
    var qs = require ('querystring');
    var config_file, config, error, pull_error = "";
    var package_json, package_copy, parsed_package, parsed_copy;
    var restart = true;
    var need_restart = false;
    var http = require('http');
    var https = require('https');
    // This an abstraction layer for different cloud services
    // all AWS specific code or other cloud vendor stuff should go in here
    var cloud = require ("./cloud.js");
    var updating_on = false;
    var sudo;
    var instance_data;

    // post a command out
    function post (url, body, port, secure, path, cb){
        var qs = require('querystring');
        body = qs.stringify (body);
        var options = {
            host: url,
            port: port,
            path: path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': body.length
            },
            rejectUnauthorized:false // add this so if someone uses a local certificate on the machine the post will still go through
        };

        var server = (secure) ? https : http;
        var req = server.request(options, function(res) {
            var result = "";
            //console.log('STATUS: ' + res.statusCode);
            //console.log('HEADERS: ' + JSON.stringify(res.headers) + '\n');
            res.setEncoding('utf8');
            res.on('data', function (chunk) {result += chunk;});
            res.on('end', function (){
                cb (null, result);
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
            cb (e.message);
        });

        // write data to request body
        req.write(body);
        req.end();
    }

    // pull the latest source
    function pull(cb, master, req){
        pull_error = "";
        function _pull (cb){
            console.log ("\nPulling the latest code from remote repository");
            // get the latest code
            var child = exec (sudo + "git pull", function (err, std, ster){
                if (err){
                    console.log ("	Error pulling reposititory. Error" + ster);
                    pull_error += "\nError pulling reposititory. Error" + ster;
                }
                else{console.log ("	" + std);}
                cb && cb ();
            });
        }
        // only pull the latest if in the cloud. For local development don't do anything. The developer must manually pull
        if (cloud.isCloud ()){
            restart = (master || master === false);
            need_restart = false;
            if (!master){
                _pull (function (){
                    if (need_restart){
                        process.exit(0);
                    }
                    cb && cb ();
                });
            }
            else { // else we are the master so find all the other AWS instances to pull from
                // get other instances that our are same type and already running
                var secure = (req.href.search ("https://") !== -1);
                var instances = cloud.getInstances (function (instances){
                    instances && instances.forEach (function (instance){
                        if (instance.dns && instance.id !== cloud.getInstanceId ()){ // don't signal ourselves
                            post (instance.dns, req,body, config.pullPort, secure, url.format (req.query));
                        }
                    });
                    // now pull and restart ourselves
                    _pull (function (){
                        if (need_restart){
                            process.exit(0);
                        }
                        cb && cb ();
                    });
                });
            }
        }
        else {cb && cb ();}
    }
    // check if any NPM dependencies changed
    function checkNodeDependencies (cb){
        // read in our files
        console.log ("\nChecking for Node version changes");
        try { package_copy = fs.readFileSync ("package.copy");}
        catch (e) { package_copy = null;}
        try {package_json = fs.readFileSync ("package.json");}
        catch (e) { package_json = null;}
        parsed_package = (package_json) ? JSON.parse (package_json) : null;
        parsed_copy = (package_copy) ? JSON.parse (package_copy) : null;
        // see if our node versions match
        if (parsed_package && parsed_package.node_version){
            var version = parsed_package.node_version.replace ('v', "");
            var node_version = process.version.replace ('v', "");
            if (version !== node_version){
                console.log ("	Upgrading Node");
                console.log ("		current version:" + node_version);
                console.log ("		requested version:" + version);
                // upgrade node using 'n'
                var child = exec (sudo + "n " + version, function (err, std, ster){
                    if (err){
                        console.log ("		Node upgrade failed. Error:" + ster);
                        pull_error += "\nNode upgrade failed. Error:" + ster;
                    }
                    else{
                        console.log ("		Node upgrade success, restarting");
                        if (restart){ process.exit (0); }// exit so we get restarted
                        else { need_restart = true;}
                    }
                    cb & cb ();
                });
            }
            else{
                console.log ("  Node is up to date");
                console.log ("      current version:" + node_version);
                cb & cb ();
            }
        }
        else{
            console.log ("	Current Node version is:" + node_version);
            cb & cb ();
        }
    }

    // check for any node module changes and reinstall the associated packages.
    // NPM doesn't do a good job of keeping track. So keep a copy of the last successful
    // update and compare it. Find ones that have changed and delete them and the
    // re-install.
    function checkNPMDependencies (cb){
        function deleteRecursiveSync(itemPath) {
            if (fs.existsSync(itemPath)){
                if (fs.existsSync(itemPath) && fs.statSync(itemPath).isDirectory()) {
                    fs.readdirSync(itemPath).forEach(function(childItemName) {
                        deleteRecursiveSync(path.join(itemPath, childItemName));
                    });
                    fs.rmdirSync(itemPath);
                } else {
                    fs.unlinkSync(itemPath);
                }
            }
        }
        console.log ("\nChecking for Node Module dependency changes");
        if (!package_json){
            console.log ("WARNING Your Application has no 'package.json' . It is highly" +
                " recommended that you use one to manage your NPM dependencies");
        }
        else{ // delete the module that have changed and re-install with new versions
            if (!package_copy || package_copy.toString() !== package_json.toString ()){
                console.log ("	NPM depency changes detected");
                if (parsed_package && parsed_package.dependencies){
                    for (var package_name in parsed_package.dependencies){
                        var copy_version = (parsed_copy && parsed_copy.dependencies) ? parsed_copy.dependencies[package_name] : "";
                        if (copy_version !== parsed_package.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                if (parsed_copy && parsed_copy.dependencies){
                    for (package_name in parsed_copy.dependencies){
                        copy_version = (parsed_package && parsed_package.dependencies) ? parsed_package.dependencies[package_name] : "";
                        if (copy_version !== parsed_copy.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                var child = exec (sudo + "npm install -d", function (err, std, ster){
                    if (err){
                        console.log ("	Error installing Node` modules. Error:" + ster);
                        pull_error += "\nError installing Node` modules. Error:" + ster;
                    }
                    else{
                        console.log ("	Sucessfully update Node Modules: " + std);
                        fs.writeFileSync ("package.copy", package_json);
                    }
                    cb && cb ();
                });
            }
            else{
                console.log ("  No node module changes detected");
                cb && cb ();
            }
        }
    }
    // start the application
    function startApp (){
        var workingDirectory = config.applicationDirectory || process.cwd();
        console.log ("\nWorking Directory is:" + process.cwd());
        process.chdir (workingDirectory);
        console.log ("\nSetting Working Directory to:" + process.cwd());
        var appEntry = config.appEntry || "start.js";
        console.log ("\nSTARTING APPLICATION CALLING: " + appEntry);
        require ('./' + appEntry);
    }

    /////////////////// CODE EXECUTION STARTS HERE ///////////////////////////
    console.log ("********** Node-Deploy Started *********");
    var date = new Date ();
    console.log (date.toString ());

    try {config_file = fs.readFileSync (".app-config.json");}
    catch (err){ error = err;}

    if (config_file){
        try {config = JSON.parse (config_file);}
        catch (err){ error = err;}
    }

    if (!config) {
        console.log ("	'app-config.json' is missing or invalid: Error:" + error);
        console.log ("	Continuing on with defaults");
        config = {};
    }
    // if nor configured this does nothing
    sudo = (config.sudo) ? "sudo " : "";

    // init the cloud code
    cloud.init (config, function (){
        instance_data = cloud.getInstanceData ();
        console.log ("\nGetting Cloud Data")
        console.log ("  Instance ID:" + cloud.getInstanceId ());
        console.log ("  Instance Data:%j", instance_data);

        // see if updating should be on or off
        if (instance_data && instance_data.deploy === true){
            updating_on = true;
        }

        // change directory to the app working directory. Default to the current directory
        var workingDirectory = config.applicationDirectory || process.cwd();
        console.log ("\nWorking Directory is:" + process.cwd());
        process.chdir (workingDirectory);
        console.log ("\nSetting Working Directory to:" + process.cwd());

        // determine if we are in the could or not and set an environment variable
        // in case other code needs to know this
        console.log ("\nServer in cloud: " + cloud.isCloud ());
        process.env['CLOUD'] = cloud.isCloud ();
        process.env['INSTANCE_ID'] = cloud.getInstanceId ();
        process.env['INSTANCE_DATA'] = cloud.getInstanceData ();

        function checkAndUpdateEnvironment (master){
            if (updating_on){
                // get the latest code
                pull (function (){
                    // check for dependency changes
                    checkNodeDependencies (function (){
                        checkNPMDependencies (function (){
                            startApp ();
                        });
                    });
                }, master);
            }
        }
        checkAndUpdateEnvironment (false);

        // create a server to listen for pull requests
        function handleRequests (req, res){
            function parseURL (req){
                var url_in = url.parse(req.url,true);
                req.query = url_in.query;
                req.href = url_in.href;
            }
            function bodyParser (req, res, func){
                if (req.method == 'POST') {
                    var body = '';
                    req.on('data', function (data) {
                        body += data;
                        if (body.length > 524488) { // limit the most data someone can send to 1/2 a meg
                            request.connection.destroy();
                        }
                    });
                    req.on('end', function () {
                        req.body = qs.parse(body);
                        if (func){func (req, res);}
                    });
                }
            }
            if (req.url.search ("/pull") !== -1){ // handle a command to pull
                var valid_request = true;
                parseURL (req);
                if (config.pullSecret){
                    valid_request = (req.query.secret == config.pullSecret) ? true : false;
                }
                if (valid_request){
                    bodyParser (req, res, function (){
                        var listensTo = (instance_data && instance_data.listensTo) ? instance_data.listensTo : "";
                        if (req.body.ref.search (listensTo) !== -1){
                            pull (function (){
                                res.writeHead(200, {'Content-Type': 'text/plain'});
                                if (pull_error){ res.end("Pull Accepted. There were Errors:" + pull_error); }
                                else {res.end("Pull Accepted"); }
                                var date = new Date ();
                                console.log ("\nPull Command, master:" + req.query.master + " @" + date.toString ());
                                console.log ("	body:%j", req.body);
                                if (pull_error){
                                    console.log ("	There were Errors:%j", pull_error);
                                }
                            }, req.query.master, req);
                        }
                        else{
                            console.log ("\nIgnoring Pull Request, wrong branch. \n\tListening for: " + config.branch +
                                "\n\t Recieved:" + body.ref);
                        }
                    });
                }
                else{
                    res.res.writeHead(200, {'Content-Type': 'text/plain'});
                    res.end("Pull Not Authorized");
                    console.log ("\nPull Not Authorized @" + date.toString ());
                    console.log ("	Secret passed in:" + !!params.secret);
                    console.log ("	Secret required:" + !!config.pullSecret);
                    console.log ("	Secrets Match:" + (config.pullSecret === params.secret));
                }
            }
            else{
                res.res.writeHead(404, {'Content-Type': 'text/plain'});
                res.end("Not Found");
            }
        }
        if (updating_on){
            var http_port = (config.pullPort || 8000), key, cert, options;
            if (config.pullKey && config.pullCert){
                try {key = fs.readFileSync (config.pullKey);}
                catch (err) {key = null;}
                try {cert = fs.readFileSync (config.pullCert);}
                catch (err) {cert = null;}
                if (key && cert) {
                    options = {key:key, cert:cert,
                    ciphers: 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH',
                    honorCipherOrder: true
                    };
                }
                if (options && config.pullPassphrase){
                    options.passphrase = config.pullPassphrase;
                }
                if (options && config.pullCa && config.pullCa.length){
                    var ca = [];
                    config.pullCa.forEach (function (_ca){
                        try {__ca = fs.readFileSync (_ca, {encoding: "aascii"});}
                        catch (err) {__ca = null;}
                        if (__ca){ ca.push (__ca);}
                    });
                    if (ca.length){
                        options.ca = ca;
                    }
                }
            }
            if (key && cert){
                console.log ("\nHTTPS Pull Server Started. Listening on Port:" + http_port);
                https.createServer (options, handleRequests).listen (http_port);
            }
            else{
                console.log ("\nWARNING cert and key not specified or invalid. Falling back to HTTP");
                console.log ("HTTP Pull Server Started. Listening on Port:" + http_port);
                http.createServer (handleRequests).listen (http_port);
            }
        }
    });
 })();
<|endoftext|>


<commit_before>/**
 * The Initial Developer of the Original Code is
 * Tarmo Alexander Sundström <ta@sundstrom.im>
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2014 Tarmo Alexander Sundström <ta@sundstrom.im>
 *
 * All Rights Reserved.
 *
 * Contributor(s):
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

jQuery( document ).ready(function() {

    jQuery('.articlepicker').each(function() {
        ArticlePicker.initArticlePicker(this);
    });

});

var ArticlePicker = {

    initArticlePicker: function(el) {
        var $url = jQuery('#basehref').text();
        var $id = jQuery(el).data('field-id');
        var $val = jQuery(el).data('field-value');

        jQuery.getJSON( $url + '/content_article/fieldParams/' + $id, function( data ) {
            var items = [];
            var $sel = '';
            jQuery.each( data, function( key, val ) {
                $sel = '';
                if($val == val.id) {
                    $sel = 'selected="selected"';
                }
                items.push('<option value="' + val.id + '" ' + $sel + '>' + val.title + '</option>');
            });

            var $html = items.join('');
            jQuery($html).appendTo(el);
        });
    }

}
<commit_msg>ArticlePicker now caches fieldParams data locally<commit_after>/**
 * The Initial Developer of the Original Code is
 * Tarmo Alexander Sundström <ta@sundstrom.im>
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2014 Tarmo Alexander Sundström <ta@sundstrom.im>
 *
 * All Rights Reserved.
 *
 * Contributor(s):
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

jQuery( document ).ready(function() {
    jQuery('.articlepicker').each(function() {
        ArticlePicker.initArticlePicker(this);
    });
});
var ArticlePicker = {

    data: {},

    initArticlePicker: function(el) {
        var $url = jQuery('#basehref').text();
        var $id = jQuery(el).data('field-id');
        var $val = jQuery(el).data('field-value');

        if (typeof ArticlePicker.data[$id] === 'undefined') {

            // No data yet, fetching it as we are the first one
            ArticlePicker.data[$id] = {};
            ArticlePicker.data[$id].ready = false;
            ArticlePicker.data[$id].callbacks = [];

            jQuery.getJSON($url + '/content_article/fieldParams/' + $id, function(data) {
                ArticlePicker.data[$id].data = data;
                ArticlePicker.data[$id].ready = true;

                // Call self again as we are done here
                ArticlePicker.initArticlePicker(el);

                // Looping through all the callbacks that we got while waiting for data
                ArticlePicker.data[$id].callbacks.forEach(function(current) {
                    ArticlePicker.initArticlePicker(current);
                });
            });
        } else {
            // There is already something, next up; we find what it is
            if (ArticlePicker.data[$id].ready) {
                // We have data. We are using it here
                var items = [];
                var $sel = '';
                var data = ArticlePicker.data[$id].data;

                jQuery.each(data, function(key, val) {
                    $sel = '';
                    if ($val == val.id) {
                        $sel = 'selected="selected"';
                    }
                    items.push('<option value="' + val.id + '" ' + $sel + '>' + val.title + '</option>');
                });

                var $html = items.join('');
                jQuery($html).appendTo(el);
            } else {
                // We don't have data. But someone is already trying to fetch it. Be nice and ask them to call back when ready
                // TODO find out if there is any, even remote possibility that the first fetch might be done before all of these callbacks have been set
                ArticlePicker.data[$id].callbacks.push(el);
            }
        }
    }
}
<|endoftext|>


<commit_before>define([
    '/bower_components/jquery/dist/jquery.min.js',
    '/assert/hyperjson.js', // serializing classes as an attribute
    '/assert/hyperscript.js', // using setAttribute
    '/common/TextPatcher.js'
], function (jQuery, Hyperjson, Hyperscript, TextPatcher) {
    var $ = window.jQuery;
    window.Hyperjson = Hyperjson;
    window.Hyperscript = Hyperscript;
    window.TextPatcher = TextPatcher;

    var assertions = 0;
    var failed = false;
    var failedOn;
    var failMessages = [];

    var ASSERTS = [];
    var runASSERTS = function () {
        ASSERTS.forEach(function (f, index) {
            f(index);
        });
    };

    var assert = function (test, msg) {
        ASSERTS.push(function (i) {
            if (test()) {
                assertions++;
            } else {
                failed = true;
                failedOn = assertions;
                failMessages.push({
                    test: i,
                    message: msg
                });
            }
        });
    };

    var $body = $('body');

    var roundTrip = function (target) {
        assert(function () {
            var hjson = Hyperjson.fromDOM(target);
            var cloned = Hyperjson.callOn(hjson, Hyperscript);

            var success = cloned.outerHTML === target.outerHTML;

            if (!success) {
                var op = TextPatcher.diff(target.outerHTML, cloned.outerHTML);
                window.DEBUG = {
                    error: "Expected equality between A and B",
                    A: target.outerHTML,
                    B: cloned.outerHTML,
                    diff: op
                };
                console.log(JSON.stringify(window.DEBUG, null, 2));
                TextPatcher.log(op);
            }

            return success;
        }, "Round trip serialization introduced artifacts.");
    };

    [   '#target',
        '#widget',
        '#quot',
    ].forEach(function (sel) {
        roundTrip($(sel)[0]);
    });

    var strungJSON = function (orig) {
        var result;
        assert(function () {
            result = JSON.stringify(JSON.parse(orig));
            return result === orig;
        }, "expected result (" + result + ") to equal original (" + orig + ")");
    };

    [   '{"border":"1","style":{"width":"500px"}}',
        '{"style":{"width":"500px"},"border":"1"}',
    ].forEach(function (orig) {
        strungJSON(orig);
    });

    //assert(function () { }, "this is expected to fail");

    /*  TODO Test how browsers handle weird elements
        like "_moz-resizing":"true"

        and anything else you can think of.

        Start with Hyperjson, turn it into a DOM and come back
    */

    var swap = function (str, dict) {
        return str.replace(/\{\{(.*?)\}\}/g, function (all, key) {
            return typeof dict[key] !== 'undefined'? dict[key] : all;
        });
    };

    var multiline = function (f) {
        var str;
        f.toString().replace(/\/\*([\s\S]*)\*\//g, function (all, out) {
            str = out;
        });
        return str || '';
    };

    var formatFailures = function () {
        var template = multiline(function () { /*

Failed on test number {{test}} with error:
> "{{message}}"

*/});
        return failMessages.map(function (obj) {
            console.log(obj);
            return swap(template, obj);
        }).join("\n");
    };

    runASSERTS();

    $("body").html(function (i, val) {
        var dict = {
            previous: val,
            totalAssertions: ASSERTS.length,
            passedAssertions: assertions,
            plural: (assertions === 1? '' : 's'),
            failMessages: formatFailures()
        };

        var SUCCESS = swap(multiline(function(){/*

{{passedAssertions}} / {{totalAssertions}} test{{plural}} passed.

{{failMessages}}

{{previous}}
        */}), dict);

        var report = SUCCESS;

        return report;
    });

    var $report = $('.report');
    $report.addClass(failed?'failure':'success');

});
<commit_msg>use hyperscript and hyperjson from common<commit_after>define([
    '/bower_components/jquery/dist/jquery.min.js',
    '/common/hyperjson.js', // serializing classes as an attribute
    '/common/hyperscript.js', // using setAttribute
    '/common/TextPatcher.js'
], function (jQuery, Hyperjson, Hyperscript, TextPatcher) {
    var $ = window.jQuery;
    window.Hyperjson = Hyperjson;
    window.Hyperscript = Hyperscript;
    window.TextPatcher = TextPatcher;

    var assertions = 0;
    var failed = false;
    var failedOn;
    var failMessages = [];

    var ASSERTS = [];
    var runASSERTS = function () {
        ASSERTS.forEach(function (f, index) {
            f(index);
        });
    };

    var assert = function (test, msg) {
        ASSERTS.push(function (i) {
            if (test()) {
                assertions++;
            } else {
                failed = true;
                failedOn = assertions;
                failMessages.push({
                    test: i,
                    message: msg
                });
            }
        });
    };

    var $body = $('body');

    var roundTrip = function (target) {
        assert(function () {
            var hjson = Hyperjson.fromDOM(target);
            var cloned = Hyperjson.callOn(hjson, Hyperscript);

            var success = cloned.outerHTML === target.outerHTML;

            if (!success) {
                var op = TextPatcher.diff(target.outerHTML, cloned.outerHTML);
                window.DEBUG = {
                    error: "Expected equality between A and B",
                    A: target.outerHTML,
                    B: cloned.outerHTML,
                    diff: op
                };
                console.log(JSON.stringify(window.DEBUG, null, 2));
                TextPatcher.log(op);
            }

            return success;
        }, "Round trip serialization introduced artifacts.");
    };

    [   '#target',
        '#widget',
        '#quot',
    ].forEach(function (sel) {
        roundTrip($(sel)[0]);
    });

    var strungJSON = function (orig) {
        var result;
        assert(function () {
            result = JSON.stringify(JSON.parse(orig));
            return result === orig;
        }, "expected result (" + result + ") to equal original (" + orig + ")");
    };

    [   '{"border":"1","style":{"width":"500px"}}',
        '{"style":{"width":"500px"},"border":"1"}',
    ].forEach(function (orig) {
        strungJSON(orig);
    });

    //assert(function () { }, "this is expected to fail");

    /*  TODO Test how browsers handle weird elements
        like "_moz-resizing":"true"

        and anything else you can think of.

        Start with Hyperjson, turn it into a DOM and come back
    */

    var swap = function (str, dict) {
        return str.replace(/\{\{(.*?)\}\}/g, function (all, key) {
            return typeof dict[key] !== 'undefined'? dict[key] : all;
        });
    };

    var multiline = function (f) {
        var str;
        f.toString().replace(/\/\*([\s\S]*)\*\//g, function (all, out) {
            str = out;
        });
        return str || '';
    };

    var formatFailures = function () {
        var template = multiline(function () { /*

Failed on test number {{test}} with error:
> "{{message}}"

*/});
        return failMessages.map(function (obj) {
            console.log(obj);
            return swap(template, obj);
        }).join("\n");
    };

    runASSERTS();

    $("body").html(function (i, val) {
        var dict = {
            previous: val,
            totalAssertions: ASSERTS.length,
            passedAssertions: assertions,
            plural: (assertions === 1? '' : 's'),
            failMessages: formatFailures()
        };

        var SUCCESS = swap(multiline(function(){/*

{{passedAssertions}} / {{totalAssertions}} test{{plural}} passed.

{{failMessages}}

{{previous}}
        */}), dict);

        var report = SUCCESS;

        return report;
    });

    var $report = $('.report');
    $report.addClass(failed?'failure':'success');

});
<|endoftext|>


<commit_before>'use strict';

const Command = require('../../Command.js');
const SyndicateEmbed = require('../../embeds/SyndicateEmbed.js');

const values = ['all', 'Arbiters of Hexis', 'Perrin Sequence', 'Cephalon Suda', 'Steel Meridian', 'New Loka', 'Red Veil'];

/**
 * Displays the currently active Invasions
 */
class Syndicates extends Command {
  /**
   * Constructs a callable command
   * @param {Genesis} bot  The bot object
   */
  constructor(bot) {
    super(bot, 'warframe.worldstate.syndicate', 'syndicate', 'Gets the starchat nodes for the desired syndicate, or all.');
    this.regex = new RegExp(`^${this.call}s?(?:(${values.join('|')}))?(?:\\s+on\\s+([pcsxb14]{2,3}))?$`, 'i');
    this.usages = [
      {
        description: 'Display syndicate nodes for a syndicate.',
        parameters: ['syndicate'],
      },
    ];
  }

  async run(message) {
    const matches = message.strippedContent.match(this.regex);
    const param1 = (matches[1] || '').toLowerCase();
    const param2 = (matches[2] || '').toLowerCase();
    const syndicate = values.indexOf(param1) > -1 ? param1 : 'all';
    let platformParam;
    if (this.platforms.indexOf(param2) > -1) {
      platformParam = param2;
    } else if (this.platforms.indexOf(param1) > -1) {
      platformParam = param1;
    }
    const platform = platformParam || await this.bot.settings.getChannelSetting(message.channel, 'platform');
    const ws = await this.bot.caches[platform.toLowerCase()].getDataJson();
    await this.messageManager.embed(message, new SyndicateEmbed(
      this.bot,
      ws.syndicateMissions, syndicate, platform,
    ), true, false);
    return this.messageManager.statuses.SUCCESS;
  }
}

module.exports = Syndicates;
<commit_msg>Update Syndicates.js<commit_after>'use strict';

const Command = require('../../Command.js');
const SyndicateEmbed = require('../../embeds/SyndicateEmbed.js');

const values = ['all', 'Arbiters of Hexis', 'Perrin Sequence', 'Cephalon Suda', 'Steel Meridian', 'New Loka', 'Red Veil', 'Ostrons', 'Assassins'];

/**
 * Displays the currently active Invasions
 */
class Syndicates extends Command {
  /**
   * Constructs a callable command
   * @param {Genesis} bot  The bot object
   */
  constructor(bot) {
    super(bot, 'warframe.worldstate.syndicate', 'syndicate', 'Gets the starchat nodes for the desired syndicate, or all.');
    this.regex = new RegExp(`^${this.call}s?(?:(${values.join('|')}))?(?:\\s+on\\s+([pcsxb14]{2,3}))?$`, 'i');
    this.usages = [
      {
        description: 'Display syndicate nodes for a syndicate.',
        parameters: ['syndicate'],
      },
    ];
  }

  async run(message) {
    const matches = message.strippedContent.match(this.regex);
    const param1 = (matches[1] || '').toLowerCase();
    const param2 = (matches[2] || '').toLowerCase();
    const syndicate = values.indexOf(param1) > -1 ? param1 : 'all';
    let platformParam;
    if (this.platforms.indexOf(param2) > -1) {
      platformParam = param2;
    } else if (this.platforms.indexOf(param1) > -1) {
      platformParam = param1;
    }
    const platform = platformParam || await this.bot.settings.getChannelSetting(message.channel, 'platform');
    const ws = await this.bot.caches[platform.toLowerCase()].getDataJson();
    await this.messageManager.embed(message, new SyndicateEmbed(
      this.bot,
      ws.syndicateMissions, syndicate, platform,
    ), true, false);
    return this.messageManager.statuses.SUCCESS;
  }
}

module.exports = Syndicates;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var QProject = Model.create({
  name: 'QProject',

  tableProperties: [
    'projectName',
    'baseURL'
  ],

  properties: [
    {
      name: 'qbug',
    },
    {
      name: 'project',
    },
    {
      name: 'baseURL',
      defaultValue: 'https://code.google.com/p/'
    },
    {
      name: 'projectName',
      scope: 'project',
      defaultValueFn: function() { return this.project.name; }
    },
    {
      name: 'summary',
      scope: 'project',
      defaultValueFn: function() { return this.project.summary; }
    },
    {
      name: 'user',
      scope: 'qbug',
      defaultValueFn: function() { return this.qbug.user; }
    },
    {
      name: 'IssueCommentNetworkDAO',
      valueFactory: function() {
        return QIssueCommentNetworkDAO.create({
          model: QIssueComment,
          url: 'https://www.googleapis.com/projecthosting/v2/projects/' + this.projectName + '/issues',
        });
      }
    },
    {
      name: 'IssueMDAO',
      valueFactory: function() {
        var dao = MDAO.create({model: QIssue});
        var auto = AutoIndex.create(dao);

        auto.addIndex(QIssue.STATUS);
        dao.addRawIndex(auto);

        return dao;
      }
    },
    {
      name: 'IssueCachingDAO',
      valueFactory: function() {
        var IssueIDBDAO = IDBDAO.create({
          model: QIssue,
          name: this.projectName + '_' + QIssue.plural
        });

        return CachingDAO.create(this.IssueMDAO, IssueIDBDAO);
      },
      transient: true
    },
    {
      name: 'IssueNetworkDAO',
      valueFactory: function() {
        return IssueRestDAO.create({
          url: 'https://www.googleapis.com/projecthosting/v2/projects/' + this.projectName + '/issues',
          model: QIssue
        });
      },
      transient: true
    },
    {
      name: 'IssueDAO',
      valueFactory: function() {
        var dao = this.IssueMDAO;

        dao = QIssueSplitDAO.create({
          local: dao,
          model: QIssue,
          remote: this.IssueNetworkDAO
        });

        dao = ActionFactoryDAO.create({
          delegate: dao,
          actionDao: this.IssueCommentNetworkDAO
        });

        dao = QIssueStarringDAO.create({
          delegate: dao,
          project: this,
          url: 'https://www.googleapis.com/projecthosting/v2/projects/' + this.projectName + '/issues'
        });

        return dao;
      },
      transient: true
    },
    {
      mode_: 'IntegerProperty',
      name: 'issueCount'
    },
    {
      name: 'url',
      defaultValueFn: function() { return this.baseURL + this.projectName; }
    },
    {
      name: 'timer',
      valueFactory: function() { return Timer.create(); },
      transient: true
    },
    {
      name: 'syncManager',
      valueFactory: function() {
        return SyncManager.create({
          syncInterval: 60*5,
          batchSize: 500,
          queryParser: QueryParser,
//          query: 'status=New,Accepted,Started OR\nupdated-after:today-60 OR\nis:starred',
          srcDAO: this.IssueNetworkDAO,
          dstDAO: this.IssueCachingDAO,
          lastModified: new Date(2014,01,01),
          modifiedProperty: QIssue.MODIFIED
        });
      }
    }
  ],

  listeners: [
    {
      model_: 'Method',
      name: 'onDAOUpdate',
      animate: true,
      code: function(evt) {
        var self = this;
        this.IssueMDAO.select(COUNT())(function (c) { self.issueCount = c.count; });
      }
    }
  ],

  methods: {
    init: function() {
      this.SUPER();

      this.IssueDAO.listen(this.onDAOUpdate);
    },

    /** Open a Browser in a Window for a Chome Packaged App. **/
    launchBrowser: function(opt_url) {
      var self = this;

      chrome.app.window.create('empty.html', {width: 1000, height: 800}, function(w) {
        w.contentWindow.onload = function() {
          var window = self.window = w.contentWindow;

          apar(
            arequire('GridView'),
            arequire('QIssueTileView'),
            arequire('Browser'),
            arequire('QIssuePreviewView'),
            arequire('QIssueCommentView'),
            arequire('QIssueCommentAuthorView'),
            arequire('QIssueCommentUpdateView'),
            arequire('ConfigureProjectsView')
          )(function () {
            $addWindow(window);
            var b = ChromeAppBrowser.create({project: self, window: window});
            window.browser = b; // for debugging
            BROWSERS.push(b); // for debugging
            w.browser = b;
            window.document.firstChild.innerHTML = b.toHTML();
            b.initHTML();
            if ( opt_url ) b.maybeImportCrbugUrl(opt_url);
            w.focus();
          });
        };

        w.onClosed.addListener(function() {
          $removeWindow(self.window);
          // for debugging
          BROWSERS.deleteI(self.window);
        });
      });
    },

    /** Create a Browser for use in a hosted app. **/
    createBrowser: function(window) {
      var b = Browser.create({project: this, window: window});
      window.browser = b;
      return b;
    },

    launchSync: function() {
      var self = this;

      chrome.app.window.create('empty.html', {width: 600, height: 600}, function(w) {
        var window = w.contentWindow;
        w.contentWindow.onload = function() {
          $addWindow(window);
          var b = ActionBorder.create(
            SyncManager,
            DetailView.create({
              model: SyncManager,
              title: ' Sync Config: ' + self.projectName,
              value: SimpleValue.create(self.syncManager)}));
          window.document.body.innerHTML = '
' + b.toHTML() + '
';
          b.initHTML();
          var extrax = window.outerWidth - window.innerWidth + 16;
          var extray = window.outerHeight - window.innerHeight + 16;

          window.resizeTo(
            window.document.body.firstChild.firstChild.firstChild.offsetWidth + extrax,
            window.document.body.firstChild.offsetHeight + extray);
          window.resizeTo(
            window.document.body.firstChild.firstChild.firstChild.offsetWidth + extrax,
            window.document.body.firstChild.offsetHeight + extray);
          w.focus();
        };
        w.onClosed.addListener(function() {
          $removeWindow(window);
        });
      });
    },

    launchConfigProjects: function() {
      var self = this;

      chrome.app.window.create('empty.html', {width: 430, height: 440}, function(w) {
        var window = w.contentWindow;
        w.contentWindow.onload = function() {
          $addWindow(window);

          var view = ConfigureProjectsView.create({ model: QUser });
          view.value.set(self.user);

          window.document.body.innerHTML = view.toHTML();
          view.initHTML();

          w.focus();
        };
        w.onClosed.addListener(function() {
          $removeWindow(window);
        });
      });
    },

    issueCommentDAO: function(id) {
      return this.IssueCommentNetworkDAO.where(EQ(QIssueComment.ISSUE_ID, id));
    }
  },

});
<commit_msg>Set the network dao to batch size of 500, since that's split dao and sync manager request.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var QProject = Model.create({
  name: 'QProject',

  tableProperties: [
    'projectName',
    'baseURL'
  ],

  properties: [
    {
      name: 'qbug',
    },
    {
      name: 'project',
    },
    {
      name: 'baseURL',
      defaultValue: 'https://code.google.com/p/'
    },
    {
      name: 'projectName',
      scope: 'project',
      defaultValueFn: function() { return this.project.name; }
    },
    {
      name: 'summary',
      scope: 'project',
      defaultValueFn: function() { return this.project.summary; }
    },
    {
      name: 'user',
      scope: 'qbug',
      defaultValueFn: function() { return this.qbug.user; }
    },
    {
      name: 'IssueCommentNetworkDAO',
      valueFactory: function() {
        return QIssueCommentNetworkDAO.create({
          model: QIssueComment,
          url: 'https://www.googleapis.com/projecthosting/v2/projects/' + this.projectName + '/issues',
        });
      }
    },
    {
      name: 'IssueMDAO',
      valueFactory: function() {
        var dao = MDAO.create({model: QIssue});
        var auto = AutoIndex.create(dao);

        auto.addIndex(QIssue.STATUS);
        dao.addRawIndex(auto);

        return dao;
      }
    },
    {
      name: 'IssueCachingDAO',
      valueFactory: function() {
        var IssueIDBDAO = IDBDAO.create({
          model: QIssue,
          name: this.projectName + '_' + QIssue.plural
        });

        return CachingDAO.create(this.IssueMDAO, IssueIDBDAO);
      },
      transient: true
    },
    {
      name: 'IssueNetworkDAO',
      valueFactory: function() {
        return IssueRestDAO.create({
          url: 'https://www.googleapis.com/projecthosting/v2/projects/' + this.projectName + '/issues',
          model: QIssue,
          batchSize: 500
        });
      },
      transient: true
    },
    {
      name: 'IssueDAO',
      valueFactory: function() {
        var dao = this.IssueMDAO;

        dao = QIssueSplitDAO.create({
          local: dao,
          model: QIssue,
          remote: this.IssueNetworkDAO
        });

        dao = ActionFactoryDAO.create({
          delegate: dao,
          actionDao: this.IssueCommentNetworkDAO
        });

        dao = QIssueStarringDAO.create({
          delegate: dao,
          project: this,
          url: 'https://www.googleapis.com/projecthosting/v2/projects/' + this.projectName + '/issues'
        });

        return dao;
      },
      transient: true
    },
    {
      mode_: 'IntegerProperty',
      name: 'issueCount'
    },
    {
      name: 'url',
      defaultValueFn: function() { return this.baseURL + this.projectName; }
    },
    {
      name: 'timer',
      valueFactory: function() { return Timer.create(); },
      transient: true
    },
    {
      name: 'syncManager',
      valueFactory: function() {
        return SyncManager.create({
          syncInterval: 60*5,
          batchSize: 500,
          queryParser: QueryParser,
//          query: 'status=New,Accepted,Started OR\nupdated-after:today-60 OR\nis:starred',
          srcDAO: this.IssueNetworkDAO,
          dstDAO: this.IssueCachingDAO,
          lastModified: new Date(2014,01,01),
          modifiedProperty: QIssue.MODIFIED
        });
      }
    }
  ],

  listeners: [
    {
      model_: 'Method',
      name: 'onDAOUpdate',
      animate: true,
      code: function(evt) {
        var self = this;
        this.IssueMDAO.select(COUNT())(function (c) { self.issueCount = c.count; });
      }
    }
  ],

  methods: {
    init: function() {
      this.SUPER();

      this.IssueDAO.listen(this.onDAOUpdate);
    },

    /** Open a Browser in a Window for a Chome Packaged App. **/
    launchBrowser: function(opt_url) {
      var self = this;

      chrome.app.window.create('empty.html', {width: 1000, height: 800}, function(w) {
        w.contentWindow.onload = function() {
          var window = self.window = w.contentWindow;

          apar(
            arequire('GridView'),
            arequire('QIssueTileView'),
            arequire('Browser'),
            arequire('QIssuePreviewView'),
            arequire('QIssueCommentView'),
            arequire('QIssueCommentAuthorView'),
            arequire('QIssueCommentUpdateView'),
            arequire('ConfigureProjectsView')
          )(function () {
            $addWindow(window);
            var b = ChromeAppBrowser.create({project: self, window: window});
            window.browser = b; // for debugging
            BROWSERS.push(b); // for debugging
            w.browser = b;
            window.document.firstChild.innerHTML = b.toHTML();
            b.initHTML();
            if ( opt_url ) b.maybeImportCrbugUrl(opt_url);
            w.focus();
          });
        };

        w.onClosed.addListener(function() {
          $removeWindow(self.window);
          // for debugging
          BROWSERS.deleteI(self.window);
        });
      });
    },

    /** Create a Browser for use in a hosted app. **/
    createBrowser: function(window) {
      var b = Browser.create({project: this, window: window});
      window.browser = b;
      return b;
    },

    launchSync: function() {
      var self = this;

      chrome.app.window.create('empty.html', {width: 600, height: 600}, function(w) {
        var window = w.contentWindow;
        w.contentWindow.onload = function() {
          $addWindow(window);
          var b = ActionBorder.create(
            SyncManager,
            DetailView.create({
              model: SyncManager,
              title: ' Sync Config: ' + self.projectName,
              value: SimpleValue.create(self.syncManager)}));
          window.document.body.innerHTML = '
' + b.toHTML() + '
';
          b.initHTML();
          var extrax = window.outerWidth - window.innerWidth + 16;
          var extray = window.outerHeight - window.innerHeight + 16;

          window.resizeTo(
            window.document.body.firstChild.firstChild.firstChild.offsetWidth + extrax,
            window.document.body.firstChild.offsetHeight + extray);
          window.resizeTo(
            window.document.body.firstChild.firstChild.firstChild.offsetWidth + extrax,
            window.document.body.firstChild.offsetHeight + extray);
          w.focus();
        };
        w.onClosed.addListener(function() {
          $removeWindow(window);
        });
      });
    },

    launchConfigProjects: function() {
      var self = this;

      chrome.app.window.create('empty.html', {width: 430, height: 440}, function(w) {
        var window = w.contentWindow;
        w.contentWindow.onload = function() {
          $addWindow(window);

          var view = ConfigureProjectsView.create({ model: QUser });
          view.value.set(self.user);

          window.document.body.innerHTML = view.toHTML();
          view.initHTML();

          w.focus();
        };
        w.onClosed.addListener(function() {
          $removeWindow(window);
        });
      });
    },

    issueCommentDAO: function(id) {
      return this.IssueCommentNetworkDAO.where(EQ(QIssueComment.ISSUE_ID, id));
    }
  },

});
<|endoftext|>


<commit_before>// Eloquent JavaScript

// Run this file in your terminal using `node my_solution.js`. Make sure it works before moving on!

// Program Structure
// Write your own variable and do something to it.
var num = 3;
num = num + 3;
console.log(num);
// => 6

// Complete one of the exercises: Looping a Triangle, FizzBuzz, or Chess Board
var tri = "";
for (var counter = 0; counter < 7; counter += 1){
  tri += "#";
  console.log(tri);

// Functions

// Complete the `minimum` exercise.

// Data Structures: Objects and Arrays
// Create an object called "me" that stores your name, age, 3 favorite foods, and a quirk below.
var me = {name: "Susan", age: "25", quirk: "I am a triplet"};
console.log(me["quirk"])<commit_msg>Update eloquent.js<commit_after>// Eloquent JavaScript

// Run this file in your terminal using `node my_solution.js`. Make sure it works before moving on!

// Program Structure
// Write your own variable and do something to it.
var num = 3;
num = num + 3;
console.log(num);
// => 6

// Complete one of the exercises: Looping a Triangle, FizzBuzz, or Chess Board
var tri = "";
for (var counter = 0; counter < 7; counter += 1){
  tri += "#";
  console.log(tri);

// Functions

// Complete the `minimum` exercise.
function min(num1, num2){
	if (num1 < num2)
		return num1;
	else
		return num2;

// Data Structures: Objects and Arrays
// Create an object called "me" that stores your name, age, 3 favorite foods, and a quirk below.
var me = {name: "Susan", age: "25", quirk: "I am a triplet"};
console.log(me["quirk"])
<|endoftext|>


<commit_before>var SERVER_SERVICE_USE_PORT = false;
var SERVER_SERVICE_USE_PROXY = true;

(function() {
  var module = angular.module('loom_server_service', []);

  // Private Variables
  var servers = [];

  var rootScope_ = null;
  var service_ = null;
  var dialogService_ = null;
  var translate_ = null;
  var http_ = null;
  var location_ = null;
  var configService_ = null;
  var q_ = null;
  var serverCount = 0;

  module.provider('serverService', function() {
    this.$get = function($rootScope, $http, $q, $location, $translate, dialogService, configService) {
      service_ = this;
      rootScope_ = $rootScope;
      dialogService_ = dialogService;
      translate_ = $translate;
      http_ = $http;
      location_ = $location;
      configService_ = configService;
      configService_.serverList = servers;
      q_ = $q;

      return this;
    };

    this.getServers = function() {
      return servers;
    };

    this.getServerById = function(id) {
      var server = null;

      if (!goog.isDefAndNotNull(id)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server id.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].id === id) {
          server = servers[index];
          break;
        }
      }

      //console.log('----[ returning server id: ', id, ', server: ', server);
      return server;
    };

    this.getServerIndex = function(id) {

      if (!goog.isDefAndNotNull(id)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server id.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].id === id) {
          return index;
        }
      }

      return -1;
    };

    this.getServerByPtype = function(ptype) {
      var server = null;

      if (!goog.isDefAndNotNull(ptype)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server ptype.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].ptype === ptype) {
          server = servers[index];
          break;
        }
      }

      //console.log('----[ returning server ptype: ', ptype, ', server: ', server);
      return server;
    };

    this.getServerByName = function(name) {
      var server = null;

      if (!goog.isDefAndNotNull(name)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server name.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].name.toLocaleLowerCase() === name.toLowerCase()) {
          server = servers[index];
          break;
        }
      }

      //console.log('----[ returning server with name: ', name, ', server: ', server);
      return server;
    };

    this.getServerLocalGeoserver = function() {
      var server = null;
      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].isLocal === true) {
          server = servers[index];
          break;
        }
      }
      return server;
    };

    this.changeCredentials = function(server) {
      var deferredResponse = q_.defer();
      var doWork = function() {
        service_.populateLayersConfig(server, true)
            .then(function(response) {
              deferredResponse.resolve(server);
            }, function(reject) {
              deferredResponse.reject(server, reject);
            });
      };

      if (goog.isDefAndNotNull(server.url)) {
        if (server.url.indexOf(location_.host()) === -1) {
          dialogService_.promptCredentials(server.url, true).then(function(credentials) {
            server.username = credentials.username;
            server.authentication = $.base64.encode(credentials.username + ':' + credentials.password);
            doWork();
          }, function(reject) {
            if (goog.isDefAndNotNull(reject) && reject.anonymous) {
              server.username = translate_('anonymous');
              server.authentication = undefined;
              doWork();
            }
          });
        } else {
          server.username = configService_.username;
          server.isLocal = true;
          doWork();
        }
      } else {
        doWork();
      }
      return deferredResponse.promise;
    };

    this.addServer = function(serverInfo) {
      var deferredResponse = q_.defer();

      // save the config object on the server object so that when we save the server, we only pass the config as opposed
      // to anything else that the app ads to the server objects.
      var server = {id: null, ptype: 'gxp_olsource', config: serverInfo, populatingLayersConfig: false};

      goog.object.extend(server, serverInfo, {});

      var doWork = function() {
        console.log('---- MapService.layerInfo. trying to add server: ', server);
        service_.populateLayersConfig(server)
            .then(function(response) {
              // set the id. it should always resolve to the length
              server.id = serverCount++;
              servers.push(server);
              rootScope_.$broadcast('server-added', server.id);
              deferredResponse.resolve(server);
            }, function(reject) {
              deferredResponse.reject(server, reject);
            });
      };

      if (goog.isDefAndNotNull(server.url)) {
        if (server.url.indexOf(location_.host()) === -1) {
          dialogService_.promptCredentials(server.url, false).then(function(credentials) {
            server.username = credentials.username;
            server.authentication = $.base64.encode(credentials.username + ':' + credentials.password);
            doWork();
          }, function(reject) {
            server.username = translate_('anonymous');
            server.authentication = undefined;
            doWork();
          });
        } else {
          server.username = configService_.username;
          server.isLocal = true;
          server.name = translate_('local_geoserver');
          doWork();
        }
      } else {
        doWork();
      }

      return deferredResponse.promise;
    };

    this.removeServer = function(id) {
      var serverIndex = -1;
      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].id === id) {
          serverIndex = index;
          break;
        }
      }
      if (serverIndex > -1) {
        var server = servers.splice(serverIndex, 1)[0];
        rootScope_.$broadcast('server-removed', server);
      }
    };

    this.configDefaultServers = function() {
      var config = null;
      console.log('----- Configuring default servers.');

      if (!goog.isDefAndNotNull(service_.getServerByPtype('gxp_bingsource'))) {
        config = {ptype: 'gxp_bingsource', name: 'Bing', defaultServer: true};
        service_.addServer(config);
      } else {
        service_.getServerByPtype('gxp_bingsource').defaultServer = true;
      }

      if (!goog.isDefAndNotNull(service_.getServerByPtype('gxp_mapquestsource'))) {
        config = {ptype: 'gxp_mapquestsource', name: 'MapQuest', defaultServer: true};
        service_.addServer(config);
      } else {
        service_.getServerByPtype('gxp_mapquestsource').defaultServer = true;
      }

      if (!goog.isDefAndNotNull(service_.getServerByPtype('gxp_osmsource'))) {
        config = {ptype: 'gxp_osmsource', name: 'OpenStreetMap', defaultServer: true};
        service_.addServer(config);
      } else {
        service_.getServerByPtype('gxp_osmsource').defaultServer = true;
      }
      if (goog.isDefAndNotNull(service_.getServerLocalGeoserver())) {
        service_.getServerLocalGeoserver().defaultServer = true;
      }
    };

    this.getLayersConfig = function(serverId) {
      var server = service_.getServerById(serverId);
      if (goog.isDefAndNotNull(server)) {
        return server.layersConfig;
      }
    };

    this.getLayerConfig = function(serverId, layerName) {
      var layersConfig = service_.getLayersConfig(serverId);
      var layerConfig = null;

      for (var index = 0; index < layersConfig.length; index += 1) {
        if (layersConfig[index].Name === layerName) {
          layerConfig = layersConfig[index];
          break;
        }
      }

      console.log('---- ServerService.getLayerConfig: ', layerConfig);
      return layerConfig;
    };

    this.populateLayersConfig = function(server, force) {
      var deferredResponse = q_.defer();
      console.log('---- ServerService.populateLayersConfig. server', server);

      if (!goog.isDefAndNotNull(server)) {
        //TODO: make sure it is okay to reject and then return the promise
        deferredResponse.reject();
        return deferredResponse.promise;
      }

      if (!goog.isDefAndNotNull(server.layersConfig) ||
          (goog.isDefAndNotNull(force) && force)) {

        // clear out layers config
        server.layersConfig = [];

        if (server.ptype === 'gxp_bingsource') {
          server.layersConfig = [
            {Title: 'BingRoad', Name: 'BingRoad', sourceParams: {imagerySet: 'Road'}},
            {Title: 'BingAerial', Name: 'BingAerial', sourceParams: {imagerySet: 'Aerial'}},
            {Title: 'BingAerialWithLabels', Name: 'BingAerialWithLabels',
              sourceParams: {imagerySet: 'AerialWithLabels'}},
            {Title: 'BingCollinsBart', Name: 'BingCollinsBart', sourceParams: {imagerySet: 'collinsBart'}},
            {Title: 'BingSurvey', Name: 'BingSurvey', sourceParams: {imagerySet: 'ordnanceSurvey'}}
          ];
          deferredResponse.resolve(server);
        } else if (server.ptype === 'gxp_mapquestsource') {
          server.layersConfig = [
            {Title: 'MapQuestSat', Name: 'MapQuestSat', sourceParams: {layer: 'sat'}},
            {Title: 'MapQuestHybrid', Name: 'MapQuestHybrid', sourceParams: {layer: 'hyb'}},
            {Title: 'MapQuestOSM', Name: 'MapQuestOSM', sourceParams: {layer: 'osm'}}
          ];
          deferredResponse.resolve(server);
        } else if (server.ptype === 'gxp_osmsource') {
          server.layersConfig = [
            {Title: 'OpenStreetMap', Name: 'mapnik'}
          ];
          deferredResponse.resolve(server);
        } else if (server.ptype === 'gxp_wmscsource' ||
            server.ptype === 'gxp_tmssource') { // currently, if it is a tms endpoint, assume it has wmsgetcapabilities
          console.log('---- ServerService.Sending GetCapabilities.server: ', server);
          if (!goog.isDefAndNotNull(server.url)) {
            dialogService_.error(translate_('error'), translate_('server_url_not_specified'));
            deferredResponse.reject(server);
          } else {
            var parser = new ol.format.WMSCapabilities();
            var url = server.url + '?SERVICE=WMS&REQUEST=GetCapabilities';
            server.populatingLayersConfig = true;
            var config = {};
            config.headers = {};
            if (goog.isDefAndNotNull(server.authentication)) {
              config.headers['Authorization'] = 'Basic ' + server.authentication;
            } else {
              config.headers['Authorization'] = '';
            }
            // server hasn't been added yet, so specify the auth headers here
            http_.get(url, config).then(function(xhr) {
              if (xhr.status === 200) {
                var response = parser.read(xhr.data);
                if (goog.isDefAndNotNull(response.Capability) &&
                    goog.isDefAndNotNull(response.Capability.Layer)) {
                  server.layersConfig = response.Capability.Layer.Layer;
                  console.log('---- populateLayersConfig.populateLayersConfig server', server);
                  rootScope_.$broadcast('layers-loaded', server.id);
                  deferredResponse.resolve(server);
                } else {
                  deferredResponse.reject(server);
                }
                server.populatingLayersConfig = false;
              } else {
                deferredResponse.reject(server);
                server.populatingLayersConfig = false;
              }
            }, function(xhr) {
              deferredResponse.reject(server);
              server.populatingLayersConfig = false;
            });
          }
        }
      }

      return deferredResponse.promise;
    };

  });
}());
<commit_msg>get the basic auth ball rolling for non-proxy requests.<commit_after>var SERVER_SERVICE_USE_PORT = false;
var SERVER_SERVICE_USE_PROXY = true;

(function() {
  var module = angular.module('loom_server_service', []);

  // Private Variables
  var servers = [];

  var rootScope_ = null;
  var service_ = null;
  var dialogService_ = null;
  var translate_ = null;
  var http_ = null;
  var location_ = null;
  var configService_ = null;
  var q_ = null;
  var serverCount = 0;

  module.provider('serverService', function() {
    this.$get = function($rootScope, $http, $q, $location, $translate, dialogService, configService) {
      service_ = this;
      rootScope_ = $rootScope;
      dialogService_ = dialogService;
      translate_ = $translate;
      http_ = $http;
      location_ = $location;
      configService_ = configService;
      configService_.serverList = servers;
      q_ = $q;

      return this;
    };

    this.getServers = function() {
      return servers;
    };

    this.getServerById = function(id) {
      var server = null;

      if (!goog.isDefAndNotNull(id)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server id.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].id === id) {
          server = servers[index];
          break;
        }
      }

      //console.log('----[ returning server id: ', id, ', server: ', server);
      return server;
    };

    this.getServerIndex = function(id) {

      if (!goog.isDefAndNotNull(id)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server id.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].id === id) {
          return index;
        }
      }

      return -1;
    };

    this.getServerByPtype = function(ptype) {
      var server = null;

      if (!goog.isDefAndNotNull(ptype)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server ptype.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].ptype === ptype) {
          server = servers[index];
          break;
        }
      }

      //console.log('----[ returning server ptype: ', ptype, ', server: ', server);
      return server;
    };

    this.getServerByName = function(name) {
      var server = null;

      if (!goog.isDefAndNotNull(name)) {
        throw ({
          name: 'serverService',
          level: 'High',
          message: 'undefined server name.',
          toString: function() {
            return this.name + ': ' + this.message;
          }
        });
      }

      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].name.toLocaleLowerCase() === name.toLowerCase()) {
          server = servers[index];
          break;
        }
      }

      //console.log('----[ returning server with name: ', name, ', server: ', server);
      return server;
    };

    this.getServerLocalGeoserver = function() {
      var server = null;
      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].isLocal === true) {
          server = servers[index];
          break;
        }
      }
      return server;
    };

    this.changeCredentials = function(server) {
      var deferredResponse = q_.defer();
      var doWork = function() {
        service_.populateLayersConfig(server, true)
            .then(function(response) {
              deferredResponse.resolve(server);
            }, function(reject) {
              deferredResponse.reject(server, reject);
            });
      };

      if (goog.isDefAndNotNull(server.url)) {
        if (server.url.indexOf(location_.host()) === -1) {
          dialogService_.promptCredentials(server.url, true).then(function(credentials) {
            server.username = credentials.username;
            server.authentication = $.base64.encode(credentials.username + ':' + credentials.password);
            doWork();
          }, function(reject) {
            if (goog.isDefAndNotNull(reject) && reject.anonymous) {
              server.username = translate_('anonymous');
              server.authentication = undefined;
              doWork();
            }
          });
        } else {
          server.username = configService_.username;
          server.isLocal = true;
          doWork();
        }
      } else {
        doWork();
      }
      return deferredResponse.promise;
    };

    this.addServer = function(serverInfo) {
      var deferredResponse = q_.defer();

      // save the config object on the server object so that when we save the server, we only pass the config as opposed
      // to anything else that the app ads to the server objects.
      var server = {id: null, ptype: 'gxp_olsource', config: serverInfo, populatingLayersConfig: false};

      goog.object.extend(server, serverInfo, {});

      var doWork = function() {
        console.log('---- MapService.layerInfo. trying to add server: ', server);
        service_.populateLayersConfig(server)
            .then(function(response) {
              // set the id. it should always resolve to the length
              server.id = serverCount++;
              servers.push(server);
              rootScope_.$broadcast('server-added', server.id);
              deferredResponse.resolve(server);
            }, function(reject) {
              deferredResponse.reject(server, reject);
            });
      };

      if (goog.isDefAndNotNull(server.url)) {
        if (server.url.indexOf(location_.host()) === -1) {
          dialogService_.promptCredentials(server.url, false).then(function(credentials) {
            server.username = credentials.username;
            server.authentication = $.base64.encode(credentials.username + ':' + credentials.password);

            var subURL = server.url.replace('/geoserver/wms', '/geoserver/rest');
            $.ajax({
              url: subURL,
              type: 'GET',
              dataType: 'jsonp',
              jsonp: 'callback',
              complete: doWork
            });
          }, function(reject) {
            server.username = translate_('anonymous');
            server.authentication = undefined;
            doWork();
          });
        } else {
          server.username = configService_.username;
          server.isLocal = true;
          server.name = translate_('local_geoserver');
          doWork();
        }
      } else {
        doWork();
      }

      return deferredResponse.promise;
    };

    this.removeServer = function(id) {
      var serverIndex = -1;
      for (var index = 0; index < servers.length; index += 1) {
        if (servers[index].id === id) {
          serverIndex = index;
          break;
        }
      }
      if (serverIndex > -1) {
        var server = servers.splice(serverIndex, 1)[0];
        rootScope_.$broadcast('server-removed', server);
      }
    };

    this.configDefaultServers = function() {
      var config = null;
      console.log('----- Configuring default servers.');

      if (!goog.isDefAndNotNull(service_.getServerByPtype('gxp_bingsource'))) {
        config = {ptype: 'gxp_bingsource', name: 'Bing', defaultServer: true};
        service_.addServer(config);
      } else {
        service_.getServerByPtype('gxp_bingsource').defaultServer = true;
      }

      if (!goog.isDefAndNotNull(service_.getServerByPtype('gxp_mapquestsource'))) {
        config = {ptype: 'gxp_mapquestsource', name: 'MapQuest', defaultServer: true};
        service_.addServer(config);
      } else {
        service_.getServerByPtype('gxp_mapquestsource').defaultServer = true;
      }

      if (!goog.isDefAndNotNull(service_.getServerByPtype('gxp_osmsource'))) {
        config = {ptype: 'gxp_osmsource', name: 'OpenStreetMap', defaultServer: true};
        service_.addServer(config);
      } else {
        service_.getServerByPtype('gxp_osmsource').defaultServer = true;
      }
      if (goog.isDefAndNotNull(service_.getServerLocalGeoserver())) {
        service_.getServerLocalGeoserver().defaultServer = true;
      }
    };

    this.getLayersConfig = function(serverId) {
      var server = service_.getServerById(serverId);
      if (goog.isDefAndNotNull(server)) {
        return server.layersConfig;
      }
    };

    this.getLayerConfig = function(serverId, layerName) {
      var layersConfig = service_.getLayersConfig(serverId);
      var layerConfig = null;

      for (var index = 0; index < layersConfig.length; index += 1) {
        if (layersConfig[index].Name === layerName) {
          layerConfig = layersConfig[index];
          break;
        }
      }

      console.log('---- ServerService.getLayerConfig: ', layerConfig);
      return layerConfig;
    };

    this.populateLayersConfig = function(server, force) {
      var deferredResponse = q_.defer();
      console.log('---- ServerService.populateLayersConfig. server', server);

      if (!goog.isDefAndNotNull(server)) {
        //TODO: make sure it is okay to reject and then return the promise
        deferredResponse.reject();
        return deferredResponse.promise;
      }

      if (!goog.isDefAndNotNull(server.layersConfig) ||
          (goog.isDefAndNotNull(force) && force)) {

        // clear out layers config
        server.layersConfig = [];

        if (server.ptype === 'gxp_bingsource') {
          server.layersConfig = [
            {Title: 'BingRoad', Name: 'BingRoad', sourceParams: {imagerySet: 'Road'}},
            {Title: 'BingAerial', Name: 'BingAerial', sourceParams: {imagerySet: 'Aerial'}},
            {Title: 'BingAerialWithLabels', Name: 'BingAerialWithLabels',
              sourceParams: {imagerySet: 'AerialWithLabels'}},
            {Title: 'BingCollinsBart', Name: 'BingCollinsBart', sourceParams: {imagerySet: 'collinsBart'}},
            {Title: 'BingSurvey', Name: 'BingSurvey', sourceParams: {imagerySet: 'ordnanceSurvey'}}
          ];
          deferredResponse.resolve(server);
        } else if (server.ptype === 'gxp_mapquestsource') {
          server.layersConfig = [
            {Title: 'MapQuestSat', Name: 'MapQuestSat', sourceParams: {layer: 'sat'}},
            {Title: 'MapQuestHybrid', Name: 'MapQuestHybrid', sourceParams: {layer: 'hyb'}},
            {Title: 'MapQuestOSM', Name: 'MapQuestOSM', sourceParams: {layer: 'osm'}}
          ];
          deferredResponse.resolve(server);
        } else if (server.ptype === 'gxp_osmsource') {
          server.layersConfig = [
            {Title: 'OpenStreetMap', Name: 'mapnik'}
          ];
          deferredResponse.resolve(server);
        } else if (server.ptype === 'gxp_wmscsource' ||
            server.ptype === 'gxp_tmssource') { // currently, if it is a tms endpoint, assume it has wmsgetcapabilities
          console.log('---- ServerService.Sending GetCapabilities.server: ', server);
          if (!goog.isDefAndNotNull(server.url)) {
            dialogService_.error(translate_('error'), translate_('server_url_not_specified'));
            deferredResponse.reject(server);
          } else {
            var parser = new ol.format.WMSCapabilities();
            var url = server.url + '?SERVICE=WMS&REQUEST=GetCapabilities';
            server.populatingLayersConfig = true;
            var config = {};
            config.headers = {};
            if (goog.isDefAndNotNull(server.authentication)) {
              config.headers['Authorization'] = 'Basic ' + server.authentication;
            } else {
              config.headers['Authorization'] = '';
            }
            // server hasn't been added yet, so specify the auth headers here
            http_.get(url, config).then(function(xhr) {
              if (xhr.status === 200) {
                var response = parser.read(xhr.data);
                if (goog.isDefAndNotNull(response.Capability) &&
                    goog.isDefAndNotNull(response.Capability.Layer)) {
                  server.layersConfig = response.Capability.Layer.Layer;
                  console.log('---- populateLayersConfig.populateLayersConfig server', server);
                  rootScope_.$broadcast('layers-loaded', server.id);
                  deferredResponse.resolve(server);
                } else {
                  deferredResponse.reject(server);
                }
                server.populatingLayersConfig = false;
              } else {
                deferredResponse.reject(server);
                server.populatingLayersConfig = false;
              }
            }, function(xhr) {
              deferredResponse.reject(server);
              server.populatingLayersConfig = false;
            });
          }
        }
      }

      return deferredResponse.promise;
    };

  });
}());
<|endoftext|>