Mercurial > pub > Impl
annotate Lib/IMPL/Web/Application.pm @ 143:d9dd3500ead3
Singleton behavior changed
| author | wizard | 
|---|---|
| date | Thu, 08 Jul 2010 23:46:49 +0400 | 
| parents | c5bc900eefd3 | 
| children | 4267a2ac3d46 | 
| rev | line source | 
|---|---|
| 49 | 1 package IMPL::Web::Application; | 
| 2 use strict; | |
| 3 use warnings; | |
| 4 | |
| 60 
b0c068da93ac
Lazy activation for the configuration objects (final concept)
 wizard parents: 
59diff
changeset | 5 use base qw(IMPL::Config IMPL::Object::Singleton); | 
| 58 | 6 | 
| 7 require IMPL::Web::Application::Action; | |
| 8 require IMPL::Web::Application::Response; | |
| 9 | |
| 49 | 10 use IMPL::Class::Property; | 
| 57 | 11 use CGI; | 
| 49 | 12 | 
| 60 
b0c068da93ac
Lazy activation for the configuration objects (final concept)
 wizard parents: 
59diff
changeset | 13 __PACKAGE__->PassThroughArgs; | 
| 
b0c068da93ac
Lazy activation for the configuration objects (final concept)
 wizard parents: 
59diff
changeset | 14 | 
| 49 | 15 BEGIN { | 
| 52 | 16 public property handlerError => prop_all; | 
| 67 | 17 public property actionFactory => prop_all; | 
| 59 
0f3e369553bd
Rewritten property implementation (probably become slower but more flexible)
 wizard parents: 
58diff
changeset | 18 public property handlersQuery => prop_all | prop_list; | 
| 65 | 19 public property responseCharset => prop_all; | 
| 73 | 20 public property security => prop_all; | 
| 63 
76b878ad6596
Added serialization support for the IMPL::Object::List
 wizard parents: 
62diff
changeset | 21 public property options => prop_all; | 
| 97 | 22 public property fetchRequestMethod => prop_all; | 
| 49 | 23 } | 
| 24 | |
| 62 | 25 sub CTOR { | 
| 26 my ($this) = @_; | |
| 27 | |
| 67 | 28 $this->actionFactory('IMPL::Web::Application::Action') unless $this->actionFactory; | 
| 65 | 29 $this->responseCharset('utf-8') unless $this->responseCharset; | 
| 97 | 30 $this->fetchRequestMethod(\&defaultFetchRequest) unless $this->fetchRequestMethod; | 
| 31 $this->handlerError(\&defaultHandlerError) unless $this->handlerError; | |
| 62 | 32 } | 
| 33 | |
| 49 | 34 sub Run { | 
| 35 my ($this) = @_; | |
| 36 | |
| 58 | 37 while (my $query = $this->FetchRequest()) { | 
| 38 | |
| 67 | 39 my $action = $this->actionFactory->new( | 
| 62 | 40 query => $query, | 
| 58 | 41 application => $this, | 
| 65 | 42 ); | 
| 43 | |
| 97 | 44 eval { | 
| 45 $action->response->charset($this->responseCharset); | |
| 46 | |
| 47 $action->ChainHandler($_) foreach $this->handlersQuery; | |
| 48 | |
| 49 $action->Invoke(); | |
| 50 | |
| 51 $action->response->Complete; | |
| 52 }; | |
| 53 if ($@) { | |
| 99 
6dd659f6f66c
Minor changes, DOM schema is in development (in the aspect of a forms)
 wizard parents: 
97diff
changeset | 54 my $e = $@; | 
| 129 | 55 # we are expecting this method to be safe otherwise we can trust nothing in this wolrd | 
| 99 
6dd659f6f66c
Minor changes, DOM schema is in development (in the aspect of a forms)
 wizard parents: 
97diff
changeset | 56 $this->handlerError()->($this,$action,$e); | 
| 97 | 57 } | 
| 49 | 58 } | 
| 59 } | |
| 60 | |
| 97 | 61 sub FetchRequest { | 
| 62 my ($this) = @_; | |
| 63 | |
| 64 if( ref $this->fetchRequestMethod eq 'CODE' ) { | |
| 65 return $this->fetchRequestMethod->($this); | |
| 66 } else { | |
| 67 die new IMPL::Exception("Unknown fetchRequestMethod type",ref $this->fetchRequestMethod); | |
| 68 } | |
| 69 } | |
| 70 | |
| 57 | 71 { | 
| 72 my $hasFetched = 0; | |
| 73 | |
| 97 | 74 sub defaultFetchRequest { | 
| 129 | 75 my ($this) = @_; | 
| 57 | 76 return undef if $hasFetched; | 
| 77 $hasFetched = 1; | |
| 130 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 78 my $query = CGIWrapper->new(); | 
| 129 | 79 $query->charset($this->responseCharset); | 
| 80 return $query; | |
| 57 | 81 } | 
| 82 } | |
| 83 | |
| 97 | 84 sub defaultHandlerError { | 
| 85 my ($this,$action,$e) = @_; | |
| 86 warn $e; | |
| 87 if ( eval { $action->ReinitResponse(); 1; } ) { | |
| 88 $action->response->contentType('text/plain'); | |
| 89 $action->response->charset($this->responseCharset); | |
| 90 $action->response->status(500); | |
| 91 my $hout = $action->response->streamBody; | |
| 92 print $hout $e; | |
| 93 $action->response->Complete(); | |
| 94 } | |
| 95 } | |
| 96 | |
| 130 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 97 package CGIWrapper; | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 98 use base qw(CGI); | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 99 | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 100 use Encode; | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 101 | 
| 138 | 102 our $NO_DECODE = 0; | 
| 103 | |
| 130 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 104 sub param { | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 105 my $this = shift; | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 106 | 
| 138 | 107 return $this->SUPER::param(@_) if $NO_DECODE; | 
| 108 | |
| 130 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 109 if (wantarray) { | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 110 my @result = $this->SUPER::param(@_); | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 111 | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 112 return map Encode::is_utf8($_) ? $_ : Encode::decode($this->charset,$_,Encode::LEAVE_SRC), @result; | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 113 } else { | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 114 my $result = $this->SUPER::param(@_); | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 115 | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 116 return Encode::is_utf8($result) ? $result : Encode::decode($this->charset,$result,Encode::LEAVE_SRC); | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 117 } | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 118 | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 119 } | 
| 
06a34c197b05
Added support for utf-8 and old versions of CGI module
 wizard parents: 
