| Filename | /appl/netdisco/perl5/lib/perl5/Dancer/App.pm |
| Statements | Executed 467 statements in 693µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 467 | 1 | 1 | 488µs | 488µs | Dancer::App::applications |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::BEGIN |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::_set_settings |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::app_exists |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::current |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::dec_lexical_prefix |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::find_route |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::find_route_through_apps |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::get |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::get_prefix |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::incr_lexical_prefix |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::init |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::init_registry |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::reload_apps |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::routes |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::set_app_prefix |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::set_prefix |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::set_running_app |
| 0 | 0 | 0 | 0s | 0s | Dancer::App::setting |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Dancer::App; | ||||
| 2 | our $AUTHORITY = 'cpan:SUKRIA'; | ||||
| 3 | # ABSTRACT: Base application class for Dancer. | ||||
| 4 | $Dancer::App::VERSION = '1.3512'; | ||||
| 5 | use strict; | ||||
| 6 | use warnings; | ||||
| 7 | use Carp; | ||||
| 8 | use base 'Dancer::Object'; | ||||
| 9 | |||||
| 10 | use Dancer::Config; | ||||
| 11 | use Dancer::ModuleLoader; | ||||
| 12 | use Dancer::Route::Registry; | ||||
| 13 | use Dancer::Logger; | ||||
| 14 | use Dancer::Exception qw(:all); | ||||
| 15 | use Dancer::Deprecation; | ||||
| 16 | |||||
| 17 | Dancer::App->attributes(qw(name app_prefix prefix registry settings on_lexical_prefix)); | ||||
| 18 | |||||
| 19 | # singleton that saves any app created, we want unicity for app names | ||||
| 20 | my $_apps = {}; | ||||
| 21 | 467 | 693µs | # spent 488µs within Dancer::App::applications which was called 467 times, avg 1µs/call:
# 467 times (488µs+0s) by Dancer::setting at line 215 of Dancer.pm, avg 1µs/call | ||
| 22 | |||||
| 23 | sub app_exists { | ||||
| 24 | my ( $self, $name ) = @_; | ||||
| 25 | grep { $_ eq $name } keys %$_apps; | ||||
| 26 | } | ||||
| 27 | |||||
| 28 | sub set_running_app { | ||||
| 29 | my ($self, $name) = @_; | ||||
| 30 | my $app = Dancer::App->get($name); | ||||
| 31 | $app = Dancer::App->new(name => $name) unless defined $app; | ||||
| 32 | Dancer::App->current($app); | ||||
| 33 | } | ||||
| 34 | |||||
| 35 | sub set_app_prefix { | ||||
| 36 | my ($self, $prefix) = @_; | ||||
| 37 | $self->app_prefix($prefix); | ||||
| 38 | $self->prefix($prefix); | ||||
| 39 | } | ||||
| 40 | |||||
| 41 | sub get_prefix { | ||||
| 42 | # return the current prefix (if undefined, return an empty string) | ||||
| 43 | return Dancer::App->current->prefix || ''; | ||||
| 44 | } | ||||
| 45 | |||||
| 46 | sub incr_lexical_prefix { | ||||
| 47 | no warnings; # for undefined | ||||
| 48 | $_[0]->on_lexical_prefix( $_[0]->on_lexical_prefix + 1 ); | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | sub dec_lexical_prefix { | ||||
| 52 | $_[0]->on_lexical_prefix( $_[0]->on_lexical_prefix - 1 ); | ||||
| 53 | } | ||||
| 54 | |||||
| 55 | sub set_prefix { | ||||
| 56 | my ($self, $prefix, $cb) = @_; | ||||
| 57 | |||||
| 58 | undef $prefix if defined($prefix) and $prefix eq "/"; | ||||
| 59 | |||||
| 60 | raise core_app => "not a valid prefix: `$prefix', must start with a /" | ||||
| 61 | if defined($prefix) && $prefix !~ /^\//; | ||||
| 62 | |||||
| 63 | my $app_prefix = defined $self->app_prefix ? $self->app_prefix : ""; | ||||
| 64 | my $previous = Dancer::App->current->prefix; | ||||
| 65 | |||||
| 66 | $prefix ||= ""; | ||||
| 67 | |||||
| 68 | if (Dancer::App->current->on_lexical_prefix) { | ||||
| 69 | Dancer::App->current->prefix($previous.$prefix); | ||||
| 70 | } else { | ||||
| 71 | Dancer::App->current->prefix($app_prefix.$prefix); | ||||
| 72 | } | ||||
| 73 | |||||
| 74 | if (ref($cb) eq 'CODE') { | ||||
| 75 | Dancer::App->current->incr_lexical_prefix; | ||||
| 76 | eval { $cb->() }; | ||||
| 77 | my $e = $@; | ||||
| 78 | Dancer::App->current->dec_lexical_prefix; | ||||
| 79 | Dancer::App->current->prefix($previous); | ||||
| 80 | die $e if $e; | ||||
| 81 | } | ||||
| 82 | return 1; # prefix may have been set to undef | ||||
| 83 | } | ||||
| 84 | |||||
| 85 | sub routes { | ||||
| 86 | my ($self, $method) = @_; | ||||
| 87 | map { $_->pattern } @{$self->registry->{'routes'}{$method}}; | ||||
| 88 | } | ||||
| 89 | |||||
| 90 | sub reload_apps { | ||||
| 91 | my ($class) = @_; | ||||
| 92 | |||||
| 93 | Dancer::Deprecation->deprecated( | ||||
| 94 | feature => 'auto_reload', | ||||
| 95 | reason => 'use plackup -r instead', | ||||
| 96 | ); | ||||
| 97 | |||||
| 98 | my @missing_modules = grep { not Dancer::ModuleLoader->load($_) } | ||||
| 99 | qw(Module::Refresh Clone); | ||||
| 100 | |||||
| 101 | if (not @missing_modules) { | ||||
| 102 | |||||
| 103 | # saving apps & purging app registries | ||||
| 104 | my $orig_apps = {}; | ||||
| 105 | while (my ($name, $app) = each %$_apps) { | ||||
| 106 | $orig_apps->{$name} = $app->clone; | ||||
| 107 | $app->registry->init(); | ||||
| 108 | } | ||||
| 109 | |||||
| 110 | # reloading changed modules, getting apps reloaded | ||||
| 111 | Module::Refresh->refresh; | ||||
| 112 | |||||
| 113 | # make sure old apps that didn't get reloaded are kept | ||||
| 114 | while (my ($name, $app) = each %$orig_apps) { | ||||
| 115 | $_apps->{$name} = $app unless defined $_apps->{$name}; | ||||
| 116 | $_apps->{$name} = $app if $_apps->{$name}->registry->is_empty; | ||||
| 117 | } | ||||
| 118 | |||||
| 119 | } | ||||
| 120 | else { | ||||
| 121 | carp "Modules required for auto_reload are missing. Install modules" | ||||
| 122 | . " [@missing_modules] or unset 'auto_reload' in your config file."; | ||||
| 123 | } | ||||
| 124 | } | ||||
| 125 | |||||
| 126 | sub find_route_through_apps { | ||||
| 127 | my ($class, $request) = @_; | ||||
| 128 | for my $app (Dancer::App->current, Dancer::App->applications) { | ||||
| 129 | my $route = $app->find_route($request); | ||||
| 130 | if ($route) { | ||||
| 131 | Dancer::App->current($route->app); | ||||
| 132 | return $route; | ||||
| 133 | } | ||||
| 134 | return $route if $route; | ||||
| 135 | } | ||||
| 136 | return; | ||||
| 137 | } | ||||
| 138 | |||||
| 139 | # instance | ||||
| 140 | |||||
| 141 | sub find_route { | ||||
| 142 | my ($self, $request) = @_; | ||||
| 143 | my $method = lc($request->method); | ||||
| 144 | |||||
| 145 | # if route cache is enabled, we check if we handled this path before | ||||
| 146 | if (Dancer::Config::setting('route_cache')) { | ||||
| 147 | my $route = Dancer::Route::Cache->get->route_from_path($method, | ||||
| 148 | $request->path_info, $self->name); | ||||
| 149 | |||||
| 150 | # NOTE maybe we should cache the match data as well | ||||
| 151 | if ($route) { | ||||
| 152 | $route->match($request); | ||||
| 153 | return $route; | ||||
| 154 | } | ||||
| 155 | } | ||||
| 156 | |||||
| 157 | my @routes = @{$self->registry->routes($method)}; | ||||
| 158 | |||||
| 159 | for my $r (@routes) { | ||||
| 160 | my $match = $r->match($request); | ||||
| 161 | |||||
| 162 | if ($match) { | ||||
| 163 | next if $r->has_options && (not $r->validate_options($request)); | ||||
| 164 | |||||
| 165 | # if we have a route cache, store the result | ||||
| 166 | if (Dancer::Config::setting('route_cache')) { | ||||
| 167 | Dancer::Route::Cache->get->store_path($method, | ||||
| 168 | $request->path_info => $r, $self->name); | ||||
| 169 | } | ||||
| 170 | |||||
| 171 | return $r; | ||||
| 172 | } | ||||
| 173 | } | ||||
| 174 | return; | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | sub init { | ||||
| 178 | my ($self) = @_; | ||||
| 179 | $self->name('main') unless defined $self->name; | ||||
| 180 | |||||
| 181 | raise core_app => "an app named '" . $self->name . "' already exists" | ||||
| 182 | if exists $_apps->{$self->name}; | ||||
| 183 | |||||
| 184 | # default values for properties | ||||
| 185 | $self->settings({}); | ||||
| 186 | $self->init_registry(); | ||||
| 187 | |||||
| 188 | $_apps->{$self->name} = $self; | ||||
| 189 | } | ||||
| 190 | |||||
| 191 | sub init_registry { | ||||
| 192 | my ($self, $reg) = @_; | ||||
| 193 | $self->registry($reg || Dancer::Route::Registry->new); | ||||
| 194 | |||||
| 195 | } | ||||
| 196 | |||||
| 197 | # singleton that saves the current active Dancer::App object | ||||
| 198 | my $_current; | ||||
| 199 | |||||
| 200 | sub current { | ||||
| 201 | my ($class, $app) = @_; | ||||
| 202 | return $_current = $app if defined $app; | ||||
| 203 | |||||
| 204 | if (not defined $_current) { | ||||
| 205 | $_current = Dancer::App->get('main') || Dancer::App->new(); | ||||
| 206 | } | ||||
| 207 | |||||
| 208 | return $_current; | ||||
| 209 | } | ||||
| 210 | |||||
| 211 | sub get { | ||||
| 212 | my ($class, $name) = @_; | ||||
| 213 | $_apps->{$name}; | ||||
| 214 | } | ||||
| 215 | |||||
| 216 | sub setting { | ||||
| 217 | my $self = shift; | ||||
| 218 | |||||
| 219 | if ($self->name eq 'main') { | ||||
| 220 | return (@_ > 1) | ||||
| 221 | ? Dancer::Config::setting( @_ ) | ||||
| 222 | : Dancer::Config::setting( $_[0] ); | ||||
| 223 | } | ||||
| 224 | |||||
| 225 | if (@_ > 1) { | ||||
| 226 | $self->_set_settings(@_) | ||||
| 227 | } else { | ||||
| 228 | my $name = shift; | ||||
| 229 | exists($self->settings->{$name}) ? $self->settings->{$name} | ||||
| 230 | : Dancer::Config::setting($name); | ||||
| 231 | } | ||||
| 232 | } | ||||
| 233 | |||||
| 234 | sub _set_settings { | ||||
| 235 | my $self = shift; | ||||
| 236 | die "Odd number of elements in set" unless @_ % 2 == 0; | ||||
| 237 | while (@_) { | ||||
| 238 | my $name = shift; | ||||
| 239 | my $value = shift; | ||||
| 240 | $self->settings->{$name} = | ||||
| 241 | Dancer::Config->normalize_setting($name => $value); | ||||
| 242 | } | ||||
| 243 | } | ||||
| 244 | |||||
| 245 | |||||
| 246 | 1; | ||||
| 247 | |||||
| 248 | __END__ |