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,
13 using System
.Xml
.Serialization
;
14 using System
.Xml
.Schema
;
15 using System
.Collections
;
16 using System
.Collections
.Specialized
;
18 using System
.CodeDom
.Compiler
;
21 using System
.Web
.Services
.Description
;
22 using System
.Web
.Services
.Discovery
;
23 using System
.Web
.Services
;
25 using Microsoft
.CSharp
;
27 namespace Mono
.WebServices
31 string ProductId
= "Web Services Description Language Utility\nMono Framework v" + Environment
.Version
;
32 const string UsageMessage
=
33 "wsdl [options] {path | URL} {path | URL} ...\n\n"
34 + " -d, -domain:domain Domain of username for server authentication.\n"
35 + " -l, -language:language Language of generated code. Allowed CS (default)\n"
36 + " and VB. You can also specify the fully qualified\n"
37 + " name of a class that implements the\n"
38 + " System.CodeDom.Compiler.CodeDomProvider Class.\n"
39 + " -n, -namespace:ns The namespace of the generated code, default\n"
40 + " namespace if none.\n"
41 + " -nologo Surpress the startup logo.\n"
42 + " -o, -out:filename The target file for generated code.\n"
43 + " -p, -password:pwd Password used to contact the server.\n"
44 + " -protocol:protocol Protocol to implement. Allowed: Soap (default),\n"
45 + " HttpGet or HttpPost.\n"
46 + " -fields Generate fields instead of properties in data\n"
48 + " -server Generate server instead of client proxy code.\n"
49 + " -u, -username:username Username used to contact the server.\n"
50 + " -proxy:url Address of the proxy.\n"
51 + " -pu, -proxyusername:username Username used to contact the proxy.\n"
52 + " -pp, -proxypassword:pwd Password used to contact the proxy.\n"
53 + " -pd, -proxydomain:domain Domain of username for proxy authentication.\n"
54 + " -urlkey, -appsettingurlkey:key Configuration key that contains the default\n"
55 + " url for the generated WS proxy.\n"
56 + " -baseurl, -appsettingbaseurl:url Base url to use when constructing the\n"
58 + " -sample:[binding/]operation Display a sample SOAP request and response.\n"
59 + " -? Display this message\n"
61 + "Options can be of the forms -option, --option or /option\n";
63 ArrayList descriptions
= new ArrayList ();
64 ArrayList schemas
= new ArrayList ();
78 string applicationSignature
;
79 string appSettingURLKey
;
80 string appSettingBaseURL
;
81 string language
= "CS";
84 string protocol
= "Soap";
85 ServiceDescriptionImportStyle style
;
86 CodeGenerationOptions options
= CodeGenerationOptions
.GenerateProperties
| CodeGenerationOptions
.GenerateNewAsync
;
89 StringCollection urls
= new StringCollection ();
93 /// Application entry point.
96 public static int Main(string[] args
)
98 Driver d
= new Driver();
104 applicationSignature
= ProductId
;
107 int Run (string[] args
)
111 // parse command line arguments
112 foreach (string argument
in args
)
113 ImportArgument(argument
);
116 Console
.WriteLine(ProductId
);
118 if (help
|| urls
.Count
== 0)
120 Console
.WriteLine(UsageMessage
);
124 CodeCompileUnit codeUnit
= new CodeCompileUnit();
125 CodeNamespace proxyCode
= GetCodeNamespace();
126 codeUnit
.Namespaces
.Add (proxyCode
);
128 WebReferenceCollection references
= new WebReferenceCollection ();
130 DiscoveryClientProtocol dcc
= CreateClient ();
132 foreach (string murl
in urls
)
136 if (!url
.StartsWith ("http://") && !url
.StartsWith ("https://") && !url
.StartsWith ("file://"))
137 url
= new Uri (Path
.GetFullPath (url
)).ToString ();
139 dcc
.DiscoverAny (url
);
144 WebReference reference
= new WebReference (dcc
.Documents
, proxyCode
, protocol
, appSettingURLKey
, appSettingBaseURL
);
145 references
.Add (reference
);
147 if (sampleSoap
!= null)
148 ConsoleSampleGenerator
.Generate (descriptions
, schemas
, sampleSoap
, protocol
);
150 if (sampleSoap
!= null)
154 GenerateCode (references
, codeUnit
);
157 catch (Exception exception
)
159 Console
.WriteLine("Error: {0}", exception
.Message
);
161 // Supress this except for when debug is enabled
162 Console
.WriteLine("Stack:\n {0}", exception
.StackTrace
);
169 /// Generate code for the specified ServiceDescription.
172 public bool GenerateCode (WebReferenceCollection references
, CodeCompileUnit codeUnit
)
174 bool hasWarnings
= false;
176 CodeDomProvider provider
= GetProvider();
178 StringCollection validationWarnings
;
179 WebReferenceOptions opts
= new WebReferenceOptions ();
180 opts
.CodeGenerationOptions
= options
;
182 opts
.Verbose
= verbose
;
183 validationWarnings
= ServiceDescriptionImporter
.GenerateWebReferences (references
, provider
, codeUnit
, opts
);
185 for (int n
=0; n
<references
.Count
; n
++)
187 WebReference wr
= references
[n
];
189 BasicProfileViolationCollection violations
= new BasicProfileViolationCollection ();
190 if (String
.Compare (protocol
, "SOAP", StringComparison
.OrdinalIgnoreCase
) == 0 && !WebServicesInteroperability
.CheckConformance (WsiProfiles
.BasicProfile1_1
, wr
, violations
)) {
191 wr
.Warnings
|= ServiceDescriptionImportWarnings
.WsiConformance
;
194 if (wr
.Warnings
!= 0)
197 WriteText ("", 0, 0);
198 WriteText ("There were some warnings while generating the code:", 0, 0);
201 WriteText ("", 0, 0);
202 WriteText (urls
[n
], 2, 2);
204 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.WsiConformance
) > 0) {
205 WriteText ("- This web reference does not conform to WS-I Basic Profile v1.1", 4, 6);
206 foreach (BasicProfileViolation vio
in violations
) {
207 WriteText (vio
.NormativeStatement
+ ": " + vio
.Details
, 8, 8);
208 foreach (string ele
in vio
.Elements
)
209 WriteText ("* " + ele
, 10, 12);
213 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.NoCodeGenerated
) > 0)
214 WriteText ("- WARNING: No proxy class was generated", 4, 6);
215 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.NoMethodsGenerated
) > 0)
216 WriteText ("- WARNING: The proxy class generated includes no methods", 4, 6);
217 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.OptionalExtensionsIgnored
) > 0)
218 WriteText ("- WARNING: At least one optional extension has been ignored", 4, 6);
219 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.RequiredExtensionsIgnored
) > 0)
220 WriteText ("- WARNING: At least one necessary extension has been ignored", 4, 6);
221 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.UnsupportedBindingsIgnored
) > 0)
222 WriteText ("- WARNING: At least one binding is of an unsupported type and has been ignored", 4, 6);
223 if ((wr
.Warnings
& ServiceDescriptionImportWarnings
.UnsupportedOperationsIgnored
) > 0)
224 WriteText ("- WARNING: At least one operation is of an unsupported type and has been ignored", 4, 6);
230 if (hasWarnings
) WriteText ("",0,0);
232 string filename
= outFilename
;
233 bool hasBindings
= false;
235 foreach (object doc
in references
[0].Documents
.Values
)
237 ServiceDescription desc
= doc
as ServiceDescription
;
238 if (desc
== null) continue;
240 if (desc
.Services
.Count
> 0 && filename
== null)
241 filename
= desc
.Services
[0].Name
+ "." + provider
.FileExtension
;
243 if (desc
.Bindings
.Count
> 0 || desc
.Services
.Count
> 0)
247 if (filename
== null)
248 filename
= "output." + provider
.FileExtension
;
251 WriteText ("Writing file '" + filename
+ "'", 0, 0);
252 StreamWriter writer
= new StreamWriter(filename
);
254 CodeGeneratorOptions compilerOptions
= new CodeGeneratorOptions();
255 provider
.GenerateCodeFromCompileUnit (codeUnit
, writer
, compilerOptions
);
264 /// Create the CodeNamespace with the generator's signature commented in.
267 CodeNamespace
GetCodeNamespace()
269 CodeNamespace codeNamespace
= new CodeNamespace(ns
);
271 if (applicationSignature
!= null)
273 codeNamespace
.Comments
.Add(new CodeCommentStatement("\n This source code was auto-generated by " + applicationSignature
+ "\n"));
276 return codeNamespace
;
282 void WriteCodeUnit(CodeCompileUnit codeUnit
, string serviceName
)
284 CodeDomProvider provider
= GetProvider();
285 ICodeGenerator generator
= provider
.CreateGenerator();
286 CodeGeneratorOptions options
= new CodeGeneratorOptions();
289 if (outFilename
!= null)
290 filename
= outFilename
;
292 filename
= serviceName
+ "." + provider
.FileExtension
;
294 Console
.WriteLine ("Writing file '{0}'", filename
);
295 StreamWriter writer
= new StreamWriter(filename
);
296 generator
.GenerateCodeFromCompileUnit(codeUnit
, writer
, options
);
302 /// Fetch the Code Provider for the language specified by the 'language' members.
305 private CodeDomProvider
GetProvider()
307 CodeDomProvider provider
;
310 switch (language
.ToUpper ()) {
312 provider
= new CSharpCodeProvider ();
315 provider
= new Microsoft
.VisualBasic
.VBCodeProvider ();
318 type
= Type
.GetType("Boo.Lang.CodeDom.BooCodeProvider, Boo.Lang.CodeDom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=32c39770e9a21a67");
320 return (CodeDomProvider
) Activator
.CreateInstance (type
);
322 throw new Exception ("Boo.Lang.CodeDom.BooCodeProvider not available");
325 type
= Type
.GetType(language
);
327 return (CodeDomProvider
) Activator
.CreateInstance (type
);
329 throw new Exception ("Unknown language");
338 /// Interperet the command-line arguments and configure the relavent components.
341 void ImportArgument(string argument
)
343 string optionValuePair
;
345 if (argument
.StartsWith("--"))
347 optionValuePair
= argument
.Substring(2);
349 else if (argument
.StartsWith("/") || argument
.StartsWith("-"))
351 optionValuePair
= argument
.Substring(1);
362 int indexOfEquals
= optionValuePair
.IndexOf(':');
363 if (indexOfEquals
> 0)
365 option
= optionValuePair
.Substring(0, indexOfEquals
);
366 value = optionValuePair
.Substring(indexOfEquals
+ 1);
370 option
= optionValuePair
;
376 case "appsettingurlkey":
378 appSettingURLKey
= value;
381 case "appsettingbaseurl":
383 appSettingBaseURL
= value;
420 proxyAddress
= value;
428 case "proxypassword":
430 proxyPassword
= value;
433 case "proxyusername":
435 proxyUsername
= value;
439 style
= ServiceDescriptionImportStyle
.Server
;
452 options
&= ~CodeGenerationOptions
.GenerateProperties
;
464 if (argument
.StartsWith ("/") && argument
.IndexOfAny (Path
.InvalidPathChars
) == -1) {
469 throw new Exception("Unknown option " + option
);
473 DiscoveryClientProtocol
CreateClient ()
475 DiscoveryClientProtocol dcc
= new DiscoveryClientProtocol ();
477 if (username
!= null || password
!= null || domain
!= null)
479 NetworkCredential credentials
= new NetworkCredential();
481 if (username
!= null)
482 credentials
.UserName
= username
;
484 if (password
!= null)
485 credentials
.Password
= password
;
488 credentials
.Domain
= domain
;
490 dcc
.Credentials
= credentials
;
493 if (proxyAddress
!= null)
495 WebProxy proxy
= new WebProxy (proxyAddress
);
496 if (proxyUsername
!= null || proxyPassword
!= null || proxyDomain
!= null)
498 NetworkCredential credentials
= new NetworkCredential();
500 if (proxyUsername
!= null)
501 credentials
.UserName
= proxyUsername
;
503 if (proxyPassword
!= null)
504 credentials
.Password
= proxyPassword
;
506 if (proxyDomain
!= null)
507 credentials
.Domain
= proxyDomain
;
509 proxy
.Credentials
= credentials
;
516 static void WriteText (string text
, int initialLeftMargin
, int leftMargin
)
519 int margin
= initialLeftMargin
;
523 Console
.WriteLine ();
527 while (n
< text
.Length
)
532 while (col
< maxCols
&& n
< text
.Length
) {
533 if (char.IsWhiteSpace (text
[n
]))
539 if (lastWhite
== -1 || col
< maxCols
)
541 else if (col
>= maxCols
)
544 Console
.WriteLine (new String (' ', margin
) + text
.Substring (sn
, lastWhite
- sn
));