PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Apache/Voodoo/Application.pm

http://github.com/maverick/ApacheVoodoo
Perl | 315 lines | 215 code | 69 blank | 31 comment | 19 complexity | 215662375c77db8ffe66bd463f9421a3 MD5 | raw file
Possible License(s): LGPL-2.0
  1. package Apache::Voodoo::Application;
  2. $VERSION = "3.0206";
  3. use strict;
  4. use warnings;
  5. use Apache::Voodoo::Constants;
  6. use Apache::Voodoo::Application::ConfigParser;
  7. use Apache::Voodoo::Session;
  8. use Apache::Voodoo::Debug;
  9. use Data::Dumper;
  10. sub new {
  11. my $class = shift;
  12. my $self = {};
  13. bless $self, $class;
  14. # $self->{'debug'} = 1;
  15. $self->{'id'} = shift;
  16. $self->{'constants'} = shift || Apache::Voodoo::Constants->new();
  17. die "ID is a required parameter." unless (defined($self->{'id'}));
  18. $self->{'parser'} = Apache::Voodoo::Application::ConfigParser->new($self->{'id'},$self->{'constants'});
  19. $self->refresh(1);
  20. return $self;
  21. }
  22. sub config {
  23. return $_[0]->{'parser'}->config();
  24. }
  25. sub databases {
  26. return $_[0]->{'parser'}->databases();
  27. }
  28. sub bootstrapped {
  29. my $self = shift;
  30. $self->{debug_handler}->bootstrapped();
  31. }
  32. sub refresh {
  33. my $self = shift;
  34. my $initial = shift;
  35. # If this is the initial load, or the config file has changed continue.
  36. unless ($initial || $self->{'parser'}->changed()) {
  37. return;
  38. }
  39. my $config = $self->{'parser'};
  40. my %old_m = %{$config->models()};
  41. my %old_v = %{$config->views()};
  42. my %old_c = %{$config->controllers()};
  43. my %old_i = %{$config->includes()};
  44. my $old_ns = $config->old_ns();
  45. $config->parse();
  46. $self->_reload_modules('m',\%old_m,$config->models());
  47. $self->_reload_modules('v',\%old_v,$config->views());
  48. if (defined($old_ns) && $old_ns != $config->old_ns()) {
  49. # They've swapped from the old style name for controller to the new syle
  50. # (or vice versa). Drop all the old controllers.
  51. $self->_debug("**Controller namespace has changed**");
  52. foreach (keys %{$self->{'controllers'}}) {
  53. $self->_debug("Removing old module: $_");
  54. delete $self->{'controllers'}->{$_};
  55. }
  56. %old_c = ();
  57. %old_i = ();
  58. }
  59. # load the new includes
  60. $self->_reload_modules('c',\%old_i,$config->includes());
  61. foreach (sort keys %{$config->controllers()}) {
  62. unless (exists($old_c{$_})) {
  63. # new module
  64. $self->_debug("Adding new module: $_");
  65. $self->_prep_page_module($_);
  66. }
  67. delete $old_c{$_};
  68. }
  69. foreach (keys %old_c) {
  70. $self->_debug("Removing old module: $_");
  71. delete $self->{'controllers'}->{$_};
  72. }
  73. # If they didn't define their own HTML view, then we'll use our own;
  74. # this is a web server after all :)
  75. unless (defined($self->{'views'}->{'HTML'})) {
  76. require Apache::Voodoo::View::HTML;
  77. $self->{'views'}->{'HTML'} = Apache::Voodoo::View::HTML->new();
  78. }
  79. # Same idea for JSON. What website these days doesn't use even
  80. # a little AJAX?
  81. unless (defined($self->{'views'}->{'JSON'})) {
  82. require Apache::Voodoo::View::JSON;
  83. $self->{'views'}->{'JSON'} = Apache::Voodoo::View::JSON->new();
  84. }
  85. # models get the config and every model except themselves
  86. # to prevent accidental circular references
  87. foreach my $key (keys %{$self->{'models'}}) {
  88. my %m = map { $_ => $self->{models}->{$_} }
  89. grep { $_ ne $key }
  90. keys %{$self->{'models'}};
  91. eval {
  92. $self->{models}->{$key}->init($config->config(),\%m);
  93. };
  94. if ($@) {
  95. warn "$@\n";
  96. $self->{'errors'}++;
  97. }
  98. }
  99. # views get just the config
  100. foreach (values %{$self->{'views'}}) {
  101. eval {
  102. $_->init($config->config());
  103. };
  104. if ($@) {
  105. warn "$@\n";
  106. $self->{'errors'}++;
  107. }
  108. }
  109. # controllers get the config and all the models
  110. foreach (values %{$self->{'controllers'}}) {
  111. eval {
  112. $_->init($config->config(),$self->{'models'});
  113. };
  114. if ($@) {
  115. warn "$@\n";
  116. $self->{'errors'}++;
  117. }
  118. }
  119. eval {
  120. $self->{'session_handler'} = Apache::Voodoo::Session->new($config->config());
  121. };
  122. if ($@) {
  123. warn "$@\n";
  124. $self->{'errors'}++;
  125. }
  126. eval {
  127. $self->{'debug_handler'} = Apache::Voodoo::Debug->new($config->config());
  128. };
  129. if ($@) {
  130. warn "$@\n";
  131. $self->{'errors'}++;
  132. }
  133. }
  134. sub map_uri {
  135. my $self = shift;
  136. my $uri = shift;
  137. if (defined($self->{'controllers'}->{$uri})) {
  138. return [$uri,"handle"];
  139. }
  140. else {
  141. no warnings 'uninitialized';
  142. my $p='';
  143. my $m='';
  144. my $o='';
  145. ($p,$m,$o) = ($uri =~ /^(.*?)([a-z]+)_(\w+)$/);
  146. return ["$p$o",$m];
  147. }
  148. }
  149. sub resolve_conf_section {
  150. my $self = shift;
  151. my $uri = shift;
  152. my $template_conf = $self->{'parser'}->template_conf();
  153. if (exists($template_conf->{$uri})) {
  154. # one specific to this page
  155. return $template_conf->{$uri};
  156. }
  157. foreach (sort { length($b) <=> length($a) } keys %{$template_conf}) {
  158. if ($uri =~ /^$_$/) {
  159. # match by uri regexp
  160. return $template_conf->{$_};
  161. }
  162. }
  163. # not one, return the default
  164. return $template_conf->{'default'};
  165. }
  166. sub _reload_modules {
  167. my $self = shift;
  168. my $ns = shift;
  169. my $old = shift;
  170. my $new = shift;
  171. # check the new list of modules against the old list
  172. foreach (sort keys %{$new}) {
  173. unless (exists($old->{$_})) {
  174. # new module (wasn't in the old list).
  175. $self->_debug("Adding new $ns module: $_");
  176. $self->_prep_module($ns,$_);
  177. }
  178. # still a valid module, so remove it from this list.
  179. delete $old->{$_};
  180. }
  181. # whatever is left in old are ones that weren't in the new list.
  182. foreach (keys %{$old}) {
  183. $self->_debug("Removing old module: $_");
  184. $_ =~ s/::/\//g;
  185. delete $self->{'controllers'}->{$_};
  186. }
  187. }
  188. sub _prep_module {
  189. my $self = shift;
  190. my $ns = shift;
  191. my $module = shift;
  192. my $obj = $self->_load_module($ns,$module);
  193. $ns = ($ns eq "m")?"models":
  194. ($ns eq "v")?"views":"controllers";
  195. $self->{$ns}->{$module} = $obj;
  196. }
  197. sub _prep_page_module {
  198. my $self = shift;
  199. my $module = shift;
  200. my $obj = $self->_load_module('c',$module);
  201. $module =~ s/::/\//g;
  202. $self->{'controllers'}->{$module} = $obj;
  203. }
  204. sub _load_module {
  205. my $self = shift;
  206. my $ns = shift;
  207. my $module = shift;
  208. unless ($ns eq "c" and $self->{'parser'}->old_ns()) {
  209. $module = uc($ns)."::".$module;
  210. }
  211. $module = $self->{'parser'}->config()->{'base_package'}."::".$module;
  212. my $obj;
  213. if ($self->{'parser'}->config()->{'dynamic_loading'}) {
  214. require Apache::Voodoo::Loader::Dynamic;
  215. $obj = Apache::Voodoo::Loader::Dynamic->new($module);
  216. }
  217. else {
  218. require Apache::Voodoo::Loader::Static;
  219. $obj = Apache::Voodoo::Loader::Static->new($module);
  220. if (ref($obj) eq "Apache::Voodoo::Zombie") {
  221. # doh! the module went boom
  222. $self->{'errors'}++;
  223. }
  224. }
  225. return $obj;
  226. }
  227. sub _debug {
  228. my $self = shift;
  229. return unless $self->{'debug'};
  230. if (ref($_[0])) {
  231. warn Dumper(@_);
  232. }
  233. else {
  234. warn join("\n",@_),"\n";
  235. }
  236. }
  237. 1;
  238. ################################################################################
  239. # Copyright (c) 2005-2010 Steven Edwards (maverick@smurfbane.org).
  240. # All rights reserved.
  241. #
  242. # You may use and distribute Apache::Voodoo under the terms described in the
  243. # LICENSE file include in this package. The summary is it's a legalese version
  244. # of the Artistic License :)
  245. #
  246. ################################################################################