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]