merged conflicts
John Napiorkowski [Fri, 20 Sep 2013 18:19:26 +0000 (14:19 -0400)]
1  2 
MANIFEST.SKIP
Makefile.PL
lib/Catalyst.pm
lib/Catalyst/Utils.pm

diff --combined MANIFEST.SKIP
@@@ -1,1 -1,2 +1,2 @@@
 -^(?!script/\w+\.pl$|TODO$|lib/.+(?<!ROADMAP)\.p(m|od)$|inc/|t/a(uthor|ggregate)/.*\.t$|t/([^/]+|.{1,2}|[^t][^m][^p].*)\.(gif|yml|pl|t)$|t/lib/.*\.pm$|t/something/(Makefile.PL|script/foo/bar/for_dist)$|t/conf/extra.conf.in$|Makefile.PL$|README$|MANIFEST$|Changes$|META.yml$)
 +^(?!script/\w+\.pl$|TODO$|lib/.+(?<!ROADMAP)\.p(m|od)$|inc/|t/a(uthor|ggregate)/.*\.t$|t/([^/]+|.{1,2}|[^t][^m][^p].*)\.(gif|yml|pl|t)$|t/lib/.*\.pm$|t/something/(Makefile.PL|script/foo/bar/for_dist)$|t/conf/extra.conf.in$|Makefile.PL$|README$|MANIFEST$|Changes$|META.yml$|.+testappencodingsetinconfig.json|.+TestMiddleware/share.*)
+ /cpanfile
diff --combined Makefile.PL
@@@ -31,10 -31,9 +31,9 @@@ requires 'namespace::autoclean' => '0.0
  requires 'namespace::clean' => '0.23';
  requires 'MooseX::Emulate::Class::Accessor::Fast' => '0.00903';
  requires 'Class::Load' => '0.12';
- requires 'Class::MOP' => '0.95';
  requires 'Data::OptList';
  requires 'Moose' => '1.03';
- requires 'MooseX::MethodAttributes::Inheritable' => '0.24';
+ requires 'MooseX::MethodAttributes::Role::AttrContainer::Inheritable' => '0.24';
  requires 'MooseX::Role::WithOverloading' => '0.09';
  requires 'Carp';
  requires 'Class::C3::Adopt::NEXT' => '0.07';
@@@ -48,7 -47,7 +47,7 @@@ requires 'HTTP::Headers' => '1.64'
  requires 'HTTP::Request' => '5.814';
  requires 'HTTP::Response' => '5.813';
  requires 'HTTP::Request::AsCGI' => '1.0';
 -requires 'Module::Pluggable' => '3.9';
 +requires 'Module::Pluggable' => '4.7';
  requires 'Path::Class' => '0.09';
  requires 'Scalar::Util';
  requires 'Sub::Exporter';
@@@ -56,7 -55,7 +55,7 @@@ requires 'Text::SimpleTable' => '0.03'
  requires 'Time::HiRes';
  requires 'Tree::Simple' => '1.15';
  requires 'Tree::Simple::Visitor::FindByPath';
- requires 'Try::Tiny';
+ requires 'Try::Tiny' => '0.17';
  requires 'Safe::Isa';
  requires 'Task::Weaken';
  requires 'Text::Balanced'; # core in 5.8.x but mentioned for completeness
@@@ -71,20 -70,21 +70,23 @@@ requires 'Class::Data::Inheritable'
  requires 'Encode' => '2.49';
  requires 'LWP' => '5.837'; # LWP had unicode fail in 5.8.26
  requires 'URI' => '1.36';
 +requires 'JSON::MaybeXS' => '1.000000',
  
  # Install the standalone Regex dispatch modules in order to ease the
- # depreciation transition
+ # deprecation transition
  requires 'Catalyst::DispatchType::Regex' => '5.90021';
  
- test_requires 'Test::Exception';
+ test_requires 'Test::Fatal';
  test_requires 'Test::More' => '0.88';
  test_requires 'Data::Dump';
  test_requires 'HTTP::Request::Common';
  test_requires 'IO::Scalar';
  test_requires 'HTTP::Status';
 +test_requires 'JSON::MaybeXS';
  
