1#!/usr/bin/perl -w 2use strict; 3use warnings; 4use Pod::Usage; 5use Getopt::Long; 6use LWP::UserAgent; 7use SOAP::WSDL::Expat::WSDLParser; 8use SOAP::WSDL::Factory::Generator; 9use Term::ReadKey; 10 11my %opt = ( 12 url => '', 13 prefix => 'My', 14 attribute_prefix => undef, 15 type_prefix => undef, 16 element_prefix => undef, 17 typemap_prefix => undef, 18 interface_prefix => undef, 19 server_prefix => undef, 20 base_path => 'lib/', 21 proxy => undef, 22 generator => 'XSD', 23 server => 0, 24 namespace => 0, 25); 26 27{ # a block just to scope "no warnings" 28 no warnings qw(redefine); 29 30 *LWP::UserAgent::get_basic_credentials = sub { 31 my ($user, $password); 32 # remove user from option if called, to force prompting for a user 33 # name the next time 34 print "URL requires authorization.\n"; 35 if (not $user = delete $opt{user}) { 36 print 'User name:'; 37 ReadMode 1; 38 $user = ReadLine(); 39 ReadMode 0; 40 chomp $user; 41 }; 42 if (not $password = delete $opt{password}) { 43 print 'Password:'; 44 ReadMode 2; 45 $password = ReadLine; 46 ReadMode 0; 47 chomp $password; 48 }; 49 return ($user, $password); 50 }; 51} 52 53GetOptions(\%opt, 54 qw( 55 prefix|p=s 56 attribute_prefix|a=s 57 type_prefix|t=s 58 element_prefix|e=s 59 typemap_prefix|m=s 60 interface_prefix|i=s 61 server_prefix|sp=s 62 base_path|b=s 63 typemap_include|mi=s 64 help|h 65 proxy|x=s 66 keep_alive 67 user=s 68 password=s 69 generator=s 70 server|s 71 namespaces|n 72 ) 73); 74 75my $url = $ARGV[0]; 76 77pod2usage( -exit => 1 , verbose => 2 ) if ($opt{help}); 78pod2usage( -exit => 1 , verbose => 1 ) if not ($url); 79 80local $ENV{HTTP_PROXY} = $opt{proxy} if $opt{proxy}; 81local $ENV{HTTPS_PROXY} = $opt{proxy} if $opt{proxy}; 82 83my $lwp = LWP::UserAgent->new( 84 $opt{keep_alive} 85 ? ( keep_alive => 1 ) 86 : () 87 ); 88$lwp->env_proxy(); # get proxy from environment. Works for both http & https. 89$lwp->agent(qq[SOAP::WSDL $SOAP::WSDL::Expat::WSDLParser::VERSION]); 90 91my $parser = SOAP::WSDL::Expat::WSDLParser->new({ 92 user_agent => $lwp, 93}); 94 95# resolve the default prefix options 96map { 97 my $opt_key = $_; 98 if ( $opt_key =~ / (\w+) _prefix $/xms # relevant option 99 && !$opt{ $opt_key } # that hasn't already been explicitly set 100 ) 101 { 102 my $prefix_type = $1; 103 $opt{ $opt_key } = $opt{prefix} . # My 104 ucfirst( $prefix_type ) . # Typemap 105 ( $prefix_type eq 'server' ? '' : 's' ); # s 106 } 107} keys %opt; 108 109my $definitions = $parser->parse_uri( $url ); 110 111my %typemap = (); 112 113if ($opt{typemap_include}) { 114 die "$opt{typemap_include} not found " if not -f $opt{typemap_include}; 115 %typemap = do $opt{typemap_include}; 116} 117 118my $generator = SOAP::WSDL::Factory::Generator->get_generator({ type => $opt{'generator'} }); 119 120if (%typemap) { 121 if ($generator->can('set_typemap')) { 122 $generator->set_typemap( \%typemap ); 123 } 124 else { 125 warn "Typemap snippet given, but generator does not support it\n"; 126 } 127}; 128 129$generator->set_attribute_prefix( $opt{ attribute_prefix }) 130 if $generator->can('set_attribute_prefix'); 131$generator->set_type_prefix( $opt{ type_prefix }) 132 if $generator->can('set_type_prefix'); 133$generator->set_typemap_prefix( $opt{ typemap_prefix }) 134 if $generator->can('set_typemap_prefix'); 135$generator->set_element_prefix($opt{ element_prefix }) 136 if $generator->can('set_element_prefix'); 137$generator->set_interface_prefix($opt{ interface_prefix }) 138 if $generator->can('set_interface_prefix'); 139$generator->set_server_prefix($opt{ server_prefix }) 140 if $generator->can('set_server_prefix'); 141$generator->set_OUTPUT_PATH($opt{ base_path }) 142 if $generator->can('set_OUTPUT_PATH'); 143$generator->set_definitions($definitions) 144 if $generator->can('set_definitions'); 145# $generator->set_wsdl($xml) if $generator->can('set_wsdl'); 146 147# start with typelib, as errors will most likely occur here... 148$generator->generate(); 149$generator->generate_interface() if ! $opt{server}; 150$generator->generate_server() if $opt{server}; 151__END__ 152 153=pod 154 155=head1 NAME 156 157wsdl2perl.pl - create perl bindings for SOAP webservices. 158 159=head1 SYNOPSIS 160 161 wsdl2perl.pl -t TYPE_PREFIX -e ELEMENT_PREFIX -m TYPEMAP_PREFIX \ 162 -i INTERFACE_PREFIX -b BASE_DIR URL 163 164=head1 OPTIONS 165 166 NAME SHORT DESCRIPTION 167 ---------------------------------------------------------------------------- 168 prefix p Prefix for all generated classes. If you set "-p=Foo", 169 you will get "FooAttributes", "FooTypes", 170 "FooElements" and so on. 171 attribute_prefix a Prefix for XML attribute classes. 172 Default: MyAttributes 173 type_prefix t Prefix for type classes. 174 Default: MyTypes 175 element_prefix e Prefix for element classes. 176 Default: MyElements 177 typemap_prefix m Prefix for typemap classes. 178 Default: MyTypemaps 179 interface_prefix i Prefix for interface classes. 180 Default: MyInterfaces 181 server_prefix sp Prefix for server classes. 182 Default: MyServer 183 base_path b Path to create classes in. 184 Default: . 185 typemap_include mi File to include in typemap. Must eval() to a valid 186 perl hash (not a hash ref !). 187 proxy x HTTP(S) proxy to use (if any). wsdl2perl will also 188 use the proxy settings specified via the HTTP_PROXY 189 and HTTPS_PROXY environment variables. 190 keep_alive Use http keep_alive. 191 user Username for HTTP authentication 192 password Password. wsdl2perl will prompt if not given. 193 generator g Generator to use. 194 Default: XSD 195 server s Generate a server interface (currently only CGI 196 supported) 197 help h Show help content 198 199=head1 DESCRIPTION 200 201Generates a interface class for a SOAP web service described by a WSDL 202definition. 203 204The following classes are created: 205 206=over 207 208=item * A interface class for every SOAP port in service 209 210Interface classes are what you will mainly deal with: They provide a method 211for accessing every web service method. 212 213If you chose to generate Server interfaces, a class for every SOAP port in 214every Web service. 215 216You'll have to implement a method for each of the implemented methods. You 217may implement these methods in the CGI script / handler, or in any class 218to dispatch calls to. 219 220=item * A typemap for every service 221 222Typemaps are used internally by SOAP::WSDL for parsing the SOAP message into 223object trees. 224 225If the WSDL definition is incomplete, you may need to add some lines to 226your typemap. Especially definitions for faults are sometimes left out. 227 228Additional typemap content may be included by passing a file name as 229typemap_include (mi) option. 230 231=item * A type class for every element, complexType or simpleType definition 232 233You may need to write additional type classes if your WSDL is incomplete. 234 235For writing your own lib classes, see L<SOAP::WSDL::XSD::Typelib::Element>, 236L<SOAP::WSDL::XSD::Typelib::ComplexType> 237and L<SOAP::WSDL::XSD::Typelib::SimpleType>. 238 239=back 240 241=head1 TROUBLESHOOTING 242 243=head2 Accessing HTTPS URLs 244 245You need Crypt::SSLeay installed for accessing HTTPS URLs. 246 247=head2 Accessing protected documents 248 249Use the -u option for specifying the user name. You will be prompted for a 250password. 251 252Alternatively, you may specify a passowrd with --password on the command 253line. 254 255=head2 Accessing documents protected by NTLM authentication 256 257Set the --keep_alive option. 258 259Note that accessing documents protected by NTLM authentication is currently 260untested, because I have no access to a system using NTLM authentication. 261If you try it, I would be glad if you could just drop me a note about 262success or failure. 263 264=head1 LICENSE 265 266Copyright 2007 Martin Kutter. 267 268This file is part of SOAP-WSDL. You may distribute/modify it under 269the same terms as perl itself 270 271=head1 AUTHOR 272 273Martin Kutter E<lt>martin.kutter fen-net.deE<gt> 274 275=cut 276