Blabos de Blebe
and 1 contributors

NAME

MAD::Loader - A tiny module loader

VERSION

Version 2.0.3

SYNOPSIS

MAD::loader is a module loader for situations when you want several modules being loaded dynamically.

For each module loaded this way an initializer method may be called with custom arguments. You may also control where the loader will search for modules, you may prefix the module names with a custom namespace and you may change how it will behave on loading errors.

    use MAD::Loader;

    my $loader = MAD::Loader->new(
        prefix      => 'Foo',
        set_inc     => [ 'my/module/dir' ],
        initializer => 'new',
        options     => [ 123, 456 ],
        on_error    => \&error_handler,
    );
    
    my $res = $loader->load(qw{ Bar Baz });
    
    my $bar_obj = $res->{Bar};
    my $baz_obj = $res->{Baz};
    
    my $etc = Foo::Bar->new( 42, 13 );

In the example above, the loader will search for modules named 'Foo::Bar' and 'Foo::Baz' only within directory 'my/module/dir'. The coderef 'error_handler' will be called for each module that fail to load. For each module found, the method 'new' will be called with the array ( 123, 456 ) as argument. All objects built this way will be returned within the hashref $res which has as keys the module names provided to method 'load'.

METHODS

new( %params )

Creates a loader object.

You may provide any optional arguments: prefix, initializer, options, add_inc, set_inc and on_error.

prefix

The namespace that will be prepended to the module names.

The default value is '' (empty string) meaning that no prefix will be used.

    my $loader = MAD::Loader->new( prefix => 'Foo' );
    $loader->load(qw{ Bar Etc 123 });
    
    ## This will load the modules:
    ##  * Foo::Bar
    ##  * Foo::Etc
    ##  * Foo::123

initializer

The name of the method used to initialize/instantiate the module.

The deault value is '' (empty string) meaning that no method will be called.

When an initializer is defined the loader will try to call it like as a constructor passing the array options as argument.

Note that the initializer must be defined as a method of the module before it can be called or it will be ignored.

The code below:

    my $loader = MAD::Loader->new(
        initializer => 'init',
        options     => [ 1, 2, 3 ],
    );
    $loader->load( 'Foo' );

Will cause something like this to occur:

    Foo->init( 1, 2, 3 )
        if Foo->can( 'init' );

options

An arrayref with the options provided to all initializers.

Note that although options be an arrayref, it will be passed as an array to initializer.

When several modules are loaded together, the same options will be passed to their initializers.

add_inc

An arrayref with directories to be prepended to @INC.

The array @INC will be localized before the loader add these directories, so the original state of @INC will be preserved out of the loader.

The default value is [] meaning that original value of @INC will be used.

set_inc

An arrayref of directories used to override @INC.

This option has priority over add_inc, that is, if set_inc is defined the value of add_inc will be ignored.

Again, @INC will be localized internally so his original values will be left untouched.

on_error

An error handler called when a module fails to load. His only argument will be the exception thrown.

This is a coderef and the default value is Carp::croak.

load( @modules )

Takes a list of module names and tries to load all of them in order.

For each module that fails to load, the error handler on_error will be called. Note that the default error handler is an alias to Carp::croak so in this case at the first fail, an exception will be thrown.

All module names will be prefixed with the provided prefix and the loader will try to make sure that they all are valid before try to load them. All modules marked as "invalid" will not be loaded.

The term "invalid" is subject of discussion ahead.

The loader will search for modules into directories pointed by @INC which may be changed by attributes add_inc and set_inc.

If an initializer was defined, it will be called for each module loaded, receiving as argument the array provided by the attribute options.

In the end, if no exception was thrown, the method load will return a hashref which the keys are the module names passed to it (without prefix) and the values are whatever the initializer returns.

prefix

Returns the namespace prefix as described above.

initializer

Returns the name of the initializer as described above.

options

Returns an arrayref with the options provided to all initializers.

add_inc

Returns the arrayref of directories prepended to @INC.

set_inc

Returns the arrayref of directories used to override @INC.

inc

Returns the arrayref of directories that represents the content of @INC internally into the loader.

on_error

Returns the coderef of the error handler.

fully_qualified_name( $module )

This method is used to build the fully qualified name of a module.

When a namespace prefix is defined, it will be prepended to the module name.

If a fully qualified name cannot be found an empty string will be returned.

LIMITATIONS

Valid Module Names

This module tries to define what is a valid module name. Arbitrarily we consider a valid module name whatever module that matches with the regular expression qr{^[a-z_]\w*(::\w+)*$}i.

This validation is to avoid injection of arbitrarily code as fake module names and the regular expression above should be changed in future versions or a better approach may be considered.

Therefore some valid module names are considered invalid within MAD::Loader as names with UTF-8 characters for example. These modules cannot be loaded by MAD::Loader yet. For now this is intentional.

The old package delimiter ' (single quote) is intentionally ignored in favor of :: (double colon). Modules with single quote as package delimiter also cannot be loaded by MAD::Loader.

CAVEATS

The options add_inc and set_inc are used to isolate the environment where the search by modules is made, allowing you precisely control where MAD::Loader will look for modules.

You may use this features when your application must load plugins and you must assure that only modules within specific directories can be valid plugins for example.

A collateral effect is that when a module loaded by MAD::Loader tries to dynamically load another module, this module will be searched only within the directories known by MAD::Laoder.

If you use the option set_inc to limitate MAD::Loader to search only within the directory /my/plugins for example, and some plugin tries to load a module placed out of this path your plugin will fail like this:

    Can't locate SomeModule.pm in @INC (@INC contains: /my/plugins) at
    /my/plugins/Myplugin.pm line 42.

Note that actually this is a feature, not a bug. If you isolate the search path with MAD::Loader you will be sure that no module will bypass your limitation, except if it know the search path of his sub-modules by itself (in this case, there is little to do :) ).

AUTHOR

Blabos de Blebe, <blabos at cpan.org>

BUGS

Please report any bugs or feature requests to bug-mad-loader at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MAD-Loader. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc MAD::Loader

You can also look for information at:

ACKNOWLEDGEMENTS

Estante Virtual http://estantevirtual.com.br

LICENSE AND COPYRIGHT

Copyright 2013 Blabos de Blebe.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.