Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1612 dpurdie 1
/*============================================================================
2
**
3
**    ERG TRANSIT SYSTEMS      Licensed software
4
**    (C) 2008                 All rights reserved
5
**
6
**============================================================================
7
**
8
**  Project/Product : wsdl-tools
9
**  Filename        : WsdlExtract.cs
10
**  Author(s)       : David Purdie
11
**
12
**  Description     : Extract WSDLs from Managed Web Service DLL
13
**
14
**
15
**  Information     :
16
**   Compiler       : CSHARP 1 and 2
17
**   Target         : Build Tools
18
**
19
**==========================================================================*/
20
 
21
using System;
22
using System.CodeDom;
23
using System.CodeDom.Compiler;
24
using System.Collections;
25
using System.IO;
26
using System.Reflection;
27
using System.Web;
28
using System.Web.Services;
29
using System.Web.Services.Description;
30
using System.Web.Services.Discovery;
31
using System.Xml;
32
 
33
using Microsoft.CSharp;
34
 
35
 
36
namespace JATS.WsdlExtractor
37
{
38
 
39
    /*
40
    **  Class to contain user command line options
41
    */
42
    public class CmdLineParams
43
    {
44
        public string AssemblyName;
45
        public string OutDir = "";
46
        public string Uri = "http://www.erggroup.com/";
47
        public int Verbose = 0;
48
        public ArrayList EnvPath = new ArrayList();
49
 
50
        /*
51
        **  Constructor
52
        */
53
        public CmdLineParams()
54
        {
55
            /*
56
            **  Add default EnvVars to the EnvPath
57
            **  Cover all bases
58
            */
59
            EnvPath.Add ("CS_LIB");
60
            EnvPath.Add ("LIB");
61
            EnvPath.Add ("PATH");
62
        }
63
    }
64
 
65
 
66
    public class App
67
    {
68
        static CmdLineParams par = new CmdLineParams();
69
        static CmdLineParams ParseCommandLine(string[] args)
70
        {
71
            /*
72
            **  Extract command line arguments - very simple
73
            **  Format:
74
            **      First must be assembly
75
            **      Remainder are program options of the form
76
            **              /x:value        (value starts at value_index)
77
            **         or   /x
78
            */
79
            const int value_index = 3;
80
 
81
            par.AssemblyName = args[0];
82
            for (int i = 1; i < args.Length; i++)
83
            {
84
                string arg = args[i];
85
                if (arg[0] != '/')
86
                {
87
                    throw new Exception("Incorrect command line parameter " + (i + 1) + " :" + arg);
88
                }
89
 
90
                switch (arg[1])
91
                {
92
                    case 'r':
93
                    case 'R':
94
                        par.Uri = arg.Substring(value_index);
95
                        break;
96
 
97
                    case 'p':
98
                    case 'P':
99
                        par.EnvPath.Insert( 0,arg.Substring(value_index));
100
                        break;
101
 
102
 
103
                    case 'o':
104
                    case 'O':
105
                        par.OutDir = arg.Substring(value_index);
106
                        break;
107
 
108
                    case 'v':
109
                    case 'V':
110
                        par.Verbose += 1;
111
                        break;
112
 
113
                    default:
114
                        throw new Exception("Incorrect command line parameter " + (i + 1) + " :" + arg);
115
                }
116
            }
117
            return par;
118
        }
119
 
120
        /*
121
        **  Main entry point
122
        */
123
        static int Main(string[] args)
124
        {
125
            Console.WriteLine("Web Service WSDL Extractor");
126
 
127
            /*
128
            **  Need at least one argument
129
            */
130
            if (args.Length <= 1)
131
            {
132
                Console.WriteLine(@"Usage: WsdlExtract assembly [/r:URI] [/o:Basedir] [/p:EnvVar] [/v]");
133
                Console.WriteLine(@"");
134
                Console.WriteLine(@"assembly   - Path to Web Services DLL");
135
                Console.WriteLine(@"/o:Output  - Set Base Directory");
136
                Console.WriteLine(@"/p:EnvVar  - A path to search for required DLLs");
137
                Console.WriteLine(@"/r:URI     - Set web service XML namespace Uri");
138
                Console.WriteLine(@"/v         - Verbose. Multiple allowed");
139
                return -1;
140
            }
141
            par = ParseCommandLine(args);
142
 
143
            try
144
            {
145
                /*
146
                **  Locate and load assembly DLL
147
                **  The assembly will load - even if it can't be used
148
                */
149
                Assembly assembly = Assembly.LoadFrom(par.AssemblyName);
150
 
151
 
152
                /*
153
                **  Install an event handler to handle resolver events
154
                **  May be used to assist in determining DLLs that need to
155
                **  be loaded
156
                */
157
                AppDomain currentDomain = AppDomain.CurrentDomain;
158
                currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
159
 
160
 
161
                if (par.Verbose > 0 )
162
                {
163
                    /*
164
                    **  Display a list of all assemblies references by the one just
165
                    **  loaded. May be useful when determining problems
166
                    */
167
                    Console.WriteLine("Referenced assemblies:");
168
                    foreach (AssemblyName an in assembly.GetReferencedAssemblies())
169
                    {
170
                        Console.WriteLine("    " + an.ToString());
171
                    }
172
                }
173
 
174
                /*
175
                **  Find every type in the assembly that has a [WebMethod]
176
                **  Extract a WSDL if any of its methods are marked
177
                */
178
                foreach (Module module in assembly.GetModules())
179
                {
180
                    foreach (Type type in module.GetTypes())
181
                    {
182
                        bool hasWebMethod = false;
183
                        foreach (MethodInfo method in type.GetMethods())
184
                        {
185
                            if (method.GetCustomAttributes(typeof(WebMethodAttribute), false).Length > 0)
186
                            {
187
                                hasWebMethod = true;
188
                                break;
189
                            }
190
                        }
191
 
192
                        if (hasWebMethod)
193
                        {
194
                            ExtractWsdl(type, par.Uri, par.OutDir + type.Name + ".wsdl");
195
                        }
196
                    }
197
                }
198
            }
199
            catch (Exception e)
200
            {
201
                Console.WriteLine(e);
202
                return -1;
203
            }
204
            return 0;
205
        }
206
 
207
 
208
        /// <summary>
209
        /// Given a web service type
210
        ///     Extract the WSDL
211
        /// </summary>
212
        /// <param name="type">The web service type</param>
213
        /// <param name="uri">The URL for the service that will be set in the constructor</param>
214
        /// <param name="path">The path to the .cs file that will be generated</param>
215
 
216
        private static void ExtractWsdl(Type type, string uri, string path)
217
        {
218
            /*
219
            **  Load up the type and create a reflection
220
            */
221
            ServiceDescriptionReflector reflector = new ServiceDescriptionReflector();
222
            reflector.Reflect(type, uri);
223
 
224
            if (reflector.ServiceDescriptions.Count > 1)
225
            {
226
                throw new Exception(string.Format("Don't know how to deal with multiple service descriptions in {0}",
227
                        type));
228
            }
229
 
230
            // Write out the basic WSDL file
231
            reflector.ServiceDescriptions[0].Write(path);
232
            Console.WriteLine("    Extracted WSDL: {1} for {0}", type.FullName, path);
233
 
234
        }
235
 
236
        /*
237
        **  Event Handler: ResolveEvents
238
        **  Called when the Assembly Loader has tried all the normal avenues
239
        **  Atempt to locate the required DLL within the toolset library
240
        **  path.
241
        **
242
        **  A bit ugly
243
        **      - Take the name of required assembly
244
        **      - Tac a .DLL to the end
245
        **      - Attempt to locate it in the configured EnvVar
246
        **      - If found, then load it
247
        **          - Check that its the correct version
248
        */
249
        static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
250
        {
251
            if (par.Verbose > 0 )
252
            {
253
                Console.WriteLine("Need to Resolve: " + args.Name);
254
            }
255
            string Name =  args.Name.Split(',')[0] + ".DLL";
256
 
257
            foreach (string Var in par.EnvPath )
258
            {
259
                if (par.Verbose > 0 )
260
                    Console.WriteLine("Use EnvVar: " + Var);
261
                string Path = Environment.GetEnvironmentVariable(Var);
262
 
263
                /*
264
                **  Ignore EnvVars that don't exist
265
                */
266
                if ( Path == null )
267
                    continue;
268
 
269
                /*
270
                **  The EnvVar is a ; sep list of dirs
271
                **  Walk the list looking for a suitable DLL
272
                */
273
                foreach (string dir in Path.Split(';') )
274
                {
275
                    if (par.Verbose > 0 )
276
                        Console.WriteLine("   Path:" + dir);
277
 
278
                    if (File.Exists( dir + "\\" + Name ) )
279
                    {
280
                        if (par.Verbose > 0 )
281
                            Console.WriteLine("" + Name + " Found in: " + dir);
282
                        Assembly assembly = Assembly.LoadFrom(dir + "\\" + Name);
283
                        if ( assembly != null )
284
                        {
285
                            if (par.Verbose > 0 )
286
                                Console.WriteLine("" + Name + " Called: " + assembly.GetName());
287
                            if(String.Compare(assembly.GetName().FullName, args.Name) == 0)
288
                            {
289
                                return assembly;
290
                            }
291
 
292
                            if (par.Verbose > 0 )
293
                            {
294
                                Console.WriteLine("Assembly Name Mismatch");
295
                                Console.WriteLine("   " + assembly.GetName().FullName);
296
                                Console.WriteLine("   " + args.Name);
297
                            }
298
                        }
299
                    }
300
                }
301
            }
302
 
303
            /*
304
            **  Not found
305
            **  Let the loader report the error
306
            */
307
            return null;
308
        }
309
    }
310
}