/[cvs]/joko/Scripts/psh/lib/RPC/XML/Server.pm
ViewVC logotype

Annotation of /joko/Scripts/psh/lib/RPC/XML/Server.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Fri Jun 14 21:22:17 2002 UTC (22 years, 3 months ago) by cvsjoko
Branch point for: nfo, MAIN
Initial revision

1 cvsjoko 1.1 ###############################################################################
2     #
3     # This file copyright (c) 2001 by Randy J. Ray <rjray@blackperl.com>,
4     # all rights reserved
5     #
6     # Copying and distribution are permitted under the terms of the Artistic
7     # License as distributed with Perl versions 5.002 and later. See
8     # http://language.perl.com/misc/Artistic.html
9     #
10     ###############################################################################
11     #
12     # $Id: Server.pm,v 1.26 2002/05/04 07:41:04 rjray Exp $
13     #
14     # Description: This class implements an RPC::XML server, using the core
15     # XML::RPC transaction code. The server may be created with
16     # or without an HTTP::Daemon object instance to answer the
17     # requests.
18     #
19     # Functions: new
20     # version
21     # url
22     # product_tokens
23     # started
24     # path
25     # host
26     # port
27     # requests
28     # response
29     # xpl_path
30     # add_method
31     # method_from_file
32     # get_method
33     # server_loop
34     # post_configure_hook
35     # pre_loop_hook
36     # process_request
37     # dispatch
38     # call
39     # add_default_methods
40     # add_methods_in_dir
41     # delete_method
42     # list_methods
43     # share_methods
44     # copy_methods
45     # timeout
46     #
47     # Libraries: AutoLoader
48     # HTTP::Daemon
49     # HTTP::Status
50     # RPC::XML
51     # RPC::XML::Parser
52     # RPC::XML::Method
53     # RPC::XML::Procedure
54     #
55     # Global Consts: $VERSION
56     # $INSTALL_DIR
57     #
58     ###############################################################################
59    
60     package RPC::XML::Server;
61    
62     use 5.005;
63     use strict;
64     use vars qw($VERSION @ISA $INSTANCE $INSTALL_DIR @XPL_PATH);
65    
66     use Carp 'carp';
67     use AutoLoader 'AUTOLOAD';
68     use File::Spec;
69    
70     BEGIN {
71     $INSTALL_DIR = (File::Spec->splitpath(__FILE__))[1];
72     @XPL_PATH = ($INSTALL_DIR, File::Spec->curdir);
73     }
74    
75     require HTTP::Daemon;
76     require HTTP::Response;
77     require HTTP::Status;
78     require URI;
79    
80     require RPC::XML;
81     require RPC::XML::Parser;
82     require RPC::XML::Procedure;
83    
84     $VERSION = do { my @r=(q$Revision: 1.26 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
85    
86     1;
87    
88     ###############################################################################
89     #
90     # Sub Name: new
91     #
92     # Description: Create a new RPC::XML::Server object. This entails getting
93     # a HTTP::Daemon object, saving several internal values, and
94     # other operations.
95     #
96     # Arguments: NAME IN/OUT TYPE DESCRIPTION
97     # $class in scalar Ref or string for the class
98     # %args in hash Additional arguments
99     #
100     # Returns: Success: object reference
101     # Failure: error string
102     #
103     ###############################################################################
104     sub new
105     {
106     my $class = shift;
107     my %args = @_;
108    
109     my ($self, $http, $resp, $host, $port, $queue, $path, $URI, $srv_name,
110     $srv_version, $timeout);
111    
112     $class = ref($class) || $class;
113     $self = bless {}, $class;
114    
115     $srv_version = $args{server_version} || $self->version;
116     $srv_name = $args{server_name} || $class;
117     $self->{__version} = "$srv_name/$srv_version";
118    
119     if ($args{no_http})
120     {
121     $self->{__host} = $args{host} || '';
122     $self->{__port} = $args{port} || '';
123     delete @args{qw(host port)};
124     }
125     else
126     {
127     $host = $args{host} || '';
128     $port = $args{port} || '';
129     $queue = $args{queue} || 5;
130     $http = HTTP::Daemon->new(Reuse => 1,
131     ($host ? (LocalHost => $host) : ()),
132     ($port ? (LocalPort => $port) : ()),
133     ($queue ? (Listen => $queue) : ()));
134     return "${class}::new: Unable to create HTTP::Daemon object"
135     unless $http;
136     $URI = URI->new($http->url);
137     $self->{__host} = $URI->host;
138     $self->{__port} = $URI->port;
139     $self->{__daemon} = $http;
140    
141     # Remove those we've processed
142     delete @args{qw(host port queue)};
143     }
144     $resp = HTTP::Response->new();
145     return "${class}::new: Unable to create HTTP::Response object"
146     unless $resp;
147     $resp->header(# This is essentially the same string returned by the
148     # default "identity" method that may be loaded from a
149     # XPL file. But it hasn't been loaded yet, and may not
150     # be, hence we set it here (possibly from option values)
151     RPC_Server => $self->{__version},
152     RPC_Encoding => 'XML-RPC');
153     $resp->code(&HTTP::Status::RC_OK);
154     $resp->message('OK');
155     $self->{__response} = $resp;
156    
157     $self->{__path} = $args{path} || '';
158     $self->{__started} = 0;
159     $self->{__method_table} = {};
160     $self->{__requests} = 0;
161     $self->{__auto_methods} = $args{auto_methods} || 0;
162     $self->{__auto_updates} = $args{auto_updates} || 0;
163     $self->{__debug} = $args{debug} || 0;
164     $self->{__parser} = RPC::XML::Parser->new();
165     $self->{__xpl_path} = $args{xpl_path} || [];
166     $self->{__timeout} = $args{timeout} || 10;
167    
168     $self->add_default_methods unless ($args{no_default});
169    
170     # Remove the args we've already dealt with directly
171     delete @args{qw(no_default no_http debug path server_name server_version)};
172     # Copy the rest over untouched
173     $self->{$_} = $args{$_} for (keys %args);
174    
175     $self;
176     }
177    
178     # Most of these tiny subs are accessors to the internal hash keys. They not
179     # only control access to the internals, they ease sub-classing.
180    
181     sub version { $RPC::XML::Server::VERSION }
182    
183     sub INSTALL_DIR { $INSTALL_DIR }
184    
185     sub url
186     {
187     my $self = shift;
188    
189     return $self->{__daemon}->url if $self->{__daemon};
190     return undef unless ($self->{__host});
191    
192     if ($self->{__port} == 443)
193     {
194     return "https://$self->{__host}$self->{__path}";
195     }
196     elsif ($self->{__port} == 80)
197     {
198     return "http://$self->{__host}$self->{__path}";
199     }
200     else
201     {
202     return "http://$self->{__host}:$self->{__port}$self->{__path}";
203     }
204     }
205    
206     sub product_tokens
207     {
208     sprintf "%s/%s", (ref $_[0] || $_[0]), $_[0]->version;
209     }
210    
211     # This fetches/sets the internal "started" timestamp
212     sub started
213     {
214     my $self = shift;
215     my $set = shift || 0;
216    
217     my $old = $self->{__started} || 0;
218     $self->{__started} = time if $set;
219    
220     $old;
221     }
222    
223     sub path { shift->{__path} }
224     sub host { shift->{__host} }
225     sub port { shift->{__port} }
226     sub requests { shift->{__requests} }
227     sub response { shift->{__response} }
228    
229     # Get/set the search path for XPL files
230     sub xpl_path
231     {
232     my $self = shift;
233     my $ret = $self->{__xpl_path};
234    
235     $self->{__xpl_path} = $_[0] if ($_[0] and ref($_[0]) eq 'ARRAY');
236     $ret;
237     }
238    
239     ###############################################################################
240     #
241     # Sub Name: add_method
242     #
243     # Description: Add a funtion-to-method mapping to the server object.
244     #
245     # Arguments: NAME IN/OUT TYPE DESCRIPTION
246     # $self in ref Object to add to
247     # $meth in scalar Hash ref of data or file name
248     #
249     # Returns: Success: $self
250     # Failure: error string
251     #
252     ###############################################################################
253     sub add_method
254     {
255     my $self = shift;
256     my $meth = shift;
257    
258     my ($name, $val);
259    
260     my $me = ref($self) . '::add_method';
261    
262     if (! ref($meth))
263     {
264     $val = $self->method_from_file($meth);
265     if (! ref($val))
266     {
267     return "$me: Error loading from file $meth: $val";
268     }
269     else
270     {
271     $meth = $val;
272     }
273     }
274     elsif (ref($meth) eq 'HASH')
275     {
276     my $class = 'RPC::XML::' . ucfirst ($meth->{type} || 'method');
277     $meth = $class->new($meth);
278     }
279     elsif (! UNIVERSAL::isa($meth, 'RPC::XML::Procedure'))
280     {
281     return "$me: Method argument must be a file name, a hash " .
282     'reference or an object derived from RPC::XML::Procedure';
283     }
284    
285     # Do some sanity-checks
286     return "$me: Method missing required data; check name, code and/or " .
287     'signature' unless $meth->is_valid;
288    
289     $name = $meth->name;
290     $self->{__method_table}->{$name} = $meth;
291    
292     $self;
293     }
294    
295     =pod
296    
297     =head1 NAME
298    
299     RPC::XML::Server - A sample server implementation based on RPC::XML
300    
301     =head1 SYNOPSIS
302    
303     use RPC::XML::Server;
304    
305     ...
306     $srv = RPC::XML::Server->new(port => 9000);
307     # Several of these, most likely:
308     $srv->add_method(...);
309     ...
310     $srv->server_loop; # Never returns
311    
312     =head1 DESCRIPTION
313    
314     This is a sample XML-RPC server built upon the B<RPC::XML> data classes, and
315     using B<HTTP::Daemon> and B<HTTP::Response> for the communication layer.
316    
317     =head1 USAGE
318    
319     Use of the B<RPC::XML::Server> is based on an object model. A server is
320     instantiated from the class, methods (subroutines) are made public by adding
321     them through the object interface, and then the server object is responsible
322     for dispatching requests (and possibly for the HTTP listening, as well).
323    
324     =head2 Methods
325    
326     The following methods are provided by the B<RPC::XML::Server> class. Unless
327     otherwise explicitly noted, all methods return the invoking object reference
328     upon success, and a non-reference error string upon failure.
329    
330     =over 4
331    
332     =item new(OPTIONS)
333    
334     Creates a new object of the class and returns the blessed reference. Depending
335     on the options, the object will contain some combination of an HTTP listener,
336     a pre-populated B<HTTP::Response> object, a B<RPC::XML::Parser> object, and
337     a dispatch table with the set of default methods pre-loaded. The options that
338     B<new> accepts are passed as a hash of key/value pairs (not a hash reference).
339     The accepted options are:
340    
341     =over 4
342    
343     =item B<no_http>
344    
345     If passed with a C<true> value, prevents the creation and storage of the
346     B<HTTP::Daemon> and the pre-configured B<HTTP::Response> objects. This allows
347     for deployment of a server object in other environments. Note that if this is
348     set, the B<accept_loop> method described below will silently return
349     immediately.
350    
351     =item B<no_default>
352    
353     If passed with a C<true> value, prevents the loading of the default methods
354     provided with the B<RPC::XML> distribution. These may be later loaded using
355     the B<add_default_methods> interface described later. The methods themselves
356     are described below (see L<"The Default Methods Provided">).
357    
358     =item B<path>
359    
360     =item B<host>
361    
362     =item B<port>
363    
364     =item B<queue>
365    
366     These four are specific to the HTTP-based nature of the server. The last
367     three are not used at all if C<no_http> is set. The B<path> argument sets the
368     additional URI path information that clients would use to contact the server.
369     Internally, it is not used except in outgoing status and introspection
370     reports. The B<host>, B<port> and B<queue> arguments are passed to the
371     B<HTTP::Daemon> constructor if they are passed. They set the hostname, TCP/IP
372     port, and socket listening queue, respectively. Again, they are not used if
373     the C<no_http> argument was set.
374    
375     =item B<xpl_path>
376    
377     If you plan to add methods to the server object by passing filenames to the
378     C<add_method> call, this argument may be used to specify one or more
379     additional directories to be searched when the passed-in filename is a
380     relative path. The value for this must be an array reference. See also
381     B<add_method> and B<xpl_path>, below.
382    
383     =item B<timeout>
384    
385     You can call this method to set the timeout of new connections after
386     they are received. This function returns the old timeout value. If
387     you pass in no value then it will return the old value without
388     modifying the current value. The default value is 10 seconds.
389    
390     =item B<auto_methods>
391    
392     If specified and set to a true value, enables the automatic searching for a
393     requested remote method that is unknown to the server object handling the
394     request. If set to "no" (or not set at all), then a request for an unknown
395     function causes the object instance to report an error. If the routine is
396     still not found, the error is reported. Enabling this is a security risk, and
397     should only be permitted by a server administrator with fully informed
398     acknowledgement and consent.
399    
400     =item B<auto_updates>
401    
402     If specified and set to a "true" value, enables the checking of the
403     modification time of the file from which a method was originally loaded. If
404     the file has changed, the method is re-loaded before execution is handed
405     off. As with the auto-loading of methods, this represents a security risk, and
406     should only be permitted by a server administrator with fully informed
407     acknowledgement and consent.
408    
409     =back
410    
411     Any other keys in the options hash not explicitly used by the constructor are
412     copied over verbatim onto the object, for the benefit of sub-classing this
413     class. All internal keys are prefixed with C<__> to avoid confusion. Feel
414     free to use this prefix only if you wish to re-introduce confusion.
415    
416     =item version
417    
418     Returns the version string associated with this package.
419    
420     =item product_tokens
421    
422     This returns the identifying string for the server, in the format
423     C<NAME/VERSION> consistent with other applications such as Apache and
424     B<LWP>. It is provided here as part of the compatibility with B<HTTP::Daemon>
425     that is required for effective integration with B<Net::Server>.
426    
427     =item url
428    
429     This returns the HTTP URL that the server will be responding to, when it is in
430     the connection-accept loop. If the server object was created without a
431     built-in HTTP listener, then this method returns C<undef>.
432    
433     =item requests
434    
435     Returns the number of requests this server object has marshalled. Note that in
436     multi-process environments (such as Apache or Net::Server::PreFork) the value
437     returned will only reflect the messages dispatched by the specific process
438     itself.
439    
440     =item response
441    
442     Each instance of this class (and any subclasses that do not completely
443     override the C<new> method) creates and stores an instance of
444     B<HTTP::Response>, which is then used by the B<HTTP::Daemon> or B<Net::Server>
445     processing loops in constructing the response to clients. The response object
446     has all common headers pre-set for efficiency. This method returns a reference
447     to that object.
448    
449     =item started([BOOL])
450    
451     Gets and possibly sets the clock-time when the server starts accepting
452     connections. If a value is passed that evaluates to true, then the current
453     clock time is marked as the starting time. In either case, the current value
454     is returned. The clock-time is based on the internal B<time> command of Perl,
455     and thus is represented as an integer number of seconds since the system
456     epoch. Generally, it is suitable for passing to either B<localtime> or to the
457     C<time2iso8601> routine exported by the B<RPC::XML> package.
458    
459     =item add_method(FILE | HASHREF | OBJECT)
460    
461     =item add_proc(FILE | HASHREF | OBJECT)
462    
463     This adds a new published method or procedure to the server object that
464     invokes it. The new method may be specified in one of three ways: as a
465     filename, a hash reference or an existing object (generally of either
466     B<RPC::XML::Procedure> or B<RPC::XML::Method> classes).
467    
468     If passed as a hash reference, the following keys are expected:
469    
470     =over 4
471    
472     =item B<name>
473    
474     The published (externally-visible) name for the method.
475    
476     =item B<version>
477    
478     An optional version stamp. Not used internally, kept mainly for informative
479     purposes.
480    
481     =item B<hidden>
482    
483     If passed and evaluates to a C<true> value, then the method should be hidden
484     from any introspection API implementations. This parameter is optional, the
485     default behavior being to make the method publically-visible.
486    
487     =item B<code>
488    
489     A code reference to the actual Perl subroutine that handles this method. A
490     symbolic reference is not accepted. The value can be passed either as a
491     reference to an existing routine, or possibly as a closure. See
492     L</"How Methods are Called"> for the semantics the referenced subroutine must
493     follow.
494    
495     =item B<signature>
496    
497     A list reference of the signatures by which this routine may be invoked. Every
498     method has at least one signature. Though less efficient for cases of exactly
499     one signature, a list reference is always used for sake of consistency.
500    
501     =item B<help>
502    
503     Optional documentation text for the method. This is the text that would be
504     returned, for example, by a B<system.methodHelp> call (providing the server
505     has such an externally-visible method).
506    
507     =back
508    
509     If a file is passed, then it is expected to be in the XML-based format,
510     described in the B<RPC::XML::Procedure> manual (see L<RPC::XML::Procedure>).
511     If the name passed is not an absolute pathname, then the file will be searched
512     for in any directories specified when the object was instantiated, then in the
513     directory into which this module was installed, and finally in the current
514     working directory. If the operation fails, the return value will be a
515     non-reference, an error message. Otherwise, the return value is the object
516     reference.
517    
518     The B<add_method> and B<add_proc> calls are essentialy identical unless called
519     with hash references. Both files and objects contain the information that
520     defines the type (method vs. procedure) of the funtionality to be added to the
521     server. If B<add_method> is called with a file that describes a procedure, the
522     resulting addition to the server object will be a B<RPC::XML::Procedure>
523     object, not a method object.
524    
525     For more on the creation and manipulation of procedures and methods as
526     objects, see L<RPC::XML::Procedure>.
527    
528     =item delete_method(NAME)
529    
530     =item delete_proc(NAME)
531    
532     Delete the named method or procedure from the calling object. Removes the
533     entry from the internal table that the object maintains. If the method is
534     shared across more than one server object (see L</share_methods>), then the
535     underlying object for it will only be destroyed when the last server object
536     releases it. On error (such as no method by that name known), an error string
537     is returned.
538    
539     The B<delete_proc> call is identical, supplied for the sake of symmetry. Both
540     calls return the matched object regardless of its underlying type.
541    
542     =item list_methods
543    
544     =item list_procs
545    
546     This returns a list of the names of methods and procedures the server current
547     has published. Note that the returned values are not the method objects, but
548     rather the names by which they are externally known. The "hidden" status of a
549     method is not consulted when this list is created; all methods and procedures
550     known are listed. The list is not sorted in any specific order.
551    
552     The <list_procs> call is provided for symmetry. Both calls list all published
553     routines on the calling server object, regardless of underlying type.
554    
555     =item xpl_path([LISTREF])
556    
557     Get and/or set the object-specific search path for C<*.xpl> files (files that
558     specify methods) that are specified in calls to B<add_method>, above. If a
559     list reference is passed, it is installed as the new path (each element of the
560     list being one directory name to search). Regardless of argument, the current
561     path is returned as a list reference. When a file is passed to B<add_method>,
562     the elements of this path are searched first, in order, before the
563     installation directory or the current working directory are searched.
564    
565     =item get_method(NAME)
566    
567     =item get_proc(NAME)
568    
569     Returns a reference to an object of the class B<RPC::XML::Method> or
570     B<RPC::XML::Procedure>, which is the current binding for the published method
571     NAME. If there is no such method known to the server, then C<undef> is
572     returned. The object is implemented as a hash, and has the same key and value
573     pairs as for C<add_method>, above. Thus, the reference returned is suitable
574     for passing back to C<add_method>. This facilitates temporary changes in what
575     a published name maps to. Note that this is a referent to the object as stored
576     on the server object itself, and thus changes to it could affect the behavior
577     of the server.
578    
579     The B<get_proc> interface is provided for symmetry.
580    
581     =item server_loop(HASH)
582    
583     Enters the connection-accept loop, which generally does not return. This is
584     the C<accept()>-based loop of B<HTTP::Daemon> if the object was created with
585     an instance of that class as a part. Otherwise, this enters the run-loop of
586     the B<Net::Server> class. It listens for requests, and marshalls them out via
587     the C<dispatch> method described below. It answers HTTP-HEAD requests
588     immediately (without counting them on the server statistics) and efficiently
589     by using a cached B<HTTP::Response> object.
590    
591     Because infinite loops requiring a C<HUP> or C<KILL> signal to terminate are
592     generally in poor taste, the B<HTTP::Daemon> side of this sets up a localized
593     signal handler which causes an exit when triggered. By default, this is
594     attached to the C<INT> signal. If the B<Net::Server> module is being used
595     instead, it provides its own signal management.
596    
597     The arguments, if passed, are interpreted as a hash of key/value options (not
598     a hash reference, please note). For B<HTTP::Daemon>, only one is recognized:
599    
600     =over 4
601    
602     =item B<signal>
603    
604     If passed, should be the traditional name for the signal that should be bound
605     to the exit function. If desired, a reference to an array of signal names may
606     be passed, in which case all signals will be given the same handler. The user
607     is responsible for not passing the name of a non-existent signal, or one that
608     cannot be caught. If the value of this argument is 0 (a C<false> value) or the
609     string C<B<NONE>>, then the signal handler will I<not> be installed, and the
610     loop may only be broken out of by killing the running process (unless other
611     arrangements are made within the application).
612    
613     =back
614    
615     The options that B<Net::Server> responds to are detailed in the manual pages
616     for that package. All options passed to C<server_loop> in this situation are
617     passed unaltered to the C<run()> method in B<Net::Server>.
618    
619     =item dispatch(REQUEST)
620    
621     This is the server method that actually manages the marshalling of an incoming
622     request into an invocation of a Perl subroutine. The parameter passed in may
623     be one of: a scalar containing the full XML text of the request, a scalar
624     reference to such a string, or a pre-constructed B<RPC::XML::request> object.
625     Unless an object is passed, the text is parsed with any errors triggering an
626     early exit. Once the object representation of the request is on hand, the
627     parameter data is extracted, as is the method name itself. The call is sent
628     along to the appropriate subroutine, and the results are collated into an
629     object of the B<RPC::XML::response> class, which is returned. Any non-reference
630     return value should be presumed to be an error string. If the dispatched
631     method encountered some sort of error, it will not be propagated upward here,
632     but rather encoded as an object of the B<RPC::XML::fault> class, and returned
633     as the result of the dispatch. This distinguishes between server-centric
634     errors, and general run-time errors.
635    
636     =item add_default_methods([DETAILS])
637    
638     This method adds all the default methods (those that are shipped with this
639     extension) to the calling server object. The files are denoted by their
640     C<*.xpl> extension, and are installed into the same directory as this
641     B<Server.pm> file. The set of default methods are described below (see
642     L<"The Default Methods Provided">).
643    
644     If any names are passed as a list of arguments to this call, then only those
645     methods specified are actually loaded. If the C<*.xpl> extension is absent on
646     any of these names, then it is silently added for testing purposes. Note that
647     the methods shipped with this package have file names without the leading
648     C<status.> part of the method name. If the very first element of the list of
649     arguments is C<except> (or C<-except>), then the rest of the list is
650     treated as a set of names to I<not> load, while all others do get read. The
651     B<Apache::RPC::Server> module uses this to prevent the loading of the default
652     C<system.status> method while still loading all the rest of the defaults. (It
653     then provides a more Apache-centric status method.)
654    
655     Note that there is no symmetric call in this case. The provided API is
656     implemented as methods, and thus only this interface is provided.
657    
658     =item add_methods_in_dir(DIR [, DETAILS])
659    
660     =item add_procs_in_dir(DIR [, DETAILS])
661    
662     This is exactly like B<add_default_methods> above, save that the caller
663     specifies which directory to scan for C<*.xpl> files. In fact, the
664     B<add_default_methods> routine simply calls this routine with the installation
665     directory as the first argument. The definition of the additional arguments is
666     the same as above.
667    
668     B<add_procs_in_dir> is provided for symmetry.
669    
670     =item share_methods(SERVER, NAMES)
671    
672     =item share_procs(SERVER, NAMES)
673    
674     The calling server object shares the methods and/or procedures listed in
675     B<NAMES> with the source-server passed as the first object. The source must
676     derive from this package in order for this operation to be permitted. At least
677     one method must be specified, and all are specified by name (not by object
678     refernce). Both objects will reference the same exact B<RPC::XML::Procedure>
679     (or B<Method>, or derivative thereof) object in this case, meaning that
680     call-statistics and the like will reflect the combined data. If one or more of
681     the passed names are not present on the source server, an error message is
682     returned and none are copied to the calling object.
683    
684     Alternately, one or more of the name parameters passed to this call may be
685     regular-expression objects (the result of the B<qr> operator). Any of these
686     detected are applied against the list of all available methods known to the
687     source server. All matching ones are inserted into the list (the list is pared
688     for redundancies in any case). This allows for easier addition of whole
689     classes such as those in the C<system.*> name space (via B<C<qr/^system\./>>),
690     for example. There is no substring matching provided. Names listed in the
691     parameters to this routine must be either complete strings or regular
692     expressions.
693    
694     The B<share_procs> interface is provided for symmetry.
695    
696     =item copy_methods(SERVER, NAMES)
697    
698     =item copy_procs(SERVER, NAMES)
699    
700     This behaves like the method B<share_methods> above, with the exception that
701     the calling object is given a clone of each method, rather than referencing
702     the same exact method as the source server. The code reference part of the
703     method is shared between the two, but all other data are copied (including a
704     fresh copy of any list references used) into a completely new
705     B<RPC::XML::Procedure> (or derivative) object, using the C<clone()> method
706     from that class. Thus, while the calling object has the same methods
707     available, and is re-using existing code in the Perl runtime, the method
708     objects (and hence the statistics and such) are kept separate. As with the
709     above, an error is flagged if one or more are not found.
710    
711     This routine also accepts regular-expression objects with the same behavior
712     and limitations. Again, B<copy_procs> is simply provided for symmetry.
713    
714     =back
715    
716     =head2 Specifying Server-Side Remote Methods
717    
718     Specifying the methods themselves can be a tricky undertaking. Some packages
719     (in other languages) delegate a specific class to handling incoming requests.
720     This works well, but it can lead to routines not intended for public
721     availability to in fact be available. There are also issues around the access
722     that the methods would then have to other resources within the same running
723     system.
724    
725     The approach taken by B<RPC::XML::Server> (and the B<Apache::RPC::Server>
726     subclass of it) require that methods be explicitly published in one of the
727     several ways provided. Methods may be added directly within code by using
728     C<add_method> as described above, with full data provided for the code
729     reference, signature list, etc. The C<add_method> technique can also be used
730     with a file that conforms to a specific XML-based format (detailed in the
731     manual page for the B<RPC::XML::Procedure> class, see L<RPC::XML::Procedure>).
732     Entire directories of files may be added using C<add_methods_in_dir>, which
733     merely reads the given directory for files that appear to be method
734     definitions.
735    
736     =head2 How Methods Are Called
737    
738     When a routine is called via the server dispatcher, it is called with the
739     arguments that the client request passed. Depending on whether the routine is
740     considered a "procedure" or a "method", there may be an extra argument at the
741     head of the list. The extra argument is present when the routine being
742     dispatched is part of a B<RPC::XML::Method> object. The extra argument is a
743     reference to a B<RPC::XML::Server> object (or a subclass thereof). This is
744     derived from a hash reference, and will include two special keys:
745    
746     =over 4
747    
748     =item method_name
749    
750     This is the name by which the method was called in the client. Most of the
751     time, this will probably be consistent for all calls to the server-side
752     method. But it does not have to be, hence the passing of the value.
753    
754     =item signature
755    
756     This is the signature that was used, when dispatching. Perl has a liberal
757     view of lists and scalars, so it is not always clear what arguments the client
758     specifically has in mind when calling the method. The signature is an array
759     reference containing one or more datatypes, each a simple string. The first
760     of the datatypes specifies the expected return type. The remainder (if any)
761     refer to the arguments themselves.
762    
763     =back
764    
765     Note that by passing the server object reference first, method-classed
766     routines are essentially expected to behave as actual methods of the server
767     class, as opposed to ordinary functions. Of course, they can also discard the
768     initial argument completely.
769    
770     The routines should not make (excessive) use of global variables, for obvious
771     reasons. When the routines are loaded from XPL files, the code is created as a
772     closure that forces execution in the B<RPC::XML::Procedure> package. If the
773     code element of a procedure/method is passed in as a direct code reference by
774     one of the other syntaxes allowed by the constructor, the package may well be
775     different. Thus, routines should strive to be as localized as possible,
776     independant of specific namespaces. If a group of routines are expected to
777     work in close concert, each should explicitly set the namespace with a
778     C<package> declaration as the first statement within the routines themselves.
779    
780     =head2 The Default Methods Provided
781    
782     The following methods are provided with this package, and are the ones
783     installed on newly-created server objects unless told not to. These are
784     identified by their published names, as they are compiled internally as
785     anonymous subroutines and thus cannot be called directly:
786    
787     =over 4
788    
789     =item B<system.identity>
790    
791     Returns a B<string> value identifying the server name, version, and possibly a
792     capability level. Takes no arguments.
793    
794     =item B<system.introspection>
795    
796     Returns a series of B<struct> objects that give overview documentation of one
797     or more of the published methods. It may be called with a B<string>
798     identifying a single routine, in which case the return value is a
799     B<struct>. It may be called with an B<array> of B<string> values, in which
800     case an B<array> of B<struct> values, one per element in, is returned. Lastly,
801     it may be called with no input parameters, in which case all published
802     routines are documented. Note that routines may be configured to be hidden
803     from such introspection queries.
804    
805     =item B<system.listMethods>
806    
807     Returns a list of the published methods or a subset of them as an B<array> of
808     B<string> values. If called with no parameters, returns all (non-hidden)
809     method names. If called with a single B<string> pattern, returns only those
810     names that contain the string as a substring of their name (case-sensitive,
811     and this is I<not> a regular expression evaluation).
812    
813     =item B<system.methodHelp>
814    
815     Takes either a single method name as a B<string>, or a series of them as an
816     B<array> of B<string>. The return value is the help text for the method, as
817     either a B<string> or B<array> of B<string> value. If the method(s) have no
818     help text, the string will be null.
819    
820     =item B<system.methodSignature>
821    
822     As above, but returns the signatures that the method accepts, as B<array> of
823     B<string> representations. If only one method is requests via a B<string>
824     parameter, then the return value is the corresponding array. If the parameter
825     in is an B<array>, then the returned value will be an B<array> of B<array> of
826     B<string>.
827    
828     =item B<system.multicall>
829    
830     This is a simple implementation of composite function calls in a single
831     request. It takes an B<array> of B<struct> values. Each B<struct> has at least
832     a C<methodName> member, which provides the name of the method to call. If
833     there is also a C<params> member, it refers to an B<array> of the parameters
834     that should be passed to the call.
835    
836     =item B<system.status>
837    
838     Takes no arguments and returns a B<struct> containing a number of system
839     status values including (but not limited to) the current time on the server,
840     the time the server was started (both of these are returned in both ISO 8601
841     and UNIX-style integer formats), number of requests dispatched, and some
842     identifying information (hostname, port, etc.).
843    
844     =back
845    
846     In addition, each of these has an accompanying help file in the C<methods>
847     sub-directory of the distribution.
848    
849     These methods are installed as C<*.xpl> files, which are generated from files
850     in the C<methods> directory of the distribution using the B<make_method> tool
851     (see L<make_method>). The files there provide the Perl code that implements
852     these, their help files and other information.
853    
854     =head1 DIAGNOSTICS
855    
856     Unless explicitly stated otherwise, all methods return some type of reference
857     on success, or an error string on failure. Non-reference return values should
858     always be interpreted as errors unless otherwise noted.
859    
860     =head1 CAVEATS
861    
862     This began as a reference implementation in which clarity of process and
863     readability of the code took precedence over general efficiency. It is now
864     being maintained as production code, but may still have parts that could be
865     written more efficiently.
866    
867     =head1 CREDITS
868    
869     The B<XML-RPC> standard is Copyright (c) 1998-2001, UserLand Software, Inc.
870     See <http://www.xmlrpc.com> for more information about the B<XML-RPC>
871     specification. A helpful patch was sent in by Tino Wuensche to fix problems
872     in the signal-setting and signal-catching code in server_loop().
873    
874     =head1 LICENSE
875    
876     This module is licensed under the terms of the Artistic License that covers
877     Perl. See <http://language.perl.com/misc/Artistic.html> for the
878     license.
879    
880     =head1 SEE ALSO
881    
882     L<RPC::XML>, L<RPC::XML::Client>, L<RPC::XML::Parser>
883    
884     =head1 AUTHOR
885    
886     Randy J. Ray <rjray@blackperl.com>
887    
888     =cut
889    
890     __END__
891    
892     ###############################################################################
893     #
894     # Sub Name: add_proc
895     #
896     # Description: This filters through to add_method, but unlike the other
897     # front-ends defined later, this one may have to alter the
898     # data in one type of calling-convention.
899     #
900     # Arguments: NAME IN/OUT TYPE DESCRIPTION
901     # $self in ref Object reference
902     # $meth in scalar Procedure to add
903     #
904     # Returns: threads through to add_method
905     #
906     ###############################################################################
907     sub add_proc
908     {
909     my ($self, $meth) = @_;
910    
911     # Anything else but a hash-reference goes through unaltered
912     $meth->{type} = 'procedure' if (ref($meth) eq 'HASH');
913    
914     $self->add_method($meth);
915     }
916    
917     ###############################################################################
918     #
919     # Sub Name: method_from_file
920     #
921     # Description: Create a RPC::XML::Procedure (or ::Method) object from the
922     # passed-in file name, using the object's search path if the
923     # name is not already absolute.
924     #
925     # Arguments: NAME IN/OUT TYPE DESCRIPTION
926     # $self in ref Object of this class
927     # $file in scalar Name of file to load
928     #
929     # Returns: Success: Method-object reference
930     # Failure: error message
931     #
932     ###############################################################################
933     sub method_from_file
934     {
935     my $self = shift;
936     my $file = shift;
937    
938     unless (File::Spec->file_name_is_absolute($file))
939     {
940     my ($path, @path);
941     push(@path, @{$self->xpl_path}) if (ref $self);
942     for (@path, @XPL_PATH)
943     {
944     $path = File::Spec->catfile($_, $file);
945     if (-e $path) { $file = File::Spec->canonpath($path); last; }
946     }
947     }
948     # Just in case it still didn't appear in the path, we really want an
949     # absolute path:
950     $file = File::Spec->rel2abs($file)
951     unless (File::Spec->file_name_is_absolute($file));
952    
953     RPC::XML::Procedure::new(undef, $file);
954     }
955    
956     # Same as above, but for name-symmetry
957     sub proc_from_file { shift->method_from_file(@_) }
958    
959     ###############################################################################
960     #
961     # Sub Name: get_method
962     #
963     # Description: Get the current binding for the remote-side method $name.
964     # Returns undef if the method is not defined for the server
965     # instance.
966     #
967     # Arguments: NAME IN/OUT TYPE DESCRIPTION
968     # $self in ref Class instance
969     # $name in scalar Name of the method being looked
970     # up
971     #
972     # Returns: Success: Method-class reference
973     # Failure: error string
974     #
975     ###############################################################################
976     sub get_method
977     {
978     my $self = shift;
979     my $name = shift;
980    
981     my $meth = $self->{__method_table}->{$name};
982     unless (defined $meth)
983     {
984     if ($self->{__auto_methods})
985     {
986     # Try to load this dynamically on the fly, from any of the dirs
987     # that are in this object's @xpl_path
988     (my $loadname = $name) =~ s/^system\.//;
989     $self->add_method("$loadname.xpl");
990     }
991     # If method is still not in the table, we were unable to load it
992     return "Unknown method: $name"
993     unless $meth = $self->{__method_table}->{$name};
994     }
995     # Check the mod-time of the file the method came from, if the test is on
996     if ($self->{__auto_updates} && $meth->{file} &&
997     ($meth->{mtime} < (stat $meth->{file})[9]))
998     {
999     $ret = $meth->reload;
1000     return "Reload of method $name failed: $ret" unless ref($ret);
1001     }
1002    
1003     $meth;
1004     }
1005    
1006     # Same as above, but for name-symmetry
1007     sub get_proc { shift->get_method(@_) }
1008    
1009     ###############################################################################
1010     #
1011     # Sub Name: server_loop
1012     #
1013     # Description: Enter a server-loop situation, using the accept() loop of
1014     # HTTP::Daemon if $self has such an object, or falling back
1015     # Net::Server otherwise.
1016     #
1017     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1018     # $self in ref Object of this class
1019     # %args in hash Additional parameters to set up
1020     # before calling the superclass
1021     # Run method
1022     #
1023     # Returns: string if error, otherwise void
1024     #
1025     ###############################################################################
1026     sub server_loop
1027     {
1028     my $self = shift;
1029     my %args = @_;
1030    
1031     if ($self->{__daemon})
1032     {
1033     my ($conn, $req, $resp, $reqxml, $return, $respxml, $exit_now,
1034     $timeout);
1035    
1036     # Localize and set the signal handler as an exit route
1037     my @exit_signals;
1038    
1039     if (exists $args{signal} and $args{signal} ne 'NONE')
1040     {
1041     @exit_signals =
1042     (ref $args{signal}) ? @{$args{signal}} : $args{signal};
1043     }
1044     else
1045     {
1046     push @exit_signals, 'INT';
1047     }
1048    
1049     local @SIG{@exit_signals} = ( sub { $exit_now++ } ) x @exit_signals;
1050    
1051     $self->started('set');
1052     $exit_now = 0;
1053     $timeout = $self->{__daemon}->timeout(1);
1054     while (! $exit_now)
1055     {
1056     $conn = $self->{__daemon}->accept;
1057    
1058     last if $exit_now;
1059     next unless $conn;
1060     $conn->timeout($self->{__timeout});
1061     $self->process_request($conn);
1062     $conn->close;
1063     undef $conn; # Free up any lingering resources
1064     }
1065    
1066     $self->{__daemon}->timeout($timeout) if defined $timeout;
1067     }
1068     else
1069     {
1070     # This is the Net::Server block
1071    
1072     # Don't do this next part if they've already given a port, or are
1073     # pointing to a config file:
1074    
1075     # An explicitly-given conf-file trumps any specified at creation
1076     $args{conf_file} = $self->{conf_file}
1077     if (exists($self->{conf_file}) and (! exists $args{conf_file}));
1078     unless ($args{conf_file} or $args{port})
1079     {
1080     $args{port} = $self->{port} || $self->{__port} || 9000;
1081     $args{host} = $self->{host} || $self->{__host} || '*';
1082     }
1083    
1084     # Try to load the Net::Server::MultiType module
1085     eval { require Net::Server::MultiType; };
1086     return ref($self) .
1087     "::server_loop: Error loading Net::Server::MultiType: $@"
1088     if ($@);
1089     unshift(@RPC::XML::Server::ISA, 'Net::Server::MultiType');
1090    
1091     $self->started('set');
1092     # ...and we're off!
1093     $self->run(%args);
1094     }
1095    
1096     return;
1097     }
1098    
1099     ###############################################################################
1100     #
1101     # Sub Name: post_configure_loop
1102     #
1103     # Description: Called by the Net::Server classes after all the config
1104     # steps have been done and merged.
1105     #
1106     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1107     # $self in ref Class object
1108     #
1109     # Returns: $self
1110     #
1111     ###############################################################################
1112     sub post_configure_hook
1113     {
1114     my $self = shift;
1115    
1116     $self->{__host} = $self->{server}->{host};
1117     $self->{__port} = $self->{server}->{port};
1118    
1119     $self;
1120     }
1121    
1122     ###############################################################################
1123     #
1124     # Sub Name: pre_loop_hook
1125     #
1126     # Description: Called by Net::Server classes after the post_bind method,
1127     # but before the socket-accept loop starts.
1128     #
1129     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1130     # $self in ref Object instance
1131     #
1132     # Globals: %ENV
1133     #
1134     # Returns: $self
1135     #
1136     ###############################################################################
1137     sub pre_loop_hook
1138     {
1139     # We have to disable the __DIE__ handler for the sake of XML::Parser::Expat
1140     $SIG{__DIE__} = '';
1141     }
1142    
1143     ###############################################################################
1144     #
1145     # Sub Name: process_request
1146     #
1147     # Description: This is provided for the case when we run as a subclass
1148     # of Net::Server.
1149     #
1150     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1151     # $self in ref This class object
1152     # $conn in ref If present, it's a connection
1153     # object from HTTP::Daemon
1154     #
1155     # Returns: void
1156     #
1157     ###############################################################################
1158     sub process_request
1159     {
1160     my $self = shift;
1161     my $conn = shift;
1162    
1163     my ($req, $reqxml, $resp, $respxml);
1164    
1165     unless ($conn and ref($conn))
1166     {
1167     $conn = $self->{server}->{client};
1168     bless $conn, 'HTTP::Daemon::ClientConn';
1169     ${*$conn}{'httpd_daemon'} = $self;
1170     }
1171    
1172     while ($req = $conn->get_request)
1173     {
1174     if ($req->method eq 'HEAD')
1175     {
1176     # The HEAD method will be answered with our return headers,
1177     # both as a means of self-identification and a verification
1178     # of live-status. All the headers were pre-set in the cached
1179     # HTTP::Response object. Also, we don't count this for stats.
1180     $conn->send_response($self->{__response});
1181     }
1182     elsif ($req->method eq 'POST')
1183     {
1184     $reqxml = $req->content;
1185     # Dispatch will always return a RPC::XML::response
1186     $resp = $self->dispatch(\$reqxml);
1187     $respxml = $resp->as_string;
1188     # Now clone the pre-fab response and add content
1189     $resp = $self->{__response}->clone;
1190     $resp->content($respxml);
1191     $conn->send_response($resp);
1192     undef $resp;
1193     }
1194     else
1195     {
1196     $conn->send_error(&HTTP::Status::RC_FORBIDDEN);
1197     }
1198     }
1199    
1200     return;
1201     }
1202    
1203     ###############################################################################
1204     #
1205     # Sub Name: dispatch
1206     #
1207     # Description: Route the request by parsing it, determining what the
1208     # Perl routine should be, etc.
1209     #
1210     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1211     # $self in ref Object of this class
1212     # $xml in ref Reference to the XML text, or
1213     # a RPC::XML::request object.
1214     # If it is a listref, assume
1215     # [ name, @args ].
1216     # $reftable in hashref If present, a reference to the
1217     # current-running table of
1218     # back-references
1219     #
1220     # Returns: RPC::XML::response object
1221     #
1222     ###############################################################################
1223     sub dispatch
1224     {
1225     my ($self, $xml) = @_;
1226    
1227     my ($reqobj, @data, $response, $name, $meth);
1228    
1229     if (ref($xml) eq 'SCALAR')
1230     {
1231     $reqobj = $self->{__parser}->parse($$xml);
1232     return RPC::XML::response
1233     ->new(RPC::XML::fault->new(200, "XML parse failure: $reqobj"))
1234     unless (ref $reqobj);
1235     }
1236     elsif (ref($xml) eq 'ARRAY')
1237     {
1238     # This is sort of a cheat, to make the system.multicall API call a
1239     # lot easier. The syntax isn't documented in the manual page, for good
1240     # reason.
1241     $reqobj = RPC::XML::request->new(shift(@$xml), @$xml);
1242     }
1243     elsif (UNIVERSAL::isa($xml, 'RPC::XML::request'))
1244     {
1245     $reqobj = $xml;
1246     }
1247     else
1248     {
1249     $reqobj = $self->{__parser}->parse($xml);
1250     return RPC::XML::response
1251     ->new(RPC::XML::fault->new(200, "XML parse failure: $reqobj"))
1252     unless (ref $reqobj);
1253     }
1254    
1255     @data = @{$reqobj->args};
1256     $name = $reqobj->name;
1257    
1258     # Get the method, call it, and bump the internal requests counter. Create
1259     # a fault object if there is problem with the method object itself.
1260     if (ref($meth = $self->get_method($name)))
1261     {
1262     $response = $meth->call($self, @data);
1263     $self->{__requests}++;
1264     }
1265     else
1266     {
1267     $response = RPC::XML::fault->new(300, $meth);
1268     }
1269    
1270     # All the eval'ing and error-trapping happened within the method class
1271     RPC::XML::response->new($response);
1272     }
1273    
1274     ###############################################################################
1275     #
1276     # Sub Name: call
1277     #
1278     # Description: This is an internal, end-run-around-dispatch() method to
1279     # allow the RPC methods that this server has and knows about
1280     # to call each other through their reference to the server
1281     # object.
1282     #
1283     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1284     # $self in ref Object of this class
1285     # $name in scalar Name of the method to call
1286     # @args in list Arguments (if any) to pass
1287     #
1288     # Returns: Success: return value of the call
1289     # Failure: error string
1290     #
1291     ###############################################################################
1292     sub call
1293     {
1294     my ($self, $name, @args) = @_;
1295    
1296     my $meth;
1297    
1298     #
1299     # Two VERY important notes here: The values in @args are not pre-treated
1300     # in any way, so not only should the receiver understand what they're
1301     # getting, there's no signature checking taking place, either.
1302     #
1303     # Second, if the normal return value is not distinguishable from a string,
1304     # then the caller may not recognize if an error occurs.
1305     #
1306    
1307     return $meth unless ref($meth = $self->get_method($name));
1308     $meth->call($self, @args);
1309     }
1310    
1311     ###############################################################################
1312     #
1313     # Sub Name: add_default_methods
1314     #
1315     # Description: This adds all the methods that were shipped with this
1316     # package, by threading through to add_methods_in_dir()
1317     # with the global constant $INSTALL_DIR.
1318     #
1319     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1320     # $self in ref Object reference/static class
1321     # @details in ref Details of names to add or skip
1322     #
1323     # Globals: $INSTALL_DIR
1324     #
1325     # Returns: $self
1326     #
1327     ###############################################################################
1328     sub add_default_methods
1329     {
1330     shift->add_methods_in_dir($INSTALL_DIR, @_);
1331     }
1332    
1333     ###############################################################################
1334     #
1335     # Sub Name: add_methods_in_dir
1336     #
1337     # Description: This adds all methods specified in the directory passed,
1338     # in accordance with the details specified.
1339     #
1340     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1341     # $self in ref Class instance
1342     # $dir in scalar Directory to scan
1343     # @details in list Possible hanky-panky with the
1344     # list of methods to install
1345     #
1346     # Returns: $self
1347     #
1348     ###############################################################################
1349     sub add_methods_in_dir
1350     {
1351     my $self = shift;
1352     my $dir = shift;
1353     my @details = @_;
1354    
1355     my $negate = 0;
1356     my $detail = 0;
1357     my (%details, $ret);
1358    
1359     if (@details)
1360     {
1361     $detail = 1;
1362     if ($details[0] =~ /^-?except/i)
1363     {
1364     $negate = 1;
1365     shift(@details);
1366     }
1367     for (@details) { $_ .= '.xpl' unless /\.xpl$/ }
1368     @details{@details} = (1) x @details;
1369     }
1370    
1371     local(*D);
1372     opendir(D, $dir) || return "Error opening $dir for reading: $!";
1373     my @files = grep($_ =~ /\.xpl$/, readdir(D));
1374     closedir D;
1375    
1376     for (@files)
1377     {
1378     # Use $detail as a short-circuit to avoid the other tests when we can
1379     next if ($detail and
1380     $negate ? $details{$_} : ! $details{$_});
1381     # n.b.: Giving the full path keeps add_method from having to search
1382     $ret = $self->add_method(File::Spec->catfile($dir, $_));
1383     return $ret unless ref $ret;
1384     }
1385    
1386     $self;
1387     }
1388    
1389     # Same as above, but for name-symmetry
1390     sub add_procs_in_dir { shift->add_methods_in_dir(@_) }
1391    
1392     ###############################################################################
1393     #
1394     # Sub Name: delete_method
1395     #
1396     # Description: Remove any current binding for the named method on the
1397     # calling server object. Note that if this method is shared
1398     # across other server objects, it won't be destroyed until
1399     # the last server deletes it.
1400     #
1401     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1402     # $self in ref Object of this class
1403     # $name in scalar Name of method to lost
1404     #
1405     # Returns: Success: $self
1406     # Failure: error message
1407     #
1408     ###############################################################################
1409     sub delete_method
1410     {
1411     my $self = shift;
1412     my $name = shift;
1413    
1414     if ($name)
1415     {
1416     if ($self->{__method_table}->{$name})
1417     {
1418     delete $self->{__method_table}->{$name};
1419     return $self;
1420     }
1421     }
1422     else
1423     {
1424     return ref($self) . "::delete_method: No such method $name";
1425     }
1426     }
1427    
1428     # Same as above, but for name-symmetry
1429     sub delete_proc { shift->delete_method(@_) }
1430    
1431     ###############################################################################
1432     #
1433     # Sub Name: list_methods
1434     #
1435     # Description: Return a list of the methods this object has published.
1436     # Returns the names, not the objects.
1437     #
1438     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1439     # $self in ref Object of this class
1440     #
1441     # Returns: List of names, possibly empty
1442     #
1443     ###############################################################################
1444     sub list_methods
1445     {
1446     keys %{$_[0]->{__method_table}};
1447     }
1448    
1449     # Same as above, but for name-symmetry
1450     sub list_procs { shift->list_methods(@_) }
1451    
1452     ###############################################################################
1453     #
1454     # Sub Name: share_methods
1455     #
1456     # Description: Share the named methods as found on $src_srv into the
1457     # method table of the calling object.
1458     #
1459     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1460     # $self in ref Object of this class
1461     # $src_srv in ref Another object of this class
1462     # @names in list One or more method names
1463     #
1464     # Returns: Success: $self
1465     # Failure: error message
1466     #
1467     ###############################################################################
1468     sub share_methods
1469     {
1470     my $self = shift;
1471     my $src_srv = shift;
1472     my @names = @_;
1473    
1474     my ($me, $pkg, %tmp, @tmp, $tmp, $meth, @list, @missing);
1475    
1476     $me = ref($self) . '::share_methods';
1477     $pkg = __PACKAGE__; # So it can go inside quoted strings
1478    
1479     return "$me: First arg not derived from $pkg, cannot share"
1480     unless ((ref $src_srv) && (UNIVERSAL::isa($src_srv, $pkg)));
1481     return "$me: Must specify at least one method name for sharing"
1482     unless @names;
1483    
1484     #
1485     # Scan @names for any regez objects, and if found insert the matches into
1486     # the list.
1487     #
1488     # Only do this once:
1489     #
1490     @tmp = keys %{$src_srv->{__method_table}};
1491     for $tmp (@names)
1492     {
1493     if (ref($names[$tmp]) eq 'Regexp')
1494     {
1495     $tmp{$_}++ for (grep($_ =~ $tmp, @tmp));
1496     }
1497     else
1498     {
1499     $tmp{$tmp}++;
1500     }
1501     }
1502     # This has the benefit of trimming any redundancies caused by regex's
1503     @names = keys %tmp;
1504    
1505     #
1506     # Note that the method refs are saved until we've verified all of them.
1507     # If we have to return a failure message, I don't want to leave a half-
1508     # finished job or have to go back and undo (n-1) additions because of one
1509     # failure.
1510     #
1511     for (@names)
1512     {
1513     $meth = $src_srv->get_method($_);
1514     if (ref $meth)
1515     {
1516     push(@list, $meth);
1517     }
1518     else
1519     {
1520     push(@missing, $_);
1521     }
1522     }
1523    
1524     if (@missing)
1525     {
1526     return "$me: One or more methods not found on source object: @missing";
1527     }
1528     else
1529     {
1530     $self->add_method($_) for (@list);
1531     }
1532    
1533     $self;
1534     }
1535    
1536     # Same as above, but for name-symmetry
1537     sub share_procs { shift->share_methods(@_) }
1538    
1539     ###############################################################################
1540     #
1541     # Sub Name: copy_methods
1542     #
1543     # Description: Copy the named methods as found on $src_srv into the
1544     # method table of the calling object. This differs from
1545     # share() above in that only the coderef is shared, the
1546     # rest of the method is a completely new object.
1547     #
1548     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1549     # $self in ref Object of this class
1550     # $src_srv in ref Another object of this class
1551     # @names in list One or more method names
1552     #
1553     # Returns: Success: $self
1554     # Failure: error message
1555     #
1556     ###############################################################################
1557     sub copy_methods
1558     {
1559     my $self = shift;
1560     my $src_srv = shift;
1561     my @names = shift;
1562    
1563     my ($me, $pkg, %tmp, @tmp, $tmp, $meth, @list, @missing);
1564    
1565     $me = ref($self) . '::copy_methods';
1566     $pkg = __PACKAGE__; # So it can go inside quoted strings
1567    
1568     return "$me: First arg not derived from $pkg, cannot copy"
1569     unless ((ref $src_srv) && (UNIVERSAL::isa($src_srv, $pkg)));
1570     return "$me: Must specify at least one method name/regex for copying"
1571     unless @names;
1572    
1573     #
1574     # Scan @names for any regez objects, and if found insert the matches into
1575     # the list.
1576     #
1577     # Only do this once:
1578     #
1579     @tmp = keys %{$src_srv->{__method_table}};
1580     for $tmp (@names)
1581     {
1582     if (ref($names[$tmp]) eq 'Regexp')
1583     {
1584     $tmp{$_}++ for (grep($_ =~ $tmp, @tmp));
1585     }
1586     else
1587     {
1588     $tmp{$tmp}++;
1589     }
1590     }
1591     # This has the benefit of trimming any redundancies caused by regex's
1592     @names = keys %tmp;
1593    
1594     #
1595     # Note that the method clones are saved until we've verified all of them.
1596     # If we have to return a failure message, I don't want to leave a half-
1597     # finished job or have to go back and undo (n-1) additions because of one
1598     # failure.
1599     #
1600     for (@names)
1601     {
1602     $meth = $src_srv->get_method($_);
1603     if (ref $meth)
1604     {
1605     push(@list, $meth->clone);
1606     }
1607     else
1608     {
1609     push(@missing, $_);
1610     }
1611     }
1612    
1613     if (@missing)
1614     {
1615     return "$me: One or more methods not found on source object: @missing";
1616     }
1617     else
1618     {
1619     $self->add_method($_) for (@list);
1620     }
1621    
1622     $self;
1623     }
1624    
1625     # Same as above, but for name-symmetry
1626     sub copy_procs { shift->copy_methods(@_) }
1627    
1628     ###############################################################################
1629     #
1630     # Sub Name: timeout
1631     #
1632     # Description: This sets the timeout for processing connections after
1633     # a new connection has been accepted. It returns the old
1634     # timeout value. If you pass in no value, it returns
1635     # the current timeout.
1636     #
1637     # Arguments: NAME IN/OUT TYPE DESCRIPTION
1638     # $self in ref Object reference/static class
1639     # $timeout in ref New timeout value
1640     #
1641     # Returns: $self->{__timeout}
1642     #
1643     ###############################################################################
1644     sub timeout
1645     {
1646     my $self = shift;
1647     my $timeout = shift;
1648    
1649     my $old_timeout = $self->{__timeout};
1650     if ($timeout)
1651     {
1652     $self->{__timeout} = $timeout;
1653     }
1654     return $old_timeout;
1655     }

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed