1 |
// CS Webservice to CS Client conversion |
/* -*- csharp -*- mode please |
2 |
// |
* |
3 |
|
* C# Webservice to C# Webservice Consumer conversion |
4 |
|
* |
5 |
|
* Copyright (C) 2001, 2003 Southern Storm Software, Pty Ltd. |
6 |
|
* |
7 |
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
* it under the terms of the GNU General Public License as published by |
9 |
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
* (at your option) any later version. |
11 |
|
* |
12 |
|
* This program is distributed in the hope that it will be useful, |
13 |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
|
* GNU General Public License for more details. |
16 |
|
* |
17 |
|
* You should have received a copy of the GNU General Public License |
18 |
|
* along with this program; if not, write to the Free Software |
19 |
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
|
* |
21 |
|
* Authors: |
22 |
|
* Adam Ballai |
23 |
|
* Chris Smith |
24 |
|
* Nicolai P Guba |
25 |
|
* |
26 |
|
* $Revision$ |
27 |
|
*/ |
28 |
|
|
29 |
using System; |
using System; |
30 |
|
using System.Web; |
31 |
|
using System.Web.Services; |
32 |
using System.Reflection; |
using System.Reflection; |
33 |
using DotGNU.XmlRpc; |
using DotGNU.XmlRpc; |
34 |
using System.Text; |
using System.Text; |
35 |
using System.IO; |
using System.IO; |
36 |
|
|
37 |
|
public class Options |
38 |
|
{ |
39 |
|
private bool verbose = false; |
40 |
|
private bool help = false; |
41 |
|
|
42 |
|
public bool Verbose |
43 |
|
{ |
44 |
|
set { |
45 |
|
verbose = value; |
46 |
|
} |
47 |
|
get { |
48 |
|
return verbose; |
49 |
|
} |
50 |
|
} |
51 |
|
|
52 |
|
public bool Help |
53 |
|
{ |
54 |
|
set { |
55 |
|
help = value; |
56 |
|
} |
57 |
|
get { |
58 |
|
return help; |
59 |
|
} |
60 |
|
} |
61 |
|
} |
62 |
|
|
63 |
public class CSWS2Client |
public class CSWS2Client |
64 |
{ |
{ |
65 |
private TextWriter writer; |
private TextWriter writer; |
66 |
private String serviceName; |
private String serviceName; |
67 |
private String webName; |
private String webName; |
68 |
private String[] typeArray; |
private String[] typeArray; |
69 |
private String xmlrpcUrl; |
private String xmlrpcUrl; |
70 |
private String classname; |
private String classname; |
71 |
|
private String inputFile; |
72 |
internal String type_mapping( Type cs_type ) |
|
73 |
{ |
internal static String IndentStr = ""; |
74 |
String type; |
private const char indentChar = ' '; |
75 |
|
private int indentLevel = 0; |
76 |
type = "unsupported"; |
private int tabWidth = 2; |
77 |
|
|
78 |
switch( (type = cs_type.ToString()) ) |
private Options opt = new Options(); |
79 |
{ |
|
80 |
case "System.String": type = "string"; break; |
// Sets the indentation to the next level |
81 |
case "System.Int32" : type = "int"; break; |
private void IndentStatement () |
82 |
case "System.Int64" : /* unsupported */ break; |
{ |
83 |
case "System.Double": type = "double"; break; |
indentLevel++; |
84 |
case "System.Single": type = "double"; break; |
SetIndentStr(); |
85 |
case "System.Bool" : type = "boolean"; break; |
} |
86 |
|
|
87 |
|
// Reduces the indentation by one level |
88 |
|
private void UnIndentStatement () |
89 |
|
{ |
90 |
|
if (indentLevel > 0) { |
91 |
|
indentLevel--; |
92 |
|
SetIndentStr(); |
93 |
|
} |
94 |
|
} |
95 |
|
|
96 |
|
// Sets the IndentStr variable to the right spacing |
97 |
|
private void SetIndentStr() |
98 |
|
{ |
99 |
|
String s = ""; |
100 |
|
for (int i = 0; i < (indentLevel * tabWidth); i++) { |
101 |
|
s += indentChar; |
102 |
|
} |
103 |
|
IndentStr = s; |
104 |
|
//writer.WriteLine("{0}// IndentLevel={1}", IndentStr, indentLevel); |
105 |
|
} |
106 |
|
|
107 |
|
|
108 |
|
internal String type_mapping( Type cs_type ) |
109 |
|
{ |
110 |
|
String type; |
111 |
|
|
112 |
|
type = "unsupported"; |
113 |
|
|
114 |
|
switch( (type = cs_type.ToString()) ) |
115 |
|
{ |
116 |
|
case "System.String": type = "string"; break; |
117 |
|
case "System.Int32" : type = "int"; break; |
118 |
|
case "System.Int64" : /* unsupported */ break; |
119 |
|
case "System.Double": type = "double"; break; |
120 |
|
case "System.Single": type = "double"; break; |
121 |
|
case "System.Bool" : type = "boolean"; break; |
122 |
|
|
123 |
default: break; |
default: break; |
124 |
|
|
125 |
} |
} |
126 |
return type; |
return type; |
127 |
} |
} |
128 |
|
|
129 |
internal int ProcessMethod(Attribute attr, |
internal void WriteCopyright () |
130 |
MethodInfo method) |
{ |
131 |
{ |
writer.WriteLine ("/* -*- csharp -*- mode please |
132 |
int count = 0; |
* |
133 |
|
* Autogenerated C# Webservice Consumer |
134 |
Console.Write( "[{0}] ", method.Name ); |
* |
135 |
//serviceName = GetServiceAttribute(method).ToString(); |
* Copyright (C) 2001, 2003 dotGNU Project |
136 |
writer.Write("\t\t[XmlRpcMethod(\""+method.Name+"\")]\n\t\tpublic "+method.ReturnType+" "+method.Name+" ( "); |
* |
137 |
|
* This program is free software; you can redistribute it and/or modify |
138 |
ParameterInfo []pinfos=method.GetParameters(); |
* it under the terms of the GNU General Public License as published by |
139 |
String parameters = String.Empty; |
* the Free Software Foundation; either version 2 of the License, or |
140 |
String argsObj = String.Empty; |
* (at your option) any later version. |
141 |
foreach(ParameterInfo pinfo in pinfos) |
* |
142 |
{ |
* This program is distributed in the hope that it will be useful, |
143 |
parameters += pinfo.ParameterType + " " + pinfo.Name + ", "; |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
144 |
argsObj += pinfo.Name + ", "; |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
145 |
} |
* GNU General Public License for more details. |
146 |
|
* |
147 |
// remove last comma |
* You should have received a copy of the GNU General Public License |
148 |
parameters = parameters.Remove(parameters.Length-2,2); |
* along with this program; if not, write to the Free Software |
149 |
argsObj = argsObj.Remove(argsObj.Length-2,2); |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
150 |
|
* |
151 |
writer.Write(parameters); |
*/ |
152 |
writer.Write(" )\n\t\t\t{\n"); |
" |
153 |
|
); |
154 |
|
} |
155 |
writer.Write("\t\t\t\txmlclient = new XmlRpcClientProtocol(typeof("+classname+"));\n"); |
|
156 |
writer.Write("\t\t\t\tXmlRpcRequest reqStream = new XmlRpcRequest();\n"); |
internal void WriteIncludes () |
157 |
writer.Write("\t\t\t\treqStream.method = \""+ method.Name + "\";\n"); |
{ |
158 |
writer.Write("\t\t\t\treqStream.args = new Object[] { "+ argsObj + " };\n"); |
writer.WriteLine( "using System;"); |
159 |
writer.Write("\t\t\t\tXmlRpcResponse resp = xmlclient.Invoke(reqStream);\n"); |
writer.WriteLine( "using DotGNU.XmlRpc;" ); |
160 |
writer.Write("\t\t\t\treturn ("+method.ReturnType+")resp.retVal;\n"); |
writer.WriteLine(); |
161 |
writer.Write("\t\t\t}\n\n"); |
} |
162 |
count++; |
|
163 |
return count; |
internal WebServiceAttribute GetServiceAttribute( Type type ) |
164 |
} |
{ |
165 |
|
Attribute[] attrs = |
166 |
|
Attribute.GetCustomAttributes( type, typeof(WebServiceAttribute), false ); |
167 |
internal WebServiceAttribute GetServiceAttribute(Type type) |
if( attrs == null ) { |
168 |
{ |
return null; |
169 |
Attribute[] attrs = Attribute.GetCustomAttributes(type |
} |
170 |
,typeof(WebServiceAttribute) |
|
171 |
,false); |
if( attrs.Length == 1 ){ |
172 |
if(attrs==null) |
return (WebServiceAttribute)attrs[0]; |
173 |
{ |
} |
174 |
return null; |
return null; |
175 |
} |
} |
176 |
if(attrs.Length==1) |
|
177 |
{ |
internal WebMethodAttribute GetAttribute( MethodInfo method ) |
178 |
return (WebServiceAttribute)attrs[0]; |
{ |
179 |
} |
Attribute[] attrs = |
180 |
return null; |
Attribute.GetCustomAttributes( method, typeof(WebMethodAttribute), false ); |
181 |
} |
|
182 |
|
if( attrs == null ) { |
183 |
internal WebMethodAttribute GetAttribute(MethodInfo method) |
return null; |
184 |
{ |
} |
185 |
Attribute[] attrs = Attribute.GetCustomAttributes( method |
if( attrs.Length == 1 ) { |
186 |
,typeof(WebMethodAttribute) |
return (WebMethodAttribute)attrs[0]; |
187 |
,false); |
} |
188 |
if(attrs==null) |
return null; |
189 |
{ |
} |
190 |
return null; |
|
191 |
} |
internal int ProcessType( Type type ) |
192 |
if(attrs.Length==1) |
{ |
193 |
{ |
String desc; |
194 |
return (WebMethodAttribute)attrs[0]; |
String ns; |
195 |
} |
int count = 0; |
196 |
return null; |
|
197 |
} |
Attribute attr = GetServiceAttribute( type ); |
198 |
|
|
199 |
|
if( attr != null ) { |
200 |
internal int ProcessType(Type type) |
desc = ((WebServiceAttribute)attr).Description; |
201 |
{ |
ns = ((WebServiceAttribute)attr).Namespace; |
202 |
String desc; |
|
203 |
String ns; |
if( ns == null ) { |
204 |
int count = 0; |
ns = "http://tempuri.org"; |
205 |
|
}; |
206 |
Attribute attr = GetServiceAttribute(type); |
} |
207 |
if(attr!=null) |
|
208 |
{ |
if( opt.Verbose ) { |
209 |
desc = ((WebServiceAttribute)attr).Description; |
Console.Write( "Processing {0}: ", type.ToString() ); |
210 |
ns = ((WebServiceAttribute)attr).Namespace; |
} |
211 |
if(ns == null) { ns = "http://tempuri.org"; }; |
|
212 |
} |
xmlrpcUrl = ns + "/" + webName; |
213 |
|
classname = typeArray[typeArray.Length-1]; |
214 |
Console.Write( "Processing {0}: ", type.ToString() ); |
|
215 |
|
writer.WriteLine(); |
216 |
xmlrpcUrl = ns + "/" + webName; |
writer.WriteLine( "{0}//", IndentStr ); |
217 |
classname = typeArray[typeArray.Length-1]; |
writer.WriteLine( "{0}// Class {1}", IndentStr, classname ); |
218 |
writer.Write("\t[XmlRpcUrl(\""+xmlrpcUrl+"\")]\n" ); |
writer.WriteLine( "{0}//", IndentStr ); |
219 |
writer.Write("\tpublic class "+classname+"\n\t{\n"); |
writer.WriteLine( "{0}[XmlRpcUrl(\"{1}\")]", IndentStr, xmlrpcUrl ); |
220 |
|
writer.WriteLine( "{0}public class {1}", IndentStr, classname ); |
221 |
writer.Write("\t\tprivate XmlRpcClientProtocol xmlclient;\n"); |
writer.WriteLine( "{0}{{ ", IndentStr ); |
222 |
|
|
223 |
MethodInfo []methods = type.GetMethods( BindingFlags.Public |
IndentStatement(); |
224 |
| BindingFlags.Static); |
writer.WriteLine( "{0}private XmlRpcClientProtocol xmlclient;", IndentStr ); |
225 |
foreach(MethodInfo method in methods) |
|
226 |
{ |
// Retrieve the methods for this class via reflection and process |
227 |
Attribute attr = GetAttribute(method); |
// them iteratively |
228 |
if(attr!=null) |
MethodInfo []methods = |
229 |
{ |
type.GetMethods( BindingFlags.Public | BindingFlags.Static); |
230 |
count += ProcessMethod(attr,method); |
|
231 |
} |
foreach( MethodInfo method in methods ) { |
232 |
} |
// Process the parameter list for the method |
233 |
|
Attribute attr = GetAttribute( method ); |
234 |
writer.Write("\n}"); |
|
235 |
|
if( attr != null ) { |
236 |
return count; |
// Process the methods body |
237 |
} |
count += ProcessMethod( attr, method ); |
238 |
|
} |
239 |
|
} |
240 |
|
UnIndentStatement(); |
241 |
|
writer.WriteLine( "{0}}}", IndentStr ); |
242 |
|
return count; |
243 |
|
} |
244 |
|
|
245 |
internal int ProcessDll(String dllName) |
internal int ProcessMethod( Attribute attr, MethodInfo method ) |
246 |
{ |
{ |
247 |
int done = 0; |
int count = 0; |
248 |
dllName = Path.GetFullPath(dllName); |
|
249 |
String prefix = Path.GetFileNameWithoutExtension(dllName); |
if( opt.Verbose ) { |
250 |
//webName = prefix + ".dgmx"; |
Console.Write( "[{0}] ", method.Name ); |
251 |
FileStream fs = new FileStream( prefix + "Client.cs", FileMode.Create ); |
} |
252 |
|
|
253 |
writer = new StreamWriter( fs, Encoding.ASCII ); |
//serviceName = GetServiceAttribute(method).ToString(); |
254 |
Console.WriteLine( "Scanning assembly '{0}'", dllName ); |
|
255 |
|
writer.WriteLine(); |
256 |
writer.Write("using System;\nusing DotGNU.XmlRpc;\n"); |
writer.WriteLine( "{0}[XmlRpcMethod(\"{1}\")]", IndentStr, method.Name); |
257 |
writer.Write("namespace DGMXClient\n{\n"); |
writer.Write( "{0}public {1} {2}", IndentStr, method.ReturnType, method.Name); |
258 |
|
|
259 |
Assembly ass = Assembly.LoadFrom(dllName); |
ParameterInfo []pinfos = method.GetParameters(); |
260 |
|
String parameters = String.Empty; |
261 |
Type[] types=ass.GetTypes(); |
String argsObj = String.Empty; |
262 |
|
|
263 |
foreach(Type type in types) |
foreach( ParameterInfo pinfo in pinfos ) { |
264 |
{ |
parameters += pinfo.ParameterType + " " + pinfo.Name + ", "; |
265 |
typeArray = type.ToString().Split('.'); |
argsObj += pinfo.Name + ", "; |
266 |
if(type.ToString()!="<Module>") done += ProcessType(type); |
} |
267 |
} |
// remove last comma |
268 |
|
parameters = parameters.Remove( (parameters.Length - 2), 2 ); |
269 |
writer.Write("\n}\n\n"); |
argsObj = argsObj.Remove( (argsObj.Length - 2), 2 ); |
270 |
|
|
271 |
writer.Flush(); |
writer.WriteLine( "( {0} ) ", parameters ); |
272 |
writer.Close(); |
writer.WriteLine( "{0}{{", IndentStr ); |
273 |
|
|
274 |
Console.WriteLine( "\n{0} exported methods found.", done ); |
IndentStatement(); |
275 |
Console.WriteLine( "Output written to {0}", prefix+"Client.cs" ); |
writer.WriteLine( "{0}xmlclient = new XmlRpcClientProtocol( typeof( {1} ) );", IndentStr, classname ); |
276 |
|
writer.WriteLine( "{0}XmlRpcRequest reqStream = new XmlRpcRequest();", IndentStr ); |
277 |
return done; |
writer.WriteLine( "{0}reqStream.Method = \"{1}\";", IndentStr, method.Name ); |
278 |
} |
writer.WriteLine( "{0}reqStream.Arguments = new Object[] {{{1}}};", IndentStr, argsObj ); |
279 |
|
writer.WriteLine( "{0}XmlRpcResponse resp = xmlclient.Invoke( reqStream );", IndentStr ); |
280 |
|
writer.WriteLine( "{0}return ({1})resp.retVal;", IndentStr, method.ReturnType ); |
281 |
internal void ProcessArgs(String []args) |
|
282 |
{ |
UnIndentStatement(); |
283 |
int done; |
writer.WriteLine( "{0}}}", IndentStr ); |
284 |
|
count++; |
285 |
foreach(String arg in args) |
return count; |
286 |
{ |
} |
287 |
if(arg.EndsWith(".dll")) |
|
288 |
{ |
internal int ProcessDll( String dllName ) |
289 |
done = ProcessDll(arg); |
{ |
290 |
if( done == 0 ) |
int done = 0; |
291 |
{ |
dllName = Path.GetFullPath( dllName ); |
292 |
Console.WriteLine( "No Exportable information found!!!" ); |
String prefix = Path.GetFileNameWithoutExtension( dllName ); |
293 |
} |
//webName = prefix + ".dgmx"; |
294 |
} |
FileStream fs = new FileStream( prefix + "Client.cs", FileMode.Create ); |
295 |
else |
|
296 |
{ |
writer = new StreamWriter( fs, Encoding.ASCII ); |
297 |
Console.WriteLine( "Supplied filename does not end with .dll" ); |
|
298 |
} |
if( opt.Verbose ) { |
299 |
} |
Console.WriteLine( "Scanning assembly '{0}'", dllName ); |
300 |
|
} |
301 |
|
|
302 |
|
// Set the header information |
303 |
|
WriteCopyright(); |
304 |
|
WriteIncludes(); |
305 |
|
|
306 |
|
writer.WriteLine ( "namespace DGMXClient\n{" ); |
307 |
|
IndentStatement(); |
308 |
|
|
309 |
|
// Load the aseembly from its dll and get the type info via |
310 |
|
// reflection, processing each type detected |
311 |
|
Assembly ass = Assembly.LoadFrom( dllName ); |
312 |
|
Type[] types = ass.GetTypes(); |
313 |
|
|
314 |
|
foreach( Type type in types ) { |
315 |
|
typeArray = type.ToString().Split( '.' ); |
316 |
|
|
317 |
|
if( type.ToString() != "<Module>" ) { |
318 |
|
done += ProcessType(type); |
319 |
|
} |
320 |
|
} |
321 |
|
|
322 |
|
writer.WriteLine( "}" ); |
323 |
|
|
324 |
|
writer.Flush(); |
325 |
|
writer.Close(); |
326 |
|
|
327 |
|
if( opt.Verbose ) { |
328 |
|
Console.WriteLine( "\n{0} exported methods found.", done ); |
329 |
|
Console.WriteLine( "Output written to {0}", prefix + "Client.cs" ); |
330 |
|
} |
331 |
|
|
332 |
|
return done; |
333 |
|
} |
334 |
|
|
335 |
|
internal void printHelp () |
336 |
|
{ |
337 |
|
Console.WriteLine( "Usage: csws2client [OPTION]... FILENAME.DLL"); |
338 |
|
Console.WriteLine( "Generates a Webservice Consumer for the Webservice FILENAME.DLL"); |
339 |
|
Console.WriteLine(); |
340 |
|
Console.WriteLine( " -v verbose output"); |
341 |
|
Console.WriteLine( " -h print help and exit"); |
342 |
|
Console.WriteLine(); |
343 |
|
Console.WriteLine( "Report bugs to <developers@dotgnu.org>"); |
344 |
|
} |
345 |
|
|
346 |
|
internal void MainLoop() |
347 |
|
{ |
348 |
|
int done; |
349 |
|
|
350 |
|
if( opt.Help ) { |
351 |
|
printHelp(); |
352 |
|
return; |
353 |
|
} |
354 |
|
|
355 |
|
if( opt.Verbose ) { |
356 |
|
Console.WriteLine( "DotGNU Execution Environment" ); |
357 |
|
Console.WriteLine( "Client Generation tool - (c)2003 netFluid Technology Ltd" ); |
358 |
|
Console.WriteLine( "And (c)2003 Adam Ballai, Cannibutter Software"); |
359 |
|
Console.WriteLine( "And (c)2003 Nicolai P Guba, dotGNU Project"); |
360 |
|
Console.WriteLine( "\nThis software comes with ABSOLUTELY NO WARRANTY. This is free software," ); |
361 |
|
Console.WriteLine( "and you are welcome to modify and redistribute it under the GPL licence.\n"); |
362 |
|
} |
363 |
|
|
364 |
|
try { |
365 |
|
if( inputFile != null ) { |
366 |
|
done = ProcessDll( inputFile ); |
367 |
|
|
368 |
|
if( done == 0 ) { |
369 |
|
Console.WriteLine( "No Exportable information found!!!" ); |
370 |
|
} |
371 |
|
} |
372 |
|
else { |
373 |
|
Console.WriteLine( "No input file given: Please supply the DLL of a WebService" ); |
374 |
|
} |
375 |
|
} |
376 |
|
catch (FileNotFoundException e) { |
377 |
|
Console.WriteLine( "{0}: File Not Found", inputFile ); |
378 |
|
} |
379 |
|
} |
380 |
|
|
381 |
|
internal void ProcessArgs( String[] args ) |
382 |
|
{ |
383 |
|
foreach( String arg in args ) { |
384 |
|
|
385 |
|
// Check for command line parameters here (is there a getopt for |
386 |
|
// c# ????) |
387 |
|
switch (arg) { |
388 |
|
case "-v": |
389 |
|
opt.Verbose = true; |
390 |
|
break; |
391 |
|
|
392 |
|
case "-h": |
393 |
|
opt.Help = true; |
394 |
|
break; |
395 |
|
|
396 |
|
default: |
397 |
|
if( arg.EndsWith( ".dll" ) ) { |
398 |
|
inputFile = arg; |
399 |
} |
} |
400 |
|
else { |
401 |
|
Console.WriteLine( "{0}: Invalid argument or file name", arg); |
|
public static void Main(String []args) |
|
|
{ |
|
|
CSWS2Client dd = new CSWS2Client(); |
|
|
|
|
|
Console.WriteLine( "DotGNU Execution Environment" ); |
|
|
Console.WriteLine( "Client Generation tool - (c)2003 netFluid Technology Ltd" ); |
|
|
Console.WriteLine( "And (c)2003 Adam Ballai, Cannibutter Software"); |
|
|
Console.WriteLine( "\nThis software comes with ABSOLUTELY NO WARRANTY. This is free software," ); |
|
|
Console.WriteLine( "and you are welcome to modify and redistribute it under the GPL licence.\n"); |
|
|
|
|
|
if(args.Length < 1) |
|
|
{ |
|
|
Console.WriteLine( "Please supply the filename of a webservice" ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
dd.ProcessArgs(args); |
|
|
} |
|
402 |
} |
} |
403 |
|
break; |
404 |
|
} |
405 |
|
} |
406 |
|
} |
407 |
|
|
408 |
|
|
409 |
|
public static void Main( String[] args ) |
410 |
|
{ |
411 |
|
CSWS2Client dd = new CSWS2Client(); |
412 |
|
dd.ProcessArgs( args ); |
413 |
|
dd.MainLoop(); |
414 |
|
} |
415 |
} |
} |