stas        2003/02/23 18:09:29

  Modified:    src/docs/2.0/api config.cfg
               src/docs/2.0/user/compat compat.pod
  Added:       src/docs/2.0/api/ModPerl MethodLookup.pod
  Log:
  add a manpage for the new module ModPerl::MethodLookup and link to it
  
  Revision  Changes    Path
  1.17      +1 -0      modperl-docs/src/docs/2.0/api/config.cfg
  
  Index: config.cfg
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/api/config.cfg,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- config.cfg        24 Feb 2003 00:14:26 -0000      1.16
  +++ config.cfg        24 Feb 2003 02:09:29 -0000      1.17
  @@ -41,6 +41,7 @@
   
       group    => 'ModPerl::',
       chapters => [qw(
  +        ModPerl/MethodLookup.pod
           ModPerl/PerlRun.pod
           ModPerl/Registry.pod
           ModPerl/RegistryBB.pod
  
  
  
  1.1                  modperl-docs/src/docs/2.0/api/ModPerl/MethodLookup.pod
  
  Index: MethodLookup.pod
  ===================================================================
  =head1 NAME
  
  ModPerl::MethodLookup -- An API for finding modules that include mod_perl 2.0 
methods
  
  =head1 Synopsis
  
    use ModPerl::MethodLookup;
    
    # return all module names containing method 'print'
    my($hint, @modules) =
        ModPerl::MethodLookup::lookup_method('print');
    
    # return only module names containing method 'print' which
    # expects the first argument to be of type 'Apache::Filter'
    # (here $filter is an Apache::Filter object)
    my($hint, @modules) =
        ModPerl::MethodLookup::lookup_method('print', $filter);
    
    # preload all mp2 modules in startup.pl
    ModPerl::MethodLookup::preload_all_modules();
  
  =head1 Description
  
  mod_perl 2.0 provides many methods, which reside in various
  modules. One has to load each of the modules before using the desired
  methods. C<ModPerl::MethodLookup> provides the Perl API for finding
  module names which contain methods in question and other helper
  functions.
  
  =head1 Api
  
  =head2 lookup_method()
  
    my($hint, @modules) =
        ModPerl::MethodLookup::lookup_method('print');
  
  The C<lookup_method()> accepts the method name as an argument.
  
  The first returned value is a string returning a human readable lookup
  result. Normally suggesting which modules should be loaded, ready for
  copy-n-paste or explaining the failure if the lookup didn't succeed.
  
  The second returned value is an array of modules which has matched the
  query, i.e. the names of the modules which contain the requested
  method.
  
    my($hint, @modules) = 
        ModPerl::MethodLookup::lookup_method('print', $object);
  
  The C<lookup_method()> accepts a second optional argument, which is a
  blessed object. If there is more than one matches this object is used
  to return only those matches who operate on the objects of the same
  kind. This usage is useful when the AUTOLOAD is used to find
  yet-unloaded modules which include called methods.
  
  =head2 preload_all_modules()
  
  The function C<preload_all_modules()> preloads all mod_perl 2.0
  modules. This is similar to the mod_perl 1.0 behavior which has most
  of its methods loaded at the startup.
  
  CPAN modules developers should make sure their distribution loads each
  of the used mod_perl 2.0 modules explicitly, and not use this
  function, as it takes the fine control away from the users. One should
  avoid doing this the production server (unless all modules are used
  indeed) in order to save memory.
  
  
  =cut
  
  =head1 Applications
  
  =head2 AUTOLOAD
  
  When Perl fails to locate a method it checks whether the package the
  object belongs to has an C<AUTOLOAD> function defined and if so, calls
  it with the same arguments as the missing method while setting a
  global variable C<$AUTOLOAD> (in that package) to the name of the
  originally called method. We can use this facility to lookup the
  modules to be loaded when such a failure occurs. Though since we have
  many packages to take care of we will use a special
  C<UNIVERSAL::AUTOLOAD> function which Perl calls if can't find the
  C<AUTOLOAD> function in the given package.
  
  In that function you can query C<ModPerl::MethodLookup>, require() the
  module that includes the called method and call that method again
  using the goto() trick:
  
    use ModPerl::MethodLookup;
    sub UNIVERSAL::AUTOLOAD {
        my($hint, @modules) =
            ModPerl::MethodLookup::lookup_method($UNIVERSAL::AUTOLOAD, @_);
        if (@modules) {
            eval "require $_" for @modules;
            goto &$UNIVERSAL::AUTOLOAD;
        }
        else {
            die $hint;
        }
    }
  
  However we don't endorse this approach. It's a better approach to
  always abort the execution which printing the C<$hint>and use fix the
  code to load the missing module. Moreover installing
  C<UNIVERSAL::AUTOLOAD> may cause a lot of problems, since once it's
  installed Perl will call it every time some method is missing
  (e.g. undefined C<DESTROY> methods). The following approach seems to
  somewhat work for me. It installs C<UNIVERSAL::AUTOLOAD> only when the
  configuration stage has completed:
  
    httpd.conf:
    -----------
    PerlPostConfigHandler ModPerl::MethodLookupAuto
  
    startup.pl:
    -----------
    {
      package ModPerl::MethodLookupAuto;
      use ModPerl::MethodLookup;
    
      use Carp;
      sub handler {
    
          # exclude DESTROY resolving
          my $skip = '^(?!DESTROY$';
          *UNIVERSAL::AUTOLOAD = sub {
              my $method = $AUTOLOAD;
              return if $method =~ /DESTROY/;
              my ($hint, @modules) =
                  ModPerl::MethodLookup::lookup_method($method, @_);
              $hint ||= "Can't find method $AUTOLOAD";
              croak $hint;
          };
          return 0;
      }
    }
  
  This example doesn't load the modules for you. It'll print to STDERR
  what module should be loaded, when a method from the not-yet-loaded
  module is called.
  
  =head2 Command Line Lookups
  
  When a method is used and mod_perl has reported a failure to find it,
  one can issue a command line query to figure out which module needs to
  be loaded. For example if when executing:
  
    $r->construct_url();
  
  mod_perl complains:
  
    Can't locate object method "construct_url" via package
    "Apache::RequestRec" at ...
  
  you can ask C<ModPerl::MethodLookup> for help:
  
    % perl -MApache2 -MModPerl::MethodLookup -le \
       'print((ModPerl::MethodLookup::lookup_method(shift))[0])' construct_url
    to use method 'construct_url' add:
            use Apache::URI ();
  
  and after copy-n-pasting the use statement in our code, the problem
  goes away.
  
  One can create a handy alias for this technique. For example, C-style
  shell users can do:
  
     % alias lookup "perl -MApache2 -MModPerl::MethodLookup -le \\
       'print((ModPerl::MethodLookup::lookup_method(shift))[0])'"
  
  For Bash-style shell users:
  
     % alias lookup="perl -MApache2 -MModPerl::MethodLookup -le \
       'print((ModPerl::MethodLookup::lookup_method(shift))[0])'"
  
  Now the lookup is even easier:
  
    % lookup construct_url
    to use method 'construct_url' add:
            use Apache::URI;
  
  
  =head1 Author
  
  Stas Bekman
  
  =cut
  
  
  
  1.49      +10 -0     modperl-docs/src/docs/2.0/user/compat/compat.pod
  
  Index: compat.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/compat/compat.pod,v
  retrieving revision 1.48
  retrieving revision 1.49
  diff -u -r1.48 -r1.49
  --- compat.pod        20 Feb 2003 00:16:45 -0000      1.48
  +++ compat.pod        24 Feb 2003 02:09:29 -0000      1.49
  @@ -153,6 +153,16 @@
   I<5.8.0/i686-linux-thread-multi/Apache2> is coming before the
   directory I<5.8.0/i686-linux-thread-multi> in C<@INC>.
   
  +Finally, mod_perl 2.0 has all its methods spread across many
  +modules. In order to use these methods the modules containing them
  +have to be loaded first. The module
  +C<L<ModPerl::MethodLookup|docs::2.0::api::ModPerl::MethodLookup>> can
  +be used to find out which modules need to be used. This module also
  +provides a function
  
+C<L<preload_all_modules()|docs::2.0::api::ModPerl::MethodLookup/preload_all_modules__>>
  +that will load all mod_perl 2.0 modules, which is useful when one
  +starts to port their mod_perl 1.0 code, though preferrably avoided in
  +the production environment.
   
   =head1 C<Apache::Registry>, C<Apache::PerlRun> and Friends
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to