Mercurial > pub > Impl
view Lib/IMPL/Web/Application.pm @ 245:7c517134c42f
Added Unsupported media type Web exception
corrected resourceLocation setting in the resource
Implemented localizable resources for text messages
fixed TT view scopings, INIT block in controls now sets globals correctly.
author | sergey |
---|---|
date | Mon, 29 Oct 2012 03:15:22 +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