home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / Chip_2000-05_cd1.bin / zkuste / Perl / ActivePerl-5.6.0.613.msi / 䆊䌷䈹䈙䏵-䞅䞆䞀㡆䞃䄦䠥 / _050c95495755873bd9e4a6abceeae28b < prev    next >
Text File  |  2000-03-15  |  8KB  |  229 lines

  1. package SOAP::EnvelopeMaker;
  2.  
  3. use strict;
  4. use vars qw($VERSION);
  5. use SOAP::Defs;
  6. use SOAP::TypeMapper;
  7. use SOAP::Envelope;
  8.  
  9. $VERSION = '0.23';
  10.  
  11. sub new {
  12.     my ($class, $print_fcn, $type_mapper) = @_;
  13.     
  14.     $type_mapper ||= SOAP::TypeMapper->defaultMapper();
  15.  
  16.     my $self = {
  17.         envelope    => undef,
  18.         print_fcn   => $print_fcn,
  19.         type_mapper => $type_mapper,
  20.     };
  21.     bless $self, $class;
  22. }
  23.  
  24. sub add_header {
  25.     my ($self, $accessor_uri, $accessor_name,
  26.                $must_understand, $is_package,
  27.                $object) = @_;
  28.  
  29.     unless (defined $object) {
  30.     die "add_header was passed a null object reference";
  31.     }
  32.  
  33.     my $serializer = $self->{type_mapper}->get_serializer($object);
  34.     my ($typeuri, $typename) = $serializer->get_typeinfo();
  35.  
  36.     my @namespaces_to_preload;
  37.     push @namespaces_to_preload, $accessor_uri if $accessor_uri;
  38.     push @namespaces_to_preload, $typeuri      if $typeuri;
  39.  
  40.     my $env = $self->_get_envelope(\@namespaces_to_preload);
  41.  
  42.     my $stream = $env->header($accessor_uri, $accessor_name,
  43.                               $typeuri, $typename,
  44.                               $must_understand, $is_package,
  45.                   ref $object ? $object : undef);
  46.     $self->_serialize_and_term($serializer, $stream);
  47. }
  48.  
  49. sub set_body {
  50.     my ($self, $accessor_uri, $accessor_name,
  51.                $is_package, $object) = @_;
  52.  
  53.     unless (defined $object) {
  54.     die "set_body was passed a null object reference";
  55.     }
  56.     my $serializer = $self->{type_mapper}->get_serializer($object);
  57.     my ($typeuri, $typename) = $serializer->get_typeinfo();
  58.  
  59.     my @namespaces_to_preload;
  60.     push @namespaces_to_preload, $accessor_uri if $accessor_uri;
  61.     push @namespaces_to_preload, $typeuri      if $typeuri;
  62.  
  63.     my $env = $self->_get_envelope(\@namespaces_to_preload);
  64.  
  65.     my $stream = $env->body($accessor_uri, $accessor_name,
  66.                             $typeuri, $typename,
  67.                             $is_package,
  68.                 ref $object ? $object : undef);
  69.     $self->_serialize_and_term($serializer, $stream);
  70.     $env->term();
  71.     $self->{envelope} = undef;
  72. }
  73.  
  74. sub _serialize_and_term {
  75.     my ($self, $serializer, $stream) = @_;
  76.  
  77.     if ($stream) {
  78.     if ($soapperl_accessor_type_simple == $serializer->get_accessor_type()) {
  79.         $self->{print_fcn}->($serializer->serialize_as_string())
  80.     }
  81.     else {        
  82.         $serializer->serialize($stream);
  83.     }
  84.     $stream->term();
  85.     }
  86. }
  87.  
  88. sub _get_envelope {
  89.     my ($self, $namespaces_to_preload) = @_;
  90.  
  91.     if (my $env = $self->{envelope}) {
  92.         return $env;
  93.     }
  94.     my $env = $self->{envelope} = SOAP::Envelope->new($self->{print_fcn},
  95.                                                       $namespaces_to_preload,
  96.                                                       $self->{type_mapper});
  97. }
  98.  
  99. 1;
  100. __END__
  101.  
  102. =head1 NAME
  103.  
  104. SOAP::EnvelopeMaker - Creates SOAP envelopes
  105.  
  106. =head1 SYNOPSIS
  107.  
  108. use SOAP::EnvelopeMaker;
  109.  
  110. my $soap_request = '';
  111. my $output_fcn = sub {
  112.     $soap_request .= shift;
  113. };
  114. my $em = SOAP::EnvelopeMaker->new($output_fcn);
  115.  
  116. my $body = {
  117.     origin => { x => 10, y => 20 },
  118.     corner => { x => 100, y => 200 },
  119. };
  120.  
  121. $em->set_body("urn:com-develop-geometry", "calculateArea", 0, $body);
  122.  
  123. my $endpoint    = "http://soapl.develop.com/soap?class=Geometry";
  124. my $method_uri  = "urn:com-develop-geometry";
  125. my $method_name = "calculateArea";
  126.  
  127. use SOAP::Transport::HTTP::Client;
  128.  
  129. my $soap_on_http = SOAP::Transport::HTTP::Client->new();
  130.  
  131. my $soap_response = $soap_on_http->send_receive($endpoint,
  132.                                                 $method_uri,
  133.                                                 $method_name,
  134.                                                 $soap_request);
  135. use SOAP::Parser;
  136. my $soap_parser = SOAP::Parser->new();
  137. $soap_parser->parsestring($soap_response);
  138.  
  139. my $area = $soap_parser->get_body()->{area};
  140.  
  141. print "The area is: $area\n";
  142.  
  143. =head1 DESCRIPTION
  144.  
  145. The overall usage pattern of SOAP::EnvelopeMaker is as follows:
  146.  
  147. 1) Determine what you want to do with the resulting SOAP packet
  148.    and create an output function that implements this policy.
  149.  
  150. 2) Create an instance of SOAP::EnvelopeMaker, passing a reference
  151.    to your output function.
  152.  
  153. (note that somebody may already have done these first two steps
  154.  on your behalf and simply passed you a reference to a pre-initialized
  155.  EnvelopeMaker - see SOAP::Transport::HTTP::Server for an example)
  156.  
  157. 3) (optional) Call add_header one or more times to specify headers.
  158.  
  159. 4) (required) Call set_body to specify the body.
  160.  
  161. 5) Throw away the EnvelopeMaker and do something with the envelope
  162.    that you've collected via your output function (assuming you've
  163.    not simply been piping the output somewhere as it's given to you).
  164.  
  165. EnvelopeMaker expects that you'll add *all* your headers *before*
  166. setting the body - if you mess this up, the results are undefined.
  167.  
  168. By the time set_body returns, a complete SOAP envelope will have been
  169. sent to your output function (in one or more chunks). You can 
  170.  
  171. =head2 new(OutputFcn)
  172.  
  173. OutputFcn should accept a single scalar parameter, and will be called
  174. multiple times with chunks of the SOAP envelope as it is constructed.
  175. You can either append these chunks into a big string, waiting until
  176. the entire envelope is constructed before you do something with it
  177. (like calculate the content-length, for instance), or you can simply
  178. pipe each chunk directly to somebody else.
  179.  
  180. =head2 add_header(AccessorUri, AccessorName, MustUnderstand, IsPackage, Object)
  181.  
  182. The first two parameters allow you to specify a QName (qualified name)
  183. for your header. Note that in SOAP, all headers MUST be namespace
  184. qualified. MustUnderstand and IsPackage turn on SOAP features that are
  185. explained in the SOAP spec; if you haven't yet grok'd SOAP packages,
  186. just pass 0 for IsPackage. Finally, Object is whatever you'd like to
  187. serialize into the header (see set_body for notes on what can go here;
  188. headers can contain the same stuff as the body).
  189.  
  190. =head2 set_body(AccessorUri, AccessorName, IsPackage, Object)
  191.  
  192. The first two parameters allow you to specify a QName (qualified name)
  193. for the body. The name of the accessor is the name of the SOAP method
  194. call you're making. IsPackage says that the body will be a SOAP package;
  195. just pass 0 if you're not sure what this means. Object is whatever you'd
  196. like to serialize. This can be one of the following things:
  197.  
  198. 1) a scalar - the body will contain the scalar content.
  199.  
  200. 2) a hash reference - the body will contain a SOAP serialized version
  201.                       of the contents of the hash.
  202.  
  203. Note that the SOAP/Perl serialization architecture deals with references
  204. very carefully, so it is possible to pass arbitrary object graphs (although
  205. each "object reference" must currently be a non-blessed scalar or hash reference).
  206.  
  207. In the future, expect to see support for passing blessed object references
  208. (if you want to do this today, see the experimental SOAP::TypeMapper).
  209.  
  210. One interesting thing SOAP (and SOAP/Perl) support is that the headers
  211. and body can share references. They can point to the same stuff. Also,
  212. cycle detection is a natural part of SOAP/Perl's serialization architecture,
  213. so you can pass linked lists, circular queues, etc. and they will be
  214. rehydrated correctly.
  215.  
  216. =head1 DEPENDENCIES
  217.  
  218. SOAP::Envelope
  219.  
  220. =head1 AUTHOR
  221.  
  222. Keith Brown
  223.  
  224. =head1 SEE ALSO
  225.  
  226. SOAP::Envelope
  227.  
  228. =cut
  229.