2 /// MonoWSDL.cs -- a WSDL to proxy code generator.
4 /// Author: Erik LeBel (eriklebel@yahoo.ca)
5 /// Lluis Sanchez (lluis@novell.com)
7 /// Copyright (C) 2003, Erik LeBel,
14 using System
.Xml
.Serialization
;
15 using System
.Xml
.Schema
;
16 using System
.Collections
;
17 using System
.Collections
.Specialized
;
19 using System
.CodeDom
.Compiler
;
22 using System
.Web
.Services
.Description
;
23 using System
.Web
.Services
.Discovery
;
24 using System
.Web
.Services
;
26 using Microsoft
.CSharp
;
28 namespace Mono
.WebServices
32 string ProductId
= "Web Services Description Language Utility\nMono Framework v" + Environment
.Version
;
33 const string UsageMessage
=
34 "wsdl [options] {path | URL} {path | URL} ...\n\n"
35 + " -d, -domain:domain Domain of username for server authentication.\n"
36 + " -l, -language:language Language of generated code. Allowed CS (default)\n"
37 + " and VB. You can also specify the fully qualified\n"
38 + " name of a class that implements the\n"
39 + " System.CodeDom.Compiler.CodeDomProvider Class.\n"
40 + " -n, -namespace:ns The namespace of the generated code, default\n"
41 + " namespace if none.\n"
42 + " -nologo Surpress the startup logo.\n"
43 + " -o, -out:filename The target file for generated code.\n"
44 + " -p, -password:pwd Password used to contact the server.\n"
45 + " -protocol:protocol Protocol to implement. Allowed: Soap (default),\n"
46 + " HttpGet or HttpPost.\n"
47 + " -fields Generate fields instead of properties in data\n"
49 + " -server Generate server instead of client proxy code.\n"
50 + " -u, -username:username Username used to contact the server.\n"
51 + " -proxy:url Address of the proxy.\n"
52 + " -pu, -proxyusername:username Username used to contact the proxy.\n"
53 + " -pp, -proxypassword:pwd Password used to contact the proxy.\n"
54 + " -pd, -proxydomain:domain Domain of username for proxy authentication.\n"
55 + " -urlkey, -appsettingurlkey:key Configuration key that contains the default\n"
56 + " url for the generated WS proxy.\n"
57 + " -baseurl, -appsettingbaseurl:url Base url to use when constructing the\n"
59 + " -sample:[binding/]operation Display a sample SOAP request and response.\n"
60 + " -? Display this message\n"
62 + "Options can be of the forms -option, --option or /option\n";
64 ArrayList descriptions
= new ArrayList ();
65 ArrayList schemas
= new ArrayList ();
79 string applicationSignature
;
80 string appSettingURLKey
;
81 string appSettingBaseURL
;
82 string language
= "CS";
85 string protocol
= "Soap";
86 ServiceDescriptionImportStyle style
;
87 CodeGenerationOptions options
= CodeGenerationOptions
.GenerateProperties
| CodeGenerationOptions
.GenerateNewAsync
;
90 StringCollection urls
= new StringCollection ();
94 /// Application entry point.
97 public static int Main(string[] args
)
99 Driver d
= new Driver();
105 applicationSignature
= ProductId
;
108 int Run (string[] args
)
112 // parse command line arguments
113 foreach (string argument
in args
)
114 ImportArgument(argument
);
117 Console
.WriteLine(ProductId
);
119 if (help
|| urls
.Count
== 0)
121 Console
.WriteLine(UsageMessage
);
125 CodeCompileUnit codeUnit
= new CodeCompileUnit();
126 CodeNamespace proxyCode
= GetCodeNamespace();
127 codeUnit
.Namespaces
.Add (proxyCode
);
129 WebReferenceCollection references
= new WebReferenceCollection ();
131 DiscoveryClientProtocol dcc
= CreateClient ();
133 foreach (string murl
in urls
)
137 if (!url
.StartsWith ("http://") && !url
.StartsWith ("https://") && !url
.StartsWith ("file://"))
138 url
= new Uri (Path
.GetFullPath (url
)).ToString ();
140 dcc
.DiscoverAny (url
);
145 WebReference reference
= new WebReference (dcc
.Documents
, proxyCode
, protocol
, appSettingURLKey
, appSettingBaseURL
);
146 references
.Add (reference
);
148 if (sampleSoap
!= null)
149 ConsoleSampleGenerator
.Generate (descriptions
, schemas
, sampleSoap
, protocol
);
151 if (sampleSoap
!= null)
155 GenerateCode (references
, codeUnit
);
158 catch (Exception exception
)
160 Console
.WriteLine("Error: {0}", exception
.Message
);
162 // Supress this except for when debug is enabled
163 Console
.WriteLine("Stack:\n {0}", exception
.StackTrace
);
170 /// Generate code for the specified ServiceDescription.
173 public bool GenerateCode (WebReferenceCollection references
, CodeCompileUnit codeUnit
)
175 bool hasWarnings
= false;
177 CodeDomProvider provider
= GetProvider();
179 StringCollection validationWarnings
;
180 WebReferenceOptions opts
= new WebReferenceOptions ();
181 opts
.CodeGenerationOptions
= options
;
183 opts
.Verbose
= verbose
;
184 validationWarnings
= ServiceDescriptionImporter
.GenerateWebReferences (references
, provider
, codeUnit
, opts
);
186 for (int n
=0; n
<references
.Count
; n
++)
188 WebReference wr
= references
[n
];
190 BasicProfileViolationCollection violations
= new BasicProfileViolationCollection ();
191 if (String
.Compare (protocol
, "SOAP", StringComparison
.OrdinalIgnoreCase
) == 0 && !WebServicesInteroperability
.CheckConformance (WsiProfiles
.BasicProfile1_1
, wr
, violations
)) {
192 wr
.Warnings
|= ServiceDescriptionImportWarnings
.WsiConformance
;
195 if (wr
.Warnings
!= 0)
198 WriteText ("", 0, 0);
199 WriteText ("There where some warnings while generating the code:", 0, 0);
202 WriteText ("", 0, 0);
203 WriteText (urls
[n
], 2, 2);
205 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.WsiConformance
) > 0) {
206 WriteText ("- This web reference does not conform to WS-I Basic Profile v1.1", 4, 6);
207 foreach (BasicProfileViolation vio
in violations
) {
208 WriteText (vio
.NormativeStatement
+ ": " + vio
.Details
, 8, 8);
209 foreach (string ele
in vio
.Elements
)
210 WriteText ("* " + ele
, 10, 12);
214 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.NoCodeGenerated
) > 0)
215 WriteText ("- WARNING: No proxy class was generated", 4, 6);
216 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.NoMethodsGenerated
) > 0)
217 WriteText ("- WARNING: The proxy class generated includes no methods", 4, 6);
218 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.OptionalExtensionsIgnored
) > 0)
219 WriteText ("- WARNING: At least one optional extension has been ignored", 4, 6);
220 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.RequiredExtensionsIgnored
) > 0)
221 WriteText ("- WARNING: At least one necessary extension has been ignored", 4, 6);
222 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.UnsupportedBindingsIgnored
) > 0)
223 WriteText ("- WARNING: At least one binding is of an unsupported type and has been ignored", 4, 6);
224 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.UnsupportedOperationsIgnored
) > 0)
225 WriteText ("- WARNING: At least one operation is of an unsupported type and has been ignored", 4, 6);
231 if (hasWarnings
) WriteText ("",0,0);
233 string filename
= outFilename
;
234 bool hasBindings
= false;
236 foreach (object doc
in references
[0].Documents
.Values
)
238 ServiceDescription desc
= doc
as ServiceDescription
;
239 if (desc
== null) continue;
241 if (desc
.Services
.Count
> 0 && filename
== null)
242 filename
= desc
.Services
[0].Name
+ "." + provider
.FileExtension
;
244 if (desc
.Bindings
.Count
> 0 || desc
.Services
.Count
> 0)
248 if (filename
== null)
249 filename
= "output." + provider
.FileExtension
;
252 WriteText ("Writing file '" + filename
+ "'", 0, 0);
253 StreamWriter writer
= new StreamWriter(filename
);
255 CodeGeneratorOptions compilerOptions
= new CodeGeneratorOptions();
256 provider
.GenerateCodeFromCompileUnit (codeUnit
, writer
, compilerOptions
);
265 /// Create the CodeNamespace with the generator's signature commented in.
268 CodeNamespace
GetCodeNamespace()
270 CodeNamespace codeNamespace
= new CodeNamespace(ns
);
272 if (applicationSignature
!= null)
274 codeNamespace
.Comments
.Add(new CodeCommentStatement("\n This source code was auto-generated by " + applicationSignature
+ "\n"));
277 return codeNamespace
;
283 void WriteCodeUnit(CodeCompileUnit codeUnit
, string serviceName
)
285 CodeDomProvider provider
= GetProvider();
286 ICodeGenerator generator
= provider
.CreateGenerator();
287 CodeGeneratorOptions options
= new CodeGeneratorOptions();
290 if (outFilename
!= null)
291 filename
= outFilename
;
293 filename
= serviceName
+ "." + provider
.FileExtension
;
295 Console
.WriteLine ("Writing file '{0}'", filename
);
296 StreamWriter writer
= new StreamWriter(filename
);
297 generator
.GenerateCodeFromCompileUnit(codeUnit
, writer
, options
);
303 /// Fetch the Code Provider for the language specified by the 'language' members.
306 private CodeDomProvider
GetProvider()
308 CodeDomProvider provider
;
311 switch (language
.ToUpper ()) {
313 provider
= new CSharpCodeProvider ();
316 provider
= new Microsoft
.VisualBasic
.VBCodeProvider ();
319 type
= Type
.GetType("Boo.Lang.CodeDom.BooCodeProvider, Boo.Lang.CodeDom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=32c39770e9a21a67");
321 return (CodeDomProvider
) Activator
.CreateInstance (type
);
323 throw new Exception ("Boo.Lang.CodeDom.BooCodeProvider not available");
326 type
= Type
.GetType(language
);
328 return (CodeDomProvider
) Activator
.CreateInstance (type
);
330 throw new Exception ("Unknown language");
339 /// Interperet the command-line arguments and configure the relavent components.
342 void ImportArgument(string argument
)
344 string optionValuePair
;
346 if (argument
.StartsWith("--"))
348 optionValuePair
= argument
.Substring(2);
350 else if (argument
.StartsWith("/") || argument
.StartsWith("-"))
352 optionValuePair
= argument
.Substring(1);
363 int indexOfEquals
= optionValuePair
.IndexOf(':');
364 if (indexOfEquals
> 0)
366 option
= optionValuePair
.Substring(0, indexOfEquals
);
367 value = optionValuePair
.Substring(indexOfEquals
+ 1);
371 option
= optionValuePair
;
377 case "appsettingurlkey":
379 appSettingURLKey
= value;
382 case "appsettingbaseurl":
384 appSettingBaseURL
= value;
421 proxyAddress
= value;
429 case "proxypassword":
431 proxyPassword
= value;
434 case "proxyusername":
436 proxyUsername
= value;
440 style
= ServiceDescriptionImportStyle
.Server
;
453 options
&= ~CodeGenerationOptions
.GenerateProperties
;
465 if (argument
.StartsWith ("/") && argument
.IndexOfAny (Path
.InvalidPathChars
) == -1) {
470 throw new Exception("Unknown option " + option
);
474 DiscoveryClientProtocol
CreateClient ()
476 DiscoveryClientProtocol dcc
= new DiscoveryClientProtocol ();
478 if (username
!= null || password
!= null || domain
!= null)
480 NetworkCredential credentials
= new NetworkCredential();
482 if (username
!= null)
483 credentials
.UserName
= username
;
485 if (password
!= null)
486 credentials
.Password
= password
;
489 credentials
.Domain
= domain
;
491 dcc
.Credentials
= credentials
;
494 if (proxyAddress
!= null)
496 WebProxy proxy
= new WebProxy (proxyAddress
);
497 if (proxyUsername
!= null || proxyPassword
!= null || proxyDomain
!= null)
499 NetworkCredential credentials
= new NetworkCredential();
501 if (proxyUsername
!= null)
502 credentials
.UserName
= proxyUsername
;
504 if (proxyPassword
!= null)
505 credentials
.Password
= proxyPassword
;
507 if (proxyDomain
!= null)
508 credentials
.Domain
= proxyDomain
;
510 proxy
.Credentials
= credentials
;
517 static void WriteText (string text
, int initialLeftMargin
, int leftMargin
)
520 int margin
= initialLeftMargin
;
524 Console
.WriteLine ();
528 while (n
< text
.Length
)
533 while (col
< maxCols
&& n
< text
.Length
) {
534 if (char.IsWhiteSpace (text
[n
]))
540 if (lastWhite
== -1 || col
< maxCols
)
542 else if (col
>= maxCols
)
545 Console
.WriteLine (new String (' ', margin
) + text
.Substring (sn
, lastWhite
- sn
));