line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::Info; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
App::Info - Information about software packages on a system |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use App::Info::Category::FooApp; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my $app = App::Info::Category::FooApp->new; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
if ($app->installed) { |
14
|
|
|
|
|
|
|
print "App name: ", $app->name, "\n"; |
15
|
|
|
|
|
|
|
print "Version: ", $app->version, "\n"; |
16
|
|
|
|
|
|
|
print "Bin dir: ", $app->bin_dir, "\n"; |
17
|
|
|
|
|
|
|
} else { |
18
|
|
|
|
|
|
|
print "App not installed on your system. :-(\n"; |
19
|
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 DESCRIPTION |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
App::Info is an abstract base class designed to provide a generalized |
24
|
|
|
|
|
|
|
interface for subclasses that provide meta data about software packages |
25
|
|
|
|
|
|
|
installed on a system. The idea is that these classes can be used in Perl |
26
|
|
|
|
|
|
|
application installers in order to determine whether software dependencies |
27
|
|
|
|
|
|
|
have been fulfilled, and to get necessary meta data about those software |
28
|
|
|
|
|
|
|
packages. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
App::Info provides an event model for handling events triggered by App::Info |
31
|
|
|
|
|
|
|
subclasses. The events are classified as "info", "error", "unknown", and |
32
|
|
|
|
|
|
|
"confirm" events, and multiple handlers may be specified to handle any or all |
33
|
|
|
|
|
|
|
of these event types. This allows App::Info clients to flexibly handle events |
34
|
|
|
|
|
|
|
in any way they deem necessary. Implementing new event handlers is |
35
|
|
|
|
|
|
|
straight-forward, and use the triggering of events by App::Info subclasses is |
36
|
|
|
|
|
|
|
likewise kept easy-to-use. |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
A few L are provided with the distribution, but |
39
|
|
|
|
|
|
|
others are invited to write their own subclasses and contribute them to the |
40
|
|
|
|
|
|
|
CPAN. Contributors are welcome to extend their subclasses to provide more |
41
|
|
|
|
|
|
|
information relevant to the application for which data is to be provided (see |
42
|
|
|
|
|
|
|
L for an example), but are |
43
|
|
|
|
|
|
|
encouraged to, at a minimum, implement the abstract methods defined here and |
44
|
|
|
|
|
|
|
in the category abstract base classes (e.g., |
45
|
|
|
|
|
|
|
L and L). |
46
|
|
|
|
|
|
|
See L for more information on implementing new |
47
|
|
|
|
|
|
|
subclasses. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=cut |
50
|
|
|
|
|
|
|
|
51
|
18
|
|
|
18
|
|
195266
|
use strict; |
|
18
|
|
|
|
|
39
|
|
|
18
|
|
|
|
|
840
|
|
52
|
18
|
|
|
18
|
|
144
|
use Carp (); |
|
18
|
|
|
|
|
50
|
|
|
18
|
|
|
|
|
525
|
|
53
|
18
|
|
|
18
|
|
13029
|
use App::Info::Handler; |
|
18
|
|
|
|
|
42
|
|
|
18
|
|
|
|
|
436
|
|
54
|
18
|
|
|
18
|
|
15292
|
use App::Info::Request; |
|
18
|
|
|
|
|
103
|
|
|
18
|
|
|
|
|
946
|
|
55
|
18
|
|
|
18
|
|
389
|
use vars qw($VERSION); |
|
18
|
|
|
|
|
33
|
|
|
18
|
|
|
|
|
44919
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
$VERSION = '0.57'; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
############################################################################## |
60
|
|
|
|
|
|
|
############################################################################## |
61
|
|
|
|
|
|
|
# This code ref is used by the abstract methods to throw an exception when |
62
|
|
|
|
|
|
|
# they're called directly. |
63
|
|
|
|
|
|
|
my $croak = sub { |
64
|
|
|
|
|
|
|
my ($caller, $meth) = @_; |
65
|
|
|
|
|
|
|
$caller = ref $caller || $caller; |
66
|
|
|
|
|
|
|
if ($caller eq __PACKAGE__) { |
67
|
|
|
|
|
|
|
$meth = __PACKAGE__ . '::' . $meth; |
68
|
|
|
|
|
|
|
Carp::croak(__PACKAGE__ . " is an abstract base class. Attempt to " . |
69
|
|
|
|
|
|
|
" call non-existent method $meth"); |
70
|
|
|
|
|
|
|
} else { |
71
|
|
|
|
|
|
|
Carp::croak("Class $caller inherited from the abstract base class " . |
72
|
|
|
|
|
|
|
__PACKAGE__ . ", but failed to redefine the $meth() " . |
73
|
|
|
|
|
|
|
"method. Attempt to call non-existent method " . |
74
|
|
|
|
|
|
|
"${caller}::$meth"); |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
}; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
############################################################################## |
79
|
|
|
|
|
|
|
# This code reference is used by new() and the on_* error handler methods to |
80
|
|
|
|
|
|
|
# set the error handlers. |
81
|
|
|
|
|
|
|
my $set_handlers = sub { |
82
|
|
|
|
|
|
|
my $on_key = shift; |
83
|
|
|
|
|
|
|
# Default is to do nothing. |
84
|
|
|
|
|
|
|
return unless $on_key; |
85
|
|
|
|
|
|
|
my $ref = ref $on_key; |
86
|
|
|
|
|
|
|
if ($ref) { |
87
|
|
|
|
|
|
|
$on_key = [$on_key] unless $ref eq 'ARRAY'; |
88
|
|
|
|
|
|
|
# Make sure they're all handlers. |
89
|
|
|
|
|
|
|
foreach my $h (@$on_key) { |
90
|
|
|
|
|
|
|
if (my $r = ref $h) { |
91
|
|
|
|
|
|
|
Carp::croak("$r object is not an App::Info::Handler") |
92
|
|
|
|
|
|
|
unless UNIVERSAL::isa($h, 'App::Info::Handler'); |
93
|
|
|
|
|
|
|
} else { |
94
|
|
|
|
|
|
|
# Look up the handler. |
95
|
|
|
|
|
|
|
$h = App::Info::Handler->new( key => $h); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
# Return 'em! |
99
|
|
|
|
|
|
|
return @$on_key; |
100
|
|
|
|
|
|
|
} else { |
101
|
|
|
|
|
|
|
# Look up the handler. |
102
|
|
|
|
|
|
|
return App::Info::Handler->new( key => $on_key); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
}; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
############################################################################## |
107
|
|
|
|
|
|
|
############################################################################## |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head1 INTERFACE |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
This section documents the public interface of App::Info. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head2 Constructor |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head3 new |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
my $app = App::Info::Category::FooApp->new(@params); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
Constructs an App::Info object and returns it. The @params arguments define |
120
|
|
|
|
|
|
|
attributes that can be used to help the App::Info object search for |
121
|
|
|
|
|
|
|
application information on the file system, as well as how the App::Info |
122
|
|
|
|
|
|
|
object will respond to certain events. The event parameters correspond to |
123
|
|
|
|
|
|
|
their like-named methods. See the L<"Event Handler Object Methods"> section |
124
|
|
|
|
|
|
|
for more information on App::Info events and how to handle them. The search |
125
|
|
|
|
|
|
|
parameters that can be passed to C are: |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=over |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item search_exe_names |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
An array reference of possible names for binary executables. These may be used |
132
|
|
|
|
|
|
|
by subclasses to search for application programs that can be used to retrieve |
133
|
|
|
|
|
|
|
application information, such as version numbers. The subclasses generally |
134
|
|
|
|
|
|
|
provide reasonable defaults for most cases. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item search_bin_dirs |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
An array reference of local directories in which to search for executables. |
139
|
|
|
|
|
|
|
These may be used to search for the value of the C attribute in |
140
|
|
|
|
|
|
|
addition to and in preference to the defaults used by each subclass. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item search_lib_names |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
An array reference of possible names for library files. These may be used by |
145
|
|
|
|
|
|
|
subclasses to search for library files for the application. The subclasses |
146
|
|
|
|
|
|
|
generally provide reasonable defaults for most cases. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item search_so_lib_names |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
An array reference of possible names for shared object library files. These |
151
|
|
|
|
|
|
|
may be used by subclasses to search for shared object library files for the |
152
|
|
|
|
|
|
|
application. The subclasses generally provide reasonable defaults for most |
153
|
|
|
|
|
|
|
cases. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item search_lib_dirs |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
An array reference of local directories in which to search for libraries. |
158
|
|
|
|
|
|
|
These may be used to search for the value of the C and C |
159
|
|
|
|
|
|
|
attributes in addition to and in preference to the defaults used by each |
160
|
|
|
|
|
|
|
subclass. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=item search_inc_names |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
An array reference of possible names for include files. These may be used by |
165
|
|
|
|
|
|
|
subclasses to search for include files for the application. The subclasses |
166
|
|
|
|
|
|
|
generally provide reasonable defaults for most cases. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=item search_inc_dirs |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
An array reference of local directories in which to search for include |
171
|
|
|
|
|
|
|
files. These may be used to search for the value of the C attribute |
172
|
|
|
|
|
|
|
in addition to and in preference to the defaults used by each subclass. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=back |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
The parameters to C for the different types of App::Info events are: |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=over 4 |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=item on_info |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item on_error |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=item on_unknown |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=item on_confirm |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=back |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
When passing event handlers to C, the list of handlers for each type |
191
|
|
|
|
|
|
|
should be an anonymous array, for example: |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
my $app = App::Info::Category::FooApp->new( on_info => \@handlers ); |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=cut |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub new { |
198
|
55
|
|
|
55
|
1
|
21883
|
my ($pkg, %p) = @_; |
199
|
55
|
|
33
|
|
|
544
|
my $class = ref $pkg || $pkg; |
200
|
|
|
|
|
|
|
# Fail if the method isn't overridden. |
201
|
55
|
50
|
|
|
|
194
|
$croak->($pkg, 'new') if $class eq __PACKAGE__; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Set up handlers. |
204
|
55
|
|
|
|
|
157
|
for (qw(on_error on_unknown on_info on_confirm)) { |
205
|
217
|
|
|
|
|
772
|
$p{$_} = [$set_handlers->($p{$_})]; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# Set up search defaults. |
209
|
54
|
|
|
|
|
157
|
for (qw(bin_dirs lib_dirs inc_dirs exe_names lib_names inc_names |
210
|
|
|
|
|
|
|
so_lib_names)) { |
211
|
378
|
|
|
|
|
673
|
local $_ = "search_$_"; |
212
|
378
|
100
|
|
|
|
907
|
if (exists $p{$_}) { |
213
|
82
|
100
|
|
|
|
461
|
$p{$_} = [$p{$_}] unless ref $p{$_} eq 'ARRAY'; |
214
|
|
|
|
|
|
|
} else { |
215
|
296
|
|
|
|
|
1058
|
$p{$_} = []; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# Do it! |
220
|
54
|
|
|
|
|
592
|
return bless \%p, $class; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
############################################################################## |
224
|
|
|
|
|
|
|
############################################################################## |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head2 Meta Data Object Methods |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
These are abstract methods in App::Info and must be provided by its |
229
|
|
|
|
|
|
|
subclasses. They provide the essential meta data of the software package |
230
|
|
|
|
|
|
|
supported by the App::Info subclass. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=head3 key_name |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
my $key_name = $app->key_name; |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
Returns a string that uniquely identifies the software for which the App::Info |
237
|
|
|
|
|
|
|
subclass provides data. This value should be unique across all App::Info |
238
|
|
|
|
|
|
|
classes. Typically, it's simply the name of the software. |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=cut |
241
|
|
|
|
|
|
|
|
242
|
1
|
|
|
1
|
1
|
14
|
sub key_name { $croak->(shift, 'key_name') } |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head3 installed |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
if ($app->installed) { |
247
|
|
|
|
|
|
|
print "App is installed.\n" |
248
|
|
|
|
|
|
|
} else { |
249
|
|
|
|
|
|
|
print "App is not installed.\n" |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
Returns a true value if the application is installed, and a false value if it |
253
|
|
|
|
|
|
|
is not. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=cut |
256
|
|
|
|
|
|
|
|
257
|
0
|
|
|
0
|
1
|
0
|
sub installed { $croak->(shift, 'installed') } |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
############################################################################## |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head3 name |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
my $name = $app->name; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
Returns the name of the application. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=cut |
268
|
|
|
|
|
|
|
|
269
|
0
|
|
|
0
|
1
|
0
|
sub name { $croak->(shift, 'name') } |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
############################################################################## |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head3 version |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my $version = $app->version; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Returns the full version number of the application. |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=cut |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
############################################################################## |
282
|
|
|
|
|
|
|
|
283
|
0
|
|
|
0
|
1
|
0
|
sub version { $croak->(shift, 'version') } |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=head3 major_version |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
my $major_version = $app->major_version; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
Returns the major version number of the application. For example, if |
290
|
|
|
|
|
|
|
C returns "7.1.2", then this method returns "7". |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=cut |
293
|
|
|
|
|
|
|
|
294
|
0
|
|
|
0
|
1
|
0
|
sub major_version { $croak->(shift, 'major_version') } |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
############################################################################## |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=head3 minor_version |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
my $minor_version = $app->minor_version; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Returns the minor version number of the application. For example, if |
303
|
|
|
|
|
|
|
C returns "7.1.2", then this method returns "1". |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=cut |
306
|
|
|
|
|
|
|
|
307
|
0
|
|
|
0
|
1
|
0
|
sub minor_version { $croak->(shift, 'minor_version') } |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
############################################################################## |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head3 patch_version |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
my $patch_version = $app->patch_version; |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Returns the patch version number of the application. For example, if |
316
|
|
|
|
|
|
|
C returns "7.1.2", then this method returns "2". |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=cut |
319
|
|
|
|
|
|
|
|
320
|
0
|
|
|
0
|
1
|
0
|
sub patch_version { $croak->(shift, 'patch_version') } |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
############################################################################## |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=head3 bin_dir |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
my $bin_dir = $app->bin_dir; |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
Returns the full path the application's bin directory, if it exists. |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=cut |
331
|
|
|
|
|
|
|
|
332
|
0
|
|
|
0
|
1
|
0
|
sub bin_dir { $croak->(shift, 'bin_dir') } |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
############################################################################## |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head3 executable |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
my $executable = $app->executable; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
Returns the full path the application's bin directory, if it exists. |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=cut |
343
|
|
|
|
|
|
|
|
344
|
0
|
|
|
0
|
1
|
0
|
sub executable { $croak->(shift, 'executable') } |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
############################################################################## |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=head3 inc_dir |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
my $inc_dir = $app->inc_dir; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Returns the full path the application's include directory, if it exists. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=cut |
355
|
|
|
|
|
|
|
|
356
|
0
|
|
|
0
|
1
|
0
|
sub inc_dir { $croak->(shift, 'inc_dir') } |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
############################################################################## |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=head3 lib_dir |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
my $lib_dir = $app->lib_dir; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
Returns the full path the application's lib directory, if it exists. |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=cut |
367
|
|
|
|
|
|
|
|
368
|
0
|
|
|
0
|
1
|
0
|
sub lib_dir { $croak->(shift, 'lib_dir') } |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
############################################################################## |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=head3 so_lib_dir |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
my $so_lib_dir = $app->so_lib_dir; |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Returns the full path the application's shared library directory, if it |
377
|
|
|
|
|
|
|
exists. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=cut |
380
|
|
|
|
|
|
|
|
381
|
0
|
|
|
0
|
1
|
0
|
sub so_lib_dir { $croak->(shift, 'so_lib_dir') } |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
############################################################################## |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=head3 home_url |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
my $home_url = $app->home_url; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
The URL for the software's home page. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=cut |
392
|
|
|
|
|
|
|
|
393
|
0
|
|
|
0
|
1
|
0
|
sub home_url { $croak->(shift, 'home_url') } |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
############################################################################## |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=head3 download_url |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
my $download_url = $app->download_url; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
The URL for the software's download page. |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=cut |
404
|
|
|
|
|
|
|
|
405
|
0
|
|
|
0
|
1
|
0
|
sub download_url { $croak->(shift, 'download_url') } |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
############################################################################## |
408
|
|
|
|
|
|
|
############################################################################## |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=head2 Search Attributes |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
These methods return lists of things to look for on the local file system when |
413
|
|
|
|
|
|
|
searching for application programs, library files, and include files. They are |
414
|
|
|
|
|
|
|
empty by default, since each subclass generally relies on its own settings, |
415
|
|
|
|
|
|
|
but you can add your own as preferred search parameters by specifying them as |
416
|
|
|
|
|
|
|
parameters to the C constructor. |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=head3 exe_names |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
my @search_exe_names = $app->search_exe_names; |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
Returns a list of possible names for an executable. Typically used by the |
423
|
|
|
|
|
|
|
C constructor to search for an executable to execute and collect |
424
|
|
|
|
|
|
|
application info. |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=cut |
427
|
|
|
|
|
|
|
|
428
|
31
|
|
|
31
|
1
|
52
|
sub search_exe_names { @{shift->{search_exe_names}} } |
|
31
|
|
|
|
|
313
|
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
############################################################################## |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=head3 search_bin_dirs |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
my @search_bin_dirs = $app->search_bin_dirs; |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
Returns a list of possible directories in which to search an executable. |
437
|
|
|
|
|
|
|
Typically used by the C constructor to find an executable to execute |
438
|
|
|
|
|
|
|
and collect application info. The found directory will also generally then |
439
|
|
|
|
|
|
|
be returned by the C method. |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=cut |
442
|
|
|
|
|
|
|
|
443
|
31
|
|
|
31
|
1
|
53
|
sub search_bin_dirs { @{shift->{search_bin_dirs}} } |
|
31
|
|
|
|
|
1303
|
|
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
############################################################################## |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=head3 lib_names |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
my @search_lib_names = $app->search_lib_names; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
Returns a list of possible names for library files. Typically used by the |
452
|
|
|
|
|
|
|
C method to find library files. |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=cut |
455
|
|
|
|
|
|
|
|
456
|
6
|
|
|
6
|
1
|
13
|
sub search_lib_names { @{shift->{search_lib_names}} } |
|
6
|
|
|
|
|
32
|
|
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
############################################################################## |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=head3 so_lib_names |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
my @search_so_lib_names = $app->search_so_lib_names; |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Returns a list of possible names for library files. Typically used by the |
465
|
|
|
|
|
|
|
C method to find shared object library files. |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
=cut |
468
|
|
|
|
|
|
|
|
469
|
4
|
|
|
4
|
1
|
11
|
sub search_so_lib_names { @{shift->{search_so_lib_names}} } |
|
4
|
|
|
|
|
20
|
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
############################################################################## |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=head3 search_lib_dirs |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
my @search_lib_dirs = $app->search_lib_dirs; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
Returns a list of possible directories in which to search for libraries. |
478
|
|
|
|
|
|
|
Typically used by the C and C methods to find |
479
|
|
|
|
|
|
|
library files. |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=cut |
482
|
|
|
|
|
|
|
|
483
|
14
|
|
|
14
|
1
|
29
|
sub search_lib_dirs { @{shift->{search_lib_dirs}} } |
|
14
|
|
|
|
|
120
|
|
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
############################################################################## |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=head3 inc_names |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
my @search_inc_names = $app->search_inc_names; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
Returns a list of possible names for include files. Typically used by the |
492
|
|
|
|
|
|
|
C method to find include files. |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=cut |
495
|
|
|
|
|
|
|
|
496
|
7
|
|
|
7
|
1
|
41
|
sub search_inc_names { @{shift->{search_inc_names}} } |
|
7
|
|
|
|
|
95
|
|
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
############################################################################## |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=head3 search_inc_dirs |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
my @search_inc_dirs = $app->search_inc_dirs; |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
Returns a list of possible directories in which to search for includes. |
505
|
|
|
|
|
|
|
Typically used by the C method to find include files. |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=cut |
508
|
|
|
|
|
|
|
|
509
|
11
|
|
|
11
|
1
|
20
|
sub search_inc_dirs { @{shift->{search_inc_dirs}} } |
|
11
|
|
|
|
|
91
|
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
############################################################################## |
512
|
|
|
|
|
|
|
############################################################################## |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=head2 Event Handler Object Methods |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
These methods provide control over App::Info event handling. Events can be |
517
|
|
|
|
|
|
|
handled by one or more objects of subclasses of App::Info::Handler. The first |
518
|
|
|
|
|
|
|
to return a true value will be the last to execute. This approach allows |
519
|
|
|
|
|
|
|
handlers to be stacked, and makes it relatively easy to create new handlers. |
520
|
|
|
|
|
|
|
L for information on writing event |
521
|
|
|
|
|
|
|
handlers. |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
Each of the event handler methods takes a list of event handlers as its |
524
|
|
|
|
|
|
|
arguments. If none are passed, the existing list of handlers for the relevant |
525
|
|
|
|
|
|
|
event type will be returned. If new handlers are passed in, they will be |
526
|
|
|
|
|
|
|
returned. |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
The event handlers may be specified as one or more objects of the |
529
|
|
|
|
|
|
|
App::Info::Handler class or subclasses, as one or more strings that tell |
530
|
|
|
|
|
|
|
App::Info construct such handlers itself, or a combination of the two. The |
531
|
|
|
|
|
|
|
strings can only be used if the relevant App::Info::Handler subclasses have |
532
|
|
|
|
|
|
|
registered strings with App::Info. For example, the App::Info::Handler::Print |
533
|
|
|
|
|
|
|
class included in the App::Info distribution registers the strings "stderr" |
534
|
|
|
|
|
|
|
and "stdout" when it starts up. These strings may then be used to tell |
535
|
|
|
|
|
|
|
App::Info to construct App::Info::Handler::Print objects that print to STDERR |
536
|
|
|
|
|
|
|
or to STDOUT, respectively. See the App::Info::Handler subclasses for what |
537
|
|
|
|
|
|
|
strings they register with App::Info. |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
=head3 on_info |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
my @handlers = $app->on_info; |
542
|
|
|
|
|
|
|
$app->on_info(@handlers); |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
Info events are triggered when the App::Info subclass wants to send an |
545
|
|
|
|
|
|
|
informational status message. By default, these events are ignored, but a |
546
|
|
|
|
|
|
|
common need is for such messages to simply print to STDOUT. Use the |
547
|
|
|
|
|
|
|
L class included with the |
548
|
|
|
|
|
|
|
App::Info distribution to have info messages print to STDOUT: |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
use App::Info::Handler::Print; |
551
|
|
|
|
|
|
|
$app->on_info('stdout'); |
552
|
|
|
|
|
|
|
# Or: |
553
|
|
|
|
|
|
|
my $stdout_handler = App::Info::Handler::Print->new('stdout'); |
554
|
|
|
|
|
|
|
$app->on_info($stdout_handler); |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=cut |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
sub on_info { |
559
|
6
|
|
|
6
|
1
|
11
|
my $self = shift; |
560
|
6
|
100
|
|
|
|
25
|
@{ $self->{on_info} } = $set_handlers->(\@_) if @_; |
|
3
|
|
|
|
|
15
|
|
561
|
6
|
|
|
|
|
8
|
return @{ $self->{on_info} }; |
|
6
|
|
|
|
|
30
|
|
562
|
|
|
|
|
|
|
} |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
=head3 on_error |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
my @handlers = $app->on_error; |
567
|
|
|
|
|
|
|
$app->on_error(@handlers); |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
Error events are triggered when the App::Info subclass runs into an unexpected |
570
|
|
|
|
|
|
|
but not fatal problem. (Note that fatal problems will likely throw an |
571
|
|
|
|
|
|
|
exception.) By default, these events are ignored. A common way of handling |
572
|
|
|
|
|
|
|
these events is to print them to STDERR, once again using the |
573
|
|
|
|
|
|
|
L class included with the |
574
|
|
|
|
|
|
|
App::Info distribution: |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
use App::Info::Handler::Print; |
577
|
|
|
|
|
|
|
my $app->on_error('stderr'); |
578
|
|
|
|
|
|
|
# Or: |
579
|
|
|
|
|
|
|
my $stderr_handler = App::Info::Handler::Print->new('stderr'); |
580
|
|
|
|
|
|
|
$app->on_error($stderr_handler); |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
Another approach might be to turn such events into fatal exceptions. Use the |
583
|
|
|
|
|
|
|
included L class for this |
584
|
|
|
|
|
|
|
purpose: |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
use App::Info::Handler::Carp; |
587
|
|
|
|
|
|
|
my $app->on_error('croak'); |
588
|
|
|
|
|
|
|
# Or: |
589
|
|
|
|
|
|
|
my $croaker = App::Info::Handler::Carp->new('croak'); |
590
|
|
|
|
|
|
|
$app->on_error($croaker); |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=cut |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
sub on_error { |
595
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
596
|
0
|
0
|
|
|
|
0
|
@{ $self->{on_error} } = $set_handlers->(\@_) if @_; |
|
0
|
|
|
|
|
0
|
|
597
|
0
|
|
|
|
|
0
|
return @{ $self->{on_error} }; |
|
0
|
|
|
|
|
0
|
|
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
=head3 on_unknown |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
my @handlers = $app->on_unknown; |
603
|
|
|
|
|
|
|
$app->on_uknown(@handlers); |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
Unknown events are triggered when the App::Info subclass cannot find the value |
606
|
|
|
|
|
|
|
to be returned by a method call. By default, these events are ignored. A |
607
|
|
|
|
|
|
|
common way of handling them is to have the application prompt the user for the |
608
|
|
|
|
|
|
|
relevant data. The App::Info::Handler::Prompt class included with the |
609
|
|
|
|
|
|
|
App::Info distribution can do just that: |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
use App::Info::Handler::Prompt; |
612
|
|
|
|
|
|
|
my $app->on_unknown('prompt'); |
613
|
|
|
|
|
|
|
# Or: |
614
|
|
|
|
|
|
|
my $prompter = App::Info::Handler::Prompt; |
615
|
|
|
|
|
|
|
$app->on_unknown($prompter); |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
See L for information |
618
|
|
|
|
|
|
|
on how it works. |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
=cut |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
sub on_unknown { |
623
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
624
|
0
|
0
|
|
|
|
0
|
@{ $self->{on_unknown} } = $set_handlers->(\@_) if @_; |
|
0
|
|
|
|
|
0
|
|
625
|
0
|
|
|
|
|
0
|
return @{ $self->{on_unknown} }; |
|
0
|
|
|
|
|
0
|
|
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=head3 on_confirm |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
my @handlers = $app->on_confirm; |
631
|
|
|
|
|
|
|
$app->on_confirm(@handlers); |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
Confirm events are triggered when the App::Info subclass has found an |
634
|
|
|
|
|
|
|
important piece of information (such as the location of the executable it'll |
635
|
|
|
|
|
|
|
use to collect information for the rest of its methods) and wants to confirm |
636
|
|
|
|
|
|
|
that the information is correct. These events will most often be triggered |
637
|
|
|
|
|
|
|
during the App::Info subclass object construction. Here, too, the |
638
|
|
|
|
|
|
|
App::Info::Handler::Prompt class included with the App::Info distribution can |
639
|
|
|
|
|
|
|
help out: |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
use App::Info::Handler::Prompt; |
642
|
|
|
|
|
|
|
my $app->on_confirm('prompt'); |
643
|
|
|
|
|
|
|
# Or: |
644
|
|
|
|
|
|
|
my $prompter = App::Info::Handler::Prompt; |
645
|
|
|
|
|
|
|
$app->on_confirm($prompter); |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
=cut |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
sub on_confirm { |
650
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
651
|
0
|
0
|
|
|
|
0
|
@{ $self->{on_confirm} } = $set_handlers->(\@_) if @_; |
|
0
|
|
|
|
|
0
|
|
652
|
0
|
|
|
|
|
0
|
return @{ $self->{on_confirm} }; |
|
0
|
|
|
|
|
0
|
|
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
############################################################################## |
656
|
|
|
|
|
|
|
############################################################################## |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=head1 SUBCLASSING |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
As an abstract base class, App::Info is not intended to be used directly. |
661
|
|
|
|
|
|
|
Instead, you'll use concrete subclasses that implement the interface it |
662
|
|
|
|
|
|
|
defines. These subclasses each provide the meta data necessary for a given |
663
|
|
|
|
|
|
|
software package, via the interface outlined above (plus any additional |
664
|
|
|
|
|
|
|
methods the class author deems sensible for a given application). |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
This section describes the facilities App::Info provides for subclassing. The |
667
|
|
|
|
|
|
|
goal of the App::Info design has been to make subclassing straight-forward, so |
668
|
|
|
|
|
|
|
that developers can focus on gathering the data they need for their |
669
|
|
|
|
|
|
|
application and minimize the work necessary to handle unknown values or to |
670
|
|
|
|
|
|
|
confirm values. As a result, there are essentially three concepts that |
671
|
|
|
|
|
|
|
developers need to understand when subclassing App::Info: organization, |
672
|
|
|
|
|
|
|
utility methods, and events. |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=head2 Organization |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
The organizational idea behind App::Info is to name subclasses by broad |
677
|
|
|
|
|
|
|
software categories. This approach allows the categories themselves to |
678
|
|
|
|
|
|
|
function as abstract base classes that extend App::Info, so that they can |
679
|
|
|
|
|
|
|
specify more methods for all of their base classes to implement. For example, |
680
|
|
|
|
|
|
|
App::Info::HTTPD has specified the C abstract method that its |
681
|
|
|
|
|
|
|
subclasses must implement. So as you get ready to implement your own subclass, |
682
|
|
|
|
|
|
|
think about what category of software you're gathering information about. |
683
|
|
|
|
|
|
|
New categories can be added as necessary. |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
=head2 Utility Methods |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
Once you've decided on the proper category, you can start implementing your |
688
|
|
|
|
|
|
|
App::Info concrete subclass. As you do so, take advantage of App::Info::Util, |
689
|
|
|
|
|
|
|
wherein I've tried to encapsulate common functionality to make subclassing |
690
|
|
|
|
|
|
|
easier. I found that most of what I was doing repetitively was looking for |
691
|
|
|
|
|
|
|
files and directories, and searching through files. Thus, App::Info::Util |
692
|
|
|
|
|
|
|
subclasses L in order to offer easy access to |
693
|
|
|
|
|
|
|
commonly-used methods from that class, e.g., C. Plus, it has several |
694
|
|
|
|
|
|
|
of its own methods to assist you in finding files and directories in lists of |
695
|
|
|
|
|
|
|
files and directories, as well as methods for searching through files and |
696
|
|
|
|
|
|
|
returning the values found in those files. See |
697
|
|
|
|
|
|
|
L for more information, and the App::Info |
698
|
|
|
|
|
|
|
subclasses in this distribution for usage examples. |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
I recommend the use of a package-scoped lexical App::Info::Util object. That |
701
|
|
|
|
|
|
|
way it's nice and handy when you need to carry out common tasks. If you find |
702
|
|
|
|
|
|
|
you're doing something over and over that's not already addressed by an |
703
|
|
|
|
|
|
|
App::Info::Util method, consider submitting a patch to App::Info::Util to add |
704
|
|
|
|
|
|
|
the functionality you need. |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
=head2 Events |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
Use the methods described below to trigger events. Events are designed to |
709
|
|
|
|
|
|
|
provide a simple way for App::Info subclass developers to send status messages |
710
|
|
|
|
|
|
|
and errors, to confirm data values, and to request a value when the class |
711
|
|
|
|
|
|
|
cannot determine a value itself. Events may optionally be handled by module |
712
|
|
|
|
|
|
|
users who assign App::Info::Handler subclass objects to your App::Info |
713
|
|
|
|
|
|
|
subclass object using the event handling methods described in the L<"Event |
714
|
|
|
|
|
|
|
Handler Object Methods"> section. |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
=cut |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
############################################################################## |
719
|
|
|
|
|
|
|
# This code reference is used by the event methods to manage the stack of |
720
|
|
|
|
|
|
|
# event handlers that may be available to handle each of the events. |
721
|
|
|
|
|
|
|
my $handler = sub { |
722
|
|
|
|
|
|
|
my ($self, $meth, $params) = @_; |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
# Sanity check. We really want to keep control over this. |
725
|
|
|
|
|
|
|
Carp::croak("Cannot call protected method $meth()") |
726
|
|
|
|
|
|
|
unless UNIVERSAL::isa($self, scalar caller(1)); |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
# Create the request object. |
729
|
|
|
|
|
|
|
$params->{type} ||= $meth; |
730
|
|
|
|
|
|
|
my $req = App::Info::Request->new(%$params); |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
# Do the deed. The ultimate handling handler may die. |
733
|
|
|
|
|
|
|
foreach my $eh (@{$self->{"on_$meth"}}) { |
734
|
|
|
|
|
|
|
last if $eh->handler($req); |
735
|
|
|
|
|
|
|
} |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
# Return the request. |
738
|
|
|
|
|
|
|
return $req; |
739
|
|
|
|
|
|
|
}; |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
############################################################################## |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
=head3 info |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
$self->info(@message); |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
Use this method to display status messages for the user. You may wish to use |
748
|
|
|
|
|
|
|
it to inform users that you're searching for a particular file, or attempting |
749
|
|
|
|
|
|
|
to parse a file or some other resource for the data you need. For example, a |
750
|
|
|
|
|
|
|
common use might be in the object constructor: generally, when an App::Info |
751
|
|
|
|
|
|
|
object is created, some important initial piece of information is being |
752
|
|
|
|
|
|
|
sought, such as an executable file. That file may be in one of many locations, |
753
|
|
|
|
|
|
|
so it makes sense to let the user know that you're looking for it: |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
$self->info("Searching for executable"); |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
Note that, due to the nature of App::Info event handlers, your informational |
758
|
|
|
|
|
|
|
message may be used or displayed any number of ways, or indeed not at all (as |
759
|
|
|
|
|
|
|
is the default behavior). |
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
The C<@message> will be joined into a single string and stored in the |
762
|
|
|
|
|
|
|
C attribute of the App::Info::Request object passed to info event |
763
|
|
|
|
|
|
|
handlers. |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
=cut |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
sub info { |
768
|
131
|
|
|
131
|
1
|
299
|
my $self = shift; |
769
|
|
|
|
|
|
|
# Execute the handler sequence. |
770
|
131
|
|
|
|
|
1365
|
my $req = $handler->($self, 'info', { message => join '', @_ }); |
771
|
|
|
|
|
|
|
} |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
############################################################################## |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
=head3 error |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
$self->error(@error); |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
Use this method to inform the user that something unexpected has happened. An |
780
|
|
|
|
|
|
|
example might be when you invoke another program to parse its output, but it's |
781
|
|
|
|
|
|
|
output isn't what you expected: |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
$self->error("Unable to parse version from `/bin/myapp -c`"); |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
As with all events, keep in mind that error events may be handled in any |
786
|
|
|
|
|
|
|
number of ways, or not at all. |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
The C<@erorr> will be joined into a single string and stored in the C |
789
|
|
|
|
|
|
|
attribute of the App::Info::Request object passed to error event handlers. If |
790
|
|
|
|
|
|
|
that seems confusing, think of it as an "error message" rather than an "error |
791
|
|
|
|
|
|
|
error." :-) |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=cut |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
sub error { |
796
|
12
|
|
|
12
|
1
|
21
|
my $self = shift; |
797
|
|
|
|
|
|
|
# Execute the handler sequence. |
798
|
12
|
|
|
|
|
54
|
my $req = $handler->($self, 'error', { message => join '', @_ }); |
799
|
|
|
|
|
|
|
} |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
############################################################################## |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
=head3 unknown |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
my $val = $self->unknown(@params); |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
Use this method when a value is unknown. This will give the user the option -- |
808
|
|
|
|
|
|
|
assuming the appropriate handler handles the event -- to provide the needed |
809
|
|
|
|
|
|
|
data. The value entered will be returned by C. The parameters are |
810
|
|
|
|
|
|
|
as follows: |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=over 4 |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=item key |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
The C parameter uniquely identifies the data point in your class, and is |
817
|
|
|
|
|
|
|
used by App::Info to ensure that an unknown event is handled only once, no |
818
|
|
|
|
|
|
|
matter how many times the method is called. The same value will be returned by |
819
|
|
|
|
|
|
|
subsequent calls to C as was returned by the first call, and no |
820
|
|
|
|
|
|
|
handlers will be activated. Typical values are "version" and "lib_dir". |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
=item prompt |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
The C parameter is the prompt to be displayed should an event handler |
825
|
|
|
|
|
|
|
decide to prompt for the appropriate value. Such a prompt might be something |
826
|
|
|
|
|
|
|
like "Path to your httpd executable?". If this parameter is not provided, |
827
|
|
|
|
|
|
|
App::Info will construct one for you using your class' C method |
828
|
|
|
|
|
|
|
and the C parameter. The result would be something like "Enter a valid |
829
|
|
|
|
|
|
|
FooApp version". The C parameter value will be stored in the |
830
|
|
|
|
|
|
|
C attribute of the App::Info::Request object passed to event |
831
|
|
|
|
|
|
|
handlers. |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
=item callback |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
Assuming a handler has collected a value for your unknown data point, it might |
836
|
|
|
|
|
|
|
make sense to validate the value. For example, if you prompt the user for a |
837
|
|
|
|
|
|
|
directory location, and the user enters one, it makes sense to ensure that the |
838
|
|
|
|
|
|
|
directory actually exists. The C parameter allows you to do this. It |
839
|
|
|
|
|
|
|
is a code reference that takes the new value or values as its arguments, and |
840
|
|
|
|
|
|
|
returns true if the value is valid, and false if it is not. For the sake of |
841
|
|
|
|
|
|
|
convenience, the first argument to the callback code reference is also stored |
842
|
|
|
|
|
|
|
in C<$_> .This makes it easy to validate using functions or operators that, |
843
|
|
|
|
|
|
|
er, operate on C<$_> by default, but still allows you to get more information |
844
|
|
|
|
|
|
|
from C<@_> if necessary. For the directory example, a good callback might be |
845
|
|
|
|
|
|
|
C. The C parameter code reference will be stored in the |
846
|
|
|
|
|
|
|
C attribute of the App::Info::Request object passed to event |
847
|
|
|
|
|
|
|
handlers. |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=item error |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
The error parameter is the error message to display in the event that the |
852
|
|
|
|
|
|
|
C code reference returns false. This message may then be used by the |
853
|
|
|
|
|
|
|
event handler to let the user know what went wrong with the data she entered. |
854
|
|
|
|
|
|
|
For example, if the unknown value was a directory, and the user entered a |
855
|
|
|
|
|
|
|
value that the C identified as invalid, a message to display might |
856
|
|
|
|
|
|
|
be something like "Invalid directory path". Note that if the C |
857
|
|
|
|
|
|
|
parameter is not provided, App::Info will supply the generic error message |
858
|
|
|
|
|
|
|
"Invalid value". This value will be stored in the C attribute of the |
859
|
|
|
|
|
|
|
App::Info::Request object passed to event handlers. |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
=back |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
This may be the event method you use most, as it should be called in every |
864
|
|
|
|
|
|
|
meta data method if you cannot provide the data needed by that method. It will |
865
|
|
|
|
|
|
|
typically be the last part of the method. Here's an example demonstrating each |
866
|
|
|
|
|
|
|
of the above arguments: |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
my $dir = $self->unknown( key => 'lib_dir', |
869
|
|
|
|
|
|
|
prompt => "Enter lib directory path", |
870
|
|
|
|
|
|
|
callback => sub { -d }, |
871
|
|
|
|
|
|
|
error => "Not a directory"); |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=cut |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
sub unknown { |
876
|
20
|
|
|
20
|
1
|
1534
|
my ($self, %params) = @_; |
877
|
20
|
100
|
|
|
|
444
|
my $key = $params{key} |
878
|
|
|
|
|
|
|
or Carp::croak("No key parameter passed to unknown()"); |
879
|
|
|
|
|
|
|
# Just return the value if we've already handled this value. Ideally this |
880
|
|
|
|
|
|
|
# shouldn't happen. |
881
|
19
|
100
|
|
|
|
118
|
return $self->{__unknown__}{$key} if exists $self->{__unknown__}{$key}; |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
# Create a prompt and error message, if necessary. |
884
|
18
|
|
66
|
|
|
160
|
$params{message} = delete $params{prompt} || |
885
|
|
|
|
|
|
|
"Enter a valid " . $self->key_name . " $key"; |
886
|
18
|
|
100
|
|
|
108
|
$params{error} ||= 'Invalid value'; |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
# Execute the handler sequence. |
889
|
18
|
|
|
|
|
71
|
my $req = $handler->($self, "unknown", \%params); |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
# Mark that we've provided this value and then return it. |
892
|
18
|
|
|
|
|
229
|
$self->{__unknown__}{$key} = $req->value; |
893
|
18
|
|
|
|
|
176
|
return $self->{__unknown__}{$key}; |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
############################################################################## |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
=head3 confirm |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
my $val = $self->confirm(@params); |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
This method is very similar to C, but serves a different purpose. |
903
|
|
|
|
|
|
|
Use this method for significant data points where you've found an appropriate |
904
|
|
|
|
|
|
|
value, but want to ensure it's really the correct value. A "significant data |
905
|
|
|
|
|
|
|
point" is usually a value essential for your class to collect meta data values. |
906
|
|
|
|
|
|
|
For example, you might need to locate an executable that you can then call to |
907
|
|
|
|
|
|
|
collect other data. In general, this will only happen once for an object -- |
908
|
|
|
|
|
|
|
during object construction -- but there may be cases in which it is needed |
909
|
|
|
|
|
|
|
more than that. But hopefully, once you've confirmed in the constructor that |
910
|
|
|
|
|
|
|
you've found what you need, you can use that information to collect the data |
911
|
|
|
|
|
|
|
needed by all of the meta data methods and can assume that they'll be right |
912
|
|
|
|
|
|
|
because that first, significant data point has been confirmed. |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
Other than where and how often to call C, its use is quite similar |
915
|
|
|
|
|
|
|
to that of C. Its parameters are as follows: |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
=over |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
=item key |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
Same as for C, a string that uniquely identifies the data point in |
922
|
|
|
|
|
|
|
your class, and ensures that the event is handled only once for a given key. |
923
|
|
|
|
|
|
|
The same value will be returned by subsequent calls to C as was |
924
|
|
|
|
|
|
|
returned by the first call for a given key. |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=item prompt |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
Same as for C. Although C is called to confirm a value, |
929
|
|
|
|
|
|
|
typically the prompt should request the relevant value, just as for |
930
|
|
|
|
|
|
|
C. The difference is that the handler I use the C |
931
|
|
|
|
|
|
|
parameter as the default should the user not provide a value. The C |
932
|
|
|
|
|
|
|
parameter will be stored in the C attribute of the App::Info::Request |
933
|
|
|
|
|
|
|
object passed to event handlers. |
934
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
=item value |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
The value to be confirmed. This is the value you've found, and it will be |
938
|
|
|
|
|
|
|
provided to the user as the default option when they're prompted for a new |
939
|
|
|
|
|
|
|
value. This value will be stored in the C attribute of the |
940
|
|
|
|
|
|
|
App::Info::Request object passed to event handlers. |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
=item callback |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
Same as for C. Because the user can enter data to replace the |
945
|
|
|
|
|
|
|
default value provided via the C parameter, you might want to validate |
946
|
|
|
|
|
|
|
it. Use this code reference to do so. The callback will be stored in the |
947
|
|
|
|
|
|
|
C attribute of the App::Info::Request object passed to event |
948
|
|
|
|
|
|
|
handlers. |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
=item error |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
Same as for C: an error message to display in the event that a |
953
|
|
|
|
|
|
|
value entered by the user isn't validated by the C code reference. |
954
|
|
|
|
|
|
|
This value will be stored in the C attribute of the App::Info::Request |
955
|
|
|
|
|
|
|
object passed to event handlers. |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=back |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
Here's an example usage demonstrating all of the above arguments: |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
my $exe = $self->confirm( key => 'shell', |
962
|
|
|
|
|
|
|
prompt => 'Path to your shell?', |
963
|
|
|
|
|
|
|
value => '/bin/sh', |
964
|
|
|
|
|
|
|
callback => sub { -x }, |
965
|
|
|
|
|
|
|
error => 'Not an executable'); |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
=cut |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
sub confirm { |
971
|
39
|
|
|
39
|
1
|
1949
|
my ($self, %params) = @_; |
972
|
39
|
100
|
|
|
|
642
|
my $key = $params{key} |
973
|
|
|
|
|
|
|
or Carp::croak("No key parameter passed to confirm()"); |
974
|
38
|
50
|
|
|
|
191
|
return $self->{__confirm__}{$key} if exists $self->{__confirm__}{$key}; |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
# Create a prompt and error message, if necessary. |
977
|
38
|
|
66
|
|
|
211
|
$params{message} = delete $params{prompt} || |
978
|
|
|
|
|
|
|
"Enter a valid " . $self->key_name . " $key"; |
979
|
38
|
|
100
|
|
|
133
|
$params{error} ||= 'Invalid value'; |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
# Execute the handler sequence. |
982
|
38
|
|
|
|
|
132
|
my $req = $handler->($self, "confirm", \%params); |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
# Mark that we've confirmed this value. |
985
|
38
|
|
|
|
|
3144
|
$self->{__confirm__}{$key} = $req->value; |
986
|
|
|
|
|
|
|
|
987
|
38
|
|
|
|
|
415
|
return $self->{__confirm__}{$key} |
988
|
|
|
|
|
|
|
} |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
1; |
991
|
|
|
|
|
|
|
__END__ |