[Catalyst-commits] r7648 - in Catalyst-Controller-SOAP/1.0/tags: . 0.9 0.9/lib/Catalyst/Controller

ruoso at dev.catalyst.perl.org ruoso at dev.catalyst.perl.org
Wed Apr 30 11:06:30 BST 2008


Author: ruoso
Date: 2008-04-30 11:06:29 +0100 (Wed, 30 Apr 2008)
New Revision: 7648

Added:
   Catalyst-Controller-SOAP/1.0/tags/0.9/
   Catalyst-Controller-SOAP/1.0/tags/0.9/Changes
   Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm
Removed:
   Catalyst-Controller-SOAP/1.0/tags/0.9/Changes
   Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm
Log:
[C-C-SOAP] Tagging version 0.9

Copied: Catalyst-Controller-SOAP/1.0/tags/0.9 (from rev 7646, Catalyst-Controller-SOAP/1.0/trunk)

Deleted: Catalyst-Controller-SOAP/1.0/tags/0.9/Changes
===================================================================
--- Catalyst-Controller-SOAP/1.0/trunk/Changes	2008-04-30 00:44:32 UTC (rev 7646)
+++ Catalyst-Controller-SOAP/1.0/tags/0.9/Changes	2008-04-30 10:06:29 UTC (rev 7648)
@@ -1,170 +0,0 @@
-------------------------------------------------------------------------
-r7549 | ruoso | 2008-04-02 16:10:18 +0100 (Qua, 02 Abr 2008) | 1 line
-
-[C-C-SOAP] Tests for Document/Literal-Wrapped working. Supports several wsdls and schemas in the config.
-------------------------------------------------------------------------
-r7548 | ruoso | 2008-04-02 15:54:42 +0100 (Qua, 02 Abr 2008) | 1 line
-
-[C-C-SOAP] Document/Literal-Wrapped support (with a big ONLY FOR COMPATIBILTY REASONS disclaimer)... Test is still failing as the SOAPAction header seems to be lost in the test...
-------------------------------------------------------------------------
-r7546 | ruoso | 2008-04-02 12:23:38 +0100 (Qua, 02 Abr 2008) | 1 line
-
-[C-C-SOAP] Better support for RPC messages, tests including an example of a RPC-Literal service, exception catching generating a SOAP Fault.
-------------------------------------------------------------------------
-r7542 | ruoso | 2008-04-01 18:05:00 +0100 (Ter, 01 Abr 2008) | 1 line
-
-[C-C-S] Now supports WSDL encoding/decoding of messages.
-------------------------------------------------------------------------
-commit 8bea90e61c8aa0cf269da57b9ccbe33987ca76c8
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Mon Nov 26 11:14:25 2007 +0000
-
-    marking new release fixing errors pointed by CPANTESTERS...
-
-commit fd36b65bea45660841790d2716ac330cc506586b
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Mon Nov 26 11:12:34 2007 +0000
-
-    Revert "Revert "PostApp now calls the interpreter with all the directories in @INC. PostApp app no longer depends on any plugin.""
-    
-    This reverts commit 58704caa35fdc5581366007aafd37cc393a94775.
-
-commit 58704caa35fdc5581366007aafd37cc393a94775
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Mon Nov 26 11:11:58 2007 +0000
-
-    Revert "PostApp now calls the interpreter with all the directories in @INC. PostApp app no longer depends on any plugin."
-    
-    This reverts commit 46870ad634f5a8228d7af797117219369dc107db.
-
-commit 46870ad634f5a8228d7af797117219369dc107db
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Mon Nov 26 11:09:35 2007 +0000
-
-    PostApp now calls the interpreter with all the directories in @INC. PostApp app no longer depends on any plugin.
-
-commit 54c6bf1c90e55eb83330ce0fb9f5cd686ac63d11
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Thu Nov 22 18:26:32 2007 +0000
-
-    marking a new release and leaving RPCEncoded out of it.
-
-commit 587c81026d0a8d13d27a124cf9175e0c2d5528d7
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Wed Nov 21 18:34:26 2007 +0000
-
-    removing directory entries from MANIFEST
-
-commit 1931438d732fe7e51942d6bc69b454e5e4dcf97a
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Wed Nov 21 18:33:27 2007 +0000
-
-    Updating changes file
-
-commit 9303bc1e368afb6def74573941eaf459f58533bc
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Wed Nov 21 18:33:13 2007 +0000
-
-    marking a new release
-
-commit 9260e5d96945a4edeb07f8676e12750f0d8d6da4
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Wed Nov 21 18:32:24 2007 +0000
-
-    Make the test more cross-platform
-
-commit 4089cc6ffd0d2cc90feac824aa39ff593d40aeca
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Wed Nov 21 18:23:14 2007 +0000
-
-    Better README and Changes file
-
-commit 865fcd5df2222b9034690fef7f4f6c800c9a75d4
-Author: Daniel Ruoso <daniel at ruoso.com>
-Date:   Wed Nov 21 18:21:23 2007 +0000
-
-    The PostApp app is now used in a test...
-
-commit 16f12fb6cda352faa2e88dacf6e468c3778d3a52
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Sun Nov 18 16:50:54 2007 +0000
-
-    now do not depend on renderview in the test. Also declare the versioned dependency on the Catalyst::Runtime
-
-commit dcdeecc9b1add94f68aa1905957cd9b9ae96c761
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Thu Nov 15 09:59:28 2007 +0000
-
-    marking new release
-
-commit a201321dde6a2575d95b88fbf854caf424ca0ccf
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Thu Nov 15 09:54:21 2007 +0000
-
-    fixing naming of modules in documentation...
-
-commit 7c2b71c1a19a521768c6debf07aaea149549195e
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 19:13:24 2007 +0000
-
-    marking new release
-
-commit e9bd4bbe2c3d3e678b7fc1440b5f72766b3307a6
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 19:12:53 2007 +0000
-
-    rpc endpoint now working
-
-commit 8baa49622fadce26d5e67ab3e1a215573b544b29
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 18:49:51 2007 +0000
-
-    inserting an application inside it as to become more easily testeable
-
-commit cbb6c48df9344176d1b7a7ca913358762758216f
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 17:44:53 2007 +0000
-
-    commenting out the post test, as I am not being able to actually test it.
-
-commit 255b3e5ecfd72b6ee80efd13352ec339bb8544b0
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 15:19:25 2007 +0000
-
-    trying to make the test POST to work
-
-commit 05f68c21b35b7e935a1cbf69841550ef4a941726
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 14:22:14 2007 +0000
-
-    fixing the attribute parsing method. HTTPGet working, POST test failing because the post data is not reaching the destination...
-
-commit ae3039a74cfe706bd3580a36f53a6221fbe7f39d
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Wed Nov 14 12:56:34 2007 +0000
-
-    Implementing a test application
-
-commit 9df23a3e824051f9b53c372c423dd40407af9b23
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Tue Nov 13 18:57:31 2007 +0000
-
-    HTTP Get implementation.
-
-commit fb83167aacbc590632158e8a4469c6d99d635887
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Tue Nov 13 18:04:29 2007 +0000
-
-    Implements minimal response generation
-
-commit 8172902febdd3686d6be6ecbc4daad5a139d383b
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Tue Nov 13 17:10:53 2007 +0000
-
-    XML::DOM doesn't support namespaces, let's move to XML::LibXML instead
-
-commit 4635f7dc730316da5952d3e533e439288508fb21
-Author: Daniel Ruoso <ruoso at pitombeira.(none)>
-Date:   Tue Nov 13 15:17:41 2007 +0000
-
-    initial revision

