home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Loader.pm < prev    next >
Encoding:
Perl POD Document  |  2001-07-18  |  5.5 KB  |  216 lines

  1. #!/usr/bin/perl -sw
  2. ##
  3. ## Class::Loader
  4. ##
  5. ## Copyright (c) 2001, Vipul Ved Prakash.  All rights reserved.
  6. ## This code is free software; you can redistribute it and/or modify
  7. ## it under the same terms as Perl itself.
  8. ##
  9. ## $Id: Loader.pm,v 2.2 2001/07/18 20:21:39 vipul Exp $
  10.  
  11. package Class::Loader;
  12. use Data::Dumper;
  13. use vars qw($VERSION);
  14.  
  15. ($VERSION)  = '$Revision: 2.02 $' =~ /\s(\d+\.\d+)\s/; 
  16. my %MAPS = ();
  17.  
  18. sub new { 
  19.     return bless {}, shift;
  20. }
  21.  
  22.  
  23. sub _load { 
  24.  
  25.     my ($self, $field, @source) = @_;
  26.     if ((scalar @source) % 2) { 
  27.         unshift @source, $field;
  28.         $field = ""
  29.     }
  30.  
  31.     local ($name, $module, $constructor, $args);
  32.     my %source = @source;
  33.     my $class = ref $self || $self;
  34.     my $object;
  35.  
  36.     for (keys %source) { ${lc($_)} = $source{$_} }
  37.  
  38.     if ($name) { 
  39.         my $classmap = $self->_retrmap ($class) || return;
  40.         my $map = $$classmap{$name} || return;
  41.         for (keys %$map) { ${lc($_)} = $$map{$_} };
  42.     } 
  43.  
  44.     if ($module) { 
  45.         unless (eval "require $module") { 
  46.             if ($source{CPAN}) { 
  47.                 require CPAN; CPAN->import;
  48.                 my $obj = CPAN::Shell->expand ('Module', $module);
  49.                 return unless $obj;
  50.                 $obj->install; 
  51.                 eval "require $module" || return;
  52.             } else { return }
  53.         }
  54.         $constructor ||= 'new';
  55.         if ($args) { 
  56.             my $topass = __prepare_args ($args);
  57.             $object = eval "$module->$constructor($topass)" or return;
  58.             undef $topass; undef $args;
  59.         } else { $object = eval "$module->$constructor" or return }
  60.     } else { return }
  61.  
  62.     return $field ? $$self{$field} = $object : $object
  63.  
  64. }
  65.  
  66.  
  67. sub _storemap { 
  68.     my ($self, %map) = @_;
  69.     my $class = ref $self;
  70.     for (keys %map) { $MAPS{$class}{$_} = $map{$_} }
  71. }
  72.  
  73.  
  74. sub _retrmap { 
  75.     my ($self) = @_; 
  76.     my $class = ref $self;
  77.     return $MAPS{$class} if $MAPS{$class};
  78.     return;
  79. }
  80.  
  81.  
  82. sub __prepare_args { 
  83.  
  84.     my $topass = Dumper shift;
  85.     $topass =~ s/\$VAR1 = \[//; 
  86.     $topass =~ s/];\s*//g; 
  87.     return $topass;
  88.  
  89. }
  90.  
  91. 1;
  92.  
  93. =head1 NAME
  94.  
  95. Class::Loader - Load modules and create objects on demand.
  96.  
  97. =head1 VERSION
  98.  
  99.     $Revision: 2.2 $
  100.     $Date: 2001/07/18 20:21:39 $
  101.  
  102. =head1 SYNOPSIS
  103.  
  104.     package Web::Server;
  105.     use Class::Loader; 
  106.     @ISA = qw(Class::Loader);
  107.     
  108.     $self->_load( 'Content_Handler', { 
  109.                              Module => "Filter::URL",
  110.                         Constructor => "new",
  111.                                Args => [ ],
  112.                          } 
  113.                 );
  114.     
  115.  
  116. =head1 DESCRIPTION
  117.  
  118. Certain applications like to defer the decision to use a particular module
  119. till runtime. This is possible in perl, and is a useful trick in
  120. situations where the type of data is not known at compile time and the
  121. application doesn't wish to pre-compile modules to handle all types of
  122. data it can work with. Loading modules at runtime can also provide
  123. flexible interfaces for perl modules. Modules can let the programmer
  124. decide what modules will be used by it instead of hard-coding their names.
  125.  
  126. Class::Loader is an inheritable class that provides a method, _load(),
  127. to load a module from disk and construct an object by calling its
  128. constructor. It also provides a way to map modules names and
  129. associated metadata with symbolic names that can be used in place of
  130. module names at _load().
  131.  
  132. =head1 METHODS
  133.  
  134. =over 4
  135.  
  136. =item B<new()>
  137.  
  138. A basic constructor. You can use this to create an object of
  139. Class::Loader, in case you don't want to inherit Class::Loader.
  140.  
  141. =item B<_load()>
  142.  
  143. _load() loads a module and calls its constructor. It returns the newly
  144. constructed object on success or a non-true value on failure. The first
  145. argument can be the name of the key in which the returned object is
  146. stored. This argument is optional. The second (or the first) argument is a
  147. hash which can take the following keys:
  148.  
  149. =over 4
  150.  
  151. =item B<Module>
  152.  
  153. This is name of the class to load. (It is not the module's filename.)
  154.  
  155. =item B<Name> 
  156.  
  157. Symbolic name of the module defined with _storemap(). Either one of Module
  158. or Name keys must be present in a call to _load().
  159.  
  160. =item B<Constructor>
  161.  
  162. Name of the Module constructor. Defaults to "new".
  163.  
  164. =item B<Args>
  165.  
  166. A reference to the list of arguments for the constructor. _load() calls
  167. the constructor with this list. If no Args are present, _load() will call
  168. the constructor without any arguments.
  169.  
  170. =item B<CPAN>
  171.  
  172. If the Module is not installed on the local system, _load() can fetch &
  173. install it from CPAN provided the CPAN key is present. This functionality
  174. assumes availability of a pre-configured CPAN shell.
  175.  
  176. =back
  177.  
  178. =item B<_storemap()>
  179.  
  180. Class::Loader maintains a class table that maps symbolic names to
  181. parameters accepted by _load(). It takes a hash as argument whose keys are
  182. symbolic names and value are hash references that contain a set of _load()
  183. arguments. Here's an example:
  184.  
  185.     $self->_storemap ( "URL" => { Module => "Filter::URL", 
  186.                                   Constructor => "foo", 
  187.                                   Args => [qw(bar baz)], 
  188.                                 }
  189.                      );
  190.  
  191.     # time passes...
  192.  
  193.     $self->{handler} = $self->_load ( Name => 'URL' );
  194.  
  195. =item B<_retrmap()>
  196.  
  197. _retrmap() returns the entire map stored with Class::Loader. Class::Loader
  198. maintains separate maps for different classes, and _retrmap() returns the
  199. map valid in the caller class.
  200.  
  201. =back
  202.  
  203. =head1 AUTHOR
  204.  
  205. Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
  206.  
  207. =head1 LICENSE
  208.  
  209. Copyright (c) 2001, Vipul Ved Prakash. All rights reserved. This code is
  210. free software; you can redistribute it and/or modify it under the same
  211. terms as Perl itself.
  212.  
  213. =cut
  214.  
  215.  
  216.