+ # see also cpanfile for authordeps -- install via
+ # cpanm --installdeps --with-develop .
  # aggregate tests if AGGREGATE_TESTS is set and a recent Test::Aggregate and a Test::Simple it works with is available
  my @author_requires;
  if ($ENV{AGGREGATE_TESTS} && can_use('Test::Simple', '0.88') && can_use('Test::Aggregate', '0.364')) {
diff --combined lib/Catalyst.pm
@@@ -35,13 -35,13 +35,14 @@@ use utf8
  use Carp qw/croak carp shortmess/;
  use Try::Tiny;
  use Safe::Isa;
+ use Moose::Util 'find_meta';
  use Plack::Middleware::Conditional;
  use Plack::Middleware::ReverseProxy;
  use Plack::Middleware::IIS6ScriptNameFix;
  use Plack::Middleware::IIS7KeepAliveFix;
  use Plack::Middleware::LighttpdScriptNameFix;
 +use Plack::Util;
- use Class::Load;
+ use Class::Load 'load_class';
  
  BEGIN { require 5.008003; }
  
@@@ -63,7 -63,6 +64,7 @@@ sub _build_request_constructor_args 
      my $self = shift;
      my %p = ( _log => $self->log );
      $p{_uploadtmp} = $self->_uploadtmp if $self->_has_uploadtmp;
 +    $p{data_handlers} = {$self->registered_data_handlers};
      \%p;
  }
  
@@@ -107,8 -106,7 +108,8 @@@ our $GO        = Catalyst::Exception::G
  __PACKAGE__->mk_classdata($_)
    for qw/components arguments dispatcher engine log dispatcher_class
    engine_loader context_class request_class response_class stats_class
 -  setup_finished _psgi_app loading_psgi_file run_options/;
 +  setup_finished _psgi_app loading_psgi_file run_options _psgi_middleware
 +  _data_handlers/;
  
  __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
  __PACKAGE__->request_class('Catalyst::Request');