129diff
changeset | 120 | 
| 138 | 121 sub upload { | 
| 122 my $this = shift; | |
| 123 | |
| 124 local $NO_DECODE = 1; | |
| 125 my $oldCharset = $this->charset(); | |
| 126 $this->charset('ISO-8859-1'); | |
| 127 | |
| 128 my $fh = $this->SUPER::upload(@_); | |
| 129 | |
| 130 $this->charset($oldCharset); | |
| 131 return $fh; | |
| 132 } | |
| 133 | |
| 49 | 134 1; | 
| 135 | |
| 52 | 136 __END__ | 
| 137 | |
| 49 | 138 =pod | 
| 139 | |
| 140 =head1 SYNOPSIS | |
| 141 | |
| 67 | 142 =begin code | 
| 143 | |
| 49 | 144 require MyApp; | 
| 67 | 145 | 
| 146 my $instance = spawn MyApp('app.config'); | |
| 147 | |
| 148 $instance->Run(); | |
| 149 | |
| 150 =end code | |
| 49 | 151 | 
| 152 =head1 DESCRIPTION | |
| 153 | |
| 73 | 154 C< use base qw( IMPL::Config IMPL::Object::Singleton )> | 
| 155 | |
| 49 | 156 Зкземпляр приложения содержит в себе глобальные настройки, реализует контроллер запросов, | 
| 52 | 157 в качестве источника запросов используется CGI или иной совместимый модуль. | 
| 49 | 158 | 
| 52 | 159 Процесс обработки запроса состоит из следующих частей | 
| 49 | 160 | 
| 67 | 161 =over | 
| 162 | |
| 163 =item 1 | |
| 164 | |
| 165 Получение cgi запроса | |
| 166 | |
| 167 =item 2 | |
| 52 | 168 | 
| 67 | 169 Создание объекта C<IMPL::Web::Application::Action> | 
| 52 | 170 | 
| 67 | 171 =item 3 | 
| 52 | 172 | 
| 67 | 173 Формирование цепочки вызовов при помощи C<< IMPL::Web::Application::Action->ChainHandler >> | 
| 174 | |
| 175 =item 4 | |
| 176 | |
| 177 Выполнение запроса C<< IMPL::Web::Application::Action->Invoke >> | |
| 49 | 178 | 
| 179 =cut | |
| 67 | 180 | 
| 181 Также приложение поддерживает отложенное создание объектов, которые по первому обращению | |
| 182 к свойствам. Это реализовано в базовом классе C< IMPL::Configuration >. Для настройки | |
| 183 активаторов можно использовать свойство C<options>, в которое должен быть помещен хеш | |
| 184 со ссылками на активаторы, см. пример ниже C<CONFIGURATION>. | |
| 185 | |
| 186 =head2 CONFIGURATION | |
| 187 | |
| 188 Ниже приведен пример конфигурации приложения | |
| 189 | |
| 190 =begin code xml | |
| 191 | |
| 192 <?xml version="1.0" encoding="UTF-8"?> | |
| 193 <Application id='app' type="Test::Web::Application::Instance"> | |
| 194 | |
| 195 <!-- Begin custom properties --> | |
| 196 <name>Sample application</name> | |
| 197 <dataSource type='IMPL::Config::Activator' id='ds'> | |
| 198 <factory>IMPL::Object</factory> | |
| 199 <parameters type='HASH'> | |
| 200 <db>data</db> | |
| 201 <user>nobody</user> | |
| 202 </parameters> | |
| 203 </dataSource> | |
| 204 <securityMod type='IMPL::Config::Activator'> | |
| 205 <factory>IMPL::Object</factory> | |
| 206 <parameters type='HASH'> | |
| 207 <ds refid='ds'/> | |
| 208 </parameters> | |
| 209 </securityMod> | |
| 210 <!-- End custom properties --> | |
| 211 | |
| 212 <!-- direct access to the activators --> | |
| 213 <options type="HASH"> | |
| 214 <dataSource refid='ds'/> | |
| 215 </options> | |
| 216 | |
| 217 <!-- Set default output encoding, can be changed due query handling --> | |
| 218 <responseCharset>utf-8</responseCharset> | |
| 219 | |
| 220 <!-- Actions creation configuration --> | |
| 221 <actionFactory type="IMPL::Object::Factory"> | |
| 222 | |
| 223 <!-- Construct actions --> | |
| 224 <factory>IMPL::Web::Application::Action</factory> | |
| 225 <parameters type='HASH'> | |
| 226 | |
| 227 <!-- with special responseFactory --> | |
| 228 <responseFactory type='IMPL::Object::Factory'> | |
| 229 | |
| 230 <!-- Where resopnses have a special streamOut --> | |
| 231 <factory>IMPL::Web::Application::Response</factory> | |
| 232 <parameters type='HASH'> | |
| 233 | |
| 234 <!-- in memory dummy output instead of STDOUT --> | |
| 235 <streamOut>memory</streamOut> | |
| 236 | |
| 237 </parameters> | |
| 238 </responseFactory> | |
| 239 </parameters> | |
| 240 </actionFactory> | |
| 241 | |
| 242 <!-- Query processing chain --> | |
| 243 <handlersQuery type="IMPL::Object::List"> | |
| 244 <item type="IMPL::Web::QueryHandler::PageFormat"> | |
| 245 <templatesCharset>cp1251</templatesCharset> | |
| 246 </item> | |
| 247 </handlersQuery> | |
| 248 </Application> | |
| 249 | |
| 250 =end code xml | |
| 251 | |
| 73 | 252 =head1 MEMBERS | 
| 253 | |
| 254 =over | |
| 255 | |
| 256 =item C<[get,set] handlerError> | |
| 257 | |
| 258 Обработчик который будет вызван в случае возникновения необработанной ошибки | |
| 259 в процессе работы приложения. После чего приложение корректно завершается. | |
| 260 | |
| 261 =item C<[get,set] actionFactory> | |
| 262 | |
| 263 Фабрика объектов, которая используется приложением, для создания объектов | |
| 264 типа C<IMPL::Web::Application::Action> при обработки C<CGI> запросов. | |
| 265 | |
| 266 =begin code | |
| 267 | |
| 268 my $action = $this->actionFactory->new( | |
| 269 query => $query, | |
| 270 application => $this, | |
| 271 ); | |
| 272 | |
| 273 =end code | |
| 274 | |
| 97 | 275 =item C< [get,set] fetchRequestMethod > | 
| 276 | |
| 277 Метод получения CGI запроса. Возвращает C<CGI> объект следующего запроса, если | |
| 278 запросов больше нет, то возвращает C<undef>. По-умолчанию использует C<defaultFetchRequest>. | |
| 279 | |
| 280 Может быть как ссылкой на функцию, так и объектом типа C<IMPL::Web::Application::RequestFetcher>. | |
| 281 | |
| 73 | 282 =item C< [get,set,list] handlersQuery > | 
| 283 | |
| 284 Список обработчиков запросов, которые будут переданы созданному объекту-действию. | |
| 285 | |
| 286 =item C< [get,set] responseCharset> | |
| 287 | |
| 288 Кодировка ответа клиенту. | |
| 289 | |
| 290 =item C< [get,set] security > | |
| 291 | |
| 292 Объект C<IMPL::Web::Security>, для работы с инфраструктурой безопасности. | |
| 293 | |
| 294 =item C< [get,set] options > | |
| 295 | |
| 296 Обычно ссылка на хеш с настраиваемыми объектами, используется для возможности | |
| 297 програмной настройки активаторов, т.к. напрямую через свойства приложения получить | |
| 298 к ним доступ не получится. | |
| 299 | |
| 300 =back | |
| 301 | |
| 302 =cut | 
