line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::Framework::Core ; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
App::Framework::Core - Base application object |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use App::Framework::Core ; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our @ISA = qw(App::Framework::Core) ; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 DESCRIPTION |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
B |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Base class for applications. Expected to be derived from by an implementable class (like App::Framework::Core::Script). |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=cut |
22
|
|
|
|
|
|
|
|
23
|
31
|
|
|
31
|
|
757
|
use strict ; |
|
30
|
|
|
|
|
49
|
|
|
30
|
|
|
|
|
1010
|
|
24
|
30
|
|
|
30
|
|
149
|
use Carp ; |
|
30
|
|
|
|
|
58
|
|
|
30
|
|
|
|
|
2352
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
our $VERSION = "1.015" ; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#============================================================================================ |
30
|
|
|
|
|
|
|
# USES |
31
|
|
|
|
|
|
|
#============================================================================================ |
32
|
30
|
|
|
30
|
|
18455
|
use App::Framework::Base ; |
|
30
|
|
|
|
|
87
|
|
|
30
|
|
|
|
|
1218
|
|
33
|
30
|
|
|
30
|
|
20162
|
use App::Framework::Settings ; |
|
30
|
|
|
|
|
75
|
|
|
30
|
|
|
|
|
783
|
|
34
|
|
|
|
|
|
|
|
35
|
30
|
|
|
30
|
|
169
|
use App::Framework::Base::Object::DumpObj ; |
|
30
|
|
|
|
|
54
|
|
|
30
|
|
|
|
|
1128
|
|
36
|
|
|
|
|
|
|
|
37
|
30
|
|
|
30
|
|
148
|
use File::Basename ; |
|
30
|
|
|
|
|
52
|
|
|
30
|
|
|
|
|
3250
|
|
38
|
30
|
|
|
30
|
|
160
|
use File::Spec ; |
|
30
|
|
|
|
|
48
|
|
|
30
|
|
|
|
|
581
|
|
39
|
30
|
|
|
30
|
|
147
|
use File::Path ; |
|
30
|
|
|
|
|
56
|
|
|
30
|
|
|
|
|
1773
|
|
40
|
30
|
|
|
30
|
|
29616
|
use File::Copy ; |
|
30
|
|
|
|
|
150502
|
|
|
30
|
|
|
|
|
2078
|
|
41
|
|
|
|
|
|
|
|
42
|
30
|
|
|
30
|
|
217
|
use Cwd ; |
|
30
|
|
|
|
|
55
|
|
|
30
|
|
|
|
|
29372
|
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
#============================================================================================ |
46
|
|
|
|
|
|
|
# OBJECT HIERARCHY |
47
|
|
|
|
|
|
|
#============================================================================================ |
48
|
|
|
|
|
|
|
our @ISA = qw(App::Framework::Base) ; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
#============================================================================================ |
51
|
|
|
|
|
|
|
# GLOBALS |
52
|
|
|
|
|
|
|
#============================================================================================ |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head2 FIELDS |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
The following fields should be defined either in the call to 'new()' or as part of the application configuration in the __DATA__ section: |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
* name = Program name (default is name of program) |
59
|
|
|
|
|
|
|
* summary = Program summary text |
60
|
|
|
|
|
|
|
* synopsis = Synopsis text (default is program name and usage) |
61
|
|
|
|
|
|
|
* description = Program description text |
62
|
|
|
|
|
|
|
* history = Release history information |
63
|
|
|
|
|
|
|
* version = Program version (default is value of 'our $VERSION') |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
* feature_config = HASH ref containing setup information for any installed features. Each feature must have it's own |
66
|
|
|
|
|
|
|
HASH of values, keyed by the feature name |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
* app_start_fn = Function called before app() function (default is application-defined 'app_start' subroutine if available) |
69
|
|
|
|
|
|
|
* app_fn = Function called to execute program (default is application-defined 'app' subroutine if available) |
70
|
|
|
|
|
|
|
* app_end_fn = Function called after app() function (default is application-defined 'app_end' subroutine if available) |
71
|
|
|
|
|
|
|
* usage_fn = Function called to display usage information (default is application-defined 'usage' subroutine if available) |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
During program execution, the following values can be accessed: |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
* package = Name of the application package (usually main::) |
76
|
|
|
|
|
|
|
* filename = Full filename path to the application (after following any links) |
77
|
|
|
|
|
|
|
* progname = Name of the program (without path or extension) |
78
|
|
|
|
|
|
|
* progpath = Pathname to program |
79
|
|
|
|
|
|
|
* progext = Extension of program |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=over 4 |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=cut |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
my %FIELDS = ( |
87
|
|
|
|
|
|
|
## Object Data |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# User-specified |
90
|
|
|
|
|
|
|
'name' => '', |
91
|
|
|
|
|
|
|
'summary' => '', |
92
|
|
|
|
|
|
|
'synopsis' => '', |
93
|
|
|
|
|
|
|
'description' => '', |
94
|
|
|
|
|
|
|
'history' => '', |
95
|
|
|
|
|
|
|
'version' => undef, |
96
|
|
|
|
|
|
|
'feature_config'=> {}, |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
'app_start_fn' => undef, |
99
|
|
|
|
|
|
|
'app_fn' => undef, |
100
|
|
|
|
|
|
|
'app_end_fn' => undef, |
101
|
|
|
|
|
|
|
'usage_fn' => undef, |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
'exit_type' => 'exit', |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Created during init |
106
|
|
|
|
|
|
|
'package' => undef, |
107
|
|
|
|
|
|
|
'filename' => undef, |
108
|
|
|
|
|
|
|
'progname' => undef, |
109
|
|
|
|
|
|
|
'progpath' => undef, |
110
|
|
|
|
|
|
|
'progext' => undef, |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
'feature_list' => [], # all registered feature names, sorted by priority |
113
|
|
|
|
|
|
|
'_feature_list' => {}, # all registered features |
114
|
|
|
|
|
|
|
'_feature_methods' => {}, # HASH or ARRAYs of any methods registered to a feature |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
'_required_features' => [qw/Data Options Args Pod/], |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
'personality' => undef, |
119
|
|
|
|
|
|
|
'extensions' => [], |
120
|
|
|
|
|
|
|
) ; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# Set of default options |
123
|
|
|
|
|
|
|
my @BASE_OPTIONS = ( |
124
|
|
|
|
|
|
|
['debug=i', 'Set debug level', 'Set the debug level value', ], |
125
|
|
|
|
|
|
|
) ; |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
our %LOADED_MODULES ; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
our $class_debug = 0 ; |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
#============================================================================================ |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=back |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 CONSTRUCTOR METHODS |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=over 4 |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=cut |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#============================================================================================ |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=item B |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Create a new App::Framework::Core. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
The %args are specified as they would be in the B method, for example: |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
'mmap_handler' => $mmap_handler |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
The full list of possible arguments are : |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
'fields' => Either ARRAY list of valid field names, or HASH of field names with default values |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=cut |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub new |
159
|
|
|
|
|
|
|
{ |
160
|
26
|
|
|
26
|
1
|
117
|
my ($obj, %args) = @_ ; |
161
|
|
|
|
|
|
|
|
162
|
26
|
|
33
|
|
|
198
|
my $class = ref($obj) || $obj ; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
## stop 'app' entry from being displayed in Features |
165
|
26
|
|
|
|
|
182
|
App::Framework::Base::Object::DumpObj::exclude('app') ; |
166
|
|
|
|
|
|
|
|
167
|
26
|
50
|
|
|
|
105
|
print "App::Framework::Core->new() class=$class\n" if $class_debug ; |
168
|
|
|
|
|
|
|
|
169
|
26
|
|
33
|
|
|
151
|
my $caller_info_aref = delete $args{'_caller_info'} || croak "$class must be called via App::Framework" ; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# Create object |
172
|
26
|
|
|
|
|
368
|
my $this = $class->SUPER::new(%args) ; |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# Set up error handler |
175
|
26
|
|
|
0
|
|
235
|
$this->set('catch_fn' => sub {$this->catch_error(@_);} ) ; |
|
0
|
|
|
|
|
0
|
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
## Get caller information |
178
|
26
|
|
|
|
|
131
|
my ($package, $filename, $line, $subr, $has_args, $wantarray) = @$caller_info_aref ; |
179
|
26
|
|
|
|
|
113
|
$this->set( |
180
|
|
|
|
|
|
|
'package' => $package, |
181
|
|
|
|
|
|
|
'filename' => $filename, |
182
|
|
|
|
|
|
|
) ; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
## now import packages into the caller's namespace |
185
|
26
|
|
|
|
|
279
|
$this->_import() ; |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
## Set program info |
189
|
26
|
|
|
|
|
3342
|
$this->set_paths($filename) ; |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
## set up functions |
192
|
|
|
|
|
|
|
# foreach my $fn (qw/app_start app app_end usage/) |
193
|
26
|
|
|
|
|
290
|
foreach my $fn_aref ( |
194
|
|
|
|
|
|
|
# prefered |
195
|
|
|
|
|
|
|
['app_start', 'app_start'], |
196
|
|
|
|
|
|
|
['app', 'app'], |
197
|
|
|
|
|
|
|
['app_end', 'app_end'], |
198
|
|
|
|
|
|
|
['usage', 'usage'], |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# alternates |
201
|
|
|
|
|
|
|
['app_begin', 'app_start'], |
202
|
|
|
|
|
|
|
['app_enter', 'app_start'], |
203
|
|
|
|
|
|
|
['app_init', 'app_start'], |
204
|
|
|
|
|
|
|
['app_finish', 'app_end'], |
205
|
|
|
|
|
|
|
['app_exit', 'app_end'], |
206
|
|
|
|
|
|
|
['app_term', 'app_end'], |
207
|
|
|
|
|
|
|
) |
208
|
|
|
|
|
|
|
{ |
209
|
260
|
|
|
|
|
451
|
my ($fn, $alias) = @$fn_aref ; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# Only add function if it's not already been specified |
212
|
260
|
|
|
|
|
844
|
$this->_register_fn($fn, $alias) ; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
## Get version |
216
|
26
|
|
|
|
|
324
|
$this->_register_scalar('VERSION', 'version') ; |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
## Ensure name set |
219
|
26
|
50
|
|
|
|
727
|
if (!$this->name()) |
220
|
|
|
|
|
|
|
{ |
221
|
26
|
|
|
|
|
704
|
$this->name($this->progname() ) ; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
## Set up default timezone |
226
|
26
|
50
|
|
|
|
153
|
if (exists($LOADED_MODULES{'Date::Manip'})) |
227
|
|
|
|
|
|
|
{ |
228
|
26
|
|
50
|
|
|
216
|
my $tz = $App::Frameowrk::Settings::DATE_TZ || 'GMT' ; |
229
|
26
|
|
50
|
|
|
186
|
my $fmt = $App::Frameowrk::Settings::DATE_FORMAT || 'non-US' ; |
230
|
26
|
|
|
|
|
56
|
eval { |
231
|
26
|
|
|
|
|
260
|
&Date_Init("TZ=$tz", "DateFormat=$fmt") ; |
232
|
|
|
|
|
|
|
} ; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
## Install required features |
236
|
26
|
|
|
|
|
20507
|
$this->install_features($this->_required_features) ; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
## Need to do some init of required features |
239
|
26
|
|
|
|
|
494
|
$this->feature('Options')->append_options(\@BASE_OPTIONS) ; |
240
|
|
|
|
|
|
|
|
241
|
26
|
50
|
|
|
|
148
|
print "App::Framework::Core->new() - END\n" if $class_debug ; |
242
|
|
|
|
|
|
|
|
243
|
26
|
|
|
|
|
1245
|
return($this) ; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
#============================================================================================ |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=back |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=head2 CLASS METHODS |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=over 4 |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=cut |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
#============================================================================================ |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=item B |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Initialises the App::Framework::Core object class variables. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=cut |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub init_class |
269
|
|
|
|
|
|
|
{ |
270
|
26
|
|
|
26
|
1
|
161
|
my $class = shift ; |
271
|
26
|
|
|
|
|
125
|
my (%args) = @_ ; |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Add extra fields |
274
|
26
|
|
|
|
|
172
|
$class->add_fields(\%FIELDS, \%args) ; |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# init class |
277
|
26
|
|
|
|
|
283
|
$class->SUPER::init_class(%args) ; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=item B |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Class instance object is not allowed |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=cut |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub allowed_class_instance |
290
|
|
|
|
|
|
|
{ |
291
|
0
|
|
|
0
|
1
|
0
|
return 0 ; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item B |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Attempt to load the module into the specified package I<$pkg> (or load it into a temporary space). |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
Then checks that the load was ok by checking the module's version number. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Returns 1 on success; 0 on failure. |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=cut |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
sub dynamic_load |
307
|
|
|
|
|
|
|
{ |
308
|
460
|
|
|
460
|
1
|
1433
|
my $class = shift ; |
309
|
460
|
|
|
|
|
1197
|
my ($module, $pkg) = @_ ; |
310
|
|
|
|
|
|
|
|
311
|
460
|
|
|
|
|
759
|
my $loaded = 0 ; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# for windoze.... |
314
|
460
|
50
|
|
|
|
23652
|
if ($^O =~ /MSWin32/i) |
315
|
|
|
|
|
|
|
{ |
316
|
0
|
0
|
|
|
|
0
|
return 0 unless $class->find_lib($module) ; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
460
|
|
100
|
|
|
2536
|
$pkg ||= 'temp_app_pkg' ; |
320
|
|
|
|
|
|
|
|
321
|
460
|
50
|
|
|
|
1296
|
print "dynamic_load($module) into $pkg\n" if $class_debug ; |
322
|
|
|
|
|
|
|
|
323
|
460
|
|
|
|
|
635
|
my $version ; |
324
|
27
|
|
|
27
|
|
22919
|
eval " |
|
26
|
|
|
26
|
|
78
|
|
|
26
|
|
|
25
|
|
735
|
|
|
26
|
|
|
25
|
|
20113
|
|
|
25
|
|
|
25
|
|
105
|
|
|
25
|
|
|
25
|
|
909
|
|
|
25
|
|
|
25
|
|
112467
|
|
|
1
|
|
|
25
|
|
3
|
|
|
1
|
|
|
25
|
|
35
|
|
|
25
|
|
|
25
|
|
14150
|
|
|
1
|
|
|
25
|
|
2
|
|
|
1
|
|
|
25
|
|
22
|
|
|
25
|
|
|
25
|
|
23241
|
|
|
25
|
|
|
25
|
|
74
|
|
|
25
|
|
|
25
|
|
985
|
|
|
25
|
|
|
25
|
|
22092
|
|
|
0
|
|
|
25
|
|
0
|
|
|
0
|
|
|
17
|
|
0
|
|
|
25
|
|
|
|
|
13608
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
33572
|
|
|
25
|
|
|
|
|
85
|
|
|
25
|
|
|
|
|
948
|
|
|
25
|
|
|
|
|
24681
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
14687
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
40648
|
|
|
25
|
|
|
|
|
110
|
|
|
25
|
|
|
|
|
1072
|
|
|
25
|
|
|
|
|
15891
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
890364
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
35912
|
|
|
25
|
|
|
|
|
99
|
|
|
25
|
|
|
|
|
944
|
|
|
25
|
|
|
|
|
15533
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
15942
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
51138
|
|
|
10
|
|
|
|
|
31
|
|
|
10
|
|
|
|
|
376
|
|
|
17
|
|
|
|
|
44599
|
|
|
16
|
|
|
|
|
58
|
|
|
16
|
|
|
|
|
632
|
|
|
460
|
|
|
|
|
43706
|
|
325
|
|
|
|
|
|
|
package $pkg; |
326
|
|
|
|
|
|
|
use $module; |
327
|
|
|
|
|
|
|
\$version = \$${module}::VERSION ; |
328
|
|
|
|
|
|
|
" ; |
329
|
|
|
|
|
|
|
#print "Version = $version\n" ; |
330
|
460
|
100
|
|
|
|
3189
|
if ($@) |
|
|
50
|
|
|
|
|
|
331
|
|
|
|
|
|
|
{ |
332
|
275
|
50
|
|
|
|
1434
|
print "dynamic_load($module, $pkg) : error : $@\nAborting dynamic_load.\n" if $class_debug ; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
elsif (defined($version)) |
335
|
|
|
|
|
|
|
{ |
336
|
185
|
|
|
|
|
420
|
$loaded = 1 ; |
337
|
|
|
|
|
|
|
} |
338
|
460
|
50
|
|
|
|
1543
|
print "dynamic_load($module, $pkg) : loaded = $loaded.\n" if $class_debug ; |
339
|
|
|
|
|
|
|
|
340
|
460
|
|
|
|
|
2546
|
return $loaded ; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=item B |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
Load the module into the caller's namespace then set it's @ISA ready for that |
348
|
|
|
|
|
|
|
module to call it's parent's new() method |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=cut |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
sub dynamic_isa |
353
|
|
|
|
|
|
|
{ |
354
|
54
|
|
|
54
|
1
|
118
|
my $class = shift ; |
355
|
54
|
|
|
|
|
117
|
my ($module, $pkg) = @_ ; |
356
|
|
|
|
|
|
|
|
357
|
54
|
50
|
|
|
|
170
|
unless ($pkg) |
358
|
|
|
|
|
|
|
{ |
359
|
0
|
|
|
|
|
0
|
my @callinfo = caller(0); |
360
|
0
|
|
|
|
|
0
|
$pkg = $callinfo[0] ; |
361
|
|
|
|
|
|
|
} |
362
|
54
|
|
|
|
|
223
|
my $loaded = $class->dynamic_load($module, $pkg) ; |
363
|
|
|
|
|
|
|
|
364
|
54
|
50
|
|
|
|
192
|
if ($loaded) |
365
|
|
|
|
|
|
|
{ |
366
|
30
|
|
|
30
|
|
187
|
no strict 'refs' ; |
|
30
|
|
|
|
|
65
|
|
|
30
|
|
|
|
|
17445
|
|
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
## Create ourself as if we're an object of the required type (but only if ISA is not already set) |
369
|
54
|
100
|
|
|
|
101
|
if (!scalar(@{"${pkg}::ISA"})) |
|
54
|
|
|
|
|
359
|
|
370
|
|
|
|
|
|
|
{ |
371
|
51
|
50
|
|
|
|
170
|
print "dynamic_isa() $pkg set ISA=$module\n" if $class_debug ; |
372
|
51
|
|
|
|
|
93
|
@{"${pkg}::ISA"} = ( $module ) ; |
|
51
|
|
|
|
|
1284
|
|
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
else |
375
|
|
|
|
|
|
|
{ |
376
|
3
|
50
|
|
|
|
12
|
print "dynamic_isa() - $pkg already got ISA=",@{"${pkg}::ISA"}," (wanted to set $module)\n" if $class_debug ; |
|
0
|
|
|
|
|
0
|
|
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
54
|
|
|
|
|
267
|
return $loaded ; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=item B< inherit($caller_class, [%args]) > |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
Initialises the object class variables. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=cut |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
sub inherit |
394
|
|
|
|
|
|
|
{ |
395
|
27
|
|
|
27
|
1
|
66
|
my $class = shift ; |
396
|
27
|
|
|
|
|
265
|
my ($caller_class, %args) = @_ ; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
## get calling package |
399
|
27
|
|
|
|
|
181
|
my $caller_pkg = (caller(0))[0] ; |
400
|
|
|
|
|
|
|
|
401
|
27
|
50
|
|
|
|
127
|
print "\n\n----------------------------------------\n" if $class_debug ; |
402
|
27
|
50
|
|
|
|
92
|
print "Core:inherit() caller=$caller_pkg\n" if $class_debug ; |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
## get inheritence stack, grab this object's class, restore list |
405
|
27
|
|
50
|
|
|
372
|
my $inheritence = delete $args{'_inheritence'} || [] ; |
406
|
|
|
|
|
|
|
|
407
|
27
|
50
|
|
|
|
115
|
print " + inherit=\n\t".join("\n\t", @$inheritence)."\n" if $class_debug ; |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
## Get parent and restore new list |
410
|
27
|
|
|
|
|
85
|
my $parent = shift @$inheritence ; |
411
|
27
|
|
|
|
|
71
|
$args{'_inheritence'} = $inheritence ; |
412
|
|
|
|
|
|
|
|
413
|
27
|
50
|
|
|
|
103
|
print "Core: $caller_class parent=$parent inherit=@$inheritence\n" if $class_debug ; |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
## load in base objects |
416
|
27
|
|
|
|
|
56
|
my $_caller = $parent ; |
417
|
27
|
|
|
|
|
93
|
foreach my $_parent (@$inheritence) |
418
|
|
|
|
|
|
|
{ |
419
|
1
|
50
|
|
|
|
3
|
print " + Preloading: load $_parent into $_caller\n" if $class_debug ; |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
## Dynamic load this parent into this caller |
422
|
1
|
|
|
|
|
4
|
my $loaded = App::Framework::Core->dynamic_isa($_parent, $_caller) ; |
423
|
1
|
50
|
|
|
|
4
|
croak "Sorry, failed to load \"$_parent\"" unless $loaded ; |
424
|
|
|
|
|
|
|
|
425
|
1
|
50
|
|
|
|
4
|
App::Framework::Core::_dumpvar($_caller) if $class_debug ; |
426
|
1
|
50
|
|
|
|
4
|
App::Framework::Core::_dumpvar($_parent) if $class_debug ; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
# update caller for next time round |
429
|
1
|
|
|
|
|
3
|
$_caller = $_parent ; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
27
|
50
|
|
|
|
276
|
print " + Loading: load $parent into $caller_pkg\n" if $class_debug ; |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
## Dynamic load this object |
435
|
27
|
|
|
|
|
114
|
my $loaded = App::Framework::Core->dynamic_isa($parent, $caller_pkg) ; |
436
|
27
|
50
|
|
|
|
130
|
croak "Sorry, failed to load \"$parent\"" unless $loaded ; |
437
|
|
|
|
|
|
|
|
438
|
27
|
50
|
|
|
|
110
|
App::Framework::Core::_dumpvar($caller_pkg) if $class_debug ; |
439
|
27
|
50
|
|
|
|
105
|
App::Framework::Core::_dumpvar($parent) if $class_debug ; |
440
|
|
|
|
|
|
|
|
441
|
27
|
50
|
|
|
|
93
|
print "Core: calling $caller_pkg -> $parent ::new()\n" if $class_debug ; |
442
|
27
|
50
|
|
|
|
105
|
App::Framework::Core::_dumpisa($caller_pkg) if $class_debug ; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
## Create object |
445
|
27
|
|
|
|
|
56
|
my $this ; |
446
|
|
|
|
|
|
|
{ |
447
|
30
|
|
|
30
|
|
220
|
no strict 'refs' ; |
|
30
|
|
|
|
|
61
|
|
|
30
|
|
|
|
|
15576
|
|
|
27
|
|
|
|
|
56
|
|
448
|
|
|
|
|
|
|
|
449
|
27
|
|
|
|
|
128
|
$this = &{"${parent}::new"}( |
|
27
|
|
|
|
|
397
|
|
450
|
|
|
|
|
|
|
$caller_class, |
451
|
|
|
|
|
|
|
%args, |
452
|
|
|
|
|
|
|
) ; |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
27
|
50
|
|
|
|
267
|
print "Core:inherit() - END\n" if $class_debug ; |
457
|
27
|
50
|
|
|
|
131
|
print "----------------------------------------\n\n" if $class_debug ; |
458
|
|
|
|
|
|
|
|
459
|
27
|
|
|
|
|
743
|
return $this ; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=item B< find_lib($module) > |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
Looks for the named module in the @INC path. If found, checks the package name inside the file |
468
|
|
|
|
|
|
|
to ensure that it really matches the capitalisation. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
(Mainly for Microsoft Windows use!) |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
=cut |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
sub find_lib |
475
|
|
|
|
|
|
|
{ |
476
|
0
|
|
|
0
|
1
|
0
|
my $class = shift ; |
477
|
0
|
|
|
|
|
0
|
my ($module) = @_ ; |
478
|
|
|
|
|
|
|
|
479
|
0
|
|
|
|
|
0
|
my @module_dirs = split /::/, $module ; |
480
|
0
|
|
|
|
|
0
|
my $pm = pop @module_dirs ; |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
#print "find_lib($module)\n" ; |
483
|
|
|
|
|
|
|
|
484
|
0
|
|
|
|
|
0
|
my $found ; |
485
|
0
|
|
|
|
|
0
|
foreach my $dir (@INC) |
486
|
|
|
|
|
|
|
{ |
487
|
0
|
|
|
|
|
0
|
my $file = File::Spec->catfile($dir, @module_dirs, "$pm.pm") ; |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
#print " + checking $file\n" ; |
490
|
0
|
0
|
|
|
|
0
|
if (-f $file) |
491
|
|
|
|
|
|
|
{ |
492
|
0
|
0
|
|
|
|
0
|
if (open my $fh, "<$file") |
493
|
|
|
|
|
|
|
{ |
494
|
0
|
|
|
|
|
0
|
my $line ; |
495
|
0
|
|
|
|
|
0
|
while (defined($line = <$fh>)) |
496
|
|
|
|
|
|
|
{ |
497
|
0
|
|
|
|
|
0
|
chomp $line ; |
498
|
0
|
0
|
|
|
|
0
|
if ($line =~ m/^\s*package\s+$module\s*;/) |
499
|
|
|
|
|
|
|
{ |
500
|
0
|
|
|
|
|
0
|
$found = $module ; |
501
|
0
|
|
|
|
|
0
|
last ; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
} |
504
|
0
|
|
|
|
|
0
|
close $fh ; |
505
|
|
|
|
|
|
|
} |
506
|
0
|
0
|
|
|
|
0
|
last if $found ; |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
#print "find_lib() = $found\n" ; |
511
|
|
|
|
|
|
|
|
512
|
0
|
|
|
|
|
0
|
return $found ; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
=item B< lib_glob($module_path) > |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
Looks for any perl modules contained under the module path. Looks at all possible locations |
520
|
|
|
|
|
|
|
in the @INC path, returning the first found. |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Returns a HASH contains the module name as key and the full filename path as the value. |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=cut |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
sub lib_glob |
527
|
|
|
|
|
|
|
{ |
528
|
0
|
|
|
0
|
1
|
0
|
my $class = shift ; |
529
|
0
|
|
|
|
|
0
|
my ($module_path) = @_ ; |
530
|
|
|
|
|
|
|
|
531
|
0
|
|
|
|
|
0
|
my %libs ; |
532
|
0
|
|
|
|
|
0
|
foreach my $dir (@INC) |
533
|
|
|
|
|
|
|
{ |
534
|
0
|
|
|
|
|
0
|
my $module_path = File::Spec->catfile($dir, $module_path, "*.pm") ; |
535
|
0
|
|
|
|
|
0
|
my @files = glob($module_path) ; |
536
|
0
|
|
|
|
|
0
|
foreach my $file (@files) |
537
|
|
|
|
|
|
|
{ |
538
|
0
|
|
|
|
|
0
|
my ($base, $path, $ext) = fileparse($file, '\..*') ; |
539
|
0
|
0
|
|
|
|
0
|
if (!exists($libs{$base})) |
540
|
|
|
|
|
|
|
{ |
541
|
0
|
|
|
|
|
0
|
$libs{$base} = $file ; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
0
|
|
|
|
|
0
|
return %libs ; |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=item B |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Starting at I, return a HASH ref in the form of a tree of it's parents. They keys are the parent module |
554
|
|
|
|
|
|
|
names, and the values are HASH refs of their parents and so on. Value is undef when last parent |
555
|
|
|
|
|
|
|
is reached. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=cut |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
sub isa_tree |
560
|
|
|
|
|
|
|
{ |
561
|
30
|
|
|
30
|
|
206
|
no strict "vars" ; |
|
30
|
|
|
|
|
78
|
|
|
30
|
|
|
|
|
1022
|
|
562
|
30
|
|
|
30
|
|
158
|
no strict "refs" ; |
|
30
|
|
|
|
|
55
|
|
|
30
|
|
|
|
|
26281
|
|
563
|
|
|
|
|
|
|
|
564
|
0
|
|
|
0
|
1
|
0
|
my $class = shift ; |
565
|
0
|
|
|
|
|
0
|
my ($packageName) = @_; |
566
|
|
|
|
|
|
|
|
567
|
0
|
|
|
|
|
0
|
my $tree_href = {} ; |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
|
570
|
0
|
|
|
|
|
0
|
foreach my $isa (@{"${packageName}::ISA"}) |
|
0
|
|
|
|
|
0
|
|
571
|
|
|
|
|
|
|
{ |
572
|
0
|
|
|
|
|
0
|
$tree_href->{$isa} = $class->isa_tree($isa) ; |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
0
|
|
|
|
|
0
|
return $tree_href ; |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
#============================================================================================ |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=back |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=head2 OBJECT METHODS |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
=over 4 |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
=cut |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
#============================================================================================ |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=item B |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
Get the full path to this application (follows links where required) |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=cut |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub set_paths |
599
|
|
|
|
|
|
|
{ |
600
|
54
|
|
|
54
|
1
|
165
|
my $this = shift ; |
601
|
54
|
|
|
|
|
129
|
my ($filename) = @_ ; |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
# Follow links |
604
|
54
|
|
|
|
|
2815
|
$filename = File::Spec->rel2abs($filename) ; |
605
|
54
|
|
|
|
|
3673
|
while ( -l $filename) |
606
|
|
|
|
|
|
|
{ |
607
|
0
|
|
|
|
|
0
|
$filename = readlink $filename ; |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
# Get info |
611
|
54
|
|
|
|
|
3580
|
my ($progname, $progpath, $progext) = fileparse($filename, '\.[^\.]+') ; |
612
|
54
|
100
|
|
|
|
266
|
if (ref($this)) |
613
|
|
|
|
|
|
|
{ |
614
|
|
|
|
|
|
|
# set if not class call |
615
|
26
|
|
|
|
|
489
|
$this->set( |
616
|
|
|
|
|
|
|
'progname' => $progname, |
617
|
|
|
|
|
|
|
'progpath' => $progpath, |
618
|
|
|
|
|
|
|
'progext' => $progext, |
619
|
|
|
|
|
|
|
) ; |
620
|
|
|
|
|
|
|
} |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
# Set up include path to add script home + script home /lib subdir |
623
|
54
|
|
|
|
|
154
|
my %inc = map {$_=>1} @INC ; |
|
700
|
|
|
|
|
2001
|
|
624
|
54
|
|
|
|
|
265
|
foreach my $path ($progpath, "$progpath/lib") |
625
|
|
|
|
|
|
|
{ |
626
|
|
|
|
|
|
|
# add new paths |
627
|
108
|
100
|
|
|
|
480
|
unshift(@INC,$path) unless exists $inc{$path} ; |
628
|
108
|
|
|
|
|
236
|
$inc{$path} = 1 ; |
629
|
108
|
50
|
|
|
|
611
|
push @INC, $path unless exists $inc{$path} ; |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
=item B |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
Function that gets called on errors. $error is as defined in L |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
=cut |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub catch_error |
642
|
|
|
|
|
|
|
{ |
643
|
1
|
|
|
1
|
1
|
2
|
my $this = shift ; |
644
|
1
|
|
|
|
|
1
|
my ($error) = @_ ; |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
# Does nothing! |
647
|
|
|
|
|
|
|
|
648
|
1
|
|
|
|
|
5
|
$this->_dispatch_entry_features($error) ; |
649
|
|
|
|
|
|
|
|
650
|
1
|
|
|
|
|
4
|
$this->_dispatch_exit_features($error) ; |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
=item B |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
Add the listed features to the application. List is an ARRAY ref list of feature names. |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
Note: names need correct capitalisation (e.g. Sql not sql) - or just use first char capitalised(?) |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
Method/feature name will be all lowercase |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
Optionally, can specify I<$feature_args> HASH ref. Each feature name in I<$feature_list> should be a key |
666
|
|
|
|
|
|
|
in the HASH, the value of which is an arguments string (which is a list of feature arguments separated by space and/or |
667
|
|
|
|
|
|
|
commas) |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=cut |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
sub install_features |
672
|
|
|
|
|
|
|
{ |
673
|
51
|
|
|
51
|
1
|
150
|
my $this = shift ; |
674
|
51
|
|
|
|
|
147
|
my ($feature_list, $feature_args_href) = @_ ; |
675
|
|
|
|
|
|
|
|
676
|
51
|
|
100
|
|
|
352
|
$feature_args_href ||= {} ; |
677
|
|
|
|
|
|
|
|
678
|
51
|
|
|
|
|
1604
|
my $features_href = $this->_feature_list() ; |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
## make a list of features |
681
|
51
|
|
|
|
|
225
|
my @features = @$feature_list ; |
682
|
|
|
|
|
|
|
|
683
|
51
|
|
|
|
|
324
|
$this->_dbg_prt(["install_features()", \@features, "features args=", $feature_args_href]) ; |
684
|
51
|
50
|
|
|
|
253
|
$class_debug = $this->debug if $this->debug >= 5 ; |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
## Now try to install them |
688
|
51
|
|
|
|
|
134
|
foreach my $feature (@features) |
689
|
|
|
|
|
|
|
{ |
690
|
130
|
|
100
|
|
|
1166
|
my $feature_args = $feature_args_href->{$feature} || "" ; |
691
|
|
|
|
|
|
|
|
692
|
130
|
|
|
|
|
303
|
my $loaded ; |
693
|
130
|
|
|
|
|
976
|
my $feature_guess = ucfirst(lc($feature)) ; |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
## skip if already loaded |
696
|
130
|
50
|
33
|
|
|
1598
|
if (exists($features_href->{$feature}) || exists($features_href->{$feature_guess})) |
697
|
|
|
|
|
|
|
{ |
698
|
|
|
|
|
|
|
## Just need to see if we've got any new args |
699
|
0
|
|
|
|
|
0
|
foreach my $feat ($feature, $feature_guess) |
700
|
|
|
|
|
|
|
{ |
701
|
0
|
0
|
|
|
|
0
|
if (exists($feature_args_href->{$feat})) |
702
|
|
|
|
|
|
|
{ |
703
|
|
|
|
|
|
|
## override args |
704
|
0
|
|
|
|
|
0
|
my $feature_obj = $features_href->{$feature}{'object'} ; |
705
|
0
|
|
|
|
|
0
|
$feature_obj->feature_args($feature_args_href->{$feat}) ; |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
} |
708
|
0
|
|
|
|
|
0
|
next ; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
# build list of module names to attempt. If personality name is set, try looking for feature |
712
|
|
|
|
|
|
|
# under personality subdir first. This allows for personality override of feature (e.g. POE:app overrides Script:app) |
713
|
|
|
|
|
|
|
# |
714
|
130
|
|
|
|
|
280
|
my @tries ; |
715
|
130
|
|
|
|
|
5224
|
my $personality = $this->personality ; |
716
|
130
|
|
|
|
|
317
|
my $root = "App::Framework::Feature" ; |
717
|
130
|
50
|
|
|
|
397
|
if ($personality) |
718
|
|
|
|
|
|
|
{ |
719
|
130
|
|
|
|
|
492
|
push @tries, "${root}::${personality}::$feature" ; |
720
|
130
|
|
|
|
|
471
|
push @tries, "${root}::${personality}::$feature_guess" ; |
721
|
|
|
|
|
|
|
} |
722
|
130
|
|
|
|
|
427
|
push @tries, "${root}::$feature" ; |
723
|
130
|
|
|
|
|
526
|
push @tries, "${root}::$feature_guess" ; |
724
|
|
|
|
|
|
|
|
725
|
130
|
|
|
|
|
294
|
foreach my $module (@tries) |
726
|
|
|
|
|
|
|
{ |
727
|
405
|
100
|
|
|
|
3470
|
if ($this->dynamic_load($module)) |
728
|
|
|
|
|
|
|
{ |
729
|
130
|
|
|
|
|
401
|
$loaded = $module ; |
730
|
130
|
|
|
|
|
958
|
last ; |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
|
734
|
130
|
|
|
|
|
2235738
|
my $cwd = cwd() ; |
735
|
130
|
50
|
|
|
|
3174
|
$this->_dbg_prt(["Feature: $feature - unable to load. CWD=$cwd.\n", "Tried=", \@tries, "\n\@INC=", \@INC]) unless ($loaded) ; |
736
|
|
|
|
|
|
|
|
737
|
130
|
50
|
|
|
|
7748
|
croak "Feature \"$feature\" not supported" unless ($loaded) ; |
738
|
|
|
|
|
|
|
|
739
|
130
|
|
|
|
|
10701
|
$this->_dbg_prt(["Feature: $feature - loaded=$loaded\n"]) ; |
740
|
|
|
|
|
|
|
|
741
|
130
|
50
|
|
|
|
12411
|
if ($loaded) |
742
|
|
|
|
|
|
|
{ |
743
|
|
|
|
|
|
|
# save in list |
744
|
130
|
|
|
|
|
720
|
my $module = $loaded ; |
745
|
130
|
|
|
|
|
787
|
my $specified_name = $feature ; |
746
|
130
|
|
|
|
|
1268
|
$feature = lc $feature ; |
747
|
|
|
|
|
|
|
|
748
|
130
|
|
|
|
|
6346
|
$features_href->{$feature} = { |
749
|
|
|
|
|
|
|
'module' => $module, # loaded module name |
750
|
|
|
|
|
|
|
'specified' => $specified_name, # as specified by user |
751
|
|
|
|
|
|
|
'name' => $feature, # name used as a method |
752
|
|
|
|
|
|
|
'object' => undef, |
753
|
|
|
|
|
|
|
'priority' => $App::Framework::Base::PRIORITY_DEFAULT, |
754
|
|
|
|
|
|
|
} ; |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
# see if we have some extra init values to pass to the feature |
757
|
130
|
|
|
|
|
4989
|
my $feature_init_href = $this->_feature_init($feature) ; |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
# create feature |
760
|
1
|
|
|
1
|
|
19
|
my $feature_obj = $module->new( |
761
|
|
|
|
|
|
|
%$feature_init_href, |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
'app' => $this, |
764
|
|
|
|
|
|
|
'name' => $feature, # ensure it matches with what the app expects |
765
|
|
|
|
|
|
|
'feature_args' => $feature_args, |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
# Set up error handler |
768
|
|
|
|
|
|
|
'catch_fn' => sub {$this->catch_error(@_);}, |
769
|
|
|
|
|
|
|
|
770
|
130
|
|
|
|
|
5141
|
) ; |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
# add to list (may already have been done if feature registers any methods) |
773
|
130
|
|
|
|
|
613
|
$features_href->{$feature}{'object'} = $feature_obj ; |
774
|
130
|
|
|
|
|
4746
|
$features_href->{$feature}{'priority'} = $feature_obj->priority ; |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
# set up alias |
777
|
|
|
|
|
|
|
{ |
778
|
30
|
|
|
30
|
|
187
|
no warnings 'redefine'; |
|
30
|
|
|
|
|
68
|
|
|
30
|
|
|
|
|
1380
|
|
|
130
|
|
|
|
|
276
|
|
779
|
30
|
|
|
30
|
|
156
|
no strict 'refs'; |
|
30
|
|
|
|
|
60
|
|
|
30
|
|
|
|
|
98316
|
|
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
## alias () |
782
|
130
|
|
|
|
|
688
|
my $alias = lc $feature ; |
783
|
130
|
|
|
|
|
5485
|
*{"App::Framework::Core::${alias}"} = sub { |
784
|
533
|
|
|
533
|
|
35452
|
my $this = shift ; |
785
|
533
|
|
|
|
|
2374
|
return $feature_obj->$alias(@_) ; |
786
|
130
|
|
|
|
|
1415
|
}; |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
## alias () |
789
|
130
|
|
|
|
|
691
|
$alias = ucfirst $feature ; |
790
|
130
|
|
|
|
|
5647
|
*{"App::Framework::Core::${alias}"} = sub { |
791
|
52
|
|
|
52
|
|
22194
|
my $this = shift ; |
792
|
52
|
|
|
|
|
378
|
return $feature_obj->$alias(@_) ; |
793
|
130
|
|
|
|
|
134286
|
}; |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
## Ensure list is sorted by priority |
800
|
51
|
|
|
|
|
1032
|
$this->feature_list( [ sort {$features_href->{$a}{'priority'} <=> $features_href->{$b}{'priority'}} keys %$features_href ] ) ; |
|
285
|
|
|
|
|
9292
|
|
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
|
803
|
51
|
|
|
|
|
1098
|
$this->_dbg_prt(["installed features = ", $features_href]) ; |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
809
|
|
|
|
|
|
|
# |
810
|
|
|
|
|
|
|
#=item B<_feature_init($feature)> |
811
|
|
|
|
|
|
|
# |
812
|
|
|
|
|
|
|
#Get any initialisation values for this feature. Returns an empty HASH ref if no |
813
|
|
|
|
|
|
|
#init specified |
814
|
|
|
|
|
|
|
# |
815
|
|
|
|
|
|
|
#=cut |
816
|
|
|
|
|
|
|
# |
817
|
|
|
|
|
|
|
sub _feature_init |
818
|
|
|
|
|
|
|
{ |
819
|
130
|
|
|
130
|
|
636
|
my $this = shift ; |
820
|
130
|
|
|
|
|
681
|
my ($feature) = @_ ; |
821
|
|
|
|
|
|
|
|
822
|
130
|
|
|
|
|
647
|
my $feature_init_href = {} ; |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
## May have some initialisation values for the feature |
825
|
130
|
|
|
|
|
19769
|
my $feature_config_href = $this->feature_config ; |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
## See if we can find a name match |
828
|
130
|
|
|
|
|
2047
|
foreach my $name (keys %$feature_config_href) |
829
|
|
|
|
|
|
|
{ |
830
|
52
|
100
|
|
|
|
598
|
if (lc $name eq lc $feature) |
831
|
|
|
|
|
|
|
{ |
832
|
14
|
|
|
|
|
229
|
$feature_init_href = $feature_config_href->{$name} ; |
833
|
|
|
|
|
|
|
#$this->prt_data("_feature_init($feature)=", $feature_init_href) ; |
834
|
14
|
|
|
|
|
159
|
last ; |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
} |
837
|
|
|
|
|
|
|
|
838
|
130
|
|
|
|
|
541
|
return $feature_init_href ; |
839
|
|
|
|
|
|
|
} |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
##---------------------------------------------------------------------------- |
842
|
|
|
|
|
|
|
# |
843
|
|
|
|
|
|
|
#=item B |
844
|
|
|
|
|
|
|
# |
845
|
|
|
|
|
|
|
#Return list of installed features |
846
|
|
|
|
|
|
|
# |
847
|
|
|
|
|
|
|
#=cut |
848
|
|
|
|
|
|
|
# |
849
|
|
|
|
|
|
|
#sub feature_list |
850
|
|
|
|
|
|
|
#{ |
851
|
|
|
|
|
|
|
# my $this = shift ; |
852
|
|
|
|
|
|
|
# |
853
|
|
|
|
|
|
|
# my $features_href = $this->_feature_list() ; |
854
|
|
|
|
|
|
|
# my @list = map {$features_href->{$_}{'specified'}} keys %$features_href ; |
855
|
|
|
|
|
|
|
# return @list ; |
856
|
|
|
|
|
|
|
#} |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
##---------------------------------------------------------------------------- |
859
|
|
|
|
|
|
|
# |
860
|
|
|
|
|
|
|
#=item B<_feature_info($name)> |
861
|
|
|
|
|
|
|
# |
862
|
|
|
|
|
|
|
#Return HASH ref of feature information for this feature. |
863
|
|
|
|
|
|
|
# |
864
|
|
|
|
|
|
|
#=cut |
865
|
|
|
|
|
|
|
# |
866
|
|
|
|
|
|
|
sub _feature_info |
867
|
|
|
|
|
|
|
{ |
868
|
978
|
|
|
978
|
|
1347
|
my $this = shift ; |
869
|
978
|
|
|
|
|
1851
|
my ($name, %args) = @_ ; |
870
|
|
|
|
|
|
|
|
871
|
978
|
|
|
|
|
28333
|
my $features_href = $this->_feature_list() ; |
872
|
978
|
|
|
|
|
1889
|
$name = lc $name ; |
873
|
|
|
|
|
|
|
|
874
|
978
|
|
|
|
|
2404
|
my $info_href ; |
875
|
978
|
50
|
|
|
|
2720
|
if (exists($features_href->{$name})) |
876
|
|
|
|
|
|
|
{ |
877
|
978
|
|
|
|
|
1837
|
$info_href = $features_href->{$name} ; |
878
|
|
|
|
|
|
|
} |
879
|
|
|
|
|
|
|
else |
880
|
|
|
|
|
|
|
{ |
881
|
0
|
|
|
|
|
0
|
$this->throw_fatal("Feature \"$name\" not found") ; |
882
|
|
|
|
|
|
|
} |
883
|
|
|
|
|
|
|
|
884
|
978
|
|
|
|
|
2084
|
return $info_href ; |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
=item B |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
Return named feature object if the feature is installed; otherwise returns undef. |
892
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
=cut |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
sub feature_installed |
896
|
|
|
|
|
|
|
{ |
897
|
15
|
|
|
15
|
1
|
28
|
my $this = shift ; |
898
|
15
|
|
|
|
|
43
|
my ($name) = @_ ; |
899
|
|
|
|
|
|
|
|
900
|
15
|
|
|
|
|
729
|
my $features_href = $this->_feature_list() ; |
901
|
15
|
|
|
|
|
57
|
$name = lc $name ; |
902
|
|
|
|
|
|
|
|
903
|
15
|
|
|
|
|
29
|
my $feature = undef ; |
904
|
15
|
100
|
|
|
|
55
|
if (exists($features_href->{$name})) |
905
|
|
|
|
|
|
|
{ |
906
|
5
|
|
|
|
|
12
|
my $feature_href = $features_href->{$name} ; |
907
|
5
|
|
|
|
|
17
|
$feature = $feature_href->{'object'} ; |
908
|
|
|
|
|
|
|
} |
909
|
|
|
|
|
|
|
|
910
|
15
|
|
|
|
|
48
|
return $feature ; |
911
|
|
|
|
|
|
|
} |
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
=item B |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
Return named feature object. Alternative interface to just calling the feature's 'get/set' method. |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
For example, 'sql' feature can be accessed either as: |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
my $sql = $app->feature("sql") ; |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
or: |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
my $sql = $app->sql() ; |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
=cut |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
sub feature |
933
|
|
|
|
|
|
|
{ |
934
|
891
|
|
|
891
|
1
|
14625
|
my $this = shift ; |
935
|
891
|
|
|
|
|
2387
|
my ($name, %args) = @_ ; |
936
|
|
|
|
|
|
|
|
937
|
891
|
|
|
|
|
2575
|
my $feature_href = $this->_feature_info($name) ; |
938
|
|
|
|
|
|
|
|
939
|
891
|
|
|
|
|
2055
|
my $feature = $feature_href->{'object'} ; |
940
|
891
|
50
|
|
|
|
2141
|
if (%args) |
941
|
|
|
|
|
|
|
{ |
942
|
0
|
|
|
|
|
0
|
$feature->set(%args) ; |
943
|
|
|
|
|
|
|
} |
944
|
|
|
|
|
|
|
|
945
|
891
|
|
|
|
|
6620
|
return $feature ; |
946
|
|
|
|
|
|
|
} |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
=item B |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
API for feature objects. Used so that they can register their methods to be called |
954
|
|
|
|
|
|
|
at the start and end of the registered functions. |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
Function list is a list of strings where the string is in the format: |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
_entry |
959
|
|
|
|
|
|
|
_exit |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
To register a call at the start of the method and/or at the end of the method. |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
This is usually called when the feature is being created (which is usually because this Core object |
964
|
|
|
|
|
|
|
is installing the feature). To ensure the core's lists are up to date, this function sets the feature object |
965
|
|
|
|
|
|
|
and priority. |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
=cut |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
sub feature_register |
970
|
|
|
|
|
|
|
{ |
971
|
57
|
|
|
57
|
1
|
184
|
my $this = shift ; |
972
|
57
|
|
|
|
|
266
|
my ($feature, $feature_obj, @function_list) = @_ ; |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
## Add methods |
975
|
57
|
|
|
|
|
2361
|
my $feature_methods_href = $this->_feature_methods() ; |
976
|
57
|
|
|
|
|
355
|
foreach my $method (@function_list) |
977
|
|
|
|
|
|
|
{ |
978
|
87
|
|
|
|
|
1444
|
my $feature_href = $this->_feature_info($feature) ; |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
# update info (ensure's core has latest info) |
981
|
87
|
|
|
|
|
229
|
$feature_href->{'object'} = $feature_obj ; |
982
|
87
|
|
|
|
|
3524
|
$feature_href->{'priority'} = $feature_obj->priority ; |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
#$this->prt_data("Feature info=", $feature_href); |
985
|
|
|
|
|
|
|
|
986
|
87
|
|
100
|
|
|
680
|
$feature_methods_href->{$method} ||= [] ; |
987
|
87
|
|
|
|
|
148
|
push @{$feature_methods_href->{$method}}, { |
|
87
|
|
|
|
|
2016
|
|
988
|
|
|
|
|
|
|
'feature' => $feature, |
989
|
|
|
|
|
|
|
'obj' => $feature_href->{'object'}, |
990
|
|
|
|
|
|
|
'priority' => $feature_href->{'priority'}, |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
} |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
#$this->prt_data("Raw feature list=", $feature_methods_href); |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
## Ensure all lists are sorted by priority |
998
|
57
|
|
|
|
|
195
|
foreach my $method (@function_list) |
999
|
|
|
|
|
|
|
{ |
1000
|
87
|
|
|
|
|
284
|
$feature_methods_href->{$method} = [ sort {$a->{'priority'} <=> $b->{'priority'}} @{$feature_methods_href->{$method}} ] ; |
|
40
|
|
|
|
|
494
|
|
|
87
|
|
|
|
|
917
|
|
1001
|
|
|
|
|
|
|
} |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
#$this->prt_data("Sorted feature list=", $feature_methods_href); |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
} |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1009
|
|
|
|
|
|
|
# |
1010
|
|
|
|
|
|
|
#=item B<_dispatch_features($method, 'entry|exit')> |
1011
|
|
|
|
|
|
|
# |
1012
|
|
|
|
|
|
|
#INTERNAL: For the specified method, run any features that registered for this method. |
1013
|
|
|
|
|
|
|
# |
1014
|
|
|
|
|
|
|
#=cut |
1015
|
|
|
|
|
|
|
# |
1016
|
|
|
|
|
|
|
sub _dispatch_features |
1017
|
|
|
|
|
|
|
{ |
1018
|
898
|
|
|
898
|
|
1214
|
my $this = shift ; |
1019
|
898
|
|
|
|
|
2010
|
my ($method, $status, @args) = @_ ; |
1020
|
|
|
|
|
|
|
|
1021
|
898
|
100
|
|
|
|
2113
|
@args = () unless @args ; |
1022
|
898
|
|
|
|
|
4370
|
$this->_dbg_prt(["_dispatch_features(method=$method, status=$status) : args=", \@args]) ; |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
# remove package name (if specified) |
1025
|
898
|
|
|
|
|
5203
|
$method =~ s/^(.*)::// ; |
1026
|
|
|
|
|
|
|
|
1027
|
898
|
|
|
|
|
25944
|
my $feature_methods_href = $this->_feature_methods() ; |
1028
|
898
|
|
|
|
|
1983
|
my $fn = "${method}_${status}" ; |
1029
|
898
|
|
|
|
|
3691
|
$this->_dbg_prt([" + method=$method fn=$fn\n"]) ; |
1030
|
|
|
|
|
|
|
|
1031
|
898
|
100
|
|
|
|
5250
|
if (exists($feature_methods_href->{$fn})) |
1032
|
|
|
|
|
|
|
{ |
1033
|
74
|
|
|
|
|
116
|
foreach my $feature_entry (@{$feature_methods_href->{$fn}}) |
|
74
|
|
|
|
|
309
|
|
1034
|
|
|
|
|
|
|
{ |
1035
|
114
|
|
|
|
|
635
|
$this->_dbg_prt([" + dispatching fn=$fn feature=$feature_entry->{feature}\n"]) ; |
1036
|
114
|
|
|
|
|
520
|
$this->_dbg_prt(["++ entry=", $feature_entry], 2) ; |
1037
|
|
|
|
|
|
|
|
1038
|
114
|
|
|
|
|
258
|
my $feature_obj = $feature_entry->{'obj'} ; |
1039
|
114
|
|
|
|
|
854
|
$feature_obj->$fn(@args) ; |
1040
|
|
|
|
|
|
|
} |
1041
|
|
|
|
|
|
|
} |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
} |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1046
|
|
|
|
|
|
|
# |
1047
|
|
|
|
|
|
|
#=item B<_dispatch_entry_features(@args)> |
1048
|
|
|
|
|
|
|
# |
1049
|
|
|
|
|
|
|
#INTERNAL: Calls _dispatch_features with the correct method name, and $status='entry' |
1050
|
|
|
|
|
|
|
# |
1051
|
|
|
|
|
|
|
#=cut |
1052
|
|
|
|
|
|
|
# |
1053
|
|
|
|
|
|
|
sub _dispatch_entry_features |
1054
|
|
|
|
|
|
|
{ |
1055
|
187
|
|
|
187
|
|
413
|
my $this = shift ; |
1056
|
187
|
|
|
|
|
384
|
my (@args) = @_ ; |
1057
|
|
|
|
|
|
|
|
1058
|
187
|
|
|
|
|
1144
|
my $method = (caller(1))[3] ; |
1059
|
187
|
|
|
|
|
1525
|
return $this->_dispatch_features($method, 'entry', @_) ; |
1060
|
|
|
|
|
|
|
} |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1064
|
|
|
|
|
|
|
# |
1065
|
|
|
|
|
|
|
#=item B<_dispatch_exit_features(@args)> |
1066
|
|
|
|
|
|
|
# |
1067
|
|
|
|
|
|
|
#INTERNAL: Calls _dispatch_features with the correct method name, and $status='exit' |
1068
|
|
|
|
|
|
|
# |
1069
|
|
|
|
|
|
|
#=cut |
1070
|
|
|
|
|
|
|
# |
1071
|
|
|
|
|
|
|
sub _dispatch_exit_features |
1072
|
|
|
|
|
|
|
{ |
1073
|
171
|
|
|
171
|
|
306
|
my $this = shift ; |
1074
|
|
|
|
|
|
|
|
1075
|
171
|
|
|
|
|
971
|
my $method = (caller(1))[3] ; |
1076
|
171
|
|
|
|
|
658
|
return $this->_dispatch_features($method, 'exit', @_) ; |
1077
|
|
|
|
|
|
|
} |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1081
|
|
|
|
|
|
|
# |
1082
|
|
|
|
|
|
|
#=item B<_dispatch_label_entry_features($label, @args)> |
1083
|
|
|
|
|
|
|
# |
1084
|
|
|
|
|
|
|
#INTERNAL: Calls _dispatch_features with the correct method name, and $status='entry' |
1085
|
|
|
|
|
|
|
# |
1086
|
|
|
|
|
|
|
#=cut |
1087
|
|
|
|
|
|
|
# |
1088
|
|
|
|
|
|
|
sub _dispatch_label_entry_features |
1089
|
|
|
|
|
|
|
{ |
1090
|
270
|
|
|
270
|
|
269
|
my $this = shift ; |
1091
|
270
|
|
|
|
|
457
|
my ($label, @args) = @_ ; |
1092
|
|
|
|
|
|
|
|
1093
|
270
|
|
|
|
|
1127
|
my $method = (caller(1))[3] ; |
1094
|
270
|
50
|
|
|
|
701
|
$method .= "_$label" if $label ; |
1095
|
270
|
|
|
|
|
1589
|
return $this->_dispatch_features($method, 'entry', @args) ; |
1096
|
|
|
|
|
|
|
} |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1100
|
|
|
|
|
|
|
# |
1101
|
|
|
|
|
|
|
#=item B<_dispatch_label_exit_features($label, @args)> |
1102
|
|
|
|
|
|
|
# |
1103
|
|
|
|
|
|
|
#INTERNAL: Calls _dispatch_features with the correct method name, and $status='exit' |
1104
|
|
|
|
|
|
|
# |
1105
|
|
|
|
|
|
|
#=cut |
1106
|
|
|
|
|
|
|
# |
1107
|
|
|
|
|
|
|
sub _dispatch_label_exit_features |
1108
|
|
|
|
|
|
|
{ |
1109
|
270
|
|
|
270
|
|
270
|
my $this = shift ; |
1110
|
270
|
|
|
|
|
459
|
my ($label, @args) = @_ ; |
1111
|
|
|
|
|
|
|
|
1112
|
270
|
|
|
|
|
1128
|
my $method = (caller(1))[3] ; |
1113
|
270
|
50
|
|
|
|
725
|
$method .= "_$label" if $label ; |
1114
|
270
|
|
|
|
|
706
|
return $this->_dispatch_features($method, 'exit', @args) ; |
1115
|
|
|
|
|
|
|
} |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
#= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
=back |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
=head3 Application execution methods |
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
=over 4 |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
=cut |
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
=item B |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
Execute the application. |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
Calls the following methods in turn: |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
* app_start |
1141
|
|
|
|
|
|
|
* application |
1142
|
|
|
|
|
|
|
* app_end |
1143
|
|
|
|
|
|
|
* exit |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
=cut |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
sub go |
1149
|
|
|
|
|
|
|
{ |
1150
|
36
|
|
|
36
|
1
|
20191
|
my $this = shift ; |
1151
|
|
|
|
|
|
|
|
1152
|
36
|
|
|
|
|
1318
|
$this->_dispatch_entry_features() ; |
1153
|
|
|
|
|
|
|
|
1154
|
36
|
|
|
|
|
474
|
$this->app_start() ; |
1155
|
36
|
|
|
|
|
451
|
$this->application() ; |
1156
|
28
|
|
|
|
|
1678
|
$this->app_end() ; |
1157
|
|
|
|
|
|
|
|
1158
|
28
|
|
|
|
|
114
|
$this->_dispatch_exit_features() ; |
1159
|
|
|
|
|
|
|
|
1160
|
28
|
|
|
|
|
526
|
$this->exit(0) ; |
1161
|
|
|
|
|
|
|
} |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1164
|
|
|
|
|
|
|
|
1165
|
|
|
|
|
|
|
=item B |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
Convert the (already processed) options list into settings. |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
Returns result of calling GetOptions |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
=cut |
1172
|
|
|
|
|
|
|
|
1173
|
|
|
|
|
|
|
sub getopts |
1174
|
|
|
|
|
|
|
{ |
1175
|
36
|
|
|
36
|
1
|
97
|
my $this = shift ; |
1176
|
|
|
|
|
|
|
|
1177
|
36
|
|
|
|
|
187
|
$this->_dispatch_entry_features() ; |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
# Parse options using GetOpts |
1180
|
36
|
|
|
|
|
174
|
my $opt = $this->feature('Options') ; |
1181
|
36
|
|
|
|
|
200
|
my $args = $this->feature('Args') ; |
1182
|
|
|
|
|
|
|
|
1183
|
36
|
|
|
|
|
263
|
my $ok = $opt->get_options() ; |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# If ok, get any specified filenames |
1186
|
36
|
50
|
|
|
|
162
|
if ($ok) |
1187
|
|
|
|
|
|
|
{ |
1188
|
|
|
|
|
|
|
# Get args |
1189
|
36
|
|
|
|
|
418
|
my $arglist = $args->get_args() ; |
1190
|
|
|
|
|
|
|
|
1191
|
36
|
|
|
|
|
282
|
$this->_dbg_prt(["getopts() : arglist=", $arglist], 2) ; |
1192
|
|
|
|
|
|
|
} |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
## Expand vars |
1195
|
36
|
|
|
|
|
141
|
my %values ; |
1196
|
36
|
|
|
|
|
283
|
my ($opt_values_href, $opt_defaults_href) = $opt->option_values_hash() ; |
1197
|
36
|
|
|
|
|
220
|
my ($args_values_href) = $args->args_values_hash() ; |
1198
|
|
|
|
|
|
|
|
1199
|
36
|
|
|
|
|
173
|
%values = (%$opt_values_href) ; |
1200
|
36
|
|
|
|
|
92
|
my %args_clash ; |
1201
|
36
|
|
|
|
|
178
|
foreach my $key (keys %$args_values_href) |
1202
|
|
|
|
|
|
|
{ |
1203
|
68
|
50
|
|
|
|
135
|
if (exists($values{$key})) |
1204
|
|
|
|
|
|
|
{ |
1205
|
0
|
|
|
|
|
0
|
$args_clash{$key} = $args_values_href->{$key} ; |
1206
|
|
|
|
|
|
|
} |
1207
|
|
|
|
|
|
|
else |
1208
|
|
|
|
|
|
|
{ |
1209
|
68
|
|
|
|
|
149
|
$values{$key} = $args_values_href->{$key} ; |
1210
|
|
|
|
|
|
|
} |
1211
|
|
|
|
|
|
|
} |
1212
|
|
|
|
|
|
|
|
1213
|
36
|
|
|
|
|
78
|
my @vars ; |
1214
|
36
|
|
|
|
|
318
|
my %app_vars = $this->vars ; |
1215
|
36
|
|
|
|
|
238
|
push @vars, \%app_vars ; |
1216
|
36
|
|
|
|
|
109
|
push @vars, \%ENV ; |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
## expand all vars |
1219
|
36
|
|
|
|
|
585
|
$this->expand_keys(\%values, \@vars) ; |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
# set new values |
1222
|
36
|
|
|
|
|
125
|
foreach my $key (keys %$opt_values_href) |
1223
|
|
|
|
|
|
|
{ |
1224
|
85
|
|
|
|
|
140
|
$opt_values_href->{$key} = $values{$key} ; |
1225
|
|
|
|
|
|
|
} |
1226
|
36
|
|
|
|
|
117
|
foreach my $key (keys %$args_values_href) |
1227
|
|
|
|
|
|
|
{ |
1228
|
68
|
|
|
|
|
114
|
$args_values_href->{$key} = $values{$key} ; |
1229
|
|
|
|
|
|
|
} |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
## handle any name clash |
1232
|
36
|
50
|
|
|
|
168
|
if (keys %args_clash) |
1233
|
|
|
|
|
|
|
{ |
1234
|
0
|
|
|
|
|
0
|
unshift @vars, \%values ; |
1235
|
0
|
|
|
|
|
0
|
$this->expand_keys(\%args_clash, \@vars) ; |
1236
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
# set new values |
1238
|
0
|
|
|
|
|
0
|
foreach my $key (keys %args_clash) |
1239
|
|
|
|
|
|
|
{ |
1240
|
0
|
|
|
|
|
0
|
$args_values_href->{$key} = $args_clash{$key} ; |
1241
|
|
|
|
|
|
|
} |
1242
|
|
|
|
|
|
|
} |
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
## update settings |
1245
|
36
|
|
|
|
|
206
|
$opt->option_values_set($opt_values_href, $opt_defaults_href) ; |
1246
|
36
|
|
|
|
|
234
|
$args->args_values_set($args_values_href) ; |
1247
|
|
|
|
|
|
|
|
1248
|
36
|
|
|
|
|
430
|
$this->_dispatch_exit_features() ; |
1249
|
|
|
|
|
|
|
|
1250
|
36
|
|
|
|
|
466
|
return $ok ; |
1251
|
|
|
|
|
|
|
} |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
=item B |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
Set up before running the application. |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
Calls the following methods in turn: |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
* getopts |
1263
|
|
|
|
|
|
|
* [internal _expand_vars method] |
1264
|
|
|
|
|
|
|
* options |
1265
|
|
|
|
|
|
|
* (Application registered 'app_start' function) |
1266
|
|
|
|
|
|
|
|
1267
|
|
|
|
|
|
|
=cut |
1268
|
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
sub app_start |
1271
|
|
|
|
|
|
|
{ |
1272
|
36
|
|
|
36
|
1
|
90
|
my $this = shift ; |
1273
|
|
|
|
|
|
|
|
1274
|
36
|
|
|
|
|
148
|
$this->_dispatch_entry_features() ; |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
## process the data |
1277
|
36
|
|
|
|
|
406
|
$this->feature('data')->process() ; |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
## allow features to add their options |
1280
|
36
|
|
|
|
|
1200
|
my $features_aref = $this->feature_list() ; |
1281
|
36
|
|
|
|
|
219
|
foreach my $feature (@$features_aref) |
1282
|
|
|
|
|
|
|
{ |
1283
|
166
|
|
|
|
|
557
|
my $feature_obj = $this->feature($feature) ; |
1284
|
166
|
|
|
|
|
6083
|
my $feature_options_aref = $feature_obj->feature_options() ; |
1285
|
166
|
100
|
|
|
|
568
|
if (@$feature_options_aref) |
1286
|
|
|
|
|
|
|
{ |
1287
|
76
|
|
|
|
|
221
|
$this->feature('Options')->append_options($feature_options_aref, $feature_obj->class) ; |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
} |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
## Add user-defined options last |
1292
|
36
|
|
|
|
|
175
|
$this->feature('Data')->append_user_options() ; |
1293
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
## Get options |
1296
|
|
|
|
|
|
|
# NOTE: Need to do this here so that derived objects work properly |
1297
|
36
|
|
|
|
|
603
|
my $ret = $this->getopts() ; |
1298
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
## Expand any variables in the data |
1300
|
36
|
|
|
|
|
556
|
$this->_expand_vars() ; |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
# Handle options errors here after expanding variables |
1303
|
36
|
50
|
|
|
|
178
|
unless ($ret) |
1304
|
|
|
|
|
|
|
{ |
1305
|
0
|
|
|
|
|
0
|
$this->usage('opt') ; |
1306
|
0
|
|
|
|
|
0
|
$this->exit(1) ; |
1307
|
|
|
|
|
|
|
} |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
# get options |
1310
|
36
|
|
|
|
|
151
|
my %options = $this->options() ; |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
## function |
1313
|
36
|
|
|
|
|
587
|
$this->_exec_fn('app_start', $this, \%options) ; |
1314
|
|
|
|
|
|
|
|
1315
|
36
|
|
|
|
|
3954
|
$this->_dispatch_exit_features() ; |
1316
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
} |
1318
|
|
|
|
|
|
|
|
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
=item B |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
Execute the application. |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
Calls the following methods in turn: |
1327
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
* (Application registered 'app' function) |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
=cut |
1332
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
|
1334
|
|
|
|
|
|
|
sub application |
1335
|
|
|
|
|
|
|
{ |
1336
|
36
|
|
|
36
|
1
|
84
|
my $this = shift ; |
1337
|
|
|
|
|
|
|
|
1338
|
36
|
|
|
|
|
149
|
$this->_dispatch_entry_features() ; |
1339
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
## Execute function |
1341
|
34
|
|
|
|
|
129
|
my %options = $this->options() ; |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
## Check args here (do this AFTER allowing derived objects/features a chance to check the options etc) |
1344
|
34
|
|
|
|
|
162
|
$this->feature("Args")->check_args() ; |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
# get args |
1347
|
28
|
|
|
|
|
112
|
my %args = $this->feature("Args")->arg_hash() ; |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
## Run application function |
1350
|
28
|
|
|
|
|
219
|
$this->_exec_fn('app', $this, \%options, \%args) ; |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
## Close any open arguments |
1353
|
28
|
|
|
|
|
3771636
|
$this->feature("Args")->close_args() ; |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
|
1356
|
28
|
|
|
|
|
161
|
$this->_dispatch_exit_features() ; |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
} |
1359
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1361
|
|
|
|
|
|
|
|
1362
|
|
|
|
|
|
|
=item B |
1363
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
Tidy up after the application. |
1365
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
Calls the following methods in turn: |
1367
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
* (Application registered 'app_end' function) |
1369
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
=cut |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
sub app_end |
1375
|
|
|
|
|
|
|
{ |
1376
|
28
|
|
|
28
|
1
|
82
|
my $this = shift ; |
1377
|
|
|
|
|
|
|
|
1378
|
28
|
|
|
|
|
134
|
$this->_dispatch_entry_features() ; |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
# get options |
1381
|
28
|
|
|
|
|
175
|
my %options = $this->options() ; |
1382
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
## Execute function |
1384
|
28
|
|
|
|
|
592
|
$this->_exec_fn('app_end', $this, \%options) ; |
1385
|
|
|
|
|
|
|
|
1386
|
28
|
|
|
|
|
4342
|
$this->_dispatch_exit_features() ; |
1387
|
|
|
|
|
|
|
} |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
|
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1392
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
=item B |
1394
|
|
|
|
|
|
|
|
1395
|
|
|
|
|
|
|
Exit the application. |
1396
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
=cut |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
sub exit |
1401
|
|
|
|
|
|
|
{ |
1402
|
0
|
|
|
0
|
1
|
0
|
my $this = shift ; |
1403
|
0
|
|
|
|
|
0
|
my ($exit_code) = @_ ; |
1404
|
|
|
|
|
|
|
|
1405
|
0
|
|
|
|
|
0
|
die "Expected generic exit to be overridden: exit code=$exit_code" ; |
1406
|
|
|
|
|
|
|
} |
1407
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
=item B |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
Show usage |
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
=cut |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
sub usage |
1417
|
|
|
|
|
|
|
{ |
1418
|
8
|
|
|
8
|
1
|
15
|
my $this = shift ; |
1419
|
8
|
|
|
|
|
13
|
my ($level) = @_ ; |
1420
|
|
|
|
|
|
|
|
1421
|
8
|
|
|
|
|
32
|
$this->_dispatch_entry_features($level) ; |
1422
|
8
|
|
|
|
|
29
|
$this->_exec_fn('usage', $this, $level) ; |
1423
|
8
|
|
|
|
|
1117
|
$this->_dispatch_exit_features($level) ; |
1424
|
|
|
|
|
|
|
|
1425
|
|
|
|
|
|
|
} |
1426
|
|
|
|
|
|
|
|
1427
|
|
|
|
|
|
|
#= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |
1428
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
=back |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
=head3 Utility methods |
1432
|
|
|
|
|
|
|
|
1433
|
|
|
|
|
|
|
=over 4 |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
=cut |
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
|
1441
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1442
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
=item B |
1444
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
Utility method |
1446
|
|
|
|
|
|
|
|
1447
|
|
|
|
|
|
|
Parses the filename and returns the full path, basename, and extension. |
1448
|
|
|
|
|
|
|
|
1449
|
|
|
|
|
|
|
Effectively does: |
1450
|
|
|
|
|
|
|
|
1451
|
|
|
|
|
|
|
$fname = File::Spec->rel2abs($fname) ; |
1452
|
|
|
|
|
|
|
($path, $base, $ext) = fileparse($fname, '\.[^\.]+') ; |
1453
|
|
|
|
|
|
|
return ($path, $base, $ext) ; |
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
=cut |
1456
|
|
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
sub file_split |
1458
|
|
|
|
|
|
|
{ |
1459
|
0
|
|
|
0
|
1
|
0
|
my $this = shift ; |
1460
|
0
|
|
|
|
|
0
|
my ($fname) = @_ ; |
1461
|
|
|
|
|
|
|
|
1462
|
0
|
|
|
|
|
0
|
$fname = File::Spec->rel2abs($fname) ; |
1463
|
0
|
|
|
|
|
0
|
my ($path, $base, $ext) = fileparse($fname, '\.[^\.]+') ; |
1464
|
0
|
|
|
|
|
0
|
return ($path, $base, $ext) ; |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
## ============================================================================================ |
1469
|
|
|
|
|
|
|
# |
1470
|
|
|
|
|
|
|
#=back |
1471
|
|
|
|
|
|
|
# |
1472
|
|
|
|
|
|
|
#=head2 PRIVATE METHODS |
1473
|
|
|
|
|
|
|
# |
1474
|
|
|
|
|
|
|
#=over 4 |
1475
|
|
|
|
|
|
|
# |
1476
|
|
|
|
|
|
|
#=cut |
1477
|
|
|
|
|
|
|
# |
1478
|
|
|
|
|
|
|
## ============================================================================================ |
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
|
1481
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1482
|
|
|
|
|
|
|
# |
1483
|
|
|
|
|
|
|
#=item B<_exec_fn($function, @args)> |
1484
|
|
|
|
|
|
|
# |
1485
|
|
|
|
|
|
|
#Execute the registered function (if one is registered). Passes @args to the function. |
1486
|
|
|
|
|
|
|
# |
1487
|
|
|
|
|
|
|
#=cut |
1488
|
|
|
|
|
|
|
# |
1489
|
|
|
|
|
|
|
sub _exec_fn |
1490
|
|
|
|
|
|
|
{ |
1491
|
100
|
|
|
100
|
|
312
|
my $this = shift ; |
1492
|
100
|
|
|
|
|
325
|
my ($fn, @args) = @_ ; |
1493
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
# Append _fn to function name, get the function, and call it if it's defined |
1495
|
100
|
|
|
|
|
246
|
my $fn_name = "${fn}_fn" ; |
1496
|
100
|
|
100
|
|
|
2879
|
my $sub = $this->$fn_name() || '' ; |
1497
|
|
|
|
|
|
|
|
1498
|
100
|
|
|
|
|
760
|
$this->_dbg_prt(["_exec_fn($fn) this=$this fn=$fn_name sub=$sub\n"], 2) ; |
1499
|
|
|
|
|
|
|
#$this->prt_data("_exec_fn($fn) args[1]=", \$args[1], "args[2]=",\$args[2]) ; |
1500
|
|
|
|
|
|
|
#if $this->debug()>=2 ; |
1501
|
|
|
|
|
|
|
|
1502
|
100
|
100
|
|
|
|
690
|
&$sub(@args) if $sub ; |
1503
|
|
|
|
|
|
|
} |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1506
|
|
|
|
|
|
|
# |
1507
|
|
|
|
|
|
|
#=item B<_import()> |
1508
|
|
|
|
|
|
|
# |
1509
|
|
|
|
|
|
|
#Load modules into caller package namespace. |
1510
|
|
|
|
|
|
|
# |
1511
|
|
|
|
|
|
|
#=cut |
1512
|
|
|
|
|
|
|
# |
1513
|
|
|
|
|
|
|
sub _import |
1514
|
|
|
|
|
|
|
{ |
1515
|
26
|
|
|
26
|
|
56
|
my $this = shift ; |
1516
|
|
|
|
|
|
|
|
1517
|
26
|
|
|
|
|
662
|
my $package = $this->package() ; |
1518
|
|
|
|
|
|
|
|
1519
|
|
|
|
|
|
|
# Debug |
1520
|
26
|
50
|
|
|
|
128
|
if ($this->debug()) |
1521
|
|
|
|
|
|
|
{ |
1522
|
0
|
0
|
|
|
|
0
|
unless ($package eq 'main') |
1523
|
|
|
|
|
|
|
{ |
1524
|
0
|
|
|
|
|
0
|
print "\n $package symbols:\n"; dumpvar($package) ; |
|
0
|
|
|
|
|
0
|
|
1525
|
|
|
|
|
|
|
} |
1526
|
|
|
|
|
|
|
} |
1527
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
## Load useful modules into caller package |
1529
|
26
|
|
|
|
|
47
|
my $code ; |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
# Set of useful modules |
1532
|
26
|
|
|
|
|
82
|
foreach my $mod (@App::Framework::Settings::MODULES) |
1533
|
|
|
|
|
|
|
{ |
1534
|
286
|
|
|
|
|
575
|
$code .= "use $mod;" ; |
1535
|
|
|
|
|
|
|
} |
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
# Get modules into this namespace |
1538
|
26
|
|
|
|
|
71
|
foreach my $mod (@App::Framework::Settings::MODULES) |
1539
|
|
|
|
|
|
|
{ |
1540
|
26
|
|
|
26
|
|
224
|
eval "use $mod;" ; |
|
26
|
|
|
26
|
|
89
|
|
|
26
|
|
|
26
|
|
1634
|
|
|
26
|
|
|
26
|
|
686
|
|
|
25
|
|
|
26
|
|
43
|
|
|
25
|
|
|
26
|
|
1279
|
|
|
26
|
|
|
26
|
|
752
|
|
|
25
|
|
|
26
|
|
40
|
|
|
25
|
|
|
26
|
|
978
|
|
|
26
|
|
|
26
|
|
162
|
|
|
26
|
|
|
26
|
|
56
|
|
|
26
|
|
|
|
|
2694
|
|
|
26
|
|
|
|
|
931
|
|
|
25
|
|
|
|
|
54
|
|
|
25
|
|
|
|
|
464
|
|
|
26
|
|
|
|
|
773
|
|
|
25
|
|
|
|
|
34
|
|
|
25
|
|
|
|
|
1205
|
|
|
26
|
|
|
|
|
149
|
|
|
26
|
|
|
|
|
55
|
|
|
26
|
|
|
|
|
1026
|
|
|
26
|
|
|
|
|
243635
|
|
|
25
|
|
|
|
|
115435
|
|
|
25
|
|
|
|
|
229
|
|
|
26
|
|
|
|
|
604
|
|
|
25
|
|
|
|
|
53
|
|
|
25
|
|
|
|
|
2563
|
|
|
26
|
|
|
|
|
225805
|
|
|
26
|
|
|
|
|
14693714
|
|
|
26
|
|
|
|
|
7311
|
|
|
26
|
|
|
|
|
61004
|
|
|
25
|
|
|
|
|
321786
|
|
|
25
|
|
|
|
|
186
|
|
|
286
|
|
|
|
|
18046
|
|
1541
|
286
|
50
|
|
|
|
7207
|
if ($@) |
1542
|
|
|
|
|
|
|
{ |
1543
|
0
|
|
|
|
|
0
|
warn "Unable to load module $mod\n" ; |
1544
|
|
|
|
|
|
|
} |
1545
|
|
|
|
|
|
|
else |
1546
|
|
|
|
|
|
|
{ |
1547
|
286
|
|
|
|
|
978
|
++$LOADED_MODULES{$mod} ; |
1548
|
|
|
|
|
|
|
} |
1549
|
|
|
|
|
|
|
} |
1550
|
|
|
|
|
|
|
|
1551
|
|
|
|
|
|
|
# Get modules into caller package namespace |
1552
|
26
|
|
|
26
|
|
574
|
eval "package $package;\n$code\n" ; |
|
25
|
|
|
26
|
|
56
|
|
|
25
|
|
|
25
|
|
1620
|
|
|
26
|
|
|
25
|
|
165
|
|
|
26
|
|
|
25
|
|
72
|
|
|
26
|
|
|
25
|
|
1627
|
|
|
25
|
|
|
25
|
|
156
|
|
|
25
|
|
|
25
|
|
49
|
|
|
25
|
|
|
25
|
|
1227
|
|
|
25
|
|
|
25
|
|
138
|
|
|
25
|
|
|
25
|
|
59
|
|
|
25
|
|
|
|
|
2208
|
|
|
25
|
|
|
|
|
158
|
|
|
25
|
|
|
|
|
55
|
|
|
25
|
|
|
|
|
605
|
|
|
25
|
|
|
|
|
165
|
|
|
25
|
|
|
|
|
110
|
|
|
25
|
|
|
|
|
1230
|
|
|
25
|
|
|
|
|
145
|
|
|
25
|
|
|
|
|
54
|
|
|
25
|
|
|
|
|
1331
|
|
|
25
|
|
|
|
|
140
|
|
|
25
|
|
|
|
|
53
|
|
|
25
|
|
|
|
|
294
|
|
|
25
|
|
|
|
|
1789
|
|
|
25
|
|
|
|
|
62
|
|
|
25
|
|
|
|
|
2433
|
|
|
25
|
|
|
|
|
173
|
|
|
25
|
|
|
|
|
53
|
|
|
25
|
|
|
|
|
4624
|
|
|
25
|
|
|
|
|
153
|
|
|
25
|
|
|
|
|
49
|
|
|
25
|
|
|
|
|
120
|
|
|
26
|
|
|
|
|
2057
|
|
1553
|
|
|
|
|
|
|
# if ($@) |
1554
|
|
|
|
|
|
|
# { |
1555
|
|
|
|
|
|
|
# warn "Unable to load modules : $@\n" ; |
1556
|
|
|
|
|
|
|
# } |
1557
|
|
|
|
|
|
|
} |
1558
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1561
|
|
|
|
|
|
|
# |
1562
|
|
|
|
|
|
|
#=item B<_register_fn()> |
1563
|
|
|
|
|
|
|
# |
1564
|
|
|
|
|
|
|
#Register a function provided as a subroutine in the caller package as an app method |
1565
|
|
|
|
|
|
|
#in this object. |
1566
|
|
|
|
|
|
|
# |
1567
|
|
|
|
|
|
|
#Will only set the field value if it's not already set. |
1568
|
|
|
|
|
|
|
# |
1569
|
|
|
|
|
|
|
#=cut |
1570
|
|
|
|
|
|
|
# |
1571
|
|
|
|
|
|
|
sub _register_fn |
1572
|
|
|
|
|
|
|
{ |
1573
|
260
|
|
|
260
|
|
386
|
my $this = shift ; |
1574
|
260
|
|
|
|
|
372
|
my ($function, $alias) = @_ ; |
1575
|
|
|
|
|
|
|
|
1576
|
260
|
|
33
|
|
|
497
|
$alias ||= $function ; |
1577
|
260
|
|
|
|
|
398
|
my $field ="${alias}_fn" ; |
1578
|
|
|
|
|
|
|
|
1579
|
260
|
100
|
|
|
|
6892
|
$this->_register_var('CODE', $function, $field) unless $this->$field() ; |
1580
|
|
|
|
|
|
|
} |
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1583
|
|
|
|
|
|
|
# |
1584
|
|
|
|
|
|
|
#=item B<_register_scalar($external_name, $field_name)> |
1585
|
|
|
|
|
|
|
# |
1586
|
|
|
|
|
|
|
#Read the value of a variable in the caller package and copy that value as a data field |
1587
|
|
|
|
|
|
|
#in this object. |
1588
|
|
|
|
|
|
|
# |
1589
|
|
|
|
|
|
|
#Will only set the field value if it's not already set. |
1590
|
|
|
|
|
|
|
# |
1591
|
|
|
|
|
|
|
#=cut |
1592
|
|
|
|
|
|
|
# |
1593
|
|
|
|
|
|
|
sub _register_scalar |
1594
|
|
|
|
|
|
|
{ |
1595
|
26
|
|
|
26
|
|
77
|
my $this = shift ; |
1596
|
26
|
|
|
|
|
71
|
my ($external_name, $field_name) = @_ ; |
1597
|
|
|
|
|
|
|
|
1598
|
26
|
50
|
|
|
|
731
|
$this->_register_var('SCALAR', $external_name, $field_name) unless $this->$field_name() ; |
1599
|
|
|
|
|
|
|
} |
1600
|
|
|
|
|
|
|
|
1601
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1602
|
|
|
|
|
|
|
# |
1603
|
|
|
|
|
|
|
#=item B<_register_var($type, $external_name, $field_name)> |
1604
|
|
|
|
|
|
|
# |
1605
|
|
|
|
|
|
|
#Read the value of a variable in the caller package and copy that value as a data field |
1606
|
|
|
|
|
|
|
#in this object. $type specifies the variable type: 'SCALAR', 'ARRAY', 'HASH', 'CODE' |
1607
|
|
|
|
|
|
|
# |
1608
|
|
|
|
|
|
|
#NOTE: This method overwrites the field value irrespective of whether it's already set. |
1609
|
|
|
|
|
|
|
# |
1610
|
|
|
|
|
|
|
#=cut |
1611
|
|
|
|
|
|
|
# |
1612
|
|
|
|
|
|
|
sub _register_var |
1613
|
|
|
|
|
|
|
{ |
1614
|
265
|
|
|
265
|
|
345
|
my $this = shift ; |
1615
|
265
|
|
|
|
|
391
|
my ($type, $external_name, $field_name) = @_ ; |
1616
|
|
|
|
|
|
|
|
1617
|
265
|
|
|
|
|
6540
|
my $package = $this->package() ; |
1618
|
|
|
|
|
|
|
|
1619
|
265
|
|
|
|
|
592
|
local (*alias); # a local typeglob |
1620
|
|
|
|
|
|
|
|
1621
|
265
|
|
|
|
|
1688
|
$this->_dbg_prt(["_register_var($type, $external_name, $field_name)\n"], 2) ; |
1622
|
|
|
|
|
|
|
|
1623
|
|
|
|
|
|
|
# We want to get access to the stash corresponding to the package |
1624
|
|
|
|
|
|
|
# name |
1625
|
30
|
|
|
30
|
|
295
|
no strict "vars" ; |
|
30
|
|
|
|
|
61
|
|
|
30
|
|
|
|
|
2773
|
|
1626
|
30
|
|
|
30
|
|
186
|
no strict "refs" ; |
|
30
|
|
|
|
|
69
|
|
|
30
|
|
|
|
|
14088
|
|
1627
|
265
|
|
|
|
|
443
|
*stash = *{"${package}::"}; # Now %stash is the symbol table |
|
265
|
|
|
|
|
653
|
|
1628
|
|
|
|
|
|
|
|
1629
|
265
|
100
|
|
|
|
1078
|
if (exists($stash{$external_name})) |
1630
|
|
|
|
|
|
|
{ |
1631
|
63
|
|
|
|
|
303
|
*alias = $stash{$external_name} ; |
1632
|
|
|
|
|
|
|
|
1633
|
63
|
|
|
|
|
543
|
$this->_dbg_prt([" + found $external_name in $package\n"], 2) ; |
1634
|
|
|
|
|
|
|
|
1635
|
63
|
100
|
|
|
|
241
|
if ($type eq 'SCALAR') |
1636
|
|
|
|
|
|
|
{ |
1637
|
26
|
100
|
|
|
|
107
|
if (defined($alias)) |
1638
|
|
|
|
|
|
|
{ |
1639
|
21
|
|
|
|
|
212
|
$this->set($field_name => $alias) ; |
1640
|
|
|
|
|
|
|
} |
1641
|
|
|
|
|
|
|
} |
1642
|
63
|
50
|
|
|
|
176
|
if ($type eq 'ARRAY') |
1643
|
|
|
|
|
|
|
{ |
1644
|
|
|
|
|
|
|
# was - if (defined(@alias)) - removed due to "deprecated" warning |
1645
|
0
|
0
|
|
|
|
0
|
if (@alias) |
1646
|
|
|
|
|
|
|
{ |
1647
|
0
|
|
|
|
|
0
|
$this->set($field_name => \@alias) ; |
1648
|
|
|
|
|
|
|
} |
1649
|
|
|
|
|
|
|
} |
1650
|
63
|
50
|
|
|
|
340
|
if ($type eq 'HASH') |
|
|
100
|
|
|
|
|
|
1651
|
|
|
|
|
|
|
{ |
1652
|
0
|
0
|
|
|
|
0
|
if (%alias) |
1653
|
|
|
|
|
|
|
{ |
1654
|
0
|
|
|
|
|
0
|
$this->set($field_name => \%alias) ; |
1655
|
|
|
|
|
|
|
} |
1656
|
|
|
|
|
|
|
} |
1657
|
|
|
|
|
|
|
elsif ($type eq 'CODE') |
1658
|
|
|
|
|
|
|
{ |
1659
|
37
|
50
|
|
|
|
146
|
if (defined(&alias)) |
1660
|
|
|
|
|
|
|
{ |
1661
|
37
|
|
|
|
|
239
|
$this->_dbg_prt([" + + Set $type - $external_name as $field_name\n"], 2) ; |
1662
|
37
|
|
|
|
|
373
|
$this->set($field_name => \&alias) ; |
1663
|
|
|
|
|
|
|
} |
1664
|
|
|
|
|
|
|
} |
1665
|
|
|
|
|
|
|
|
1666
|
|
|
|
|
|
|
} |
1667
|
|
|
|
|
|
|
} |
1668
|
|
|
|
|
|
|
|
1669
|
|
|
|
|
|
|
|
1670
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1671
|
|
|
|
|
|
|
# |
1672
|
|
|
|
|
|
|
#=item B<_expand_vars()> |
1673
|
|
|
|
|
|
|
# |
1674
|
|
|
|
|
|
|
#Run through some of the application variables/fields and expand any instances of variables embedded |
1675
|
|
|
|
|
|
|
#within the values. |
1676
|
|
|
|
|
|
|
# |
1677
|
|
|
|
|
|
|
#Example: |
1678
|
|
|
|
|
|
|
# |
1679
|
|
|
|
|
|
|
# __DATA_ |
1680
|
|
|
|
|
|
|
# |
1681
|
|
|
|
|
|
|
# [SYNOPSIS] |
1682
|
|
|
|
|
|
|
# |
1683
|
|
|
|
|
|
|
# $name [options] |
1684
|
|
|
|
|
|
|
# |
1685
|
|
|
|
|
|
|
#Here the 'synopsis' field contains the $name field variable. This needs to be expanded to the value of $name. |
1686
|
|
|
|
|
|
|
# |
1687
|
|
|
|
|
|
|
#NOTE: Currently this will NOT cope with cross references (so, if in the above example $name also contains a variable |
1688
|
|
|
|
|
|
|
#then that variable may or may not be expanded before the synopsis field is processed) |
1689
|
|
|
|
|
|
|
# |
1690
|
|
|
|
|
|
|
# |
1691
|
|
|
|
|
|
|
#=cut |
1692
|
|
|
|
|
|
|
# |
1693
|
|
|
|
|
|
|
sub _expand_vars |
1694
|
|
|
|
|
|
|
{ |
1695
|
36
|
|
|
36
|
|
90
|
my $this = shift ; |
1696
|
|
|
|
|
|
|
|
1697
|
36
|
|
|
|
|
309
|
$this->_dbg_prt(["_expand_vars() - START\n"], 2) ; |
1698
|
|
|
|
|
|
|
|
1699
|
|
|
|
|
|
|
# Get hash of fields |
1700
|
36
|
|
|
|
|
166
|
my %fields = $this->vars() ; |
1701
|
|
|
|
|
|
|
|
1702
|
|
|
|
|
|
|
#$this->_dbg_prt([" + fields=", \%fields], 2) ; |
1703
|
|
|
|
|
|
|
|
1704
|
|
|
|
|
|
|
# work through each field, create a list of those that have changed |
1705
|
36
|
|
|
|
|
206
|
my %changed ; |
1706
|
36
|
|
|
|
|
801
|
foreach my $field (sort keys %fields) |
1707
|
|
|
|
|
|
|
{ |
1708
|
|
|
|
|
|
|
# Skip non-scalars |
1709
|
1218
|
100
|
|
|
|
2737
|
next if ref($fields{$field}) ; |
1710
|
|
|
|
|
|
|
|
1711
|
|
|
|
|
|
|
# First see if this contains a '$' |
1712
|
717
|
|
100
|
|
|
1745
|
$fields{$field} ||= "" ; |
1713
|
717
|
|
|
|
|
994
|
my $ix = index $fields{$field}, '$' ; |
1714
|
717
|
100
|
|
|
|
1423
|
if ($ix >= 0) |
1715
|
|
|
|
|
|
|
{ |
1716
|
16
|
|
|
|
|
163
|
$this->_dbg_prt([" + + $field = $fields{$field} : index=$ix\n"], 3) ; |
1717
|
|
|
|
|
|
|
|
1718
|
|
|
|
|
|
|
# Do replacement |
1719
|
16
|
|
|
|
|
174
|
$fields{$field} =~ s{ |
1720
|
|
|
|
|
|
|
\$ # find a literal dollar sign |
1721
|
|
|
|
|
|
|
\{{0,1} # optional brace |
1722
|
|
|
|
|
|
|
(\w+) # find a "word" and store it in $1 |
1723
|
|
|
|
|
|
|
\}{0,1} # optional brace |
1724
|
|
|
|
|
|
|
}{ |
1725
|
30
|
|
|
30
|
|
207
|
no strict 'refs'; # for $$1 below |
|
30
|
|
|
|
|
56
|
|
|
30
|
|
|
|
|
9808
|
|
1726
|
16
|
50
|
|
|
|
84
|
if (defined $fields{$1}) { |
1727
|
16
|
|
|
|
|
99
|
$fields{$1}; # expand global variables only |
1728
|
|
|
|
|
|
|
} else { |
1729
|
0
|
|
|
|
|
0
|
"\${$1}"; # leave it |
1730
|
|
|
|
|
|
|
} |
1731
|
|
|
|
|
|
|
}egx; |
1732
|
|
|
|
|
|
|
|
1733
|
|
|
|
|
|
|
|
1734
|
16
|
|
|
|
|
122
|
$this->_dbg_prt([" + + + new = $fields{$field}\n"], 3) ; |
1735
|
|
|
|
|
|
|
|
1736
|
|
|
|
|
|
|
# Add to list |
1737
|
16
|
|
|
|
|
64
|
$changed{$field} = $fields{$field} ; |
1738
|
|
|
|
|
|
|
} |
1739
|
|
|
|
|
|
|
} |
1740
|
|
|
|
|
|
|
|
1741
|
36
|
|
|
|
|
351
|
$this->_dbg_prt([" + changed=", \%changed], 2) ; |
1742
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
# If some have changed then set them |
1744
|
36
|
100
|
|
|
|
212
|
if (keys %changed) |
1745
|
|
|
|
|
|
|
{ |
1746
|
16
|
|
|
|
|
109
|
$this->_dbg_prt([" + + set changed\n"], 2) ; |
1747
|
16
|
|
|
|
|
101
|
$this->set(%changed) ; |
1748
|
|
|
|
|
|
|
} |
1749
|
|
|
|
|
|
|
|
1750
|
36
|
|
|
|
|
200
|
$this->_dbg_prt(["_expand_vars() - END\n"], 2) ; |
1751
|
|
|
|
|
|
|
} |
1752
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
|
1755
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1756
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
=item B |
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
Print out the items in the $items_aref ARRAY ref iff the application's debug level is >0. |
1760
|
|
|
|
|
|
|
If $min_debug is specified, will only print out items if the application's debug level is >= $min_debug. |
1761
|
|
|
|
|
|
|
|
1762
|
|
|
|
|
|
|
=cut |
1763
|
|
|
|
|
|
|
|
1764
|
|
|
|
|
|
|
sub debug_prt |
1765
|
|
|
|
|
|
|
{ |
1766
|
0
|
|
|
0
|
1
|
|
my $this = shift ; |
1767
|
0
|
|
|
|
|
|
my ($items_aref, $min_debug) = @_ ; |
1768
|
|
|
|
|
|
|
|
1769
|
0
|
|
0
|
|
|
|
$min_debug ||= 1 ; |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
## check debug level setting |
1772
|
0
|
0
|
|
|
|
|
if ($this->options->option('debug') >= $min_debug) |
1773
|
|
|
|
|
|
|
{ |
1774
|
0
|
|
|
|
|
|
$this->prt_data(@$items_aref) ; |
1775
|
|
|
|
|
|
|
} |
1776
|
|
|
|
|
|
|
} |
1777
|
|
|
|
|
|
|
|
1778
|
|
|
|
|
|
|
|
1779
|
|
|
|
|
|
|
|
1780
|
|
|
|
|
|
|
# ============================================================================================ |
1781
|
|
|
|
|
|
|
# PRIVATE FUNCTIONS |
1782
|
|
|
|
|
|
|
# ============================================================================================ |
1783
|
|
|
|
|
|
|
|
1784
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1785
|
|
|
|
|
|
|
# |
1786
|
|
|
|
|
|
|
#=item B<_dumpisa(package)> |
1787
|
|
|
|
|
|
|
# |
1788
|
|
|
|
|
|
|
#Starting at I, show the parents |
1789
|
|
|
|
|
|
|
# |
1790
|
|
|
|
|
|
|
#=cut |
1791
|
|
|
|
|
|
|
# |
1792
|
|
|
|
|
|
|
sub _dumpisa |
1793
|
|
|
|
|
|
|
{ |
1794
|
30
|
|
|
30
|
|
183
|
no strict "vars" ; |
|
30
|
|
|
|
|
69
|
|
|
30
|
|
|
|
|
1905
|
|
1795
|
30
|
|
|
30
|
|
219
|
no strict "refs" ; |
|
30
|
|
|
|
|
71
|
|
|
30
|
|
|
|
|
5100
|
|
1796
|
|
|
|
|
|
|
|
1797
|
0
|
|
|
0
|
|
|
my ($packageName, $level) = @_; |
1798
|
|
|
|
|
|
|
|
1799
|
|
|
|
|
|
|
|
1800
|
0
|
0
|
|
|
|
|
if (!defined($level)) |
1801
|
|
|
|
|
|
|
{ |
1802
|
0
|
|
|
|
|
|
print "#### PACKAGE: $packageName ISA HIERARCHY ###########################\n" ; |
1803
|
|
|
|
|
|
|
} |
1804
|
|
|
|
|
|
|
else |
1805
|
|
|
|
|
|
|
{ |
1806
|
0
|
|
|
|
|
|
print " "x$level ; |
1807
|
0
|
|
|
|
|
|
print "$packageName\n" ; |
1808
|
|
|
|
|
|
|
} |
1809
|
|
|
|
|
|
|
|
1810
|
0
|
|
|
|
|
|
foreach my $isa (@{"${packageName}::ISA"}) |
|
0
|
|
|
|
|
|
|
1811
|
|
|
|
|
|
|
{ |
1812
|
0
|
|
|
|
|
|
_dumpisa($isa, ++$level) ; |
1813
|
|
|
|
|
|
|
} |
1814
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
|
1816
|
0
|
0
|
|
|
|
|
if (!defined($level)) |
1817
|
|
|
|
|
|
|
{ |
1818
|
0
|
|
|
|
|
|
print "######################################################\n" ; |
1819
|
|
|
|
|
|
|
} |
1820
|
|
|
|
|
|
|
} |
1821
|
|
|
|
|
|
|
|
1822
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
1823
|
|
|
|
|
|
|
# |
1824
|
|
|
|
|
|
|
#=item B<_dumpvar(package)> |
1825
|
|
|
|
|
|
|
# |
1826
|
|
|
|
|
|
|
#Dump out all of the symbols in package I |
1827
|
|
|
|
|
|
|
# |
1828
|
|
|
|
|
|
|
#=cut |
1829
|
|
|
|
|
|
|
# |
1830
|
|
|
|
|
|
|
sub _dumpvar |
1831
|
|
|
|
|
|
|
{ |
1832
|
30
|
|
|
30
|
|
184
|
no strict "vars" ; |
|
30
|
|
|
|
|
82
|
|
|
30
|
|
|
|
|
1085
|
|
1833
|
30
|
|
|
30
|
|
160
|
no strict "refs" ; |
|
30
|
|
|
|
|
81
|
|
|
30
|
|
|
|
|
9722
|
|
1834
|
|
|
|
|
|
|
|
1835
|
0
|
|
|
0
|
|
|
my ($packageName) = @_; |
1836
|
|
|
|
|
|
|
|
1837
|
0
|
|
|
|
|
|
print "#### PACKAGE: $packageName ###########################\n" ; |
1838
|
|
|
|
|
|
|
|
1839
|
0
|
|
|
|
|
|
local (*alias); # a local typeglob |
1840
|
|
|
|
|
|
|
# We want to get access to the stash corresponding to the package |
1841
|
|
|
|
|
|
|
# name |
1842
|
0
|
|
|
|
|
|
*stash = *{"${packageName}::"}; # Now %stash is the symbol table |
|
0
|
|
|
|
|
|
|
1843
|
0
|
|
|
|
|
|
$, = " "; # Output separator for print |
1844
|
|
|
|
|
|
|
# Iterate through the symbol table, which contains glob values |
1845
|
|
|
|
|
|
|
# indexed by symbol names. |
1846
|
0
|
|
|
|
|
|
while (($varName, $globValue) = each %stash) { |
1847
|
0
|
|
|
|
|
|
print "$varName ============================= \n"; |
1848
|
0
|
|
|
|
|
|
*alias = $globValue; |
1849
|
0
|
0
|
|
|
|
|
if (defined ($alias)) { |
1850
|
0
|
|
|
|
|
|
print "\t \$$varName $alias \n"; |
1851
|
|
|
|
|
|
|
} |
1852
|
0
|
0
|
|
|
|
|
if (@alias) { |
1853
|
0
|
|
|
|
|
|
print "\t \@$varName @alias \n"; |
1854
|
|
|
|
|
|
|
} |
1855
|
0
|
0
|
|
|
|
|
if (%alias) { |
1856
|
0
|
|
|
|
|
|
print "\t \%$varName ",%alias," \n"; |
1857
|
|
|
|
|
|
|
} |
1858
|
0
|
0
|
|
|
|
|
if (defined (&alias)) { |
1859
|
0
|
|
|
|
|
|
print "\t \&$varName \n"; |
1860
|
|
|
|
|
|
|
} |
1861
|
|
|
|
|
|
|
} |
1862
|
|
|
|
|
|
|
|
1863
|
0
|
|
|
|
|
|
print "######################################################\n" ; |
1864
|
|
|
|
|
|
|
|
1865
|
|
|
|
|
|
|
} |
1866
|
|
|
|
|
|
|
|
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
# ============================================================================================ |
1869
|
|
|
|
|
|
|
# END OF PACKAGE |
1870
|
|
|
|
|
|
|
|
1871
|
|
|
|
|
|
|
=back |
1872
|
|
|
|
|
|
|
|
1873
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
1874
|
|
|
|
|
|
|
|
1875
|
|
|
|
|
|
|
Setting the debug flag to level 1 prints out (to STDOUT) some debug messages, setting it to level 2 prints out more verbose messages. |
1876
|
|
|
|
|
|
|
|
1877
|
|
|
|
|
|
|
=head1 AUTHOR |
1878
|
|
|
|
|
|
|
|
1879
|
|
|
|
|
|
|
Steve Price C<< >> |
1880
|
|
|
|
|
|
|
|
1881
|
|
|
|
|
|
|
=head1 BUGS |
1882
|
|
|
|
|
|
|
|
1883
|
|
|
|
|
|
|
None that I know of! |
1884
|
|
|
|
|
|
|
|
1885
|
|
|
|
|
|
|
=cut |
1886
|
|
|
|
|
|
|
|
1887
|
|
|
|
|
|
|
|
1888
|
|
|
|
|
|
|
|
1889
|
|
|
|
|
|
|
1; |
1890
|
|
|
|
|
|
|
|
1891
|
|
|
|
|
|
|
__END__ |