text: /**
   * Module dependencies.
   */
  
  var connect = require('connect')
    , Router = require('./router')
    , methods = require('methods')
    , middleware = require('./middleware')
    , debug = require('debug')('express:application')
    , locals = require('./utils').locals
    , View = require('./view')
    , url = require('url')
    , utils = connect.utils
    , path = require('path')
    , http = require('http')
    , join = path.join
    , fs = require('fs');
  
  /**
   * Application prototype.
   */
  
  var app = exports = module.exports = {};
  
  /**
   * Initialize the server.
   *
   *   - setup default configuration
   *   - setup default middleware
   *   - setup route reflection methods
   *
   * @api private
   */
  
  app.init = function(){
    var self = this;
    this.cache = {};
    this.settings = {};
    this.engines = {};
    this.viewCallbacks = [];
    this.defaultConfiguration();
  };
  
  /**
   * Initialize application configuration.
   *
   * @api private
   */
  
  app.defaultConfiguration = function(){
    var self = this;
  
    // default settings
    this.set('env', process.env.NODE_ENV || 'development');
    debug('booting in %s mode', this.get('env'));
  
    // implicit middleware
    this.use(connect.query());
    this.use(middleware.init(this));
  
    // inherit protos
    this.on('mount', function(parent){
      this.request.__proto__ = parent.request;
      this.response.__proto__ = parent.response;
      this.engines.__proto__ = parent.engines;
    });
  
    // router
    this._router = new Router(this);
    this.routes = this._router.map;
    this.__defineGetter__('router', function(){
      this._usedRouter = true;
      this._router.caseSensitive = this.enabled('case sensitive routing');
      this._router.strict = this.enabled('strict routing');
      return this._router.middleware;
    });
  
    // setup locals
    this.locals = locals(this);
  
    // default locals
    this.locals.settings = this.settings;
  
    // default configuration
    this.enable('jsonp callback');
    this.set('jsonp callback name', 'callback');
  
    this.configure('development', function(){
      this.set('json spaces', 2);
    });
  
    this.configure('production', function(){
      this.enable('view cache');
    });
  };
  
  /**
   * Proxy `connect#use()` to apply settings to
   * mounted applications.
   *
   * @param {String|Function|Server} route
   * @param {Function|Server} fn
   * @return {app} for chaining
   * @api public
   */
  
  app.use = function(route, fn){
    var app, home, handle;
  
    // default route to '/'
    if ('string' != typeof route) fn = route, route = '/';
  
    // express app
    if (fn.handle && fn.set) app = fn;
  
    // restore .app property on req and res
    if (app) {
      app.route = route;
      fn = function(req, res, next) {
        var orig = req.app;
        app.handle(req, res, function(err){
          req.app = res.app = orig;
          req.__proto__ = orig.request;
          res.__proto__ = orig.response;
          next(err);
        });
      };
    }
  
    connect.proto.use.call(this, route, fn);
  
    // mounted an app
    if (app) {
      app.parent = this;
      app.emit('mount', this);
    }
  
    return this;
  };
  
  /**
   * Register the given template engine callback `fn`
   * as `ext`.
   *
   * By default will `require()` the engine based on the
   * file extension. For example if you try to render
   * a "foo.jade" file Express will invoke the following internally:
   *
   *     app.engine('jade', require('jade').__express);
   *
   * For engines that do not provide `.__express` out of the box,
   * or if you wish to "map" a different extension to the template engine
   * you may use this method. For example mapping the EJS template engine to
   * ".html" files:
   *
   *     app.engine('html', require('ejs').renderFile);
   *
   * In this case EJS provides a `.renderFile()` method with
   * the same signature that Express expects: `(path, options, callback)`,
   * though note that it aliases this method as `ejs.__express` internally
   * so if you're using ".ejs" extensions you dont need to do anything.
   *
   * Some template engines do not follow this convention, the
   * [Consolidate.js](https://github.com/visionmedia/consolidate.js)
   * library was created to map all of node's popular template
   * engines to follow this convention, thus allowing them to
   * work seemlessly within Express.
   *
   * @param {String} ext
   * @param {Function} fn
   * @return {app} for chaining
   * @api public
   */
  
  app.engine = function(ext, fn){
    if ('function' != typeof fn) throw new Error('callback function required');
    if ('.' != ext[0]) ext = '.' + ext;
    this.engines[ext] = fn;
    return this;
  };
  
  /**
   * Map the given param placeholder `name`(s) to the given callback(s).
   *
   * Parameter mapping is used to provide pre-conditions to routes
   * which use normalized placeholders. For example a _:user_id_ parameter
   * could automatically load a user's information from the database without
   * any additional code,
   *
   * The callback uses the samesignature as middleware, the only differencing
   * being that the value of the placeholder is passed, in this case the _id_
   * of the user. Once the `next()` function is invoked, just like middleware
   * it will continue on to execute the route, or subsequent parameter functions.
   *
   *      app.param('user_id', function(req, res, next, id){
   *        User.find(id, function(err, user){
   *          if (err) {
   *            next(err);
   *          } else if (user) {
   *            req.user = user;
   *            next();
   *          } else {
   *            next(new Error('failed to load user'));
   *          }
   *        });
   *      });
   *
   * @param {String|Array} name
   * @param {Function} fn
   * @return {app} for chaining
   * @api public
   */
  
  app.param = function(name, fn){
    var self = this
      , fns = [].slice.call(arguments, 1);
  
    // array
    if (Array.isArray(name)) {
      name.forEach(function(name){
        fns.forEach(function(fn){
          self.param(name, fn);
        });
      });
    // param logic
    } else if ('function' == typeof name) {
      this._router.param(name);
    // single
    } else {
      if (':' == name[0]) name = name.substr(1);
      fns.forEach(function(fn){
        self._router.param(name, fn);
      });
    }
  
    return this;
  };
  
  /**
   * Assign `setting` to `val`, or return `setting`'s value.
   *
   *    app.set('foo', 'bar');
   *    app.get('foo');
   *    // => "bar"
   *
   * Mounted servers inherit their parent server's settings.
   *
   * @param {String} setting
   * @param {String} val
   * @return {Server} for chaining
   * @api public
   */
  
  app.set = function(setting, val){
    if (1 == arguments.length) {
      if (this.settings.hasOwnProperty(setting)) {
        return this.settings[setting];
      } else if (this.parent) {
        return this.parent.set(setting);
      }
    } else {
      this.settings[setting] = val;
      return this;
    }
  };
  
  /**
   * Return the app's absolute pathname
   * based on the parent(s) that have
   * mounted it.
   *
   * For example if the application was
   * mounted as "/admin", which itself
   * was mounted as "/blog" then the
   * return value would be "/blog/admin".
   *
   * @return {String}
   * @api private
   */
  
  app.path = function(){
    return this.parent
      ? this.parent.path() + this.route
      : '';
  };
  
  /**
   * Check if `setting` is enabled (truthy).
   *
   *    app.enabled('foo')
   *    // => false
   *
   *    app.enable('foo')
   *    app.enabled('foo')
   *    // => true
   *
   * @param {String} setting
   * @return {Boolean}
   * @api public
   */
  
  app.enabled = function(setting){
    return !!this.set(setting);
  };
  
  /**
   * Check if `setting` is disabled.
   *
   *    app.disabled('foo')
   *    // => true
   *
   *    app.enable('foo')
   *    app.disabled('foo')
   *    // => false
   *
   * @param {String} setting
   * @return {Boolean}
   * @api public
   */
  
  app.disabled = function(setting){
    return !this.set(setting);
  };
  
  /**
   * Enable `setting`.
   *
   * @param {String} setting
   * @return {app} for chaining
   * @api public
   */
  
  app.enable = function(setting){
    return this.set(setting, true);
  };
  
  /**
   * Disable `setting`.
   *
   * @param {String} setting
   * @return {app} for chaining
   * @api public
   */
  
  app.disable = function(setting){
    return this.set(setting, false);
  };
  
  /**
   * Configure callback for zero or more envs,
   * when no `env` is specified that callback will
   * be invoked for all environments. Any combination
   * can be used multiple times, in any order desired.
   *
   * Examples:
   *
   *    app.configure(function(){
   *      // executed for all envs
   *    });
   *
   *    app.configure('stage', function(){
   *      // executed staging env
   *    });
   *
   *    app.configure('stage', 'production', function(){
   *      // executed for stage and production
   *    });
   *
   * Note:
   *
   *  These callbacks are invoked immediately, and
   *  are effectively sugar for the following:
   *
   *     var env = process.env.NODE_ENV || 'development';
   *
   *      switch (env) {
   *        case 'development':
   *          ...
   *          break;
   *        case 'stage':
   *          ...
   *          break;
   *        case 'production':
   *          ...
   *          break;
   *      }
   *
   * @param {String} env...
   * @param {Function} fn
   * @return {app} for chaining
   * @api public
   */
  
  app.configure = function(env, fn){
    var envs = 'all'
      , args = [].slice.call(arguments);
    fn = args.pop();
    if (args.length) envs = args;
    if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
    return this;
  };
  
  /**
   * Delegate `.VERB(...)` calls to `.route(VERB, ...)`.
   */
  
  methods.forEach(function(method){
    app[method] = function(path){
      if ('get' == method && 1 == arguments.length) return this.set(path); 
      var args = [method].concat([].slice.call(arguments));
      if (!this._usedRouter) this.use(this.router);
      return this._router.route.apply(this._router, args);
    }
  });
  
  /**
   * Special-cased "all" method, applying the given route `path`,
   * middleware, and callback to _every_ HTTP method.
   *
   * @param {String} path
   * @param {Function} ...
   * @return {app} for chaining
   * @api public
   */
  
  app.all = function(path){
    var args = arguments;
    methods.forEach(function(method){
      app[method].apply(this, args);
    }, this);
    return this;
  };
  
  // del -> delete alias
  
  app.del = app.delete;
  
  /**
   * Render the given view `name` name with `options`
   * and a callback accepting an error and the
   * rendered template string.
   *
   * Example:
   *
   *    app.render('email', { name: 'Tobi' }, function(err, html){
   *      // ...
   *    })
   *
   * @param {String} name
   * @param {String|Function} options or fn
   * @param {Function} fn
   * @api public
   */
  
  app.render = function(name, options, fn){
    var self = this
      , opts = {}
      , cache = this.cache
      , engines = this.engines
      , view;
  
    // support callback function as second arg
    if ('function' == typeof options) {
      fn = options, options = {};
    }
  
    // merge app.locals
    utils.merge(opts, this.locals);
  
    // merge options.locals
    if (options.locals) utils.merge(opts, options.locals);
  
    // merge options
    utils.merge(opts, options);
  
    // set .cache unless explicitly provided
    opts.cache = null == opts.cache
      ? this.enabled('view cache')
      : opts.cache;
  
    // primed cache
    if (opts.cache) view = cache[name];
  
    // view
    if (!view) {
      view = new View(name, {
          defaultEngine: this.get('view engine')
        , root: this.get('views') || process.cwd() + '/views'
        , engines: engines
      });
  
      if (!view.path) {
        var err = new Error('Failed to lookup view "' + name + '"');
        err.view = view;
        return fn(err);
      }
  
      // prime the cache
      if (opts.cache) cache[name] = view;
    }
  
    // render
    try {
      view.render(opts, fn);
    } catch (err) {
      fn(err);
    }
  };
  
  /**
   * Listen for connections.
   *
   * A node `http.Server` is returned, with this
   * application (which is a `Function`) as its
   * callback. If you wish to create both an HTTP
   * and HTTPS server you may do so with the "http"
   * and "https" modules as shown here:
   *
   *    var http = require('http')
   *      , https = require('https')
   *      , express = require('express')
   *      , app = express();
   *
   *    http.createServer(app).listen(80);
   *    http.createServer({ ... }, app).listen(443);
   *
   * @return {http.Server}
   * @api public
   */
  
  app.listen = function(){
    var server = http.createServer(this);
    return server.listen.apply(server, arguments);
  };
  