@@@ -117,7 -115,7 +118,7 @@@ __PACKAGE__->stats_class('Catalyst::Sta
  
  # Remember to update this in Catalyst::Runtime as well!
  
 -our $VERSION = '5.90042';
 +our $VERSION = '5.90049_002';
  
  sub import {
      my ( $class, @arguments ) = @_;
@@@ -326,7 -324,18 +327,18 @@@ cookies, HTTP headers, etc.). See L<Cat
  
  =head2 $c->forward( $class, $method, [, \@arguments ] )
  
- Forwards processing to another action, by its private name. If you give a
+ This is one way of calling another action (method) in the same or
+ a different controller. You can also use C<< $self->my_method($c, @args) >>
+ in the same controller or C<< $c->controller('MyController')->my_method($c, @args) >>
+ in a different controller.
+ The main difference is that 'forward' uses some of the Catalyst request
+ cycle overhead, including debugging, which may be useful to you. On the
+ other hand, there are some complications to using 'forward', restrictions
+ on values returned from 'forward', and it may not handle errors as you prefer.
+ Whether you use 'forward' or not is up to you; it is not considered superior to
+ the other ways to call a method.
+ 'forward' calls  another action, by its private name. If you give a
  class name but no method, C<process()> is called. You may also optionally
  pass arguments in an arrayref. The action will receive the arguments in
  C<@_> and C<< $c->req->args >>. Upon returning from the function,
@@@ -1112,8 -1121,6 +1124,8 @@@ sub setup 
  
      $class->setup_log( delete $flags->{log} );
      $class->setup_plugins( delete $flags->{plugins} );
 +    $class->setup_middleware();
 +    $class->setup_data_handlers();
      $class->setup_dispatcher( delete $flags->{dispatcher} );
      if (my $engine = delete $flags->{engine}) {
          $class->log->warn("Specifying the engine in ->setup is no longer supported, see Catalyst::Upgrading");
              $class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" );
          }
  
 +        my @middleware = map {
 +          ref $_ eq 'CODE' ? 
 +            "Inline Coderef" : 
 +              (ref($_) .'  '. ($_->can('VERSION') ? $_->VERSION || '' : '') 
 +                || '')  } $class->registered_middlewares;
 +
 +        if (@middleware) {
 +            my $column_width = Catalyst::Utils::term_width() - 6;
 +            my $t = Text::SimpleTable->new($column_width);
 +            $t->row($_) for @middleware;
 +            $class->log->debug( "Loaded PSGI Middleware:\n" . $t->draw . "\n" );
 +        }
 +
 +        my %dh = $class->registered_data_handlers;
 +        if (my @data_handlers = keys %dh) {
 +            my $column_width = Catalyst::Utils::term_width() - 6;
 +            my $t = Text::SimpleTable->new($column_width);
 +            $t->row($_) for @data_handlers;
 +            $class->log->debug( "Loaded Request Data Handlers:\n" . $t->draw . "\n" );
 +        }
 +
          my $dispatcher = $class->dispatcher;
          my $engine     = $class->engine;
          my $home       = $class->config->{home};
@@@ -2488,7 -2474,7 +2500,7 @@@ sub run 
  
  sub _make_immutable_if_needed {
      my $class = shift;
-     my $meta = Class::MOP::get_metaclass_by_name($class);
+     my $meta = find_meta($class);
      my $isa_ca = $class->isa('Class::Accessor::Fast') || $class->isa('Class::Accessor');
      if (
          $meta->is_immutable
@@@ -2679,7 -2665,7 +2691,7 @@@ sub setup_dispatcher 
          $dispatcher = $class->dispatcher_class;
      }
  
-     Class::MOP::load_class($dispatcher);
+     load_class($dispatcher);
  
      # dispatcher instance
      $class->dispatcher( $dispatcher->new );
@@@ -2729,7 -2715,7 +2741,7 @@@ sub setup_engine 
      # Don't really setup_engine -- see _setup_psgi_app for explanation.
      return if $class->loading_psgi_file;
  
-     Class::MOP::load_class($engine);
+     load_class($engine);
  
      if ($ENV{MOD_PERL}) {
          my $apache = $class->engine_loader->auto;
      return;
  }
  
 +## This exists just to supply a prebuild psgi app for mod_perl and for the 
 +## build in server support (back compat support for pre psgi port behavior).
 +## This is so that we don't build a new psgi app for each request when using
 +## the mod_perl handler or the built in servers (http and fcgi, etc).
 +
  sub _finalized_psgi_app {
      my ($app) = @_;
  
      return $app->_psgi_app;
  }
  
 +## Look for a psgi file like 'myapp_web.psgi' (if the app is MyApp::Web) in the
 +## home directory and load that and return it (just assume it is doing the 
 +## right thing :) ).  If that does not exist, call $app->psgi_app, wrap that
 +## in default_middleware and return it ( this is for backward compatibility
 +## with pre psgi port behavior ).
 +
  sub _setup_psgi_app {
      my ($app) = @_;
  
@@@ -2885,8 -2860,7 +2897,8 @@@ reference of your Catalyst application 
  
  sub psgi_app {
      my ($app) = @_;
 -    return $app->engine->build_psgi_app($app);
 +    my $psgi = $app->engine->build_psgi_app($app);
 +    return $app->Catalyst::Utils::apply_registered_middleware($psgi);
  }
  
  =head2 $c->setup_home
@@@ -3005,7 -2979,7 +3017,7 @@@ the plugin name does not begin with C<C
          my ( $proto, $plugin, $instant ) = @_;
          my $class = ref $proto || $proto;
  
-         Class::MOP::load_class( $plugin );
+         load_class( $plugin );
          $class->log->warn( "$plugin inherits from 'Catalyst::Component' - this is deprecated and will not work in 5.81" )
              if $plugin->isa( 'Catalyst::Component' );
          my $plugin_meta = Moose::Meta::Class->create($plugin);
           } @{ $plugins };
  
          for my $plugin ( reverse @plugins ) {
-             Class::MOP::load_class($plugin->[0], $plugin->[1]);
+             load_class($plugin->[0], $plugin->[1]);
              my $meta = find_meta($plugin->[0]);
              next if $meta && $meta->isa('Moose::Meta::Role');
  
              $class => @roles
          ) if @roles;
      }
 +}    
 +
 +=head2 registered_middlewares
 +
 +Read only accessor that returns an array of all the middleware in the order
 +that they were added (which is the REVERSE of the order they will be applied).
 +
 +The values returned will be either instances of L<Plack::Middleware> or of a
 +compatible interface, or a coderef, which is assumed to be inlined middleware
 +
 +=head2 setup_middleware (?@middleware)
 +
 +Read configuration information stored in configuration key C<psgi_middleware> or
 +from passed @args.
 +
 +See under L</CONFIGURATION> information regarding C<psgi_middleware> and how
 +to use it to enable L<Plack::Middleware>
 +
 +This method is automatically called during 'setup' of your application, so
 +you really don't need to invoke it.
 +
 +When we read middleware definitions from configuration, we reverse the list
 +which sounds odd but is likely how you expect it to work if you have prior
 +experience with L<Plack::Builder> or if you previously used the plugin
 +L<Catalyst::Plugin::EnableMiddleware> (which is now considered deprecated)
 +
 +=cut
 +
 +sub registered_middlewares {
 +    my $class = shift;
 +    if(my $middleware = $class->_psgi_middleware) {
 +        return @$middleware;
 +    } else {
 +        die "You cannot call ->registered_middlewares until middleware has been setup";
 +    }
 +}
 +
 +sub setup_middleware {
 +    my ($class, @middleware_definitions) = @_;
 +    push @middleware_definitions, reverse(
 +      @{$class->config->{'psgi_middleware'}||[]});
 +
 +    my @middleware = ();
 +    while(my $next = shift(@middleware_definitions)) {
 +        if(ref $next) {
 +            if(Scalar::Util::blessed $next && $next->can('wrap')) {
 +                push @middleware, $next;
 +            } elsif(ref $next eq 'CODE') {
 +                push @middleware, $next;
 +            } elsif(ref $next eq 'HASH') {
 +                my $namespace = shift @middleware_definitions;
 +                my $mw = $class->Catalyst::Utils::build_middleware($namespace, %$next);
 +                push @middleware, $mw;
 +            } else {
 +              die "I can't handle middleware definition ${\ref $next}";
 +            }
 +        } else {
 +          my $mw = $class->Catalyst::Utils::build_middleware($next);
 +          push @middleware, $mw;
 +        }
 +    }
 +
 +    $class->_psgi_middleware(\@middleware);
 +}
 +
 +=head2 registered_data_handlers
 +
 +A read only copy of registered Data Handlers returned as a Hash, where each key
 +is a content type and each value is a subref that attempts to decode that content
 +type.
 +
 +=head2 setup_data_handlers (?@data_handler)
 +
 +Read configuration information stored in configuration key C<data_handlers> or
 +from passed @args.
 +
 +See under L</CONFIGURATION> information regarding C<data_handlers>.
 +
 +This method is automatically called during 'setup' of your application, so
 +you really don't need to invoke it.
 +
 +=head2 default_data_handlers
 +
 +Default Data Handler that come bundled with L<Catalyst>.  Currently there is
 +only one default data handler, for 'application/json'.  This uses L<JSON::MaybeXS>
 +which uses the dependency free L<JSON::PP> OR L<Cpanel::JSON::XS> if you have
 +installed it.  If you don't mind the XS dependency, you should add the faster
 +L<Cpanel::JSON::XS> to you dependency list (in your Makefile.PL or dist.ini, or
 +cpanfile, etc.)
 +
 +L<JSON::MaybeXS> is loaded the first time you ask for it (so if you never ask
 +for it, its never used).
 +
 +=cut
 +
 +sub registered_data_handlers {
 +    my $class = shift;
 +    if(my $data_handlers = $class->_data_handlers) {
 +        return %$data_handlers;
 +    } else {
 +        die "You cannot call ->registered_data_handlers until data_handers has been setup";
 +    }
 +}
 +
 +sub setup_data_handlers {
 +    my ($class, %data_handler_callbacks) = @_;
 +    %data_handler_callbacks = (
 +      %{$class->default_data_handlers},
 +      %{$class->config->{'data_handlers'}||+{}},
 +      %data_handler_callbacks);
 +
 +    $class->_data_handlers(\%data_handler_callbacks);
 +}
 +
 +sub default_data_handlers {
 +    my ($class) = @_;
 +    return +{
 +      'application/json' => sub {
 +          local $/;
 +          Class::Load::load_class("JSON::MaybeXS");
 +          JSON::MaybeXS::decode_json $_->getline },
 +    };
  }
  
  =head2 $c->stack
