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