Copied: Catalyst-Controller-SOAP/1.0/tags/0.9/Changes (from rev 7647, Catalyst-Controller-SOAP/1.0/trunk/Changes)
===================================================================
--- Catalyst-Controller-SOAP/1.0/tags/0.9/Changes	                        (rev 0)
+++ Catalyst-Controller-SOAP/1.0/tags/0.9/Changes	2008-04-30 10:06:29 UTC (rev 7648)
@@ -0,0 +1,212 @@
+------------------------------------------------------------------------
+r7645 | ruoso | 2008-04-30 01:42:45 +0100 (Qua, 30 Abr 2008) | 1 line
+
+[C-C-SOAP] Better support for literal messages
+------------------------------------------------------------------------
+r7629 | drew | 2008-04-23 17:23:21 +0100 (Qua, 23 Abr 2008) | 1 line
+
+Get XML string before parsing so we can see invalid xml
+------------------------------------------------------------------------
+r7628 | drew | 2008-04-23 16:29:40 +0100 (Qua, 23 Abr 2008) | 2 lines
+
+Added logging of incoming and outgoing XML messages.
+
+------------------------------------------------------------------------
+r7619 | ruoso | 2008-04-17 14:02:47 +0100 (Qui, 17 Abr 2008) | 1 line
+
+[C-C-SOAP] Now generates SOAP1.1 fault messages. It was generating SOAP1.2 even in the SOAP1.1 namespace.
+------------------------------------------------------------------------
+r7618 | ruoso | 2008-04-17 12:07:36 +0100 (Qui, 17 Abr 2008) | 1 line
+
+[C-C-SOAP] forces "elements_qualified" on the schema writer.
+------------------------------------------------------------------------
+r7609 | drew | 2008-04-10 11:09:42 +0100 (Qui, 10 Abr 2008) | 2 lines
+
+Added documentation about using Catalyst::Test and WSDL files.
+
+------------------------------------------------------------------------
+r7582 | drew | 2008-04-07 11:56:50 +0100 (Seg, 07 Abr 2008) | 2 lines
+
+Fixed bracing style
+
+------------------------------------------------------------------------
+r7581 | drew | 2008-04-07 11:52:59 +0100 (Seg, 07 Abr 2008) | 3 lines
+
+- Fixed example for xml_compile options
+- Added debug information
+
+------------------------------------------------------------------------
+r7573 | ruoso | 2008-04-06 11:21:21 +0100 (Dom, 06 Abr 2008) | 1 line
+
+[C-C-SOAP] The test failures are from a bad make dist... Will upload again, with a sane make dist now. Increasing version to 0.8
+------------------------------------------------------------------------
+------------------------------------------------------------------------
+r7549 | ruoso | 2008-04-02 16:10:18 +0100 (Qua, 02 Abr 2008) | 1 line
+
+[C-C-SOAP] Tests for Document/Literal-Wrapped working. Supports several wsdls and schemas in the config.
+------------------------------------------------------------------------
+r7548 | ruoso | 2008-04-02 15:54:42 +0100 (Qua, 02 Abr 2008) | 1 line
+
+[C-C-SOAP] Document/Literal-Wrapped support (with a big ONLY FOR COMPATIBILTY REASONS disclaimer)... Test is still failing as the SOAPAction header seems to be lost in the test...
+------------------------------------------------------------------------
+r7546 | ruoso | 2008-04-02 12:23:38 +0100 (Qua, 02 Abr 2008) | 1 line
+
+[C-C-SOAP] Better support for RPC messages, tests including an example of a RPC-Literal service, exception catching generating a SOAP Fault.
+------------------------------------------------------------------------
+r7542 | ruoso | 2008-04-01 18:05:00 +0100 (Ter, 01 Abr 2008) | 1 line
+
+[C-C-S] Now supports WSDL encoding/decoding of messages.
+------------------------------------------------------------------------
+commit 8bea90e61c8aa0cf269da57b9ccbe33987ca76c8
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Mon Nov 26 11:14:25 2007 +0000
+
+    marking new release fixing errors pointed by CPANTESTERS...
+
+commit fd36b65bea45660841790d2716ac330cc506586b
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Mon Nov 26 11:12:34 2007 +0000
+
+    Revert "Revert "PostApp now calls the interpreter with all the directories in @INC. PostApp app no longer depends on any plugin.""
+    
+    This reverts commit 58704caa35fdc5581366007aafd37cc393a94775.
+
+commit 58704caa35fdc5581366007aafd37cc393a94775
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Mon Nov 26 11:11:58 2007 +0000
+
+    Revert "PostApp now calls the interpreter with all the directories in @INC. PostApp app no longer depends on any plugin."
+    
+    This reverts commit 46870ad634f5a8228d7af797117219369dc107db.
+
+commit 46870ad634f5a8228d7af797117219369dc107db
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Mon Nov 26 11:09:35 2007 +0000
+
+    PostApp now calls the interpreter with all the directories in @INC. PostApp app no longer depends on any plugin.
+
+commit 54c6bf1c90e55eb83330ce0fb9f5cd686ac63d11
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Thu Nov 22 18:26:32 2007 +0000
+
+    marking a new release and leaving RPCEncoded out of it.
+
+commit 587c81026d0a8d13d27a124cf9175e0c2d5528d7
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Wed Nov 21 18:34:26 2007 +0000
+
+    removing directory entries from MANIFEST
+
+commit 1931438d732fe7e51942d6bc69b454e5e4dcf97a
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Wed Nov 21 18:33:27 2007 +0000
+
+    Updating changes file
+
+commit 9303bc1e368afb6def74573941eaf459f58533bc
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Wed Nov 21 18:33:13 2007 +0000
+
+    marking a new release
+
+commit 9260e5d96945a4edeb07f8676e12750f0d8d6da4
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Wed Nov 21 18:32:24 2007 +0000
+
+    Make the test more cross-platform
+
+commit 4089cc6ffd0d2cc90feac824aa39ff593d40aeca
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Wed Nov 21 18:23:14 2007 +0000
+
+    Better README and Changes file
+
+commit 865fcd5df2222b9034690fef7f4f6c800c9a75d4
+Author: Daniel Ruoso <daniel at ruoso.com>
+Date:   Wed Nov 21 18:21:23 2007 +0000
+
+    The PostApp app is now used in a test...
+
+commit 16f12fb6cda352faa2e88dacf6e468c3778d3a52
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Sun Nov 18 16:50:54 2007 +0000
+
+    now do not depend on renderview in the test. Also declare the versioned dependency on the Catalyst::Runtime
+
+commit dcdeecc9b1add94f68aa1905957cd9b9ae96c761
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Thu Nov 15 09:59:28 2007 +0000
+
+    marking new release
+
+commit a201321dde6a2575d95b88fbf854caf424ca0ccf
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Thu Nov 15 09:54:21 2007 +0000
+
+    fixing naming of modules in documentation...
+
+commit 7c2b71c1a19a521768c6debf07aaea149549195e
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 19:13:24 2007 +0000
+
+    marking new release
+
+commit e9bd4bbe2c3d3e678b7fc1440b5f72766b3307a6
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 19:12:53 2007 +0000
+
+    rpc endpoint now working
+
+commit 8baa49622fadce26d5e67ab3e1a215573b544b29
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 18:49:51 2007 +0000
+
+    inserting an application inside it as to become more easily testeable
+
+commit cbb6c48df9344176d1b7a7ca913358762758216f
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 17:44:53 2007 +0000
+
+    commenting out the post test, as I am not being able to actually test it.
+
+commit 255b3e5ecfd72b6ee80efd13352ec339bb8544b0
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 15:19:25 2007 +0000
+
+    trying to make the test POST to work
+
+commit 05f68c21b35b7e935a1cbf69841550ef4a941726
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 14:22:14 2007 +0000
+
+    fixing the attribute parsing method. HTTPGet working, POST test failing because the post data is not reaching the destination...
+
+commit ae3039a74cfe706bd3580a36f53a6221fbe7f39d
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Wed Nov 14 12:56:34 2007 +0000
+
+    Implementing a test application
+
+commit 9df23a3e824051f9b53c372c423dd40407af9b23
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Tue Nov 13 18:57:31 2007 +0000
+
+    HTTP Get implementation.
+
+commit fb83167aacbc590632158e8a4469c6d99d635887
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Tue Nov 13 18:04:29 2007 +0000
+
+    Implements minimal response generation
+
+commit 8172902febdd3686d6be6ecbc4daad5a139d383b
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Tue Nov 13 17:10:53 2007 +0000
+
+    XML::DOM doesn't support namespaces, let's move to XML::LibXML instead
+
+commit 4635f7dc730316da5952d3e533e439288508fb21
+Author: Daniel Ruoso <ruoso at pitombeira.(none)>
+Date:   Tue Nov 13 15:17:41 2007 +0000
+
+    initial revision