@@@ -3381,14 -3233,6 +3393,14 @@@ use like
  
  In the future this might become the default behavior.
  
 +=item *
 +
 +C<psgi_middleware> - See L<PSGI MIDDLEWARE>.
 +
 +=item *
 +
 +C<data_handlers> - See L<DATA HANDLERS>.
 +
  =back
  
  =head1 INTERNAL ACTIONS
@@@ -3480,171 -3324,6 +3492,171 @@@ If you plan to operate in a threaded en
  modules you are using must also be thread-safe. Some modules, most notably
  L<DBD::SQLite>, are not thread-safe.
  
 +=head1 DATA HANDLERS
 +
 +The L<Catalyst::Request> object uses L<HTTP::Body> to populate 'classic' HTML
 +form parameters and URL search query fields.  However it has become common
 +for various alternative content types to be PUT or POSTed to your controllers
 +and actions.  People working on RESTful APIs, or using AJAX often use JSON,
 +XML and other content types when communicating with an application server.  In
 +order to better support this use case, L<Catalyst> defines a global configuration
 +option, C<data_handlers>, which lets you associate a content type with a coderef
 +that parses that content type into something Perl can readily access.
 +
 +    package MyApp::Web;
 + 
 +    use Catalyst;
 +    use JSON::Maybe;
 + 
 +    __PACKAGE__->config(
 +      data_handlers => {
 +        'application/json' => sub { local $/; decode_json $_->getline },
 +      },
 +      ## Any other configuration.
 +    );
 + 
 +    __PACKAGE__->setup;
 +
 +By default L<Catalyst> comes with a generic JSON data handler similar to the
 +example given above, which uses L<JSON::Maybe> to provide either L<JSON::PP>
 +(a pure Perl, dependency free JSON parser) or L<Cpanel::JSON::XS> if you have
 +it installed (if you want the faster XS parser, add it to you project Makefile.PL
 +or dist.ini, cpanfile, etc.)
 +
 +The C<data_handlers> configuation is a hashref whose keys are HTTP Content-Types
 +(matched against the incoming request type using a regexp such as to be case
 +insensitive) and whose values are coderefs that receive a localized version of
 +C<$_> which is a filehandle object pointing to received body.
 +
 +This feature is considered an early access release and we reserve the right
 +to alter the interface in order to provide a performant and secure solution to
 +alternative request body content.  Your reports welcomed!
 +
 +=head1 PSGI MIDDLEWARE
 +
 +You can define middleware, defined as L<Plack::Middleware> or a compatible
 +interface in configuration.  Your middleware definitions are in the form of an
 +arrayref under the configuration key C<psgi_middleware>.  Here's an example
 +with details to follow:
 +
 +    package MyApp::Web;
 + 
 +    use Catalyst;
 +    use Plack::Middleware::StackTrace;
 + 
 +    my $stacktrace_middleware = Plack::Middleware::StackTrace->new;
 + 
 +    __PACKAGE__->config(
 +      'psgi_middleware', [
 +        'Debug',
 +        '+MyApp::Custom',
 +        $stacktrace_middleware,
 +        'Session' => {store => 'File'},
 +        sub {
 +          my $app = shift;
 +          return sub {
 +            my $env = shift;
 +            $env->{myapp.customkey} = 'helloworld';
 +            $app->($env);
 +          },
 +        },
 +      ],
 +    );
 + 
 +    __PACKAGE__->setup;
 +
 +So the general form is:
 +
 +    __PACKAGE__->config(psgi_middleware => \@middleware_definitions);
 +
 +Where C<@middleware> is one or more of the following, applied in the REVERSE of
 +the order listed (to make it function similarly to L<Plack::Builder>:
 + 
 +=over 4
 + 
 +=item Middleware Object
 + 
 +An already initialized object that conforms to the L<Plack::Middleware>
 +specification:
 + 
 +    my $stacktrace_middleware = Plack::Middleware::StackTrace->new;
 + 
 +    __PACKAGE__->config(
 +      'psgi_middleware', [
 +        $stacktrace_middleware,
 +      ]);
 + 
 + 
 +=item coderef
 + 
 +A coderef that is an inlined middleware:
 + 
 +    __PACKAGE__->config(
 +      'psgi_middleware', [
 +        sub {
 +          my $app = shift;
 +          return sub {
 +            my $env = shift;
 +            if($env->{PATH_INFO} =~m/forced/) {
 +              Plack::App::File
 +                ->new(file=>TestApp->path_to(qw/share static forced.txt/))
 +                ->call($env);
 +            } else {
 +              return $app->($env);
 +            }
 +         },
 +      },
 +    ]);
 + 
 + 
 + 
 +=item a scalar
 + 
 +We assume the scalar refers to a namespace after normalizing it using the
 +following rules:
 +
 +(1) If the scalar is prefixed with a "+" (as in C<+MyApp::Foo>) then the full string
 +is assumed to be 'as is', and we just install and use the middleware.
 +
 +(2) If the scalar begins with "Plack::Middleware" or your application namespace
 +(the package name of your Catalyst application subclass), we also assume then
 +that it is a full namespace, and use it.
 +
 +(3) Lastly, we then assume that the scalar is a partial namespace, and attempt to
 +resolve it first by looking for it under your application namespace (for example
 +if you application is "MyApp::Web" and the scalar is "MyMiddleware", we'd look
 +under "MyApp::Web::Middleware::MyMiddleware") and if we don't find it there, we
 +will then look under the regular L<Plack::Middleware> namespace (i.e. for the
 +previous we'd try "Plack::Middleware::MyMiddleware").  We look under your application
 +namespace first to let you 'override' common L<Plack::Middleware> locally, should
 +you find that a good idea.
 +
 +Examples:
 +
 +    package MyApp::Web;
 +
 +    __PACKAGE__->config(
 +      'psgi_middleware', [
 +        'Debug',  ## MyAppWeb::Middleware::Debug->wrap or Plack::Middleware::Debug->wrap
 +        'Plack::Middleware::Stacktrace', ## Plack::Middleware::Stacktrace->wrap
 +        '+MyApp::Custom',  ## MyApp::Custom->wrap
 +      ],
 +    );
 + 
 +=item a scalar followed by a hashref
 + 
 +Just like the previous, except the following C<HashRef> is used as arguments
 +to initialize the middleware object.
 + 
 +    __PACKAGE__->config(
 +      'psgi_middleware', [
 +         'Session' => {store => 'File'},
 +    ]);
 +
 +=back
 +
 +Please see L<PSGI> for more on middleware.
 +
  =head1 ENCODING
  
  On request, decodes all params from encoding into a sequence of
diff --combined lib/Catalyst/Utils.pm
@@@ -7,9 -7,8 +7,9 @@@ use Path::Class
  use URI;
  use Carp qw/croak/;
  use Cwd;
- use Class::MOP;
+ use Class::Load 'is_class_loaded';
  use String::RewritePrefix;
 +use Class::Load ();
  
  use namespace::clean;
  
@@@ -137,9 -136,8 +137,8 @@@ sub class2tempdir 
  
      if ( $create && !-e $tmpdir ) {
  
-         eval { $tmpdir->mkpath };
-         if ($@) {
+         eval { $tmpdir->mkpath; 1 }
+         or do {
              # don't load Catalyst::Exception as a BEGIN in Utils,
              # because Utils often gets loaded before MyApp.pm, and if
              # Catalyst::Exception is loaded before MyApp.pm, it does
@@@ -298,7 -296,7 +297,7 @@@ sub ensure_class_loaded 
      # if it already has symbol table entries. This is to support things like Schema::Loader, which
      # part-generate classes in memory, but then also load some of their contents from disk.
      return if !$opts->{ ignore_loaded }
-         && Class::MOP::is_class_loaded($class); # if a symbol entry exists we don't load again
+         && is_class_loaded($class); # if a symbol entry exists we don't load again
  
      # this hack is so we don't overwrite $@ if the load did not generate an error
      my $error;
      die $error if $error;
  
      warn "require $class was successful but the package is not defined."
-         unless Class::MOP::is_class_loaded($class);
+         unless is_class_loaded($class);
  
      return 1;
  }
@@@ -392,17 -390,17 +391,17 @@@ my $_term_width
  sub term_width {
      return $_term_width if $_term_width;
  
-     my $width = eval '
-         use Term::Size::Any;
+     my $width;
+     eval '
+         require Term::Size::Any;
          my ($columns, $rows) = Term::Size::Any::chars;
-         return $columns;
-     ';
-     if ($@) {
+         $width = $columns;
+         1;
+     ' or do {
          $width = $ENV{COLUMNS}
              if exists($ENV{COLUMNS})
              && $ENV{COLUMNS} =~ m/^\d+$/;
-     }
+     };
  
      $width = 80 unless ($width && $width >= 80);
      return $_term_width = $width;
@@@ -434,56 -432,6 +433,56 @@@ sub resolve_namespace 
      }, @classes);
  }
  
 +=head2 build_middleware (@args)
 +
 +Internal application that converts a single middleware definition (see
 +L<Catalyst/psgi_middleware>) into an actual instance of middleware.
 +
 +=cut
 +
 +sub build_middleware {
 +    my ($class, $namespace, @init_args) = @_;
 +
 +    if(
 +      $namespace =~s/^\+// ||
 +      $namespace =~/^Plack::Middleware/ ||
 +      $namespace =~/^$class/
 +    ) {  ## the string is a full namespace
 +        return Class::Load::try_load_class($namespace) ?
 +          $namespace->new(@init_args) :
 +            die "Can't load class $namespace";
 +    } else { ## the string is a partial namespace
 +      if(Class::Load::try_load_class($class .'::Middleware::'. $namespace)) { ## Load Middleware from Project namespace
 +          my $ns = $class .'::Middleware::'. $namespace;
 +          return $ns->new(@init_args);
 +        } elsif(Class::Load::try_load_class("Plack::Middleware::$namespace")) { ## Act like Plack::Builder
 +          return "Plack::Middleware::$namespace"->new(@init_args);
 +        }
 +    }
 +
 +    return; ## be sure we can count on a proper return when valid
 +}
 +
 +=head2 apply_registered_middleware ($psgi)
 +
 +Given a $psgi reference, wrap all the L<Catalyst/registered_middlewares>
 +around it and return the wrapped version.
 +
 +This exists to deal with the fact Catalyst registered middleware can be
 +either an object with a wrap method or a coderef.
 +
 +=cut
 +
 +sub apply_registered_middleware {
 +    my ($class, $psgi) = @_;
 +    my $new_psgi = $psgi;
 +    foreach my $middleware ($class->registered_middlewares) {
 +        $new_psgi = Scalar::Util::blessed $middleware ?
 +          $middleware->wrap($new_psgi) :
 +            $middleware->($new_psgi);
 +    }
 +    return $new_psgi;
 +}
  
  =head1 AUTHORS