some more comments and little changes as well as some notes. test output still the...
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
1 package Catalyst;
2
3 use Moose;
4 extends 'Catalyst::Component';
5 use bytes;
6 use Catalyst::Exception;
7 use Catalyst::Log;
8 use Catalyst::Request;
9 use Catalyst::Request::Upload;
10 use Catalyst::Response;
11 use Catalyst::Utils;
12 use Catalyst::Controller;
13 use Devel::InnerPackage ();
14 use File::stat;
15 use Module::Pluggable::Object ();
16 use NEXT;
17 use Text::SimpleTable ();
18 use Path::Class::Dir ();
19 use Path::Class::File ();
20 use Time::HiRes qw/gettimeofday tv_interval/;
21 use URI ();
22 use URI::http;
23 use URI::https;
24 use Scalar::Util qw/weaken blessed/;
25 use Tree::Simple qw/use_weak_refs/;
26 use Tree::Simple::Visitor::FindByUID;
27 use attributes;
28 use utf8;
29 use Carp qw/croak carp/;
30
31 BEGIN { require 5.008001; }
32
33 has stack     => (is => 'rw');
34 has stash     => (is => 'rw');
35 has state     => (is => 'rw');
36 has stats     => (is => 'rw');
37 has action    => (is => 'rw');
38 has counter   => (is => 'rw');
39 has request   => (is => 'rw');
40 has response  => (is => 'rw');
41 has namespace => (is => 'rw');
42
43
44 attributes->import( __PACKAGE__, \&namespace, 'lvalue' );
45
46 sub depth { scalar @{ shift->stack || [] }; }
47
48 # Laziness++
49 *comp = \&component;
50 *req  = \&request;
51 *res  = \&response;
52
53 # For backwards compatibility
54 *finalize_output = \&finalize_body;
55
56 # For statistics
57 our $COUNT     = 1;
58 our $START     = time;
59 our $RECURSION = 1000;
60 our $DETACH    = "catalyst_detach\n";
61
62 __PACKAGE__->mk_classdata($_)
63   for qw/components arguments dispatcher engine log dispatcher_class
64   engine_class context_class request_class response_class stats_class
65   setup_finished/;
66
67 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
68 __PACKAGE__->engine_class('Catalyst::Engine::CGI');
69 __PACKAGE__->request_class('Catalyst::Request');
70 __PACKAGE__->response_class('Catalyst::Response');
71 __PACKAGE__->stats_class('Catalyst::Stats');
72
73 # Remember to update this in Catalyst::Runtime as well!
74
75 our $VERSION = '5.7013';
76
77 sub import {
78     my ( $class, @arguments ) = @_;
79
80     # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
81     # callers @ISA.
82     return unless $class eq 'Catalyst';
83
84     my $caller = caller(0);
85
86     #why does called have to ISA Catalyst and ISA Controller ?
87     unless ( $caller->isa('Catalyst') ) {
88         no strict 'refs';
89         if( $caller->can('meta') ){
90           my @superclasses = ($caller->meta->superclasses, $class, 'Catalyst::Controller');
91           $caller->meta->superclasses(@superclasses);
92         } else {
93           push @{"$caller\::ISA"}, $class, 'Catalyst::Controller';
94         }
95     }
96
97     $caller->arguments( [@arguments] );
98     $caller->setup_home;
99 }
100
101 =head1 NAME
102
103 Catalyst - The Elegant MVC Web Application Framework
104
105 =head1 SYNOPSIS
106
107 See the L<Catalyst::Manual> distribution for comprehensive
108 documentation and tutorials.
109
110     # Install Catalyst::Devel for helpers and other development tools
111     # use the helper to create a new application
112     catalyst.pl MyApp
113
114     # add models, views, controllers
115     script/myapp_create.pl model MyDatabase DBIC::Schema create=dynamic dbi:SQLite:/path/to/db
116     script/myapp_create.pl view MyTemplate TT
117     script/myapp_create.pl controller Search
118
119     # built in testserver -- use -r to restart automatically on changes
120     # --help to see all available options
121     script/myapp_server.pl
122
123     # command line testing interface
124     script/myapp_test.pl /yada
125
126     ### in lib/MyApp.pm
127     use Catalyst qw/-Debug/; # include plugins here as well
128
129     ### In lib/MyApp/Controller/Root.pm (autocreated)
130     sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
131         my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
132         $c->stash->{template} = 'foo.tt'; # set the template
133         # lookup something from db -- stash vars are passed to TT
134         $c->stash->{data} =
135           $c->model('Database::Foo')->search( { country => $args[0] } );
136         if ( $c->req->params->{bar} ) { # access GET or POST parameters
137             $c->forward( 'bar' ); # process another action
138             # do something else after forward returns
139         }
140     }
141
142     # The foo.tt TT template can use the stash data from the database
143     [% WHILE (item = data.next) %]
144         [% item.foo %]
145     [% END %]
146
147     # called for /bar/of/soap, /bar/of/soap/10, etc.
148     sub bar : Path('/bar/of/soap') { ... }
149
150     # called for all actions, from the top-most controller downwards
151     sub auto : Private {
152         my ( $self, $c ) = @_;
153         if ( !$c->user_exists ) { # Catalyst::Plugin::Authentication
154             $c->res->redirect( '/login' ); # require login
155             return 0; # abort request and go immediately to end()
156         }
157         return 1; # success; carry on to next action
158     }
159
160     # called after all actions are finished
161     sub end : Private {
162         my ( $self, $c ) = @_;
163         if ( scalar @{ $c->error } ) { ... } # handle errors
164         return if $c->res->body; # already have a response
165         $c->forward( 'MyApp::View::TT' ); # render template
166     }
167
168     ### in MyApp/Controller/Foo.pm
169     # called for /foo/bar
170     sub bar : Local { ... }
171
172     # called for /blargle
173     sub blargle : Global { ... }
174
175     # an index action matches /foo, but not /foo/1, etc.
176     sub index : Private { ... }
177
178     ### in MyApp/Controller/Foo/Bar.pm
179     # called for /foo/bar/baz
180     sub baz : Local { ... }
181
182     # first Root auto is called, then Foo auto, then this
183     sub auto : Private { ... }
184
185     # powerful regular expression paths are also possible
186     sub details : Regex('^product/(\w+)/details$') {
187         my ( $self, $c ) = @_;
188         # extract the (\w+) from the URI
189         my $product = $c->req->captures->[0];
190     }
191
192 See L<Catalyst::Manual::Intro> for additional information.
193
194 =head1 DESCRIPTION
195
196 Catalyst is a modern framework for making web applications without the
197 pain usually associated with this process. This document is a reference
198 to the main Catalyst application. If you are a new user, we suggest you
199 start with L<Catalyst::Manual::Tutorial> or L<Catalyst::Manual::Intro>.
200
201 See L<Catalyst::Manual> for more documentation.
202
203 Catalyst plugins can be loaded by naming them as arguments to the "use
204 Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the
205 plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes
206 C<My::Module>.
207
208     use Catalyst qw/My::Module/;
209
210 If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
211 fully qualify the name by using a unary plus:
212
213     use Catalyst qw/
214         My::Module
215         +Fully::Qualified::Plugin::Name
216     /;
217
218 Special flags like C<-Debug> and C<-Engine> can also be specified as
219 arguments when Catalyst is loaded:
220
221     use Catalyst qw/-Debug My::Module/;
222
223 The position of plugins and flags in the chain is important, because
224 they are loaded in the order in which they appear.
225
226 The following flags are supported:
227
228 =head2 -Debug
229
230 Enables debug output. You can also force this setting from the system
231 environment with CATALYST_DEBUG or <MYAPP>_DEBUG. The environment
232 settings override the application, with <MYAPP>_DEBUG having the highest
233 priority.
234
235 =head2 -Engine
236
237 Forces Catalyst to use a specific engine. Omit the
238 C<Catalyst::Engine::> prefix of the engine name, i.e.:
239
240     use Catalyst qw/-Engine=CGI/;
241
242 =head2 -Home
243
244 Forces Catalyst to use a specific home directory, e.g.:
245
246     use Catalyst qw[-Home=/usr/mst];
247
248 This can also be done in the shell environment by setting either the
249 C<CATALYST_HOME> environment variable or C<MYAPP_HOME>; where C<MYAPP>
250 is replaced with the uppercased name of your application, any "::" in
251 the name will be replaced with underscores, e.g. MyApp::Web should use
252 MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used.
253
254 =head2 -Log
255
256 Specifies log level.
257
258 =head2 -Stats
259
260 Enables statistics collection and reporting. You can also force this setting
261 from the system environment with CATALYST_STATS or <MYAPP>_STATS. The
262 environment settings override the application, with <MYAPP>_STATS having the
263 highest priority.
264
265 e.g.
266
267    use Catalyst qw/-Stats=1/
268
269 =head1 METHODS
270
271 =head2 INFORMATION ABOUT THE CURRENT REQUEST
272
273 =head2 $c->action
274
275 Returns a L<Catalyst::Action> object for the current action, which
276 stringifies to the action name. See L<Catalyst::Action>.
277
278 =head2 $c->namespace
279
280 Returns the namespace of the current action, i.e., the URI prefix
281 corresponding to the controller of the current action. For example:
282
283     # in Controller::Foo::Bar
284     $c->namespace; # returns 'foo/bar';
285
286 =head2 $c->request
287
288 =head2 $c->req
289
290 Returns the current L<Catalyst::Request> object, giving access to
291 information about the current client request (including parameters,
292 cookies, HTTP headers, etc.). See L<Catalyst::Request>.
293
294 =head2 REQUEST FLOW HANDLING
295
296 =head2 $c->forward( $action [, \@arguments ] )
297
298 =head2 $c->forward( $class, $method, [, \@arguments ] )
299
300 Forwards processing to another action, by its private name. If you give a
301 class name but no method, C<process()> is called. You may also optionally
302 pass arguments in an arrayref. The action will receive the arguments in
303 C<@_> and C<< $c->req->args >>. Upon returning from the function,
304 C<< $c->req->args >> will be restored to the previous values.
305
306 Any data C<return>ed from the action forwarded to, will be returned by the
307 call to forward.
308
309     my $foodata = $c->forward('/foo');
310     $c->forward('index');
311     $c->forward(qw/MyApp::Model::DBIC::Foo do_stuff/);
312     $c->forward('MyApp::View::TT');
313
314 Note that forward implies an C<<eval { }>> around the call (actually
315 C<execute> does), thus de-fatalizing all 'dies' within the called
316 action. If you want C<die> to propagate you need to do something like:
317
318     $c->forward('foo');
319     die $c->error if $c->error;
320
321 Or make sure to always return true values from your actions and write
322 your code like this:
323
324     $c->forward('foo') || return;
325
326 =cut
327
328 sub forward { my $c = shift; $c->dispatcher->forward( $c, @_ ) }
329
330 =head2 $c->detach( $action [, \@arguments ] )
331
332 =head2 $c->detach( $class, $method, [, \@arguments ] )
333
334 =head2 $c->detach()
335
336 The same as C<forward>, but doesn't return to the previous action when
337 processing is finished.
338
339 When called with no arguments it escapes the processing chain entirely.
340
341 =cut
342
343 sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
344
345 =head2 $c->response
346
347 =head2 $c->res
348
349 Returns the current L<Catalyst::Response> object, see there for details.
350
351 =head2 $c->stash
352
353 Returns a hashref to the stash, which may be used to store data and pass
354 it between components during a request. You can also set hash keys by
355 passing arguments. The stash is automatically sent to the view. The
356 stash is cleared at the end of a request; it cannot be used for
357 persistent storage (for this you must use a session; see
358 L<Catalyst::Plugin::Session> for a complete system integrated with
359 Catalyst).
360
361     $c->stash->{foo} = $bar;
362     $c->stash( { moose => 'majestic', qux => 0 } );
363     $c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref
364
365     # stash is automatically passed to the view for use in a template
366     $c->forward( 'MyApp::View::TT' );
367
368 =cut
369
370 around stash => sub {
371     my $orig = shift;
372     my $c = shift;
373     if (@_) {
374         my $stash = @_ > 1 ? {@_} : $_[0];
375         croak('stash takes a hash or hashref') unless ref $stash;
376         foreach my $key ( keys %$stash ) {
377             $c->$orig()->{$key} = $stash->{$key};
378         }
379     }
380     return $c->$orig();
381 };
382
383 =head2 $c->error
384
385 =head2 $c->error($error, ...)
386
387 =head2 $c->error($arrayref)
388
389 Returns an arrayref containing error messages.  If Catalyst encounters an
390 error while processing a request, it stores the error in $c->error.  This
391 method should only be used to store fatal error messages.
392
393     my @error = @{ $c->error };
394
395 Add a new error.
396
397     $c->error('Something bad happened');
398
399 =cut
400
401 sub error {
402     my $c = shift;
403     if ( $_[0] ) {
404         my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
405         croak @$error unless ref $c;
406         push @{ $c->{error} }, @$error;
407     }
408     elsif ( defined $_[0] ) { $c->{error} = undef }
409     return $c->{error} || [];
410 }
411
412
413 =head2 $c->state
414
415 Contains the return value of the last executed action.
416
417 =head2 $c->clear_errors
418
419 Clear errors.  You probably don't want to clear the errors unless you are
420 implementing a custom error screen.
421
422 This is equivalent to running
423
424     $c->error(0);
425
426 =cut
427
428 sub clear_errors {
429     my $c = shift;
430     $c->error(0);
431 }
432
433
434 # search via regex
435 sub _comp_search {
436     my ( $c, @names ) = @_;
437
438     foreach my $name (@names) {
439         foreach my $component ( keys %{ $c->components } ) {
440             return $c->components->{$component} if $component =~ /$name/i;
441         }
442     }
443
444     return undef;
445 }
446
447 # try explicit component names
448 sub _comp_explicit {
449     my ( $c, @names ) = @_;
450
451     foreach my $try (@names) {
452         return $c->components->{$try} if ( exists $c->components->{$try} );
453     }
454
455     return undef;
456 }
457
458 # like component, but try just these prefixes before regex searching,
459 #  and do not try to return "sort keys %{ $c->components }"
460 sub _comp_prefixes {
461     my ( $c, $name, @prefixes ) = @_;
462
463     my $appclass = ref $c || $c;
464
465     my @names = map { "${appclass}::${_}::${name}" } @prefixes;
466
467     my $comp = $c->_comp_explicit(@names);
468     return $comp if defined($comp);
469     $comp = $c->_comp_search($name);
470     return $comp;
471 }
472
473 # Find possible names for a prefix
474
475 sub _comp_names {
476     my ( $c, @prefixes ) = @_;
477
478     my $appclass = ref $c || $c;
479
480     my @pre = map { "${appclass}::${_}::" } @prefixes;
481
482     my @names;
483
484     COMPONENT: foreach my $comp ($c->component) {
485         foreach my $p (@pre) {
486             if ($comp =~ s/^$p//) {
487                 push(@names, $comp);
488                 next COMPONENT;
489             }
490         }
491     }
492
493     return @names;
494 }
495
496 # Return a component if only one matches.
497 sub _comp_singular {
498     my ( $c, @prefixes ) = @_;
499
500     my $appclass = ref $c || $c;
501
502     my ( $comp, $rest ) =
503       map { $c->_comp_search("^${appclass}::${_}::") } @prefixes;
504     return $comp unless $rest;
505 }
506
507 # Filter a component before returning by calling ACCEPT_CONTEXT if available
508 sub _filter_component {
509     my ( $c, $comp, @args ) = @_;
510     if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
511         return $comp->ACCEPT_CONTEXT( $c, @args );
512     }
513     else { return $comp }
514 }
515
516 =head2 COMPONENT ACCESSORS
517
518 =head2 $c->controller($name)
519
520 Gets a L<Catalyst::Controller> instance by name.
521
522     $c->controller('Foo')->do_stuff;
523
524 If the name is omitted, will return the controller for the dispatched
525 action.
526
527 =cut
528
529 sub controller {
530     my ( $c, $name, @args ) = @_;
531     return $c->_filter_component( $c->_comp_prefixes( $name, qw/Controller C/ ),
532         @args )
533       if ($name);
534     return $c->component( $c->action->class );
535 }
536
537 =head2 $c->model($name)
538
539 Gets a L<Catalyst::Model> instance by name.
540
541     $c->model('Foo')->do_stuff;
542
543 Any extra arguments are directly passed to ACCEPT_CONTEXT.
544
545 If the name is omitted, it will look for
546  - a model object in $c->stash{current_model_instance}, then
547  - a model name in $c->stash->{current_model}, then
548  - a config setting 'default_model', or
549  - check if there is only one model, and return it if that's the case.
550
551 =cut
552
553 sub model {
554     my ( $c, $name, @args ) = @_;
555     return $c->_filter_component( $c->_comp_prefixes( $name, qw/Model M/ ),
556         @args )
557       if $name;
558     if (ref $c) {
559         return $c->stash->{current_model_instance}
560           if $c->stash->{current_model_instance};
561         return $c->model( $c->stash->{current_model} )
562           if $c->stash->{current_model};
563     }
564     return $c->model( $c->config->{default_model} )
565       if $c->config->{default_model};
566     return $c->_filter_component( $c->_comp_singular(qw/Model M/) );
567
568 }
569
570 =head2 $c->controllers
571
572 Returns the available names which can be passed to $c->controller
573
574 =cut
575
576 sub controllers {
577     my ( $c ) = @_;
578     return $c->_comp_names(qw/Controller C/);
579 }
580
581
582 =head2 $c->view($name)
583
584 Gets a L<Catalyst::View> instance by name.
585
586     $c->view('Foo')->do_stuff;
587
588 Any extra arguments are directly passed to ACCEPT_CONTEXT.
589
590 If the name is omitted, it will look for
591  - a view object in $c->stash{current_view_instance}, then
592  - a view name in $c->stash->{current_view}, then
593  - a config setting 'default_view', or
594  - check if there is only one view, and return it if that's the case.
595
596 =cut
597
598 sub view {
599     my ( $c, $name, @args ) = @_;
600     return $c->_filter_component( $c->_comp_prefixes( $name, qw/View V/ ),
601         @args )
602       if $name;
603     if (ref $c) {
604         return $c->stash->{current_view_instance}
605           if $c->stash->{current_view_instance};
606         return $c->view( $c->stash->{current_view} )
607           if $c->stash->{current_view};
608     }
609     return $c->view( $c->config->{default_view} )
610       if $c->config->{default_view};
611     return $c->_filter_component( $c->_comp_singular(qw/View V/) );
612 }
613
614 =head2 $c->models
615
616 Returns the available names which can be passed to $c->model
617
618 =cut
619
620 sub models {
621     my ( $c ) = @_;
622     return $c->_comp_names(qw/Model M/);
623 }
624
625
626 =head2 $c->views
627
628 Returns the available names which can be passed to $c->view
629
630 =cut
631
632 sub views {
633     my ( $c ) = @_;
634     return $c->_comp_names(qw/View V/);
635 }
636
637 =head2 $c->comp($name)
638
639 =head2 $c->component($name)
640
641 Gets a component object by name. This method is not recommended,
642 unless you want to get a specific component by full
643 class. C<< $c->controller >>, C<< $c->model >>, and C<< $c->view >>
644 should be used instead.
645
646 =cut
647
648 sub component {
649     my $c = shift;
650
651     if (@_) {
652
653         my $name = shift;
654
655         my $appclass = ref $c || $c;
656
657         my @names = (
658             $name, "${appclass}::${name}",
659             map { "${appclass}::${_}::${name}" }
660               qw/Model M Controller C View V/
661         );
662
663         my $comp = $c->_comp_explicit(@names);
664         return $c->_filter_component( $comp, @_ ) if defined($comp);
665
666         $comp = $c->_comp_search($name);
667         return $c->_filter_component( $comp, @_ ) if defined($comp);
668     }
669
670     return sort keys %{ $c->components };
671 }
672
673
674
675 =head2 CLASS DATA AND HELPER CLASSES
676
677 =head2 $c->config
678
679 Returns or takes a hashref containing the application's configuration.
680
681     __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } );
682
683 You can also use a C<YAML>, C<XML> or C<Config::General> config file
684 like myapp.yml in your applications home directory. See
685 L<Catalyst::Plugin::ConfigLoader>.
686
687     ---
688     db: dsn:SQLite:foo.db
689
690
691 =cut
692
693 around config => sub {
694     my $orig = shift;
695     my $c = shift;
696
697     $c->log->warn("Setting config after setup has been run is not a good idea.")
698       if ( @_ and $c->setup_finished );
699
700     $c->$orig(@_);
701 };
702
703 =head2 $c->log
704
705 Returns the logging object instance. Unless it is already set, Catalyst
706 sets this up with a L<Catalyst::Log> object. To use your own log class,
707 set the logger with the C<< __PACKAGE__->log >> method prior to calling
708 C<< __PACKAGE__->setup >>.
709
710  __PACKAGE__->log( MyLogger->new );
711  __PACKAGE__->setup;
712
713 And later:
714
715     $c->log->info( 'Now logging with my own logger!' );
716
717 Your log class should implement the methods described in
718 L<Catalyst::Log>.
719
720
721 =head2 $c->debug
722
723 Overload to enable debug messages (same as -Debug option).
724
725 Note that this is a static method, not an accessor and should be overloaded
726 by declaring "sub debug { 1 }" in your MyApp.pm, not by calling $c->debug(1).
727
728 =cut
729
730 sub debug { 0 }
731
732 =head2 $c->dispatcher
733
734 Returns the dispatcher instance. Stringifies to class name. See
735 L<Catalyst::Dispatcher>.
736
737 =head2 $c->engine
738
739 Returns the engine instance. Stringifies to the class name. See
740 L<Catalyst::Engine>.
741
742
743 =head2 UTILITY METHODS
744
745 =head2 $c->path_to(@path)
746
747 Merges C<@path> with C<< $c->config->{home} >> and returns a
748 L<Path::Class::Dir> object.
749
750 For example:
751
752     $c->path_to( 'db', 'sqlite.db' );
753
754 =cut
755
756 sub path_to {
757     my ( $c, @path ) = @_;
758     my $path = Path::Class::Dir->new( $c->config->{home}, @path );
759     if ( -d $path ) { return $path }
760     else { return Path::Class::File->new( $c->config->{home}, @path ) }
761 }
762
763 =head2 $c->plugin( $name, $class, @args )
764
765 Helper method for plugins. It creates a classdata accessor/mutator and
766 loads and instantiates the given class.
767
768     MyApp->plugin( 'prototype', 'HTML::Prototype' );
769
770     $c->prototype->define_javascript_functions;
771
772 =cut
773
774 sub plugin {
775     my ( $class, $name, $plugin, @args ) = @_;
776     $class->_register_plugin( $plugin, 1 );
777
778     eval { $plugin->import };
779     $class->mk_classdata($name);
780     my $obj;
781     eval { $obj = $plugin->new(@args) };
782
783     if ($@) {
784         Catalyst::Exception->throw( message =>
785               qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
786     }
787
788     $class->$name($obj);
789     $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
790       if $class->debug;
791 }
792
793 =head2 MyApp->setup
794
795 Initializes the dispatcher and engine, loads any plugins, and loads the
796 model, view, and controller components. You may also specify an array
797 of plugins to load here, if you choose to not load them in the C<use
798 Catalyst> line.
799
800     MyApp->setup;
801     MyApp->setup( qw/-Debug/ );
802
803 =cut
804
805 sub setup {
806     my ( $class, @arguments ) = @_;
807
808     $class->log->warn("Running setup twice is not a good idea.")
809       if ( $class->setup_finished );
810
811     unless ( $class->isa('Catalyst') ) {
812
813         Catalyst::Exception->throw(
814             message => qq/'$class' does not inherit from Catalyst/ );
815     }
816
817     if ( $class->arguments ) {
818         @arguments = ( @arguments, @{ $class->arguments } );
819     }
820
821     # Process options
822     my $flags = {};
823
824     foreach (@arguments) {
825
826         if (/^-Debug$/) {
827             $flags->{log} =
828               ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
829         }
830         elsif (/^-(\w+)=?(.*)$/) {
831             $flags->{ lc $1 } = $2;
832         }
833         else {
834             push @{ $flags->{plugins} }, $_;
835         }
836     }
837
838     $class->setup_home( delete $flags->{home} );
839
840     $class->setup_log( delete $flags->{log} );
841     $class->setup_plugins( delete $flags->{plugins} );
842     $class->setup_dispatcher( delete $flags->{dispatcher} );
843     $class->setup_engine( delete $flags->{engine} );
844     $class->setup_stats( delete $flags->{stats} );
845
846     for my $flag ( sort keys %{$flags} ) {
847
848         if ( my $code = $class->can( 'setup_' . $flag ) ) {
849             &$code( $class, delete $flags->{$flag} );
850         }
851         else {
852             $class->log->warn(qq/Unknown flag "$flag"/);
853         }
854     }
855
856     eval { require Catalyst::Devel; };
857     if( !$@ && $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::Devel::CATALYST_SCRIPT_GEN ) ) {
858         $class->log->warn(<<"EOF");
859 You are running an old script!
860
861   Please update by running (this will overwrite existing files):
862     catalyst.pl -force -scripts $class
863
864   or (this will not overwrite existing files):
865     catalyst.pl -scripts $class
866
867 EOF
868     }
869
870     if ( $class->debug ) {
871         my @plugins = map { "$_  " . ( $_->VERSION || '' ) } $class->registered_plugins;
872
873         if (@plugins) {
874             my $t = Text::SimpleTable->new(74);
875             $t->row($_) for @plugins;
876             $class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" );
877         }
878
879         my $dispatcher = $class->dispatcher;
880         my $engine     = $class->engine;
881         my $home       = $class->config->{home};
882
883         $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
884         $class->log->debug(qq/Loaded engine "$engine"/);
885
886         $home
887           ? ( -d $home )
888           ? $class->log->debug(qq/Found home "$home"/)
889           : $class->log->debug(qq/Home "$home" doesn't exist/)
890           : $class->log->debug(q/Couldn't find home/);
891     }
892
893     # Call plugins setup
894     {
895         no warnings qw/redefine/;
896         local *setup = sub { };
897         $class->setup;
898     }
899
900     # Initialize our data structure
901     $class->components( {} );
902
903     $class->setup_components;
904
905     if ( $class->debug ) {
906         my $t = Text::SimpleTable->new( [ 63, 'Class' ], [ 8, 'Type' ] );
907         for my $comp ( sort keys %{ $class->components } ) {
908             my $type = ref $class->components->{$comp} ? 'instance' : 'class';
909             $t->row( $comp, $type );
910         }
911         $class->log->debug( "Loaded components:\n" . $t->draw . "\n" )
912           if ( keys %{ $class->components } );
913     }
914
915     # Add our self to components, since we are also a component
916     $class->components->{$class} = $class;
917
918     $class->setup_actions;
919
920     if ( $class->debug ) {
921         my $name = $class->config->{name} || 'Application';
922         $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
923     }
924     $class->log->_flush() if $class->log->can('_flush');
925
926     $class->setup_finished(1);
927 }
928
929 =head2 $c->uri_for( $path, @args?, \%query_values? )
930
931 Merges path with C<< $c->request->base >> for absolute URIs and with
932 C<< $c->namespace >> for relative URIs, then returns a normalized L<URI>
933 object. If any args are passed, they are added at the end of the path.
934 If the last argument to C<uri_for> is a hash reference, it is assumed to
935 contain GET parameter key/value pairs, which will be appended to the URI
936 in standard fashion.
937
938 Note that uri_for is destructive to the passed hashref.  Subsequent calls
939 with the same hashref may have unintended results.
940
941 Instead of C<$path>, you can also optionally pass a C<$action> object
942 which will be resolved to a path using
943 C<< $c->dispatcher->uri_for_action >>; if the first element of
944 C<@args> is an arrayref it is treated as a list of captures to be passed
945 to C<uri_for_action>.
946
947 =cut
948
949 sub uri_for {
950     my ( $c, $path, @args ) = @_;
951
952     if ( Scalar::Util::blessed($path) ) { # action object
953         my $captures = ( scalar @args && ref $args[0] eq 'ARRAY'
954                          ? shift(@args)
955                          : [] );
956         $path = $c->dispatcher->uri_for_action($path, $captures);
957         return undef unless defined($path);
958         $path = '/' if $path eq '';
959     }
960
961     undef($path) if (defined $path && $path eq '');
962
963     my $params =
964       ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
965
966     carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
967     s/([^$URI::uric])/$URI::Escape::escapes{$1}/go for @args;
968
969     unshift(@args, $path);
970
971     unless (defined $path && $path =~ s!^/!!) { # in-place strip
972         my $namespace = $c->namespace;
973         if (defined $path) { # cheesy hack to handle path '../foo'
974            $namespace =~ s{(?:^|/)[^/]+$}{} while $args[0] =~ s{^\.\./}{};
975         }
976         unshift(@args, $namespace || '');
977     }
978
979     # join args with '/', or a blank string
980     my $args = join('/', grep { defined($_) } @args);
981     $args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
982     $args =~ s!^/!!;
983     my $base = $c->req->base;
984     my $class = ref($base);
985     $base =~ s{(?<!/)$}{/};
986
987     my $query = '';
988
989     if (my @keys = keys %$params) {
990       # somewhat lifted from URI::_query's query_form
991       $query = '?'.join('&', map {
992           s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
993           s/ /+/g;
994           my $key = $_;
995           my $val = $params->{$_};
996           $val = '' unless defined $val;
997           (map {
998               $_ = "$_";
999               utf8::encode( $_ ) if utf8::is_utf8($_);
1000               # using the URI::Escape pattern here so utf8 chars survive
1001               s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
1002               s/ /+/g;
1003               "${key}=$_"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
1004       } @keys);
1005     }
1006
1007     my $res = bless(\"${base}${args}${query}", $class);
1008     $res;
1009 }
1010
1011 =head2 $c->welcome_message
1012
1013 Returns the Catalyst welcome HTML page.
1014
1015 =cut
1016
1017 sub welcome_message {
1018     my $c      = shift;
1019     my $name   = $c->config->{name};
1020     my $logo   = $c->uri_for('/static/images/catalyst_logo.png');
1021     my $prefix = Catalyst::Utils::appprefix( ref $c );
1022     $c->response->content_type('text/html; charset=utf-8');
1023     return <<"EOF";
1024 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1025     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1026 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1027     <head>
1028     <meta http-equiv="Content-Language" content="en" />
1029     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1030         <title>$name on Catalyst $VERSION</title>
1031         <style type="text/css">
1032             body {
1033                 color: #000;
1034                 background-color: #eee;
1035             }
1036             div#content {
1037                 width: 640px;
1038                 margin-left: auto;
1039                 margin-right: auto;
1040                 margin-top: 10px;
1041                 margin-bottom: 10px;
1042                 text-align: left;
1043                 background-color: #ccc;
1044                 border: 1px solid #aaa;
1045             }
1046             p, h1, h2 {
1047                 margin-left: 20px;
1048                 margin-right: 20px;
1049                 font-family: verdana, tahoma, sans-serif;
1050             }
1051             a {
1052                 font-family: verdana, tahoma, sans-serif;
1053             }
1054             :link, :visited {
1055                     text-decoration: none;
1056                     color: #b00;
1057                     border-bottom: 1px dotted #bbb;
1058             }
1059             :link:hover, :visited:hover {
1060                     color: #555;
1061             }
1062             div#topbar {
1063                 margin: 0px;
1064             }
1065             pre {
1066                 margin: 10px;
1067                 padding: 8px;
1068             }
1069             div#answers {
1070                 padding: 8px;
1071                 margin: 10px;
1072                 background-color: #fff;
1073                 border: 1px solid #aaa;
1074             }
1075             h1 {
1076                 font-size: 0.9em;
1077                 font-weight: normal;
1078                 text-align: center;
1079             }
1080             h2 {
1081                 font-size: 1.0em;
1082             }
1083             p {
1084                 font-size: 0.9em;
1085             }
1086             p img {
1087                 float: right;
1088                 margin-left: 10px;
1089             }
1090             span#appname {
1091                 font-weight: bold;
1092                 font-size: 1.6em;
1093             }
1094         </style>
1095     </head>
1096     <body>
1097         <div id="content">
1098             <div id="topbar">
1099                 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
1100                     $VERSION</h1>
1101              </div>
1102              <div id="answers">
1103                  <p>
1104                  <img src="$logo" alt="Catalyst Logo" />
1105                  </p>
1106                  <p>Welcome to the  world of Catalyst.
1107                     This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
1108                     framework will make web development something you had
1109                     never expected it to be: Fun, rewarding, and quick.</p>
1110                  <h2>What to do now?</h2>
1111                  <p>That really depends  on what <b>you</b> want to do.
1112                     We do, however, provide you with a few starting points.</p>
1113                  <p>If you want to jump right into web development with Catalyst
1114                     you might want want to start with a tutorial.</p>
1115 <pre>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
1116 </pre>
1117 <p>Afterwards you can go on to check out a more complete look at our features.</p>
1118 <pre>
1119 <code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
1120 <!-- Something else should go here, but the Catalyst::Manual link seems unhelpful -->
1121 </code></pre>
1122                  <h2>What to do next?</h2>
1123                  <p>Next it's time to write an actual application. Use the
1124                     helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&amp;mode=all">controllers</a>,
1125                     <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&amp;mode=all">models</a>, and
1126                     <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&amp;mode=all">views</a>;
1127                     they can save you a lot of work.</p>
1128                     <pre><code>script/${prefix}_create.pl -help</code></pre>
1129                     <p>Also, be sure to check out the vast and growing
1130                     collection of <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3APlugin%3A%3A&amp;mode=all">plugins for Catalyst on CPAN</a>;
1131                     you are likely to find what you need there.
1132                     </p>
1133
1134                  <h2>Need help?</h2>
1135                  <p>Catalyst has a very active community. Here are the main places to
1136                     get in touch with us.</p>
1137                  <ul>
1138                      <li>
1139                          <a href="http://dev.catalyst.perl.org">Wiki</a>
1140                      </li>
1141                      <li>
1142                          <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
1143                      </li>
1144                      <li>
1145                          <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
1146                      </li>
1147                  </ul>
1148                  <h2>In conclusion</h2>
1149                  <p>The Catalyst team hopes you will enjoy using Catalyst as much
1150                     as we enjoyed making it. Please contact us if you have ideas
1151                     for improvement or other feedback.</p>
1152              </div>
1153          </div>
1154     </body>
1155 </html>
1156 EOF
1157 }
1158
1159 =head1 INTERNAL METHODS
1160
1161 These methods are not meant to be used by end users.
1162
1163 =head2 $c->components
1164
1165 Returns a hash of components.
1166
1167 =head2 $c->context_class
1168
1169 Returns or sets the context class.
1170
1171 =head2 $c->counter
1172
1173 Returns a hashref containing coderefs and execution counts (needed for
1174 deep recursion detection).
1175
1176 =head2 $c->depth
1177
1178 Returns the number of actions on the current internal execution stack.
1179
1180 =head2 $c->dispatch
1181
1182 Dispatches a request to actions.
1183
1184 =cut
1185
1186 sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
1187
1188 =head2 $c->dispatcher_class
1189
1190 Returns or sets the dispatcher class.
1191
1192 =head2 $c->dump_these
1193
1194 Returns a list of 2-element array references (name, structure) pairs
1195 that will be dumped on the error page in debug mode.
1196
1197 =cut
1198
1199 sub dump_these {
1200     my $c = shift;
1201     [ Request => $c->req ],
1202     [ Response => $c->res ],
1203     [ Stash => $c->stash ],
1204     [ Config => $c->config ];
1205 }
1206
1207 =head2 $c->engine_class
1208
1209 Returns or sets the engine class.
1210
1211 =head2 $c->execute( $class, $coderef )
1212
1213 Execute a coderef in given class and catch exceptions. Errors are available
1214 via $c->error.
1215
1216 =cut
1217
1218 sub execute {
1219     my ( $c, $class, $code ) = @_;
1220     $class = $c->component($class) || $class;
1221     $c->state(0);
1222
1223     if ( $c->depth >= $RECURSION ) {
1224         my $action = "$code";
1225         $action = "/$action" unless $action =~ /->/;
1226         my $error = qq/Deep recursion detected calling "$action"/;
1227         $c->log->error($error);
1228         $c->error($error);
1229         $c->state(0);
1230         return $c->state;
1231     }
1232
1233     my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats;
1234
1235     push( @{ $c->stack }, $code );
1236
1237     eval { $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 ) };
1238
1239     $c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info;
1240
1241     my $last = pop( @{ $c->stack } );
1242
1243     if ( my $error = $@ ) {
1244         if ( !ref($error) and $error eq $DETACH ) { die $DETACH if $c->depth > 1 }
1245         else {
1246             unless ( ref $error ) {
1247                 no warnings 'uninitialized';
1248                 chomp $error;
1249                 my $class = $last->class;
1250                 my $name  = $last->name;
1251                 $error = qq/Caught exception in $class->$name "$error"/;
1252             }
1253             $c->error($error);
1254             $c->state(0);
1255         }
1256     }
1257     return $c->state;
1258 }
1259
1260 sub _stats_start_execute {
1261     my ( $c, $code ) = @_;
1262
1263     return if ( ( $code->name =~ /^_.*/ )
1264         && ( !$c->config->{show_internal_actions} ) );
1265
1266     $c->counter->{"$code"}++;
1267
1268     my $action = "$code";
1269     $action = "/$action" unless $action =~ /->/;
1270
1271     # determine if the call was the result of a forward
1272     # this is done by walking up the call stack and looking for a calling
1273     # sub of Catalyst::forward before the eval
1274     my $callsub = q{};
1275     for my $index ( 2 .. 11 ) {
1276         last
1277         if ( ( caller($index) )[0] eq 'Catalyst'
1278             && ( caller($index) )[3] eq '(eval)' );
1279
1280         if ( ( caller($index) )[3] =~ /forward$/ ) {
1281             $callsub = ( caller($index) )[3];
1282             $action  = "-> $action";
1283             last;
1284         }
1285     }
1286
1287     my $uid = "$code" . $c->counter->{"$code"};
1288
1289     # is this a root-level call or a forwarded call?
1290     if ( $callsub =~ /forward$/ ) {
1291
1292         # forward, locate the caller
1293         if ( my $parent = $c->stack->[-1] ) {
1294             $c->stats->profile(
1295                 begin  => $action,
1296                 parent => "$parent" . $c->counter->{"$parent"},
1297                 uid    => $uid,
1298             );
1299         }
1300         else {
1301
1302             # forward with no caller may come from a plugin
1303             $c->stats->profile(
1304                 begin => $action,
1305                 uid   => $uid,
1306             );
1307         }
1308     }
1309     else {
1310
1311         # root-level call
1312         $c->stats->profile(
1313             begin => $action,
1314             uid   => $uid,
1315         );
1316     }
1317     return $action;
1318
1319 }
1320
1321 sub _stats_finish_execute {
1322     my ( $c, $info ) = @_;
1323     $c->stats->profile( end => $info );
1324 }
1325
1326 =head2 $c->_localize_fields( sub { }, \%keys );
1327
1328 =cut
1329
1330 #Why does this exist? This is no longer safe and WILL NOT WORK.
1331 # it doesnt seem to be used anywhere. can we remove it?
1332 sub _localize_fields {
1333     my ( $c, $localized, $code ) = ( @_ );
1334
1335     my $request = delete $localized->{request} || {};
1336     my $response = delete $localized->{response} || {};
1337
1338     local @{ $c }{ keys %$localized } = values %$localized;
1339     local @{ $c->request }{ keys %$request } = values %$request;
1340     local @{ $c->response }{ keys %$response } = values %$response;
1341
1342     $code->();
1343 }
1344
1345 =head2 $c->finalize
1346
1347 Finalizes the request.
1348
1349 =cut
1350
1351 sub finalize {
1352     my $c = shift;
1353
1354     for my $error ( @{ $c->error } ) {
1355         $c->log->error($error);
1356     }
1357
1358     # Allow engine to handle finalize flow (for POE)
1359     my $engine = $c->engine;
1360     if ( my $code = $engine->can('finalize') ) {
1361         $engine->$code($c);
1362     }
1363     else {
1364
1365         $c->finalize_uploads;
1366
1367         # Error
1368         if ( $#{ $c->error } >= 0 ) {
1369             $c->finalize_error;
1370         }
1371
1372         $c->finalize_headers;
1373
1374         # HEAD request
1375         if ( $c->request->method eq 'HEAD' ) {
1376             $c->response->body('');
1377         }
1378
1379         $c->finalize_body;
1380     }
1381
1382     if ($c->use_stats) {
1383         my $elapsed = sprintf '%f', $c->stats->elapsed;
1384         my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
1385         $c->log->info(
1386             "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
1387     }
1388
1389     return $c->response->status;
1390 }
1391
1392 =head2 $c->finalize_body
1393
1394 Finalizes body.
1395
1396 =cut
1397
1398 sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1399
1400 =head2 $c->finalize_cookies
1401
1402 Finalizes cookies.
1403
1404 =cut
1405
1406 sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
1407
1408 =head2 $c->finalize_error
1409
1410 Finalizes error.
1411
1412 =cut
1413
1414 sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1415
1416 =head2 $c->finalize_headers
1417
1418 Finalizes headers.
1419
1420 =cut
1421
1422 sub finalize_headers {
1423     my $c = shift;
1424
1425     my $response = $c->response; #accessor calls can add up?
1426
1427     # Moose TODO: Maybe this should be an attribute too?
1428     # Check if we already finalized headers
1429     return if $response->{_finalized_headers};
1430
1431     # Handle redirects
1432     if ( my $location = $response->redirect ) {
1433         $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
1434         $response->header( Location => $location );
1435
1436         #Moose TODO: we should probably be using a predicate method here ?
1437         if ( !$response->body ) {
1438             # Add a default body if none is already present
1439             $response->body(
1440                 qq{<html><body><p>This item has moved <a href="$location">here</a>.</p></body></html>}
1441             );
1442         }
1443     }
1444
1445     # Content-Length
1446     if ( $response->body && !$response->content_length ) {
1447
1448         # get the length from a filehandle
1449         if ( blessed( $response->body ) && $response->body->can('read') )
1450         {
1451             my $stat = stat $response->body;
1452             if ( $stat && $stat->size > 0 ) {
1453                 $response->content_length( $stat->size );
1454             }
1455             else {
1456                 $c->log->warn('Serving filehandle without a content-length');
1457             }
1458         }
1459         else {
1460             # everything should be bytes at this point, but just in case
1461             $response->content_length( bytes::length( $response->body ) );
1462         }
1463     }
1464
1465     # Errors
1466     if ( $response->status =~ /^(1\d\d|[23]04)$/ ) {
1467         $response->headers->remove_header("Content-Length");
1468         $response->body('');
1469     }
1470
1471     $c->finalize_cookies;
1472
1473     $c->engine->finalize_headers( $c, @_ );
1474
1475     # Done
1476     $response->{_finalized_headers} = 1;
1477 }
1478
1479 =head2 $c->finalize_output
1480
1481 An alias for finalize_body.
1482
1483 =head2 $c->finalize_read
1484
1485 Finalizes the input after reading is complete.
1486
1487 =cut
1488
1489 sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1490
1491 =head2 $c->finalize_uploads
1492
1493 Finalizes uploads. Cleans up any temporary files.
1494
1495 =cut
1496
1497 sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1498
1499 =head2 $c->get_action( $action, $namespace )
1500
1501 Gets an action in a given namespace.
1502
1503 =cut
1504
1505 sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
1506
1507 =head2 $c->get_actions( $action, $namespace )
1508
1509 Gets all actions of a given name in a namespace and all parent
1510 namespaces.
1511
1512 =cut
1513
1514 sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1515
1516 =head2 $c->handle_request( $class, @arguments )
1517
1518 Called to handle each HTTP request.
1519
1520 =cut
1521
1522 sub handle_request {
1523     my ( $class, @arguments ) = @_;
1524
1525     # Always expect worst case!
1526     my $status = -1;
1527     eval {
1528         if ($class->debug) {
1529             my $secs = time - $START || 1;
1530             my $av = sprintf '%.3f', $COUNT / $secs;
1531             my $time = localtime time;
1532             $class->log->info("*** Request $COUNT ($av/s) [$$] [$time] ***");
1533         }
1534
1535         my $c = $class->prepare(@arguments);
1536         $c->dispatch;
1537         $status = $c->finalize;
1538     };
1539
1540     if ( my $error = $@ ) {
1541         chomp $error;
1542         $class->log->error(qq/Caught exception in engine "$error"/);
1543     }
1544
1545     $COUNT++;
1546     $class->log->_flush() if $class->log->can('_flush');
1547     return $status;
1548 }
1549
1550 =head2 $c->prepare( @arguments )
1551
1552 Creates a Catalyst context from an engine-specific request (Apache, CGI,
1553 etc.).
1554
1555 =cut
1556
1557 sub prepare {
1558     my ( $class, @arguments ) = @_;
1559
1560     $class->context_class( ref $class || $class ) unless $class->context_class;
1561     #Moose TODO: if we make empty containers the defaults then that can be
1562     #handled by the context class itself instead of having this here
1563     my $c = $class->context_class->new(
1564         {
1565             counter => {},
1566             stack   => [],
1567             request => $class->request_class->new(
1568                 {
1569                     arguments        => [],
1570                     body_parameters  => {},
1571                     cookies          => {},
1572                     headers          => HTTP::Headers->new,
1573                     parameters       => {},
1574                     query_parameters => {},
1575                     secure           => 0,
1576                     captures         => [],
1577                     uploads          => {}
1578                 }
1579             ),
1580             response => $class->response_class->new(
1581                 {
1582                     body    => '',
1583                     cookies => {},
1584                     headers => HTTP::Headers->new(),
1585                     status  => 200
1586                 }
1587             ),
1588             stash => {},
1589             state => 0
1590         }
1591     );
1592
1593     $c->stats($class->stats_class->new)->enable($c->use_stats);
1594     if ( $c->debug ) {
1595         $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
1596     }
1597
1598     # For on-demand data
1599     $c->request->_context($c);
1600     $c->response->_context($c);
1601
1602     #XXX reuse coderef from can
1603     # Allow engine to direct the prepare flow (for POE)
1604     if ( $c->engine->can('prepare') ) {
1605         $c->engine->prepare( $c, @arguments );
1606     }
1607     else {
1608         $c->prepare_request(@arguments);
1609         $c->prepare_connection;
1610         $c->prepare_query_parameters;
1611         $c->prepare_headers;
1612         $c->prepare_cookies;
1613         $c->prepare_path;
1614
1615         # Prepare the body for reading, either by prepare_body
1616         # or the user, if they are using $c->read
1617         $c->prepare_read;
1618
1619         # Parse the body unless the user wants it on-demand
1620         unless ( $c->config->{parse_on_demand} ) {
1621             $c->prepare_body;
1622         }
1623     }
1624
1625     my $method  = $c->req->method  || '';
1626     my $path    = $c->req->path    || '/';
1627     my $address = $c->req->address || '';
1628
1629     $c->log->debug(qq/"$method" request for "$path" from "$address"/)
1630       if $c->debug;
1631
1632     $c->prepare_action;
1633
1634     return $c;
1635 }
1636
1637 =head2 $c->prepare_action
1638
1639 Prepares action. See L<Catalyst::Dispatcher>.
1640
1641 =cut
1642
1643 sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1644
1645 =head2 $c->prepare_body
1646
1647 Prepares message body.
1648
1649 =cut
1650
1651 sub prepare_body {
1652     my $c = shift;
1653
1654     #Moose TODO: what is  _body ??
1655     # Do we run for the first time?
1656     return if defined $c->request->{_body};
1657
1658     # Initialize on-demand data
1659     $c->engine->prepare_body( $c, @_ );
1660     $c->prepare_parameters;
1661     $c->prepare_uploads;
1662
1663     if ( $c->debug && keys %{ $c->req->body_parameters } ) {
1664         my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1665         for my $key ( sort keys %{ $c->req->body_parameters } ) {
1666             my $param = $c->req->body_parameters->{$key};
1667             my $value = defined($param) ? $param : '';
1668             $t->row( $key,
1669                 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1670         }
1671         $c->log->debug( "Body Parameters are:\n" . $t->draw );
1672     }
1673 }
1674
1675 =head2 $c->prepare_body_chunk( $chunk )
1676
1677 Prepares a chunk of data before sending it to L<HTTP::Body>.
1678
1679 See L<Catalyst::Engine>.
1680
1681 =cut
1682
1683 sub prepare_body_chunk {
1684     my $c = shift;
1685     $c->engine->prepare_body_chunk( $c, @_ );
1686 }
1687
1688 =head2 $c->prepare_body_parameters
1689
1690 Prepares body parameters.
1691
1692 =cut
1693
1694 sub prepare_body_parameters {
1695     my $c = shift;
1696     $c->engine->prepare_body_parameters( $c, @_ );
1697 }
1698
1699 =head2 $c->prepare_connection
1700
1701 Prepares connection.
1702
1703 =cut
1704
1705 sub prepare_connection {
1706     my $c = shift;
1707     $c->engine->prepare_connection( $c, @_ );
1708 }
1709
1710 =head2 $c->prepare_cookies
1711
1712 Prepares cookies.
1713
1714 =cut
1715
1716 sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1717
1718 =head2 $c->prepare_headers
1719
1720 Prepares headers.
1721
1722 =cut
1723
1724 sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1725
1726 =head2 $c->prepare_parameters
1727
1728 Prepares parameters.
1729
1730 =cut
1731
1732 sub prepare_parameters {
1733     my $c = shift;
1734     $c->prepare_body_parameters;
1735     $c->engine->prepare_parameters( $c, @_ );
1736 }
1737
1738 =head2 $c->prepare_path
1739
1740 Prepares path and base.
1741
1742 =cut
1743
1744 sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1745
1746 =head2 $c->prepare_query_parameters
1747
1748 Prepares query parameters.
1749
1750 =cut
1751
1752 sub prepare_query_parameters {
1753     my $c = shift;
1754
1755     $c->engine->prepare_query_parameters( $c, @_ );
1756
1757     if ( $c->debug && keys %{ $c->request->query_parameters } ) {
1758         my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
1759         for my $key ( sort keys %{ $c->req->query_parameters } ) {
1760             my $param = $c->req->query_parameters->{$key};
1761             my $value = defined($param) ? $param : '';
1762             $t->row( $key,
1763                 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1764         }
1765         $c->log->debug( "Query Parameters are:\n" . $t->draw );
1766     }
1767 }
1768
1769 =head2 $c->prepare_read
1770
1771 Prepares the input for reading.
1772
1773 =cut
1774
1775 sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1776
1777 =head2 $c->prepare_request
1778
1779 Prepares the engine request.
1780
1781 =cut
1782
1783 sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1784
1785 =head2 $c->prepare_uploads
1786
1787 Prepares uploads.
1788
1789 =cut
1790
1791 sub prepare_uploads {
1792     my $c = shift;
1793
1794     $c->engine->prepare_uploads( $c, @_ );
1795
1796     if ( $c->debug && keys %{ $c->request->uploads } ) {
1797         my $t = Text::SimpleTable->new(
1798             [ 12, 'Parameter' ],
1799             [ 26, 'Filename' ],
1800             [ 18, 'Type' ],
1801             [ 9,  'Size' ]
1802         );
1803         for my $key ( sort keys %{ $c->request->uploads } ) {
1804             my $upload = $c->request->uploads->{$key};
1805             for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
1806                 $t->row( $key, $u->filename, $u->type, $u->size );
1807             }
1808         }
1809         $c->log->debug( "File Uploads are:\n" . $t->draw );
1810     }
1811 }
1812
1813 =head2 $c->prepare_write
1814
1815 Prepares the output for writing.
1816
1817 =cut
1818
1819 sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1820
1821 =head2 $c->request_class
1822
1823 Returns or sets the request class.
1824
1825 =head2 $c->response_class
1826
1827 Returns or sets the response class.
1828
1829 =head2 $c->read( [$maxlength] )
1830
1831 Reads a chunk of data from the request body. This method is designed to
1832 be used in a while loop, reading C<$maxlength> bytes on every call.
1833 C<$maxlength> defaults to the size of the request if not specified.
1834
1835 You have to set C<< MyApp->config->{parse_on_demand} >> to use this
1836 directly.
1837
1838 Warning: If you use read(), Catalyst will not process the body,
1839 so you will not be able to access POST parameters or file uploads via
1840 $c->request.  You must handle all body parsing yourself.
1841
1842 =cut
1843
1844 sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1845
1846 =head2 $c->run
1847
1848 Starts the engine.
1849
1850 =cut
1851
1852 sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1853
1854 =head2 $c->set_action( $action, $code, $namespace, $attrs )
1855
1856 Sets an action in a given namespace.
1857
1858 =cut
1859
1860 sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1861
1862 =head2 $c->setup_actions($component)
1863
1864 Sets up actions for a component.
1865
1866 =cut
1867
1868 sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1869
1870 =head2 $c->setup_components
1871
1872 Sets up components. Specify a C<setup_components> config option to pass
1873 additional options directly to L<Module::Pluggable>. To add additional
1874 search paths, specify a key named C<search_extra> as an array
1875 reference. Items in the array beginning with C<::> will have the
1876 application class name prepended to them.
1877
1878 =cut
1879
1880 sub setup_components {
1881     my $class = shift;
1882
1883     my @paths   = qw( ::Controller ::C ::Model ::M ::View ::V );
1884     my $config  = $class->config->{ setup_components };
1885     my $extra   = delete $config->{ search_extra } || [];
1886
1887     push @paths, @$extra;
1888
1889     my $locator = Module::Pluggable::Object->new(
1890         search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
1891         %$config
1892     );
1893
1894     my @comps = sort { length $a <=> length $b } $locator->plugins;
1895     my %comps = map { $_ => 1 } @comps;
1896
1897     for my $component ( @comps ) {
1898
1899         # We pass ignore_loaded here so that overlay files for (e.g.)
1900         # Model::DBI::Schema sub-classes are loaded - if it's in @comps
1901         # we know M::P::O found a file on disk so this is safe
1902
1903         #Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } );
1904         Class::MOP::load_class($component);
1905
1906         my $module  = $class->setup_component( $component );
1907         my %modules = (
1908             $component => $module,
1909             map {
1910                 $_ => $class->setup_component( $_ )
1911             } grep {
1912               not exists $comps{$_}
1913             } Devel::InnerPackage::list_packages( $component )
1914         );
1915
1916         for my $key ( keys %modules ) {
1917             $class->components->{ $key } = $modules{ $key };
1918         }
1919     }
1920 }
1921
1922 =head2 $c->setup_component
1923
1924 =cut
1925
1926 sub setup_component {
1927     my( $class, $component ) = @_;
1928
1929     unless ( $component->can( 'COMPONENT' ) ) {
1930         return $component;
1931     }
1932
1933     my $suffix = Catalyst::Utils::class2classsuffix( $component );
1934     my $config = $class->config->{ $suffix } || {};
1935
1936     my $instance = eval { $component->COMPONENT( $class, $config ); };
1937
1938     if ( my $error = $@ ) {
1939         chomp $error;
1940         Catalyst::Exception->throw(
1941             message => qq/Couldn't instantiate component "$component", "$error"/
1942         );
1943     }
1944
1945     Catalyst::Exception->throw(
1946         message =>
1947         qq/Couldn't instantiate component "$component", "COMPONENT() didn't return an object-like value"/
1948     ) unless eval { $instance->can( 'can' ) };
1949
1950     return $instance;
1951 }
1952
1953 =head2 $c->setup_dispatcher
1954
1955 Sets up dispatcher.
1956
1957 =cut
1958
1959 sub setup_dispatcher {
1960     my ( $class, $dispatcher ) = @_;
1961
1962     if ($dispatcher) {
1963         $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
1964     }
1965
1966     if ( my $env = Catalyst::Utils::env_value( $class, 'DISPATCHER' ) ) {
1967         $dispatcher = 'Catalyst::Dispatcher::' . $env;
1968     }
1969
1970     unless ($dispatcher) {
1971         $dispatcher = $class->dispatcher_class;
1972     }
1973
1974     Class::MOP::load_class($dispatcher);
1975     #unless (Class::Inspector->loaded($dispatcher)) {
1976     #    require Class::Inspector->filename($dispatcher);
1977     #}
1978
1979     # dispatcher instance
1980     $class->dispatcher( $dispatcher->new );
1981 }
1982
1983 =head2 $c->setup_engine
1984
1985 Sets up engine.
1986
1987 =cut
1988
1989 sub setup_engine {
1990     my ( $class, $engine ) = @_;
1991
1992     if ($engine) {
1993         $engine = 'Catalyst::Engine::' . $engine;
1994     }
1995
1996     if ( my $env = Catalyst::Utils::env_value( $class, 'ENGINE' ) ) {
1997         $engine = 'Catalyst::Engine::' . $env;
1998     }
1999
2000     if ( $ENV{MOD_PERL} ) {
2001
2002         # create the apache method
2003         {
2004             no strict 'refs';
2005             *{"$class\::apache"} = sub { shift->engine->apache };
2006         }
2007
2008         my ( $software, $version ) =
2009           $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
2010
2011         $version =~ s/_//g;
2012         $version =~ s/(\.[^.]+)\./$1/g;
2013
2014         if ( $software eq 'mod_perl' ) {
2015
2016             if ( !$engine ) {
2017
2018                 if ( $version >= 1.99922 ) {
2019                     $engine = 'Catalyst::Engine::Apache2::MP20';
2020                 }
2021
2022                 elsif ( $version >= 1.9901 ) {
2023                     $engine = 'Catalyst::Engine::Apache2::MP19';
2024                 }
2025
2026                 elsif ( $version >= 1.24 ) {
2027                     $engine = 'Catalyst::Engine::Apache::MP13';
2028                 }
2029
2030                 else {
2031                     Catalyst::Exception->throw( message =>
2032                           qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
2033                 }
2034
2035             }
2036
2037             # install the correct mod_perl handler
2038             if ( $version >= 1.9901 ) {
2039                 *handler = sub  : method {
2040                     shift->handle_request(@_);
2041                 };
2042             }
2043             else {
2044                 *handler = sub ($$) { shift->handle_request(@_) };
2045             }
2046
2047         }
2048
2049         elsif ( $software eq 'Zeus-Perl' ) {
2050             $engine = 'Catalyst::Engine::Zeus';
2051         }
2052
2053         else {
2054             Catalyst::Exception->throw(
2055                 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
2056         }
2057     }
2058
2059     unless ($engine) {
2060         $engine = $class->engine_class;
2061     }
2062
2063     Class::MOP::load_class($engine);
2064     #unless (Class::Inspector->loaded($engine)) {
2065     #    require Class::Inspector->filename($engine);
2066     #}
2067
2068     # check for old engines that are no longer compatible
2069     my $old_engine;
2070     if ( $engine->isa('Catalyst::Engine::Apache')
2071         && !Catalyst::Engine::Apache->VERSION )
2072     {
2073         $old_engine = 1;
2074     }
2075
2076     elsif ( $engine->isa('Catalyst::Engine::Server::Base')
2077         && Catalyst::Engine::Server->VERSION le '0.02' )
2078     {
2079         $old_engine = 1;
2080     }
2081
2082     elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
2083         && $engine->VERSION eq '0.01' )
2084     {
2085         $old_engine = 1;
2086     }
2087
2088     elsif ($engine->isa('Catalyst::Engine::Zeus')
2089         && $engine->VERSION eq '0.01' )
2090     {
2091         $old_engine = 1;
2092     }
2093
2094     if ($old_engine) {
2095         Catalyst::Exception->throw( message =>
2096               qq/Engine "$engine" is not supported by this version of Catalyst/
2097         );
2098     }
2099
2100     # engine instance
2101     $class->engine( $engine->new );
2102 }
2103
2104 =head2 $c->setup_home
2105
2106 Sets up the home directory.
2107
2108 =cut
2109
2110 sub setup_home {
2111     my ( $class, $home ) = @_;
2112
2113     if ( my $env = Catalyst::Utils::env_value( $class, 'HOME' ) ) {
2114         $home = $env;
2115     }
2116
2117     unless ($home) {
2118         $home = Catalyst::Utils::home($class);
2119     }
2120
2121     #I remember recently being scolded for assigning config values like this
2122     if ($home) {
2123         #I remember recently being scolded for assigning config values like this
2124         $class->config->{home} ||= $home;
2125         $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
2126     }
2127 }
2128
2129 =head2 $c->setup_log
2130
2131 Sets up log.
2132
2133 =cut
2134
2135 sub setup_log {
2136     my ( $class, $debug ) = @_;
2137
2138     unless ( $class->log ) {
2139         $class->log( Catalyst::Log->new );
2140     }
2141
2142     my $env_debug = Catalyst::Utils::env_value( $class, 'DEBUG' );
2143     if ( defined($env_debug) ? $env_debug : $debug ) {
2144         no strict 'refs';
2145         #Moose todo: dying to be made a bool attribute
2146         *{"$class\::debug"} = sub { 1 };
2147         $class->log->debug('Debug messages enabled');
2148     }
2149 }
2150
2151 =head2 $c->setup_plugins
2152
2153 Sets up plugins.
2154
2155 =cut
2156
2157 =head2 $c->setup_stats
2158
2159 Sets up timing statistics class.
2160
2161 =cut
2162
2163 sub setup_stats {
2164     my ( $class, $stats ) = @_;
2165
2166     Catalyst::Utils::ensure_class_loaded($class->stats_class);
2167
2168     my $env = Catalyst::Utils::env_value( $class, 'STATS' );
2169     if ( defined($env) ? $env : ($stats || $class->debug ) ) {
2170         no strict 'refs';
2171         #Moose todo: dying to be made a bool attribute
2172         *{"$class\::use_stats"} = sub { 1 };
2173         $class->log->debug('Statistics enabled');
2174     }
2175 }
2176
2177
2178 =head2 $c->registered_plugins
2179
2180 Returns a sorted list of the plugins which have either been stated in the
2181 import list or which have been added via C<< MyApp->plugin(@args); >>.
2182
2183 If passed a given plugin name, it will report a boolean value indicating
2184 whether or not that plugin is loaded.  A fully qualified name is required if
2185 the plugin name does not begin with C<Catalyst::Plugin::>.
2186
2187  if ($c->registered_plugins('Some::Plugin')) {
2188      ...
2189  }
2190
2191 =cut
2192
2193 {
2194
2195     sub registered_plugins {
2196         my $proto = shift;
2197         return sort keys %{ $proto->_plugins } unless @_;
2198         my $plugin = shift;
2199         return 1 if exists $proto->_plugins->{$plugin};
2200         return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
2201     }
2202
2203     sub _register_plugin {
2204         my ( $proto, $plugin, $instant ) = @_;
2205         my $class = ref $proto || $proto;
2206
2207         # no ignore_loaded here, the plugin may already have been
2208         # defined in memory and we don't want to error on "no file" if so
2209
2210         Catalyst::Utils::ensure_class_loaded( $plugin );
2211
2212         $proto->_plugins->{$plugin} = 1;
2213         unless ($instant) {
2214             no strict 'refs';
2215             if( $class->can('meta') ){
2216               my @superclasses = ($plugin, $class->meta->superclasses );
2217               $class->meta->superclasses(@superclasses);
2218             } else {
2219               unshift @{"$class\::ISA"}, $plugin;
2220             }
2221         }
2222         return $class;
2223     }
2224
2225     sub setup_plugins {
2226         my ( $class, $plugins ) = @_;
2227
2228         $class->_plugins( {} ) unless $class->_plugins;
2229         $plugins ||= [];
2230         for my $plugin ( reverse @$plugins ) {
2231
2232             unless ( $plugin =~ s/\A\+// ) {
2233                 $plugin = "Catalyst::Plugin::$plugin";
2234             }
2235
2236             $class->_register_plugin($plugin);
2237         }
2238     }
2239 }
2240
2241 =head2 $c->stack
2242
2243 Returns an arrayref of the internal execution stack (actions that are
2244 currently executing).
2245
2246 =head2 $c->stats_class
2247
2248 Returns or sets the stats (timing statistics) class.
2249
2250 =head2 $c->use_stats
2251
2252 Returns 1 when stats collection is enabled.  Stats collection is enabled
2253 when the -Stats options is set, debug is on or when the <MYAPP>_STATS
2254 environment variable is set.
2255
2256 Note that this is a static method, not an accessor and should be overloaded
2257 by declaring "sub use_stats { 1 }" in your MyApp.pm, not by calling $c->use_stats(1).
2258
2259 =cut
2260
2261 sub use_stats { 0 }
2262
2263
2264 =head2 $c->write( $data )
2265
2266 Writes $data to the output stream. When using this method directly, you
2267 will need to manually set the C<Content-Length> header to the length of
2268 your output data, if known.
2269
2270 =cut
2271
2272 sub write {
2273     my $c = shift;
2274
2275     # Finalize headers if someone manually writes output
2276     $c->finalize_headers;
2277
2278     return $c->engine->write( $c, @_ );
2279 }
2280
2281 =head2 version
2282
2283 Returns the Catalyst version number. Mostly useful for "powered by"
2284 messages in template systems.
2285
2286 =cut
2287
2288 sub version { return $Catalyst::VERSION }
2289
2290 =head1 INTERNAL ACTIONS
2291
2292 Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2293 C<_ACTION>, and C<_END>. These are by default not shown in the private
2294 action table, but you can make them visible with a config parameter.
2295
2296     MyApp->config->{show_internal_actions} = 1;
2297
2298 =head1 CASE SENSITIVITY
2299
2300 By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
2301 mapped to C</foo/bar>. You can activate case sensitivity with a config
2302 parameter.
2303
2304     MyApp->config->{case_sensitive} = 1;
2305
2306 This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
2307
2308 =head1 ON-DEMAND PARSER
2309
2310 The request body is usually parsed at the beginning of a request,
2311 but if you want to handle input yourself, you can enable on-demand
2312 parsing with a config parameter.
2313
2314     MyApp->config->{parse_on_demand} = 1;
2315
2316 =head1 PROXY SUPPORT
2317
2318 Many production servers operate using the common double-server approach,
2319 with a lightweight frontend web server passing requests to a larger
2320 backend server. An application running on the backend server must deal
2321 with two problems: the remote user always appears to be C<127.0.0.1> and
2322 the server's hostname will appear to be C<localhost> regardless of the
2323 virtual host that the user connected through.
2324
2325 Catalyst will automatically detect this situation when you are running
2326 the frontend and backend servers on the same machine. The following
2327 changes are made to the request.
2328
2329     $c->req->address is set to the user's real IP address, as read from
2330     the HTTP X-Forwarded-For header.
2331
2332     The host value for $c->req->base and $c->req->uri is set to the real
2333     host, as read from the HTTP X-Forwarded-Host header.
2334
2335 Obviously, your web server must support these headers for this to work.
2336
2337 In a more complex server farm environment where you may have your
2338 frontend proxy server(s) on different machines, you will need to set a
2339 configuration option to tell Catalyst to read the proxied data from the
2340 headers.
2341
2342     MyApp->config->{using_frontend_proxy} = 1;
2343
2344 If you do not wish to use the proxy support at all, you may set:
2345
2346     MyApp->config->{ignore_frontend_proxy} = 1;
2347
2348 =head1 THREAD SAFETY
2349
2350 Catalyst has been tested under Apache 2's threading C<mpm_worker>,
2351 C<mpm_winnt>, and the standalone forking HTTP server on Windows. We
2352 believe the Catalyst core to be thread-safe.
2353
2354 If you plan to operate in a threaded environment, remember that all other
2355 modules you are using must also be thread-safe. Some modules, most notably
2356 L<DBD::SQLite>, are not thread-safe.
2357
2358 =head1 SUPPORT
2359
2360 IRC:
2361
2362     Join #catalyst on irc.perl.org.
2363
2364 Mailing Lists:
2365
2366     http://lists.rawmode.org/mailman/listinfo/catalyst
2367     http://lists.rawmode.org/mailman/listinfo/catalyst-dev
2368
2369 Web:
2370
2371     http://catalyst.perl.org
2372
2373 Wiki:
2374
2375     http://dev.catalyst.perl.org
2376
2377 =head1 SEE ALSO
2378
2379 =head2 L<Task::Catalyst> - All you need to start with Catalyst
2380
2381 =head2 L<Catalyst::Manual> - The Catalyst Manual
2382
2383 =head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
2384
2385 =head2 L<Catalyst::Engine> - Core engine
2386
2387 =head2 L<Catalyst::Log> - Log class.
2388
2389 =head2 L<Catalyst::Request> - Request object
2390
2391 =head2 L<Catalyst::Response> - Response object
2392
2393 =head2 L<Catalyst::Test> - The test suite.
2394
2395 =head1 CREDITS
2396
2397 Andy Grundman
2398
2399 Andy Wardley
2400
2401 Andreas Marienborg
2402
2403 Andrew Bramble
2404
2405 Andrew Ford
2406
2407 Andrew Ruthven
2408
2409 Arthur Bergman
2410
2411 Autrijus Tang
2412
2413 Brian Cassidy
2414
2415 Carl Franks
2416
2417 Christian Hansen
2418
2419 Christopher Hicks
2420
2421 Dan Sully
2422
2423 Danijel Milicevic
2424
2425 David Kamholz
2426
2427 David Naughton
2428
2429 Drew Taylor
2430
2431 Gary Ashton Jones
2432
2433 Geoff Richards
2434
2435 Jesse Sheidlower
2436
2437 Jesse Vincent
2438
2439 Jody Belka
2440
2441 Johan Lindstrom
2442
2443 Juan Camacho
2444
2445 Leon Brocard
2446
2447 Marcus Ramberg
2448
2449 Matt S Trout
2450
2451 Robert Sedlacek
2452
2453 Sam Vilain
2454
2455 Sascha Kiefer
2456
2457 Sebastian Willert
2458
2459 Tatsuhiko Miyagawa
2460
2461 Ulf Edvinsson
2462
2463 Yuval Kogman
2464
2465 =head1 AUTHOR
2466
2467 Sebastian Riedel, C<sri@oook.de>
2468
2469 =head1 LICENSE
2470
2471 This library is free software, you can redistribute it and/or modify it under
2472 the same terms as Perl itself.
2473
2474 =cut
2475
2476 1;