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