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:
59
diff
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:
59
diff
changeset
|
13 __PACKAGE__->PassThroughArgs; |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
59
diff
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:
58
diff
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:
62
diff
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:
97
diff
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:
97
diff
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:
129
diff
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:
129
diff
changeset
|
97 package CGIWrapper; |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
98 use base qw(CGI); |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
99 |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
100 use Encode; |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
101 |
138 | 102 our $NO_DECODE = 0; |
103 | |
130
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
104 sub param { |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
105 my $this = shift; |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
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:
129
diff
changeset
|
109 if (wantarray) { |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
110 my @result = $this->SUPER::param(@_); |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
111 |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
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:
129
diff
changeset
|
113 } else { |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
114 my $result = $this->SUPER::param(@_); |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
115 |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
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:
129
diff
changeset
|
117 } |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
118 |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
changeset
|
119 } |
06a34c197b05
Added support for utf-8 and old versions of CGI module
wizard
parents:
129
diff
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 |