Deleted: Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm
===================================================================
--- Catalyst-Controller-SOAP/1.0/trunk/lib/Catalyst/Controller/SOAP.pm	2008-04-30 00:44:32 UTC (rev 7646)
+++ Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm	2008-04-30 10:06:29 UTC (rev 7648)
@@ -1,599 +0,0 @@
-{   package Catalyst::Controller::SOAP;
-
-    use strict;
-    use base qw/Catalyst::Controller/;
-    use XML::LibXML;
-    use XML::Compile::WSDL11;
-    use UNIVERSAL qw(isa);
-
-    use constant NS_SOAP_ENV => "http://schemas.xmlsoap.org/soap/envelope/";
-    use constant NS_WSDLSOAP => "http://schemas.xmlsoap.org/wsdl/soap/";
-
-    our $VERSION = '0.8';
-
-    __PACKAGE__->mk_accessors qw(wsdl wsdlobj decoders encoders
-         ports wsdlservice xml_compile soap_action_prefix rpc_endpoint_paths);
-
-    # XXX - This is here as a temporary fix for a bug in _parse_attrs
-    # that makes it impossible to return more than one
-    # "final_attribute", a patch was already submitted and should make
-    # into the next release.
-    sub _parse_attrs {
-        my ( $self, $c, $name, @attrs ) = @_;
-
-        my @others = grep { $_ !~ /^WSDLPort/ } @attrs;
-        my $final = $self->SUPER::_parse_attrs($c, $name, @others);
-
-        my ($attr) = grep { $_ && $_ =~ /^WSDLPort/ } @attrs;
-        return $final unless $attr;
-
-        if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/ ) )
-        {
-            if ( defined $value ) {
-                ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
-            }
-            my %ret = $self->_parse_WSDLPort_attr($c, $name, $value);
-            push( @{ $final->{$_} }, $ret{$_} ) for
-              keys %ret;
-        }
-
-
-        return $final;
-    }
-
-
-    sub __init_wsdlobj {
-        my ($self, $c) = @_;
-
-        my $wsdlfile = $self->wsdl;
-
-        if ($wsdlfile) {
-            if (!$self->wsdlobj) {
-                my $schema;
-                if (ref $wsdlfile eq 'HASH') {
-                    $schema = $wsdlfile->{schema};
-                    $wsdlfile = $wsdlfile->{wsdl};
-                }
-
-                if (ref $wsdlfile eq 'ARRAY') {
-                    my $main = shift @{$wsdlfile};
-                    $c->log->debug("WSDL: adding main WSDL $main");
-                    $self->wsdlobj(XML::Compile::WSDL11->new($main));
-                    foreach my $file (@{$wsdlfile}) {
-                        $c->log->debug("WSDL: adding additional WSDL $file");
-                        $self->wsdlobj->addWSDL($file);
-                    }
-                } else {
-                    $c->log->debug("WSDL: adding WSDL $wsdlfile");
-                    $self->wsdlobj(XML::Compile::WSDL11->new($wsdlfile));
-                }
-
-                if (ref $schema eq 'ARRAY') {
-                    foreach my $file (@$schema) {
-                        $c->log->debug("WSDL: Import schema $file");
-                        $self->wsdlobj->importDefinitions($file);
-                    }
-                } elsif ($schema) {
-                    $c->log->debug("WSDL: Import schema $schema");
-                    $self->wsdlobj->importDefinitions($schema)
-                }
-            }
-        }
-
-        return $self->wsdlobj ? 1 : 0;
-    }
-
-    sub _parse_WSDLPort_attr {
-        my ($self, $c, $name, $value) = @_;
-
-        die 'Cannot use WSDLPort without WSDL.'
-          unless $self->__init_wsdlobj($c);
-
-        $self->ports({}) unless $self->ports();
-        $self->ports->{$name} = $value;
-        my $operation = $self->wsdlobj->operation($name,
-                                                  port => $value,
-                                                  service => $self->wsdlservice)
-          or die 'Every operation should be on the WSDL when using one.';
-
-        # TODO: Use more intelligence when selecting the address.
-        my ($path) = $operation->endPointAddresses();
-
-        $path =~ s#^[^:]+://[^/]+##;
-
-        # Finding out the style and input body use for this operation
-        my $binding = $self->wsdlobj->find(binding => $operation->port->{binding});
-        my $style = $binding->{'{'.NS_WSDLSOAP.'}binding'}[0]->getAttribute('style');
-        my ($use) = map { $_->{input}{'{'.NS_WSDLSOAP.'}body'}[0]->getAttribute('use') }
-          grep { $_->{name} eq $name } @{ $binding->{operation} || [] };
-
-        $style = $style =~ /document/i ? 'Document' : 'RPC';
-        $use = $use =~ /literal/i ? 'Literal' : 'Encoded';
-        $c->log->debug("WSDLPort: [$name] [$value] [$path] [$style] [$use]");
-
-        if ($style eq 'Document') {
-            return
-              (
-               Path => $path,
-               $self->_parse_SOAP_attr($c, $name, $style.$use)
-              );
-        } else {
-            $self->rpc_endpoint_paths([]) unless $self->rpc_endpoint_paths;
-            $path =~ s/\/$//;
-            push @{$self->rpc_endpoint_paths}, $path
-              unless grep { $_ eq $path }
-                @{$self->rpc_endpoint_paths};
-            return $self->_parse_SOAP_attr($c, $name, $style.$use)
-        }
-    }
-
-    # Let's create the rpc_endpoint action.
-    sub register_actions {
-        my $self = shift;
-        my ($c) = @_;
-        $self->SUPER::register_actions(@_);
-
-        if ($self->rpc_endpoint_paths) {
-            my $namespace = $self->action_namespace($c);
-            my $action = $self->create_action
-              (
-               name => '___base_rpc_endpoint',
-               code => sub { },
-               reverse => ($namespace ? $namespace.'/' : '') . '___base_rpc_endpoint',
-               namespace => $namespace,
-               class => (ref $self || $self),
-               attributes => { ActionClass => [ 'Catalyst::Action::SOAP::RPCEndpoint' ],
-                               Path => $self->rpc_endpoint_paths }
-              );
-            $c->dispatcher->register($c, $action);
-        }
-    }
-
-    sub _parse_SOAP_attr {
-        my ($self, $c, $name, $value) = @_;
-
-        my $wsdlfile     = $self->wsdl;
-        my $wsdlservice  = $self->wsdlservice;
-        my $compile_opts = $self->xml_compile || {};
-        my $reader_opts  = $compile_opts->{reader} || {};
-        my $writer_opts  = $compile_opts->{writer} || {};
-
-        if ($wsdlfile) {
-
-            die 'WSDL initialization failed.'
-              unless $self->__init_wsdlobj($c);
-
-            $self->ports({}) unless $self->ports();
-            my $operation = $self->wsdlobj->operation($name,
-                                                      port => $self->ports->{$name},
-                                                      service => $wsdlservice)
-              or die 'Every operation should be on the WSDL when using one.';
-            my $portop = $operation->portOperation();
-            $c->log->debug("SOAP: @{[$operation->name]} $portop->{input}{message} $portop->{output}{message}");
-
-            my $input_parts = $self->wsdlobj->find(message => $portop->{input}{message})
-              ->{part};
-            for (@{$input_parts}) {
-                my $type = $_->{type} ? $_->{type} : $_->{element};
-                $c->log->debug("SOAP: @{[$operation->name]} input part $_->{name}, type $type");
-                $_->{compiled_reader} = $self->wsdlobj->schemas->compile
-                  (READER => $type,
-                   %$reader_opts);
-            };
-
-            $self->decoders({}) unless $self->decoders();
-            $self->decoders->{$name} = sub {
-                my $body = shift;
-                my @nodes = grep { UNIVERSAL::isa($_, 'XML::LibXML::Element') } $body->childNodes();
-                return
-                  {
-                   map {
-                       my $data = $_->{compiled_reader}->(shift @nodes);
-                       $_->{name} => $data;
-                   } @{$input_parts}
-                  }, @nodes;
-            };
-
-            my $output_parts = $self->wsdlobj->find(message => $portop->{output}{message})
-              ->{part};
-            for (@{$output_parts}) {
-                my $type = $_->{type} ? $_->{type} : $_->{element};
-                $c->log->debug("SOAP: @{[$operation->name]} out part $_->{name}, type $type");
-                $_->{compiled_writer} = $self->wsdlobj->schemas->compile
-                  (WRITER => $_->{type} ? $_->{type} : $_->{element},
-                   elements_qualified => 'ALL',
-                   %$writer_opts);
-            }
-
-            $self->encoders({}) unless $self->encoders();
-            $self->encoders->{$name} = sub {
-                my ($doc, $data) = @_;
-                return
-                  [
-                   map {
-                       $_->{compiled_writer}->($doc, $data->{$_->{name}})
-                   } @{$output_parts}
-                  ];
-            };
-        }
-
-        my $actionclass = ($value =~ /^\+/ ? $value :
-          'Catalyst::Action::SOAP::'.$value);
-        (
-         ActionClass => $actionclass,
-        )
-    }
-
-    # this is implemented as to respond a SOAP message according to
-    # what has been sent to $c->stash->{soap}
-    sub end : Private {
-        my ($self, $c) = (shift, shift);
-        my $soap = $c->stash->{soap};
-
-        return $self->NEXT::end($c, @_) unless $soap;
-
-        if (scalar @{$c->error}) {
-            $c->stash->{soap}->fault
-              ({ code => 'Client',
-                 reason => 'Unexpected Error', detail =>
-                 'Unexpected error in the application: '.(join "\n", @{$c->error} ).'!'});
-            $c->error(0);
-        }
-
-        my $namespace = $soap->namespace || NS_SOAP_ENV;
-        my $response = XML::LibXML->createDocument('1.0','UTF8');
-
-        my $envelope = $response->createElementNS
-          ($namespace,"SOAPENV:Envelope");
-
-        $response->setDocumentElement($envelope);
-
-        # TODO: we don't support header generation in response yet.
-
-        my $body = $response->createElementNS
-          ($namespace,"SOAPENV:Body");
-
-        $envelope->appendChild($body);
-
-        if ($soap->fault) {
-            my $fault = $response->createElementNS
-              ($namespace, "SOAPENV:Fault");
-            $body->appendChild($fault);
-
-            my $code = $response->createElementNS
-              ($namespace, "SOAPENV:faultcode");
-            $fault->appendChild($code);
-            my $codestr = $soap->fault->{code};
-            if (my ($ns, $val) = $codestr =~ m/^\{(.+)\}(.+)$/) {
-                my $prefix = $code->lookupNamespacePrefix($ns);
-                if ($prefix) {
-                    $code->appendText($prefix.':'.$val);
-                } else {
-                    $code->appendText($val);
-                }
-            } else {
-                $code->appendText('SOAPENV:'.$codestr);
-            }
-
-            my $faultstring = $response->createElementNS
-              ($namespace, "SOAPENV:faultstring");
-            $fault->appendChild($faultstring);
-            $faultstring->appendText($soap->fault->{reason});
-
-            if (UNIVERSAL::isa($soap->fault->{detail}, 'XML::LibXML::Node')) {
-                my $detail = $response->createElementNS
-                  ($namespace, "SOAPENV:detail");
-                $detail->appendChild($soap->fault->{detail});
-                $fault->appendChild($detail);
-            } elsif ($soap->fault->{detail}) {
-                my $detail = $response->createElementNS
-                  ($namespace, "SOAPENV:detail");
-                $fault->appendChild($detail);
-                # TODO: we don't support the xml:lang attribute yet.
-                my $text = $response->createElementNS
-                  ('http://www.w3.org/2001/XMLSchema','xsd:documentation');
-                $detail->appendChild($text);
-                $text->appendText($soap->fault->{detail});
-            }
-        } else {
-            if ($soap->string_return) {
-                $body->appendText($soap->string_return);
-            } elsif (my $lit = $soap->literal_return) {
-                if (ref $lit eq 'XML::LibXML::NodeList') {
-                    for ($lit->get_nodelist) {
-                        $body->appendChild($_);
-                    }
-                } else {
-                    $body->appendChild($lit);
-                }
-            } elsif (my $cmp = $soap->compile_return) {
-                die 'Tried to use compile_return without WSDL'
-                  unless $self->wsdlobj;
-
-                my $arr = $self->encoders->{$soap->operation_name}->($response, $cmp);
-                $body->appendChild($_) for @$arr;
-            }
-        }
-
-        $c->log->debug("Outgoing XML: ".$envelope->toString());
-        $c->res->content_type('text/xml');
-        $c->res->body($envelope->toString());
-    }
-
-
-};
-
-{   package Catalyst::Controller::SOAP::Helper;
-
-    use base qw(Class::Accessor::Fast);
-
-    __PACKAGE__->mk_accessors(qw{envelope parsed_envelope arguments fault namespace
-                                 encoded_return literal_return string_return
-                                 compile_return operation_name});
-
-
-};
-
-
-1;
-
-__END__
-
-=head1 NAME
-
-Catalyst::Controller::SOAP - Catalyst SOAP Controller
-
-=head1 SYNOPSIS
-
-    package MyApp::Controller::Example;
-    use base 'Catalyst::Controller::SOAP';
-
-    # When using a WSDL, you can just specify the Port name, and it
-    # will infer the style and use. To do that, you just need to use
-    # the WSDLPort attribute. This might be required if your service
-    # has more than one port.  This operation will be made available
-    # using the path part of the location attribute of the port
-    # definition.
-    __PACKAGE__->config->{wsdl} = 'file.wsdl';
-    sub servicefoo : WSDLPort('ServicePort') {}
-
-    # available in "/example" as operation "ping". The arguments are
-    # treated as a literal document and passed to the method as a
-    # XML::LibXML object
-    # Using XML::Compile here will help you reading the message.
-    sub ping : SOAP('RPCLiteral') {
-        my ( $self, $c, $xml) = @_;
-        my $name = $xml->findValue('some xpath expression');
-    }
-
-    # avaiable as "/example/world" in document context. The entire body
-    # is delivered to the method as a XML::LibXML object.
-    # Using XML::Compile here will help you reading the message.
-    sub world :Local SOAP('DocumentLiteral')  {
-        my ($self, $c, $xml) = @_;
-    }
-
-    # avaiable as "/example/get" in HTTP get context.
-    # the get attributes will be available as any other
-    # get operation in Catalyst.
-    sub get :Local SOAP('HTTPGet')  {
-        my ($self, $c) = @_;
-    }
-
-    # this is the endpoint from where the RPC operations will be
-    # dispatched. This code won't be executed at all.
-    # See Catalyst::Controller::SOAP::RPC.
-    sub index :Local SOAP('RPCEndpoint') {}
-
-
-=head1 ABSTACT
-
-Implements SOAP serving support in Catalyst.
-
-=head1 DESCRIPTION
-
-SOAP Controller for Catalyst which we tried to make compatible with
-the way Catalyst works with URLS.It is important to notice that this
-controller declares by default an index operation which will dispatch
-the RPC operations under this class.
-
-=head1 ATTRIBUTES
-
-This class implements the SOAP attribute wich is used to do the
-mapping of that operation to the apropriate action class. The name of
-the class used is formed as Catalyst::Action::SOAP::$value, unless the
-parameter of the attribute starts with a '+', which implies complete
-namespace.
-
-The implementation of SOAP Action classes helps delivering specific
-SOAP scenarios, like HTTP GET, RPC Encoded, RPC Literal or Document
-Literal, or even Document RDF or just about any required combination.
-
-See L<Catalyst::Action::SOAP::DocumentLiteral> for an example.
-
-=head1 ACCESSORS
-
-Once you tagged one of the methods, you'll have an $c->stash->{soap}
-accessor which will return an C<Catalyst::Controller::SOAP::Helper>
-object. It's important to notice that this is achieved by the fact
-that all the SOAP Action classes are subclasses of
-Catalyst::Action::SOAP, which implements most of that.
-
-You can query this object as follows:
-
-=over 4
-
-=item $c->stash->{soap}->envelope()
-
-The original SOAP envelope as string.
-
-=item $c->stash->{soap}->parsed_envelope()
-
-The parsed envelope as an XML::LibXML object.
-
-=item $c->stash->{soap}->arguments()
-
-The arguments of a RPC call.
-
-=item $c->stash->{soap}->fault({code => $code,reason => $reason, detail => $detail])
-
-Allows you to set fault code and message. Optionally, you may define
-the code itself as an arrayref where the first item will be this code
-and the second will be the subcode, which recursively may be another
-arrayref.
-
-=item $c->stash->{soap}->encoded_return(\@data)
-
-This method will prepare the return value to be a soap encoded data.
-
-  # TODO: At this moment, only Literals are working...
-
-=item $c->stash->{soap}->literal_return($xml_node)
-
-This method will prepare the return value to be a literal XML
-document, in this case, you can pass just the node that will be the
-root in the return message or a nodelist.
-
-Using XML::Compile will help to elaborate schema based returns.
-
-=item $c->stash->{soap}->string_return($non_xml_text)
-
-In this case, the given text is encoded as CDATA inside the SOAP
-message.
-
-=back
-
-=head1 USING WSDL
-
-If you define the "wsdl" configuration key, Catalyst::Controller::SOAP
-will automatically map your operations into the WSDL operations, in
-which case you will receive the parsed Perl structure as returned by
-XML::Compile according to the type defined in the WSDL message.
-
-You can define additional wsdl files or even additional schema
-files. If $wsdl is an arrayref, the first element is the one passed to
-new, and the others will be the argument to subsequent addWsdl calls.
-If $wsdl is a hashref, the "wsdl" key will be handled like above and
-the "schema" key will be used to importDefinitions. If the content of
-the schema key is an arrayref, it will result in several calls to
-importDefinition.
-
-When using WSDL, you can use the WSDLPort attribute, that not only
-sets the port name but also infer which is the style of the binding,
-the use of the input body and also declares the Path for the operation
-according to the 'location' attribute in the WSDL file. For RPC
-operations, the endpoint action will be created dinamically also in
-the path defined by the WSDL file.
-
-This is the most convenient way of defining a SOAP service, which, in
-the end, will require you to have it as simple as:
-
-  package SOAPApp::Controller::WithWSDL;
-  use base 'Catalyst::Controller::SOAP';
-  __PACKAGE__->config->{wsdl} = 't/hello4.wsdl';
-  
-  # in this case, the input has two parts, named 'who' and 'greeting'
-  # and the output has a single 'greeting' part.
-  sub Greet : WSDLPort('Greet') {
-    my ( $self, $c, $args ) = @_;
-    my $who = $args->{who};
-    my $grt = $args->{greeting};
-    $c->stash->{soap}->compile_return({ greeting => $grt.' '.$who.'!' });
-  }
-
-When using WSDL with more than one port, the use of this attribute is
-mandatory.
-
-When the WSDL describes more than one service, the controller can only
-represent one of them, so you must define the 'wsdlservice' config key
-that will be used to select the service.
-
-Also, when using wsdl, you can define the response using:
-
-  $c->stash->{soap}->compile_return($perl_structure)
-
-In this case, the given structure will be transformed by XML::Compile,
-according to what's described in the WSDL file.
-
-If you define "xml_compile" as a configuration key (which is a 
-hashref with keys 'reader' and 'writer', which both have a hashref
-as their value), those key / value pairs will be passed as options
-to the XML::Compile::Schema::compile() method.
-
-  __PACKAGE__->config->{xml_compile} = {
-      reader => {sloppy_integers => 1}, writer => {sloppy_integers => 1},
-  };
-
-=head1 USING WSDL AND Catalyst::Test
-
-If you'd like to use the built-in server from Catalyst::Test with your
-WSDL file (which likely defines an <address location="..."> that differs
-from the standard test server) you'll need to use the transport_hook
-option available with $wsdl->compileClient() in your test file.
-
-
-    # t/soap_message.t
-    use XML::Compile::WSDL11;
-    use XML::Compile::Transport::SOAPHTTP;
-    use Test::More qw(no_plan);
-
-    BEGIN {
-        use_ok 'Catalyst::Test', 'MyServer';
-    }
-
-    sub proxy_to_test_app
-    {
-        my ($request, $trace) = @_;
-        # request() is a function inserted by Catalyst::Test which
-        # sends HTTP requests to the just-started test server.
-        return request($request);
-    }
-
-    my $xml       = '/path/to/wsdl/file';
-    my $message   = 'YourMessage';
-    my $port_name = 'YourPort';
-    my $wsdl      = XML::Compile::WSDL11->new($xml);
-    my $client    = $wsdl->compileClient($message, 
-        port => $port_name, transport_hook => \&proxy_to_test_app,
-    );
-    $client->(...);
-
-
-=head1 TODO
-
-No header features are implemented yet.
-
-The SOAP Encoding support is also missing, when that is ready you'll
-be able to do something like the code below:
-
-    # available in "/example" as operation "echo"
-    # parsing the arguments as soap-encoded.
-    sub echo : SOAP('RPCEncoded') {
-        my ( $self, $c, @args ) = @_;
-    }
-
-=head1 SEE ALSO
-
-L<Catalyst::Action::SOAP>, L<XML::LibXML>, L<XML::Compile>
-L<Catalyst::Action::SOAP::DocumentLiteral>,
-L<Catalyst::Action::SOAP::RPCLiteral>,
-L<Catalyst::Action::SOAP::HTTPGet>, L<XML::Compile::WSDL11>,
-L<XML::Compile::Schema>
-
-=head1 AUTHORS
-
-Daniel Ruoso C<daniel.ruoso at verticalone.pt>
-
-Drew Taylor C<drew at drewtaylor.com>
-
-=head1 BUG REPORTS
-
-Please submit all bugs regarding C<Catalyst::Controller::SOAP> to
-C<bug-catalyst-controller-soap at rt.cpan.org>
-
-=head1 LICENSE
-
-This library is free software, you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut

