--- /dev/null
+///\r
+/// MonoWSDL.cs -- a WSDL to proxy code generator.\r
+///\r
+/// Author: Erik LeBel (eriklebel@yahoo.ca)\r
+/// Lluis Sanchez (lluis@novell.com)\r
+///\r
+/// Copyright (C) 2003, Erik LeBel,\r
+///\r
+\r
+using System;\r
+using System.Xml;\r
+using System.Xml.Serialization;\r
+using System.Xml.Schema;\r
+using System.Collections;\r
+using System.Collections.Specialized;\r
+using System.CodeDom;\r
+using System.CodeDom.Compiler;\r
+using System.IO;\r
+using System.Net;\r
+using System.Web.Services.Description;\r
+using System.Web.Services.Discovery;\r
+using System.Web.Services;\r
+\r
+using Microsoft.CSharp;\r
+\r
+namespace Mono.WebServices\r
+{\r
+ public class Driver\r
+ {\r
+ string ProductId = "Web Services Description Language Utility\nMono Framework v" + Environment.Version;\r
+ const string UsageMessage = \r
+ "wsdl [options] {path | URL} {path | URL} ...\n\n"\r
+ + " -d, -domain:domain Domain of username for server authentication.\n"\r
+ + " -l, -language:language Language of generated code. Allowed CS (default)\n"\r
+ + " and VB.\n"\r
+ + " -n, -namespace:ns The namespace of the generated code, default\n"\r
+ + " namespace if none.\n"\r
+ + " -nologo Surpress the startup logo.\n"\r
+ + " -o, -out:filename The target file for generated code.\n"\r
+ + " -p, -password:pwd Password used to contact the server.\n"\r
+ + " -protocol:protocol Protocol to implement. Allowed: Soap (default),\n"\r
+ + " HttpGet or HttpPost.\n"\r
+ + " -fields Generate fields instead of properties in data\n"\r
+ + " classes.\n"\r
+ + " -server Generate server instead of client proxy code.\n"\r
+ + " -u, -username:username Username used to contact the server.\n"\r
+ + " -proxy:url Address of the proxy.\n"\r
+ + " -pu, -proxyusername:username Username used to contact the proxy.\n"\r
+ + " -pp, -proxypassword:pwd Password used to contact the proxy.\n"\r
+ + " -pd, -proxydomain:domain Domain of username for proxy authentication.\n"\r
+ + " -urlkey, -appsettingurlkey:key Configuration key that contains the default\n"\r
+ + " url for the generated WS proxy.\n"\r
+ + " -baseurl, -appsettingbaseurl:url Base url to use when constructing the\n"\r
+ + " service url.\n"\r
+ + " -sample:[binding/]operation Display a sample SOAP request and response.\n"\r
+ + " -? Display this message\n"\r
+ + "\n"\r
+ + "Options can be of the forms -option, --option or /option\n";\r
+ \r
+ ArrayList descriptions = new ArrayList ();\r
+ ArrayList schemas = new ArrayList ();\r
+ \r
+ bool noLogo;\r
+ bool help;\r
+ string sampleSoap;\r
+ \r
+ string proxyAddress;\r
+ string proxyDomain;\r
+ string proxyPassword;\r
+ string proxyUsername;\r
+ string username;\r
+ string password;\r
+ string domain;\r
+ \r
+ string applicationSignature;\r
+ string appSettingURLKey;\r
+ string appSettingBaseURL;\r
+ string language = "CS";\r
+ string ns;\r
+ string outFilename;\r
+ string protocol = "Soap";\r
+ ServiceDescriptionImportStyle style;\r
+ CodeGenerationOptions options = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;\r
+ bool verbose;\r
+ \r
+ StringCollection urls = new StringCollection ();\r
+\r
+ ///\r
+ /// <summary>\r
+ /// Application entry point.\r
+ /// </summary>\r
+ ///\r
+ public static int Main(string[] args)\r
+ {\r
+ Driver d = new Driver();\r
+ return d.Run(args);\r
+ }\r
+ \r
+ Driver()\r
+ {\r
+ applicationSignature = ProductId;\r
+ }\r
+ \r
+ int Run (string[] args)\r
+ {\r
+ try\r
+ {\r
+ // parse command line arguments\r
+ foreach (string argument in args)\r
+ ImportArgument(argument);\r
+ \r
+ if (noLogo == false)\r
+ Console.WriteLine(ProductId);\r
+ \r
+ if (help || urls.Count == 0)\r
+ {\r
+ Console.WriteLine(UsageMessage);\r
+ return 0;\r
+ }\r
+ \r
+ CodeCompileUnit codeUnit = new CodeCompileUnit();\r
+ CodeNamespace proxyCode = GetCodeNamespace();\r
+ codeUnit.Namespaces.Add (proxyCode);\r
+ \r
+ WebReferenceCollection references = new WebReferenceCollection ();\r
+ foreach (string url in urls) \r
+ {\r
+ DiscoveryClientProtocol dcc = CreateClient ();\r
+ \r
+ dcc.DiscoverAny (url);\r
+ dcc.ResolveAll ();\r
+ \r
+ WebReference reference = new WebReference (dcc.Documents, proxyCode, protocol, appSettingURLKey, appSettingBaseURL);\r
+ references.Add (reference);\r
+ \r
+ if (sampleSoap != null)\r
+ ConsoleSampleGenerator.Generate (descriptions, schemas, sampleSoap, protocol);\r
+ }\r
+ \r
+ if (sampleSoap != null)\r
+ return 0;\r
+ \r
+ // generate the code\r
+ if (GenerateCode (references, codeUnit))\r
+ return 1;\r
+ else\r
+ return 0;\r
+ }\r
+ catch (Exception exception)\r
+ {\r
+ Console.WriteLine("Error: {0}", exception.Message);\r
+ \r
+ // Supress this except for when debug is enabled\r
+ Console.WriteLine("Stack:\n {0}", exception.StackTrace);\r
+ return 2;\r
+ }\r
+ }\r
+ \r
+ ///\r
+ /// <summary>\r
+ /// Generate code for the specified ServiceDescription.\r
+ /// </summary>\r
+ ///\r
+ public bool GenerateCode (WebReferenceCollection references, CodeCompileUnit codeUnit)\r
+ {\r
+ bool hasWarnings = false;\r
+ \r
+ CodeDomProvider provider = GetProvider();\r
+ ICodeGenerator generator = provider.CreateGenerator();\r
+ \r
+ StringCollection validationWarnings;\r
+ validationWarnings = ServiceDescriptionImporter.GenerateWebReferences (references, options, style, generator, codeUnit, verbose);\r
+ \r
+ for (int n=0; n<references.Count; n++)\r
+ {\r
+ WebReference wr = references [n];\r
+ \r
+ BasicProfileViolationCollection violations = new BasicProfileViolationCollection ();\r
+ if (!WebServicesInteroperability.CheckConformance (WsiClaims.BP10, wr, violations)) {\r
+ wr.Warnings |= ServiceDescriptionImportWarnings.WsiConformance;\r
+ }\r
+ \r
+ if (wr.Warnings != 0)\r
+ {\r
+ if (!hasWarnings) {\r
+ WriteText ("", 0, 0);\r
+ WriteText ("There where some warnings while generating the code:", 0, 0);\r
+ }\r
+ \r
+ WriteText ("", 0, 0);\r
+ WriteText (urls[n], 2, 2);\r
+ \r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.WsiConformance) > 0) {\r
+ WriteText ("- This web reference does not conform to WS-I Basic Profile v1.0", 4, 6); \r
+ foreach (BasicProfileViolation vio in violations) {\r
+ WriteText (vio.NormativeStatement + ": " + vio.Details, 8, 8);\r
+ foreach (string ele in vio.Elements)\r
+ WriteText ("* " + ele, 10, 12);\r
+ }\r
+ }\r
+ \r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.NoCodeGenerated) > 0)\r
+ WriteText ("- WARNING: No proxy class was generated", 4, 6); \r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.NoMethodsGenerated) > 0)\r
+ WriteText ("- WARNING: The proxy class generated includes no methods", 4, 6);\r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.OptionalExtensionsIgnored) > 0)\r
+ WriteText ("- WARNING: At least one optional extension has been ignored", 4, 6);\r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.RequiredExtensionsIgnored) > 0)\r
+ WriteText ("- WARNING: At least one necessary extension has been ignored", 4, 6);\r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.UnsupportedBindingsIgnored) > 0)\r
+ WriteText ("- WARNING: At least one binding is of an unsupported type and has been ignored", 4, 6);\r
+ if ((wr.Warnings & ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored) > 0)\r
+ WriteText ("- WARNING: At least one operation is of an unsupported type and has been ignored", 4, 6);\r
+ \r
+ hasWarnings = true;\r
+ }\r
+ }\r
+
+ if (hasWarnings) WriteText ("",0,0);\r
+ \r
+ ServiceDescription rootDesc = null;\r
+
+ foreach (object doc in references[0].Documents.Values) {\r
+ ServiceDescription desc = doc as ServiceDescription;
+ if (desc != null && desc.Services.Count > 0) {
+ rootDesc = desc;
+ break;
+ }
+ }
+ \r
+ if (rootDesc != null)\r
+ {\r
+ string filename;\r
+ if (outFilename != null)\r
+ filename = outFilename;\r
+ else\r
+ filename = rootDesc.Services[0].Name + "." + provider.FileExtension;\r
+ \r
+ WriteText ("Writing file '" + filename + "'", 0, 0);\r
+ StreamWriter writer = new StreamWriter(filename);\r
+ \r
+ CodeGeneratorOptions compilerOptions = new CodeGeneratorOptions();\r
+ generator.GenerateCodeFromCompileUnit (codeUnit, writer, compilerOptions);\r
+ writer.Close();\r
+ }\r
+ \r
+ return hasWarnings;\r
+ }\r
+ \r
+ ///\r
+ /// <summary>\r
+ /// Create the CodeNamespace with the generator's signature commented in.\r
+ /// </summary>\r
+ ///\r
+ CodeNamespace GetCodeNamespace()\r
+ {\r
+ CodeNamespace codeNamespace = new CodeNamespace(ns);\r
+ \r
+ if (applicationSignature != null)\r
+ {\r
+ codeNamespace.Comments.Add(new CodeCommentStatement("\n This source code was auto-generated by " + applicationSignature + "\n"));\r
+ }\r
+ \r
+ return codeNamespace;\r
+ }\r
+ \r
+ ///\r
+ /// <summary/>\r
+ ///\r
+ void WriteCodeUnit(CodeCompileUnit codeUnit, string serviceName)\r
+ {\r
+ CodeDomProvider provider = GetProvider();\r
+ ICodeGenerator generator = provider.CreateGenerator();\r
+ CodeGeneratorOptions options = new CodeGeneratorOptions();\r
+ \r
+ string filename;\r
+ if (outFilename != null)\r
+ filename = outFilename;\r
+ else\r
+ filename = serviceName + "." + provider.FileExtension;\r
+ \r
+ Console.WriteLine ("Writing file '{0}'", filename);\r
+ StreamWriter writer = new StreamWriter(filename);\r
+ generator.GenerateCodeFromCompileUnit(codeUnit, writer, options);\r
+ writer.Close();\r
+ }\r
+ \r
+ ///\r
+ /// <summary>\r
+ /// Fetch the Code Provider for the language specified by the 'language' members.\r
+ /// </summary>\r
+ ///\r
+ private CodeDomProvider GetProvider()\r
+ {\r
+ // FIXME these should be loaded dynamically using reflection\r
+ CodeDomProvider provider;\r
+ \r
+ switch (language.ToUpper())\r
+ {\r
+ case "CS":\r
+ provider = new CSharpCodeProvider();\r
+ break;\r
+ \r
+ case "VB":\r
+ provider = new Microsoft.VisualBasic.VBCodeProvider();\r
+ break;\r
+ \r
+ default:\r
+ throw new Exception("Unknow language");\r
+ }\r
+\r
+ return provider;\r
+ }\r
+ \r
+\r
+\r
+ ///\r
+ /// <summary>\r
+ /// Interperet the command-line arguments and configure the relavent components.\r
+ /// </summary>\r
+ /// \r
+ void ImportArgument(string argument)\r
+ {\r
+ string optionValuePair;\r
+ \r
+ if (argument.StartsWith("--"))\r
+ {\r
+ optionValuePair = argument.Substring(2);\r
+ }\r
+ else if (argument.StartsWith("/") || argument.StartsWith("-"))\r
+ {\r
+ optionValuePair = argument.Substring(1);\r
+ }\r
+ else\r
+ {\r
+ urls.Add (argument);\r
+ return;\r
+ }\r
+ \r
+ string option;\r
+ string value;\r
+ \r
+ int indexOfEquals = optionValuePair.IndexOf(':');\r
+ if (indexOfEquals > 0)\r
+ {\r
+ option = optionValuePair.Substring(0, indexOfEquals);\r
+ value = optionValuePair.Substring(indexOfEquals + 1);\r
+ }\r
+ else\r
+ {\r
+ option = optionValuePair;\r
+ value = null;\r
+ }\r
+ \r
+ switch (option)\r
+ {\r
+ case "appsettingurlkey":\r
+ case "urlkey":\r
+ appSettingURLKey = value;\r
+ break;\r
+\r
+ case "appsettingbaseurl":\r
+ case "baseurl":\r
+ appSettingBaseURL = value;\r
+ break;\r
+\r
+ case "d":\r
+ case "domain":\r
+ domain = value;\r
+ break;\r
+\r
+ case "l":\r
+ case "language":\r
+ language = value;\r
+ break;\r
+\r
+ case "n":\r
+ case "namespace":\r
+ ns = value;\r
+ break;\r
+\r
+ case "nologo":\r
+ noLogo = true;\r
+ break;\r
+\r
+ case "o":\r
+ case "out":\r
+ outFilename = value;\r
+ break;\r
+\r
+ case "p":\r
+ case "password":\r
+ password = value;\r
+ break;\r
+\r
+ case "protocol":\r
+ protocol = value;\r
+ break;\r
+\r
+ case "proxy":\r
+ proxyAddress = value;\r
+ break;\r
+\r
+ case "proxydomain":\r
+ case "pd":\r
+ proxyDomain = value;\r
+ break;\r
+\r
+ case "proxypassword":\r
+ case "pp":\r
+ proxyPassword = value;\r
+ break;\r
+\r
+ case "proxyusername":\r
+ case "pu":\r
+ proxyUsername = value;\r
+ break;\r
+\r
+ case "server":\r
+ style = ServiceDescriptionImportStyle.Server;\r
+ break;\r
+\r
+ case "u":\r
+ case "username":\r
+ username = value;\r
+ break;\r
+ \r
+ case "verbose":\r
+ verbose = true;\r
+ break;\r
+ \r
+ case "fields":\r
+ options &= ~CodeGenerationOptions.GenerateProperties;\r
+ break;\r
+ \r
+ case "sample":\r
+ sampleSoap = value;\r
+ break;\r
+\r
+ case "?":\r
+ help = true;\r
+ break;\r
+\r
+ default:\r
+ throw new Exception("Unknown option " + option);\r
+ }\r
+ }\r
+ \r
+ DiscoveryClientProtocol CreateClient ()\r
+ {\r
+ DiscoveryClientProtocol dcc = new DiscoveryClientProtocol ();\r
+ \r
+ if (username != null || password != null || domain != null)\r
+ {\r
+ NetworkCredential credentials = new NetworkCredential();\r
+ \r
+ if (username != null)\r
+ credentials.UserName = username;\r
+ \r
+ if (password != null)\r
+ credentials.Password = password;\r
+ \r
+ if (domain != null)\r
+ credentials.Domain = domain;\r
+ \r
+ dcc.Credentials = credentials;\r
+ }\r
+ \r
+ if (proxyAddress != null)\r
+ {\r
+ WebProxy proxy = new WebProxy (proxyAddress);\r
+ if (proxyUsername != null || proxyPassword != null || proxyDomain != null)\r
+ {\r
+ NetworkCredential credentials = new NetworkCredential();\r
+ \r
+ if (proxyUsername != null)\r
+ credentials.UserName = proxyUsername;\r
+ \r
+ if (proxyPassword != null)\r
+ credentials.Password = proxyPassword;\r
+ \r
+ if (proxyDomain != null)\r
+ credentials.Domain = proxyDomain;\r
+ \r
+ proxy.Credentials = credentials;\r
+ }\r
+ } \r
+ \r
+ return dcc;\r
+ }\r
+ \r
+ static void WriteText (string text, int initialLeftMargin, int leftMargin)\r
+ {\r
+ int n = 0;\r
+ int margin = initialLeftMargin;\r
+ int maxCols = 80;\r
+ \r
+ if (text == "") {\r
+ Console.WriteLine ();\r
+ return;\r
+ }\r
+ \r
+ while (n < text.Length)\r
+ {\r
+ int col = margin;\r
+ int lastWhite = -1;\r
+ int sn = n;\r
+ while (col < maxCols && n < text.Length) {\r
+ if (char.IsWhiteSpace (text[n]))\r
+ lastWhite = n;\r
+ col++;\r
+ n++;\r
+ }\r
+ \r
+ if (lastWhite == -1 || col < maxCols)\r
+ lastWhite = n;\r
+ else if (col >= maxCols)\r
+ n = lastWhite + 1;\r
+ \r
+ Console.WriteLine (new String (' ', margin) + text.Substring (sn, lastWhite - sn));\r
+ margin = leftMargin;\r
+ }\r
+ }\r
+ }\r
+}