File Coverage

blib/lib/App/Info.pm
Criterion Covered Total %
statement 44 94 46.8
branch 6 22 27.3
condition 3 13 23.1
subroutine 12 35 34.3
pod 30 30 100.0
total 95 194 49.0


line stmt bran cond sub pod time code
1             package App::Info;
2              
3             # $Id: Info.pm 3154 2006-09-16 00:01:20Z theory $
4              
5             =head1 NAME
6            
7             App::Info - Information about software packages on a system
8            
9             =head1 SYNOPSIS
10            
11             use App::Info::Category::FooApp;
12            
13             my $app = App::Info::Category::FooApp->new;
14            
15             if ($app->installed) {
16             print "App name: ", $app->name, "\n";
17             print "Version: ", $app->version, "\n";
18             print "Bin dir: ", $app->bin_dir, "\n";
19             } else {
20             print "App not installed on your system. :-(\n";
21             }
22            
23             =head1 DESCRIPTION
24            
25             App::Info is an abstract base class designed to provide a generalized
26             interface for subclasses that provide metadata about software packages
27             installed on a system. The idea is that these classes can be used in Perl
28             application installers in order to determine whether software dependencies
29             have been fulfilled, and to get necessary metadata about those software
30             packages.
31            
32             App::Info provides an event model for handling events triggered by App::Info
33             subclasses. The events are classified as "info", "error", "unknown", and
34             "confirm" events, and multiple handlers may be specified to handle any or all
35             of these event types. This allows App::Info clients to flexibly handle events
36             in any way they deem necessary. Implementing new event handlers is
37             straight-forward, and use the triggering of events by App::Info subclasses is
38             likewise kept easy-to-use.
39            
40             A few L<sample subclasses|"SEE ALSO"> are provided with the distribution, but
41             others are invited to write their own subclasses and contribute them to the
42             CPAN. Contributors are welcome to extend their subclasses to provide more
43             information relevant to the application for which data is to be provided (see
44             L<App::Info::HTTPD::Apache|App::Info::HTTPD::Apache> for an example), but are
45             encouraged to, at a minimum, implement the abstract methods defined here and
46             in the category abstract base classes (e.g.,
47             L<App::Info::HTTPD|App::Info::HTTPD> and L<App::Info::Lib|App::Info::Lib>).
48             See L<Subclassing|"SUBCLASSING"> for more information on implementing new
49             subclasses.
50            
51             =cut
52              
53 2     2   26 use strict;
  2         17  
  2         25  
54 2     2   29 use Carp ();
  2         17  
  2         21  
55 2     2   116 use App::Info::Handler;
  2         22  
  2         35  
56 2     2   81 use App::Info::Request;
  2         21  
  2         39  
57 2     2   33 use vars qw($VERSION);
  2         19  
  2         26  
