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