Mercurial > pub > Impl
view Lib/IMPL/Web/Application.pm @ 263:0f59b2de72af
*fixed IMPL::DOM::Schema circular module references
*modified IMPL::Object::Singleton, added auto-activation
*code cleanups, docs
author | sergey |
---|---|
date | Wed, 09 Jan 2013 05:17:44 +0400 |
parents | a02b110da931 |
children | 546957c50a36 |
line wrap: on
line source
package IMPL::Web::Application; use strict; use warnings; use CGI; use Carp qw(carp); use IMPL::Const qw(:prop); use IMPL::declare { require => { Locator => 'IMPL::Web::AutoLocator', TAction => 'IMPL::Web::Application::Action', HttpResponse => 'IMPL::Web::HttpResponse', TFactory => '-IMPL::Object::Factory', Exception => 'IMPL::Exception', InvalidOperationException => '-IMPL::InvalidOperationException', Loader => 'IMPL::Code::Loader' }, base => [ 'IMPL::Config' => '@_', 'IMPL::Object::Singleton' => '@_' ], props => [ baseUrl => PROP_RW, actionFactory => PROP_RW, handlers => PROP_RW | PROP_LIST, security => PROP_RW, options => PROP_RW, requestCharset => PROP_RW, output => PROP_RW, location => PROP_RO ] }; sub CTOR { my ($this) = @_; die IMPL::InvalidArgumentException->new( "handlers", "At least one handler should be supplied" ) unless $this->handlers->Count; $this->baseUrl('/') unless $this->baseUrl; $this->actionFactory(TAction) unless $this->actionFactory; $this->location(Locator->new(base => $this->baseUrl)); } sub Run { my ($this) = @_; my $handler; $handler = _ChainHandler( $_, $handler ) foreach $this->handlers; while ( my $query = $this->FetchRequest() ) { my $action = $this->actionFactory->new( query => $query, application => $this, ); eval { my $result = $handler->($action); die InvalidOperationException->new( "Invalid handlers result. A reference to IMPL::Web::HttpResponse is expexted." ) unless eval { $result->isa(HttpResponse) }; $result->PrintResponse( $this->output ); }; if ($@) { my $e = $@; HttpResponse->InternalError( type => 'text/plain', charset => 'utf-8', body => $e )->PrintResponse( $this->output ); } } } sub _ChainHandler { my ( $handler, $next ) = @_; if ( ref $handler eq 'CODE' ) { return sub { my ($action) = @_; return $handler->( $action, $next ); }; } elsif ( eval { $handler->can('Invoke') } ) { return sub { my ($action) = @_; return $handler->Invoke( $action, $next ); }; } elsif ( eval { $handler->isa(TFactory) } ) { return sub { my ($action) = @_; my $inst = $handler->new(); return $inst->Invoke( $action, $next ); } } elsif ( $handler and not ref $handler and $handler =~ m/^(-)?(\w+(?:::\w+)*)$/ ) { my $class = $2; if ( not $1 ) { Loader->safe->Require($class); die IMPL::InvalidArgumentException->( "An invalid handler supplied", $handler ) unless $class->can('Invoke'); } return sub { my ($action) = @_; my $inst = $class->new(); return $inst->Invoke( $action, $next ); }; } else { die new IMPL::InvalidArgumentException( "An invalid handler supplied", $handler ); } } sub FetchRequest { return; } 1; __END__ =pod =head1 NAME C<IMPL::Web::Application> Базовай класс для создания экземпляров приложения =head1 SYNOPSIS =begin code use IMPL::require { App => 'IMPL::Web::Application' }; my $instance = App->spawn(); # will use ./IMPL/Web/Application.xml as configuration $instance->Run; =end code =head1 DESCRIPTION Создает экземпляр объекта, который получает и обрабатывает C<HTTP> запрос. Приложение можно загрузить из C<xml> файла в котором описано состояние свойств, для этого используется механизм C<IMPL::Serialization>. Приложение представлет собой модульную конструкцию, которая состоит из цепочки обработчиков. Цепочка обработчиков вызывается снизу вверх, при этом каждый обработчик самостоятельно рекурсивно вызывает следующий (более высокого уровня). См. также C<IMPL::Web::CGIApplication> =cut