58              
59             $VERSION = '0.51';
60              
61             ##############################################################################
62             ##############################################################################
63             # This code ref is used by the abstract methods to throw an exception when
64             # they're called directly.
65             my $croak = sub {
66                 my ($caller, $meth) = @_;
67                 $caller = ref $caller || $caller;
68                 if ($caller eq __PACKAGE__) {
69                     $meth = __PACKAGE__ . '::' . $meth;
70                     Carp::croak(__PACKAGE__ . " is an abstract base class. Attempt to " .
71                                 " call non-existent method $meth");
72                 } else {
73                     Carp::croak("Class $caller inherited from the abstract base class " .
74                                 __PACKAGE__ . ", but failed to redefine the $meth() " .
75                                 "method. Attempt to call non-existent method " .
76                                 "${caller}::$meth");
77                 }
78             };
79              
80             ##############################################################################
81             # This code reference is used by new() and the on_* error handler methods to
82             # set the error handlers.
83             my $set_handlers = sub {
84                 my $on_key = shift;
85             # Default is to do nothing.
86                 return unless $on_key;
87                 my $ref = ref $on_key;
88                 if ($ref) {
89                     $on_key = [$on_key] unless $ref eq 'ARRAY';
90             # Make sure they're all handlers.
91                     foreach my $h (@$on_key) {
92                         if (my $r = ref $h) {
93                             Carp::croak("$r object is not an App::Info::Handler")
94                               unless UNIVERSAL::isa($h, 'App::Info::Handler');
95                         } else {
96             # Look up the handler.
97                             $h = App::Info::Handler->new( key => $h);
98                         }
99                     }
100             # Return 'em!
101                     return @$on_key;
102                 } else {
103             # Look up the handler.
104                     return App::Info::Handler->new( key => $on_key);
105                 }
106             };
107              
108             ##############################################################################
109             ##############################################################################
110              
111             =head1 INTERFACE
112            
113             This section documents the public interface of App::Info.
114            
115             =head2 Constructor
116            
117             =head3 new
118            
119             my $app = App::Info::Category::FooApp->new(@params);
120            
121             Constructs an App::Info object and returns it. The @params arguments define
122             attributes that can be used to help the App::Info object search for
123             application information on the file system, as well as how the App::Info
124             object will respond to certain events. The event parameters correspond to
125             their like-named methods. See the L<"Event Handler Object Methods"> section
126             for more information on App::Info events and how to handle them. The search
127             parameters that can be passed to C<new()> are:
128            
129             =over
130            
131             =item search_exe_names
132            
133             An array reference of possible names for binary executables. These may be used
134             by subclases to search for application programs that can be used to retreive
135             application information, such as version numbers. The subclasses generally
136             provide reasonable defaults for most cases.
137            
138             =item search_bin_dirs
139            
140             An array reference of local directories in which to search for executables.
141             These may be used to search for the value of the C<bin_dir> attribute in
142             addition to and in preference to the defaults used by each subclass.
143            
144             =item search_lib_names
145            
146             An array reference of possible names for library files. These may be used by
147             subclases to search for library files for the application. The subclasses
148             generally provide reasonable defaults for most cases.
149            
150             =item search_so_lib_names
151            
152             An array reference of possible names for shared object library files. These
153             may be used by subclases to search for shared object library files for the
154             application. The subclasses generally provide reasonable defaults for most
155             cases.
156            
157             =item search_lib_dirs
158            
159             An array reference of local directories in which to search for libraries.
160             These may be used to search for the value of the C<lib_dir> and C<so_lib_dir>
161             attributes in addition to and in preference to the defaults used by each
162             subclass.
163            
164             =item search_inc_names
165            
166             An array reference of possible names for include files. These may be used by
167             subclases to search for include files for the application. The subclasses
168             generally provide reasonable defaults for most cases.
169            
170             =item search_inc_dirs
171            
172             An array reference of local directories in which to search for include
173             files. These may be used to search for the value of the C<inc_dir> attribute
174             in addition to and in preference to the defaults used by each subclass.
175            
176             =back
177            
178             The parameters to C<new()> for the different types of App::Info events are:
179            
180             =over 4
181            
182             =item on_info
183            
184             =item on_error
185            
186             =item on_unknown
187            
188             =item on_confirm
189            
190             =back
191            
192             When passing event handlers to C<new()>, the list of handlers for each type
193             should be an anonymous array, for example:
194            
195             my $app = App::Info::Category::FooApp->new( on_info => \@handlers );
196            
197             =cut
198              
199             sub new {
200 2     2 1 33     my ($pkg, %p) = @_;
201 2   33     37     my $class = ref $pkg || $pkg;
202             # Fail if the method isn't overridden.
203 2 50       25     $croak->($pkg, 'new') if $class eq __PACKAGE__;
204              
205             # Set up handlers.
206 2         21     for (qw(on_error on_unknown on_info on_confirm)) {
207 8         220         $p{$_} = [$set_handlers->($p{$_})];
208                 }
209              
210             # Set up search defaults.
211 2         22     for (qw(bin_dirs lib_dirs inc_dirs exe_names lib_names inc_names
212             so_lib_names)) {
213 14         131         local $_ = "search_$_";
214 14 100       132         if (exists $p{$_}) {
215 8 50       112             $p{$_} = [$p{$_}] unless ref $p{$_} eq 'ARRAY';
216                     } else {
217 6         69             $p{$_} = [];
218                     }
219                 }
220              
221             # Do it!
222 2         34     return bless \%p, $class;
223             }
224              
225             ##############################################################################
226             ##############################################################################
227              
228             =head2 Metadata Object Methods
229            
230             These are abstract methods in App::Info and must be provided by its
231             subclasses. They provide the essential metadata of the software package
232             supported by the App::Info subclass.
233            
234             =head3 key_name
235            
236             my $key_name = $app->key_name;
237            
238             Returns a string that uniquely identifies the software for which the App::Info
239             subclass provides data. This value should be unique across all App::Info
240             classes. Typically, it's simply the name of the software.
241            
242             =cut
243              
244 0     0 1 0 sub key_name { $croak->(shift, 'key_name') }
245              
246             =head3 installed
247            
248             if ($app->installed) {
249             print "App is installed.\n"
250             } else {
251             print "App is not installed.\n"
252             }
253            
254             Returns a true value if the application is installed, and a false value if it
255             is not.
256            
257             =cut
258              
259 0     0 1 0 sub installed { $croak->(shift, 'installed') }
260              
261             ##############################################################################
262              
263             =head3 name
264            
265             my $name = $app->name;
266            
267             Returns the name of the application.
268            
269             =cut
270              
271 0     0 1 0 sub name { $croak->(shift, 'name') }
272              
273             ##############################################################################
274              
275             =head3 version
276            
277             my $version = $app->version;
278            
279             Returns the full version number of the application.
280            
281             =cut
282              
283             ##############################################################################
284              
285 0     0 1 0 sub version { $croak->(shift, 'version') }
286              
287             =head3 major_version
288            
289             my $major_version = $app->major_version;
290            
291             Returns the major version number of the application. For example, if
292             C<version()> returns "7.1.2", then this method returns "7".
293            
294             =cut
295              
296 0     0 1 0 sub major_version { $croak->(shift, 'major_version') }
297              
298             ##############################################################################
299              
300             =head3 minor_version
301            
302             my $minor_version = $app->minor_version;
303            
304             Returns the minor version number of the application. For example, if
305             C<version()> returns "7.1.2", then this method returns "1".
306            
307             =cut
308              
309 0     0 1 0 sub minor_version { $croak->(shift, 'minor_version') }
310              
311             ##############################################################################
312              
313             =head3 patch_version
314            
315             my $patch_version = $app->patch_version;
316            
317             Returns the patch version number of the application. For example, if
318             C<version()> returns "7.1.2", then this method returns "2".
319            
320             =cut
321              
322 0     0 1 0 sub patch_version { $croak->(shift, 'patch_version') }
323              
324             ##############################################################################
325              
326             =head3 bin_dir
327            
328             my $bin_dir = $app->bin_dir;
329            
330             Returns the full path the application's bin directory, if it exists.
331            
332             =cut
333              
334 0     0 1 0 sub bin_dir { $croak->(shift, 'bin_dir') }
335              
336             ##############################################################################
337              
338             =head3 executable
339            
340             my $executable = $app->executable;
341            
342             Returns the full path the application's bin directory, if it exists.
343            
344             =cut
345              
346 0     0 1 0 sub executable { $croak->(shift, 'executable') }
347              
348             ##############################################################################
349              
350             =head3 inc_dir
351            
352             my $inc_dir = $app->inc_dir;
353            
354             Returns the full path the application's include directory, if it exists.
355            
356             =cut
357              
358 0     0 1 0 sub inc_dir { $croak->(shift, 'inc_dir') }
359              
360             ##############################################################################
361              
362             =head3 lib_dir
363            
364             my $lib_dir = $app->lib_dir;
365            
366             Returns the full path the application's lib directory, if it exists.
367            
368             =cut
369              
370 0     0 1 0 sub lib_dir { $croak->(shift, 'lib_dir') }
371              
372             ##############################################################################
373              
374             =head3 so_lib_dir
375            
376             my $so_lib_dir = $app->so_lib_dir;
377            
378             Returns the full path the application's shared library directory, if it
379             exists.
380            
381             =cut
382              
383 0     0 1 0 sub so_lib_dir { $croak->(shift, 'so_lib_dir') }
384              
385             ##############################################################################
386              
387             =head3 home_url
388            
389             my $home_url = $app->home_url;
390            
391             The URL for the software's home page.
392            
393             =cut
394              
395 0     0 1 0 sub home_url { $croak->(shift, 'home_url') }
396              
397             ##############################################################################
398              
399             =head3 download_url
400            
401             my $download_url = $app->download_url;
402            
403             The URL for the software's download page.
404            
405             =cut
406              
407 0     0 1 0 sub download_url { $croak->(shift, 'download_url') }
408              
409             ##############################################################################
410             ##############################################################################
411              
412             =head2 Search Attributes
413            
414             These methods return lists of things to look for on the local file system when
415             searching for appliation programs, library files, and include files. They are
416             empty by default, since each subclass generally relies on its own settings,
417             but you can add your own as preferred search parameters by specifying them
418             as parameters to the C<new()> constructor.
419            
420