Blame | Last modification | View Log | RSS feed
/*============================================================================**** ERG TRANSIT SYSTEMS Licensed software** (C) 2008 All rights reserved****============================================================================**** Project/Product : wsdl-tools** Filename : WsdlExtract.cs** Author(s) : David Purdie**** Description : Extract WSDLs from Managed Web Service DLL****** Information :** Compiler : CSHARP 1 and 2** Target : Build Tools****==========================================================================*/using System;using System.CodeDom;using System.CodeDom.Compiler;using System.Collections;using System.IO;using System.Reflection;using System.Web;using System.Web.Services;using System.Web.Services.Description;using System.Web.Services.Discovery;using System.Xml;using Microsoft.CSharp;namespace JATS.WsdlExtractor{/*** Class to contain user command line options*/public class CmdLineParams{public string AssemblyName;public string OutDir = "";public string Uri = "http://www.erggroup.com/";public int Verbose = 0;public ArrayList EnvPath = new ArrayList();/*** Constructor*/public CmdLineParams(){/*** Add default EnvVars to the EnvPath** Cover all bases*/EnvPath.Add ("CS_LIB");EnvPath.Add ("LIB");EnvPath.Add ("PATH");}}public class App{static CmdLineParams par = new CmdLineParams();static CmdLineParams ParseCommandLine(string[] args){/*** Extract command line arguments - very simple** Format:** First must be assembly** Remainder are program options of the form** /x:value (value starts at value_index)** or /x*/const int value_index = 3;par.AssemblyName = args[0];for (int i = 1; i < args.Length; i++){string arg = args[i];if (arg[0] != '/'){throw new Exception("Incorrect command line parameter " + (i + 1) + " :" + arg);}switch (arg[1]){case 'r':case 'R':par.Uri = arg.Substring(value_index);break;case 'p':case 'P':par.EnvPath.Insert( 0,arg.Substring(value_index));break;case 'o':case 'O':par.OutDir = arg.Substring(value_index);break;case 'v':case 'V':par.Verbose += 1;break;default:throw new Exception("Incorrect command line parameter " + (i + 1) + " :" + arg);}}return par;}/*** Main entry point*/static int Main(string[] args){Console.WriteLine("Web Service WSDL Extractor");/*** Need at least one argument*/if (args.Length <= 1){Console.WriteLine(@"Usage: WsdlExtract assembly [/r:URI] [/o:Basedir] [/p:EnvVar] [/v]");Console.WriteLine(@"");Console.WriteLine(@"assembly - Path to Web Services DLL");Console.WriteLine(@"/o:Output - Set Base Directory");Console.WriteLine(@"/p:EnvVar - A path to search for required DLLs");Console.WriteLine(@"/r:URI - Set web service XML namespace Uri");Console.WriteLine(@"/v - Verbose. Multiple allowed");return -1;}par = ParseCommandLine(args);try{/*** Locate and load assembly DLL** The assembly will load - even if it can't be used*/Assembly assembly = Assembly.LoadFrom(par.AssemblyName);/*** Install an event handler to handle resolver events** May be used to assist in determining DLLs that need to** be loaded*/AppDomain currentDomain = AppDomain.CurrentDomain;currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);if (par.Verbose > 0 ){/*** Display a list of all assemblies references by the one just** loaded. May be useful when determining problems*/Console.WriteLine("Referenced assemblies:");foreach (AssemblyName an in assembly.GetReferencedAssemblies()){Console.WriteLine(" " + an.ToString());}}/*** Find every type in the assembly that has a [WebMethod]** Extract a WSDL if any of its methods are marked*/foreach (Module module in assembly.GetModules()){foreach (Type type in module.GetTypes()){bool hasWebMethod = false;foreach (MethodInfo method in type.GetMethods()){if (method.GetCustomAttributes(typeof(WebMethodAttribute), false).Length > 0){hasWebMethod = true;break;}}if (hasWebMethod){ExtractWsdl(type, par.Uri, par.OutDir + type.Name + ".wsdl");}}}}catch (Exception e){Console.WriteLine(e);return -1;}return 0;}/// <summary>/// Given a web service type/// Extract the WSDL/// </summary>/// <param name="type">The web service type</param>/// <param name="uri">The URL for the service that will be set in the constructor</param>/// <param name="path">The path to the .cs file that will be generated</param>private static void ExtractWsdl(Type type, string uri, string path){/*** Load up the type and create a reflection*/ServiceDescriptionReflector reflector = new ServiceDescriptionReflector();reflector.Reflect(type, uri);if (reflector.ServiceDescriptions.Count > 1){throw new Exception(string.Format("Don't know how to deal with multiple service descriptions in {0}",type));}// Write out the basic WSDL filereflector.ServiceDescriptions[0].Write(path);Console.WriteLine(" Extracted WSDL: {1} for {0}", type.FullName, path);}/*** Event Handler: ResolveEvents** Called when the Assembly Loader has tried all the normal avenues** Atempt to locate the required DLL within the toolset library** path.**** A bit ugly** - Take the name of required assembly** - Tac a .DLL to the end** - Attempt to locate it in the configured EnvVar** - If found, then load it** - Check that its the correct version*/static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args){if (par.Verbose > 0 ){Console.WriteLine("Need to Resolve: " + args.Name);}string Name = args.Name.Split(',')[0] + ".DLL";foreach (string Var in par.EnvPath ){if (par.Verbose > 0 )Console.WriteLine("Use EnvVar: " + Var);string Path = Environment.GetEnvironmentVariable(Var);/*** Ignore EnvVars that don't exist*/if ( Path == null )continue;/*** The EnvVar is a ; sep list of dirs** Walk the list looking for a suitable DLL*/foreach (string dir in Path.Split(';') ){if (par.Verbose > 0 )Console.WriteLine(" Path:" + dir);if (File.Exists( dir + "\\" + Name ) ){if (par.Verbose > 0 )Console.WriteLine("" + Name + " Found in: " + dir);Assembly assembly = Assembly.LoadFrom(dir + "\\" + Name);if ( assembly != null ){if (par.Verbose > 0 )Console.WriteLine("" + Name + " Called: " + assembly.GetName());if(String.Compare(assembly.GetName().FullName, args.Name) == 0){return assembly;}if (par.Verbose > 0 ){Console.WriteLine("Assembly Name Mismatch");Console.WriteLine(" " + assembly.GetName().FullName);Console.WriteLine(" " + args.Name);}}}}}/*** Not found** Let the loader report the error*/return null;}}}