NAME
App::Info - Information about software packages on a system
SYNOPSIS
use App::Info::Category::FooApp;
my $app = App::Info::Category::FooApp->new( error_level => 'croak' );
if ($app->installed) {
print "App name: ", $app->name, "\n";
print "Version: ", $app->version, "\n";
print "Bin dir: ", $app->bin_dir, "\n";
} else {
print "App not installed on your system. :-(\n";
}
DESCRIPTION
App::Info is an abstract base class designed to provide a generalized interface for subclasses that provide metadata about software packages installed on a system. The idea is that these classes can be used in Perl application installers in order to determine whether software dependencies have been fulfilled, and to get necessary metadata about those software packages.
A few sample subclasses are provided with the distribution, but others are invited to write their own subclasses and contribute them to the CPAN. Contributors are welcome to extend their subclasses to provide more information relevant to the application for which data is to be provided (see App::Info::HTTPD::Apache for an example), but are encouraged to, at a minimum, implement the methods defined here and in the category abstract base classes (e.g. App::Info::HTTPD and App::Info::Lib. See "NOTES ON SUBCLASSING" for more information on implementing new subclasses.
CONSTRUTORS
new
my $app = App::Info::Category::FooApp->new;
my $app = App::Info::Category::FooApp->new( error_level => 'confess' );
Consructs the FooApp App::Info object and returns it. The error_level
parameter determines how the object will behave when it encounters an error, such as when a specific file can't be found or a value can't be parsed from a file. The options are:
- confess
-
Calls
Carp::confess()
, causing the application to die and display a detailed stack trace, as well as the error message. - croak
-
Calls
Carp::croak()
, causing the application to die and display the error message. - die
-
Alias for "croak"
- cluck
-
Calls
Carp::cluck()
, which prints the error message and a complete stack trace as a warning. - carp
-
Calls
Carp::carp()
, which prints the error message as a warning. This is the default error level. - warn
-
Alias for "carp".
- silent
-
Ignores the error.
In the cases of "cluck", "carp", "warn", and "silent", the last error can always be retrieved via the last_error()
method.
OBJECT METHODS
installed
if ($app->installed) {
print "App is installed.\n"
} else {
print "App is not installed.\n"
}
Returns a true value if the application is installed, and a false value if it is not.
name
my $name = $app->name;
Returns the name of the application.
version
my $version = $app->version;
Returns the full version number of the application.
major_version
my $major_version = $app->major_version;
Returns the major version number of the application. For example, if version()
returns "7.1.2", then this method returns "7".
minor_version
my $minor_version = $app->minor_version;
Returns the minor version number of the application. For example, if version()
returns "7.1.2", then this method returns "1".
patch_version
my $patch_version = $app->patch_version;
Returns the patch version number of the application. For example, if version()
returns "7.1.2", then this method returns "2".
bin_dir
my $bin_dir = $app->bin_dir;
Returns the full path the application's bin directory, if it exists.
inc_dir
my $inc_dir = $app->inc_dir;
Returns the full path the application's include directory, if it exists.
lib_dir
my $lib_dir = $app->lib_dir;
Returns the full path the application's lib directory, if it exists.
so_lib_dir
my $so_lib_dir = $app->so_lib_dir;
Returns the full path the application's shared library directory, if it exists.
home_url
my $home_url = $app->home_url;
The URL for the software's home page.
download_url
my $download_url = $app->download_url;
The URL for the software's download page.
last_error
my $err = $app->last_error;
Returns the last error encountered by the object. Useful for instances where error_level
is set to "silent", though in truth it returns the last non-fatal error.
PROTECTED OBJECT METHODS
error
my $version = parse_version();
$self->error("Unable to parse version number") unless $version;
The error()
method should be considered the sole method for alerting the clients of App::Info subclasses that an error was encountered. Think of it as a substitute for Carp::warn
(serious exceptions can use Carp::croak()
, instead. Using the error()
method allows App::Info subclass clients to handle the errors in any of several ways. See the description the new method above to see how clients can manage error levels. Do not assume that errors will be fatal. See Notes on Sublcassing below for more on subclassing App::Info. The error()
method is a protected method and therefore cannot be used by client libraries.
NOTES ON SUBCLASSING
The organizational idea behind App::Info is to name subclasses by broad software categories. This approach allows the categories to function as abstract base classes that extend App::Info, so that they can specify more methods for all of their base classes to implement. For example, App::Info::HTTPD has specified the httpd_root()
abstract method that its subclasses must implement. So as you get ready to implement your own subclass, think about what category of software you're gathering information about.
Here are some guidelines for subclassing App::Info.
Always subclass an App::Info category subclass. This will help to keep the App::Info namespace well-organized. New categories can be added as needed.
When you create the new() constructor, always call SUPER::new(). This ensures that the methods handle by the App::Info base classes (e.g.,
error()
) work properly.Use a package-scoped lexical App::Info::Util object to carry out common tasks. If you find you're doing something over and over that's not already addressed by an App::Info::Util method, consider submitting a patch to App::Info::Util to add the functionality you need. See App::Info::Util for complete documentation of its interface.
Use the
error()
method to report problems to clients of your App::Info subclass. Doing so ensures that all problems encountered in interrogating software package can be reported to and handled by client users in a uniform manner. Furthermore, don't assume that callingerror()
causes the program to exit or to return from method execution. Clients can choose to ignore errors by using the "silent"error_level
. Of course, fatal problem should still be fatal, but non-fatal issues -- such as when an important file cannot be found, resulting in less metadata being provided by the App::Info object -- should be noted by use of theerror()
method exclusively.Be sure to implement all of the abstract methods defined by your category abstract base class -- even if they don't do anything. Doing so ensures that all App::Info subclasses share a common interface, and can, if necessary, be used without regard to subclass. Any method not implemented but called on an object will generate a fatal exception.
Feel free to use the subclasses included in this distribution as examples to follow when creating your own subclasses. I've tried to encapsulate common functionality in App::Info::Util to make the job easier. I found that most of what I was doing repetitively was looking for files and directories, and searching through files. Thus, App::Info::Util subclasses File::Spec in order to offer easy access to commonly-used methods from that class (e.g., path()
. Plus, it has several of its own methods to assist you in finding files and directories in lists of files and directories, as well as methods for searching through files and returning the values found in those files. See App::Info::Util for more information, and the App::Info subclasses in this distribution for actual usage examples.
Otherwise, have fun! There are a lot of software packages for which relevant information might be collected and aggregated into an App::Info subclass (witness all of the Automake macros in the world!), and folks who are knowledgeable about particular software packages or categories of software are warmly invited to contribute. As more subclasses are implemented, it will make sense, I think, to create separate distributions based on category -- or even, when necessary, on a single software package. Broader categories can then be aggregated in Bundle distributions.
But I get ahead of myself...
BUGS
Can there really be much in the way of bugs in an abstract base class? Drop me a line if you happen to discover any.
AUTHOR
David Wheeler <david@wheeler.net>
SEE ALSO
App::Info::Lib, App::Info::Lib, App::Info::Lib, App::Info::HTTPD::Apache, App::Info::RDBMS::PostgreSQL, App::Info::Lib, App::Info::Lib
COPYRIGHT AND LICENSE
Copyright (c) 2002, David Wheeler. All Rights Reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.