Copied: Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm (from rev 7647, Catalyst-Controller-SOAP/1.0/trunk/lib/Catalyst/Controller/SOAP.pm)
===================================================================
--- Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm	                        (rev 0)
+++ Catalyst-Controller-SOAP/1.0/tags/0.9/lib/Catalyst/Controller/SOAP.pm	2008-04-30 10:06:29 UTC (rev 7648)
@@ -0,0 +1,599 @@
+{   package Catalyst::Controller::SOAP;
+
+    use strict;
+    use base qw/Catalyst::Controller/;
+    use XML::LibXML;
+    use XML::Compile::WSDL11;
+    use UNIVERSAL qw(isa);
+
+    use constant NS_SOAP_ENV => "http://schemas.xmlsoap.org/soap/envelope/";
+    use constant NS_WSDLSOAP => "http://schemas.xmlsoap.org/wsdl/soap/";
+
+    our $VERSION = '0.9';
+
+    __PACKAGE__->mk_accessors qw(wsdl wsdlobj decoders encoders
+         ports wsdlservice xml_compile soap_action_prefix rpc_endpoint_paths);
+
+    # XXX - This is here as a temporary fix for a bug in _parse_attrs
+    # that makes it impossible to return more than one
+    # "final_attribute", a patch was already submitted and should make
+    # into the next release.
+    sub _parse_attrs {
+        my ( $self, $c, $name, @attrs ) = @_;
+
+        my @others = grep { $_ !~ /^WSDLPort/ } @attrs;
+        my $final = $self->SUPER::_parse_attrs($c, $name, @others);
+
+        my ($attr) = grep { $_ && $_ =~ /^WSDLPort/ } @attrs;
+        return $final unless $attr;
+
+        if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/ ) )
+        {
+            if ( defined $value ) {
+                ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
+            }
+            my %ret = $self->_parse_WSDLPort_attr($c, $name, $value);
+            push( @{ $final->{$_} }, $ret{$_} ) for
+              keys %ret;
+        }
+
+
+        return $final;
+    }
+
+
+    sub __init_wsdlobj {
+        my ($self, $c) = @_;
+
+        my $wsdlfile = $self->wsdl;
+
+        if ($wsdlfile) {
+            if (!$self->wsdlobj) {
+                my $schema;
+                if (ref $wsdlfile eq 'HASH') {
+                    $schema = $wsdlfile->{schema};
+                    $wsdlfile = $wsdlfile->{wsdl};
+                }
+
+                if (ref $wsdlfile eq 'ARRAY') {
+                    my $main = shift @{$wsdlfile};
+                    $c->log->debug("WSDL: adding main WSDL $main");
+                    $self->wsdlobj(XML::Compile::WSDL11->new($main));
+                    foreach my $file (@{$wsdlfile}) {
+                        $c->log->debug("WSDL: adding additional WSDL $file");
+                        $self->wsdlobj->addWSDL($file);
+                    }
+                } else {
+                    $c->log->debug("WSDL: adding WSDL $wsdlfile");
+                    $self->wsdlobj(XML::Compile::WSDL11->new($wsdlfile));
+                }
+
+                if (ref $schema eq 'ARRAY') {
+                    foreach my $file (@$schema) {
+                        $c->log->debug("WSDL: Import schema $file");
+                        $self->wsdlobj->importDefinitions($file);
+                    }
+                } elsif ($schema) {
+                    $c->log->debug("WSDL: Import schema $schema");
+                    $self->wsdlobj->importDefinitions($schema)
+                }
+            }
+        }
+
+        return $self->wsdlobj ? 1 : 0;
+    }
+
+    sub _parse_WSDLPort_attr {
+        my ($self, $c, $name, $value) = @_;
+
+        die 'Cannot use WSDLPort without WSDL.'
+          unless $self->__init_wsdlobj($c);
+
+        $self->ports({}) unless $self->ports();
+        $self->ports->{$name} = $value;
+        my $operation = $self->wsdlobj->operation($name,
+                                                  port => $value,
+                                                  service => $self->wsdlservice)
+          or die 'Every operation should be on the WSDL when using one.';
+
+        # TODO: Use more intelligence when selecting the address.
+        my ($path) = $operation->endPointAddresses();
+
+        $path =~ s#^[^:]+://[^/]+##;
+
+        # Finding out the style and input body use for this operation
+        my $binding = $self->wsdlobj->find(binding => $operation->port->{binding});
+        my $style = $binding->{'{'.NS_WSDLSOAP.'}binding'}[0]->getAttribute('style');
+        my ($use) = map { $_->{input}{'{'.NS_WSDLSOAP.'}body'}[0]->getAttribute('use') }
+          grep { $_->{name} eq $name } @{ $binding->{operation} || [] };
+
+        $style = $style =~ /document/i ? 'Document' : 'RPC';
+        $use = $use =~ /literal/i ? 'Literal' : 'Encoded';
+        $c->log->debug("WSDLPort: [$name] [$value] [$path] [$style] [$use]");
+
+        if ($style eq 'Document') {
+            return
+              (
+               Path => $path,
+               $self->_parse_SOAP_attr($c, $name, $style.$use)
+              );
+        } else {
+            $self->rpc_endpoint_paths([]) unless $self->rpc_endpoint_paths;
+            $path =~ s/\/$//;
+            push @{$self->rpc_endpoint_paths}, $path
+              unless grep { $_ eq $path }
+                @{$self->rpc_endpoint_paths};
+            return $self->_parse_SOAP_attr($c, $name, $style.$use)
+        }
+    }
+
+    # Let's create the rpc_endpoint action.
+    sub register_actions {
+        my $self = shift;
+        my ($c) = @_;
+        $self->SUPER::register_actions(@_);
+
+        if ($self->rpc_endpoint_paths) {
+            my $namespace = $self->action_namespace($c);
+            my $action = $self->create_action
+              (
+               name => '___base_rpc_endpoint',
+               code => sub { },
+               reverse => ($namespace ? $namespace.'/' : '') . '___base_rpc_endpoint',
+               namespace => $namespace,
+               class => (ref $self || $self),
+               attributes => { ActionClass => [ 'Catalyst::Action::SOAP::RPCEndpoint' ],
+                               Path => $self->rpc_endpoint_paths }
+              );
+            $c->dispatcher->register($c, $action);
+        }
+    }
+
+    sub _parse_SOAP_attr {
+        my ($self, $c, $name, $value) = @_;
+
+        my $wsdlfile     = $self->wsdl;
+        my $wsdlservice  = $self->wsdlservice;
+        my $compile_opts = $self->xml_compile || {};
+        my $reader_opts  = $compile_opts->{reader} || {};
+        my $writer_opts  = $compile_opts->{writer} || {};
+
+        if ($wsdlfile) {
+
+            die 'WSDL initialization failed.'
+              unless $self->__init_wsdlobj($c);
+
+            $self->ports({}) unless $self->ports();
+            my $operation = $self->wsdlobj->operation($name,
+                                                      port => $self->ports->{$name},
+                                                      service => $wsdlservice)
+              or die 'Every operation should be on the WSDL when using one.';
+            my $portop = $operation->portOperation();
+            $c->log->debug("SOAP: @{[$operation->name]} $portop->{input}{message} $portop->{output}{message}");
+
+            my $input_parts = $self->wsdlobj->find(message => $portop->{input}{message})
+              ->{part};
+            for (@{$input_parts}) {
+                my $type = $_->{type} ? $_->{type} : $_->{element};
+                $c->log->debug("SOAP: @{[$operation->name]} input part $_->{name}, type $type");
+                $_->{compiled_reader} = $self->wsdlobj->schemas->compile
+                  (READER => $type,
+                   %$reader_opts);
+            };
+
+            $self->decoders({}) unless $self->decoders();
+            $self->decoders->{$name} = sub {
+                my $body = shift;
+                my @nodes = grep { UNIVERSAL::isa($_, 'XML::LibXML::Element') } $body->childNodes();
+                return
+                  {
+                   map {
+                       my $data = $_->{compiled_reader}->(shift @nodes);
+                       $_->{name} => $data;
+                   } @{$input_parts}
+                  }, @nodes;
+            };
+
+            my $output_parts = $self->wsdlobj->find(message => $portop->{output}{message})
+              ->{part};
+            for (@{$output_parts}) {
+                my $type = $_->{type} ? $_->{type} : $_->{element};
+                $c->log->debug("SOAP: @{[$operation->name]} out part $_->{name}, type $type");
+                $_->{compiled_writer} = $self->wsdlobj->schemas->compile
+                  (WRITER => $_->{type} ? $_->{type} : $_->{element},
+                   elements_qualified => 'ALL',
+                   %$writer_opts);
+            }
+
+            $self->encoders({}) unless $self->encoders();
+            $self->encoders->{$name} = sub {
+                my ($doc, $data) = @_;
+                return
+                  [
+                   map {
+                       $_->{compiled_writer}->($doc, $data->{$_->{name}})
+                   } @{$output_parts}
+                  ];
+            };
+        }
+
+        my $actionclass = ($value =~ /^\+/ ? $value :
+          'Catalyst::Action::SOAP::'.$value);
+        (
+         ActionClass => $actionclass,
+        )
+    }
+
+    # this is implemented as to respond a SOAP message according to
+    # what has been sent to $c->stash->{soap}
+    sub end : Private {
+        my ($self, $c) = (shift, shift);
+        my $soap = $c->stash->{soap};
+
+        return $self->NEXT::end($c, @_) unless $soap;
+
+        if (scalar @{$c->error}) {
+            $c->stash->{soap}->fault
+              ({ code => 'Client',
+                 reason => 'Unexpected Error', detail =>
+                 'Unexpected error in the application: '.(join "\n", @{$c->error} ).'!'});
+            $c->error(0);
+        }
+
+        my $namespace = $soap->namespace || NS_SOAP_ENV;
+        my $response = XML::LibXML->createDocument('1.0','UTF8');
+
+        my $envelope = $response->createElementNS
+          ($namespace,"SOAPENV:Envelope");
+
+        $response->setDocumentElement($envelope);
+
+        # TODO: we don't support header generation in response yet.
+
+        my $body = $response->createElementNS
+          ($namespace,"SOAPENV:Body");
+
+        $envelope->appendChild($body);
+
+        if ($soap->fault) {
+            my $fault = $response->createElementNS
+              ($namespace, "SOAPENV:Fault");
+            $body->appendChild($fault);
+
+            my $code = $response->createElementNS
+              ($namespace, "SOAPENV:faultcode");
+            $fault->appendChild($code);
+            my $codestr = $soap->fault->{code};
+            if (my ($ns, $val) = $codestr =~ m/^\{(.+)\}(.+)$/) {
+                my $prefix = $code->lookupNamespacePrefix($ns);
+                if ($prefix) {
+                    $code->appendText($prefix.':'.$val);
+                } else {
+                    $code->appendText($val);
+                }
+            } else {
+                $code->appendText('SOAPENV:'.$codestr);
+            }
+
+            my $faultstring = $response->createElementNS
+              ($namespace, "SOAPENV:faultstring");
+            $fault->appendChild($faultstring);
+            $faultstring->appendText($soap->fault->{reason});
+
+            if (UNIVERSAL::isa($soap->fault->{detail}, 'XML::LibXML::Node')) {
+                my $detail = $response->createElementNS
+                  ($namespace, "SOAPENV:detail");
+                $detail->appendChild($soap->fault->{detail});
+                $fault->appendChild($detail);
+            } elsif ($soap->fault->{detail}) {
+                my $detail = $response->createElementNS
+                  ($namespace, "SOAPENV:detail");
+                $fault->appendChild($detail);
+                # TODO: we don't support the xml:lang attribute yet.
+                my $text = $response->createElementNS
+                  ('http://www.w3.org/2001/XMLSchema','xsd:documentation');
+                $detail->appendChild($text);
+                $text->appendText($soap->fault->{detail});
+            }
+        } else {
+            if ($soap->string_return) {
+                $body->appendText($soap->string_return);
+            } elsif (my $lit = $soap->literal_return) {
+                if (ref $lit eq 'XML::LibXML::NodeList') {
+                    for ($lit->get_nodelist) {
+                        $body->appendChild($_);
+                    }
+                } else {
+                    $body->appendChild($lit);
+                }
+            } elsif (my $cmp = $soap->compile_return) {
+                die 'Tried to use compile_return without WSDL'
+                  unless $self->wsdlobj;
+
+                my $arr = $self->encoders->{$soap->operation_name}->($response, $cmp);
+                $body->appendChild($_) for @$arr;
+            }
+        }
+
+        $c->log->debug("Outgoing XML: ".$envelope->toString());
+        $c->res->content_type('text/xml');
+        $c->res->body($envelope->toString());
+    }
+
+
+};
+
+{   package Catalyst::Controller::SOAP::Helper;
+
+    use base qw(Class::Accessor::Fast);
+
+    __PACKAGE__->mk_accessors(qw{envelope parsed_envelope arguments fault namespace
+                                 encoded_return literal_return string_return
+                                 compile_return operation_name});
+
+
+};
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+Catalyst::Controller::SOAP - Catalyst SOAP Controller
+
+=head1 SYNOPSIS
+
+    package MyApp::Controller::Example;
+    use base 'Catalyst::Controller::SOAP';
+
+    # When using a WSDL, you can just specify the Port name, and it
+    # will infer the style and use. To do that, you just need to use
+    # the WSDLPort attribute. This might be required if your service
+    # has more than one port.  This operation will be made available
+    # using the path part of the location attribute of the port
+    # definition.
+    __PACKAGE__->config->{wsdl} = 'file.wsdl';
+    sub servicefoo : WSDLPort('ServicePort') {}
+
+    # available in "/example" as operation "ping". The arguments are
+    # treated as a literal document and passed to the method as a
+    # XML::LibXML object
+    # Using XML::Compile here will help you reading the message.
+    sub ping : SOAP('RPCLiteral') {
+        my ( $self, $c, $xml) = @_;
+        my $name = $xml->findValue('some xpath expression');
+    }
+
+    # avaiable as "/example/world" in document context. The entire body
+    # is delivered to the method as a XML::LibXML object.
+    # Using XML::Compile here will help you reading the message.
+    sub world :Local SOAP('DocumentLiteral')  {
+        my ($self, $c, $xml) = @_;
+    }
+
+    # avaiable as "/example/get" in HTTP get context.
+    # the get attributes will be available as any other
+    # get operation in Catalyst.
+    sub get :Local SOAP('HTTPGet')  {
+        my ($self, $c) = @_;
+    }
+
+    # this is the endpoint from where the RPC operations will be
+    # dispatched. This code won't be executed at all.
+    # See Catalyst::Controller::SOAP::RPC.
+    sub index :Local SOAP('RPCEndpoint') {}
+
+
+=head1 ABSTACT
+
+Implements SOAP serving support in Catalyst.
+
+=head1 DESCRIPTION
+
+SOAP Controller for Catalyst which we tried to make compatible with
+the way Catalyst works with URLS.It is important to notice that this
+controller declares by default an index operation which will dispatch
+the RPC operations under this class.
+
+=head1 ATTRIBUTES
+
+This class implements the SOAP attribute wich is used to do the
+mapping of that operation to the apropriate action class. The name of
+the class used is formed as Catalyst::Action::SOAP::$value, unless the
+parameter of the attribute starts with a '+', which implies complete
+namespace.
+
+The implementation of SOAP Action classes helps delivering specific
+SOAP scenarios, like HTTP GET, RPC Encoded, RPC Literal or Document
+Literal, or even Document RDF or just about any required combination.
+
+See L<Catalyst::Action::SOAP::DocumentLiteral> for an example.
+
+=head1 ACCESSORS
+
+Once you tagged one of the methods, you'll have an $c->stash->{soap}
+accessor which will return an C<Catalyst::Controller::SOAP::Helper>
+object. It's important to notice that this is achieved by the fact
+that all the SOAP Action classes are subclasses of
+Catalyst::Action::SOAP, which implements most of that.
+
+You can query this object as follows:
+
+=over 4
+
+=item $c->stash->{soap}->envelope()
+
+The original SOAP envelope as string.
+
+=item $c->stash->{soap}->parsed_envelope()
+
+The parsed envelope as an XML::LibXML object.
+
+=item $c->stash->{soap}->arguments()
+
+The arguments of a RPC call.
+
+=item $c->stash->{soap}->fault({code => $code,reason => $reason, detail => $detail])
+
+Allows you to set fault code and message. Optionally, you may define
+the code itself as an arrayref where the first item will be this code
+and the second will be the subcode, which recursively may be another
+arrayref.
+
+=item $c->stash->{soap}->encoded_return(\@data)
+
+This method will prepare the return value to be a soap encoded data.
+
+  # TODO: At this moment, only Literals are working...
+
+=item $c->stash->{soap}->literal_return($xml_node)
+
+This method will prepare the return value to be a literal XML
+document, in this case, you can pass just the node that will be the
+root in the return message or a nodelist.
+
+Using XML::Compile will help to elaborate schema based returns.
+
+=item $c->stash->{soap}->string_return($non_xml_text)
+
+In this case, the given text is encoded as CDATA inside the SOAP
+message.
+
+=back
+
+=head1 USING WSDL
+
+If you define the "wsdl" configuration key, Catalyst::Controller::SOAP
+will automatically map your operations into the WSDL operations, in
+which case you will receive the parsed Perl structure as returned by
+XML::Compile according to the type defined in the WSDL message.
+
+You can define additional wsdl files or even additional schema
+files. If $wsdl is an arrayref, the first element is the one passed to
+new, and the others will be the argument to subsequent addWsdl calls.
+If $wsdl is a hashref, the "wsdl" key will be handled like above and
+the "schema" key will be used to importDefinitions. If the content of
+the schema key is an arrayref, it will result in several calls to
+importDefinition.
+
+When using WSDL, you can use the WSDLPort attribute, that not only
+sets the port name but also infer which is the style of the binding,
+the use of the input body and also declares the Path for the operation
+according to the 'location' attribute in the WSDL file. For RPC
+operations, the endpoint action will be created dinamically also in
+the path defined by the WSDL file.
+
+This is the most convenient way of defining a SOAP service, which, in
+the end, will require you to have it as simple as:
+
+  package SOAPApp::Controller::WithWSDL;
+  use base 'Catalyst::Controller::SOAP';
+  __PACKAGE__->config->{wsdl} = 't/hello4.wsdl';
+  
+  # in this case, the input has two parts, named 'who' and 'greeting'
+  # and the output has a single 'greeting' part.
+  sub Greet : WSDLPort('Greet') {
+    my ( $self, $c, $args ) = @_;
+    my $who = $args->{who};
+    my $grt = $args->{greeting};
+    $c->stash->{soap}->compile_return({ greeting => $grt.' '.$who.'!' });
+  }
+
+When using WSDL with more than one port, the use of this attribute is
+mandatory.
+
+When the WSDL describes more than one service, the controller can only
+represent one of them, so you must define the 'wsdlservice' config key
+that will be used to select the service.
+
+Also, when using wsdl, you can define the response using:
+
+  $c->stash->{soap}->compile_return($perl_structure)
+
+In this case, the given structure will be transformed by XML::Compile,
+according to what's described in the WSDL file.
+
+If you define "xml_compile" as a configuration key (which is a 
+hashref with keys 'reader' and 'writer', which both have a hashref
+as their value), those key / value pairs will be passed as options
+to the XML::Compile::Schema::compile() method.
+
+  __PACKAGE__->config->{xml_compile} = {
+      reader => {sloppy_integers => 1}, writer => {sloppy_integers => 1},
+  };
+
+=head1 USING WSDL AND Catalyst::Test
+
+If you'd like to use the built-in server from Catalyst::Test with your
+WSDL file (which likely defines an <address location="..."> that differs
+from the standard test server) you'll need to use the transport_hook
+option available with $wsdl->compileClient() in your test file.
+
+
+    # t/soap_message.t
+    use XML::Compile::WSDL11;
+    use XML::Compile::Transport::SOAPHTTP;
+    use Test::More qw(no_plan);
+
+    BEGIN {
+        use_ok 'Catalyst::Test', 'MyServer';
+    }
+
+    sub proxy_to_test_app
+    {
+        my ($request, $trace) = @_;
+        # request() is a function inserted by Catalyst::Test which
+        # sends HTTP requests to the just-started test server.
+        return request($request);
+    }
+
+    my $xml       = '/path/to/wsdl/file';
+    my $message   = 'YourMessage';
+    my $port_name = 'YourPort';
+    my $wsdl      = XML::Compile::WSDL11->new($xml);
+    my $client    = $wsdl->compileClient($message, 
+        port => $port_name, transport_hook => \&proxy_to_test_app,
+    );
+    $client->(...);
+
+
+=head1 TODO
+
+No header features are implemented yet.
+
+The SOAP Encoding support is also missing, when that is ready you'll
+be able to do something like the code below:
+
+    # available in "/example" as operation "echo"
+    # parsing the arguments as soap-encoded.
+    sub echo : SOAP('RPCEncoded') {
+        my ( $self, $c, @args ) = @_;
+    }
+
+=head1 SEE ALSO
+
+L<Catalyst::Action::SOAP>, L<XML::LibXML>, L<XML::Compile>
+L<Catalyst::Action::SOAP::DocumentLiteral>,
+L<Catalyst::Action::SOAP::RPCLiteral>,
+L<Catalyst::Action::SOAP::HTTPGet>, L<XML::Compile::WSDL11>,
+L<XML::Compile::Schema>
+
+=head1 AUTHORS
+
+Daniel Ruoso C<daniel.ruoso at verticalone.pt>
+
+Drew Taylor C<drew at drewtaylor.com>
+
+=head1 BUG REPORTS
+
+Please submit all bugs regarding C<Catalyst::Controller::SOAP> to
+C<bug-catalyst-controller-soap at rt.cpan.org>
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut




More information about the Catalyst-commits mailing list