2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / tools / svcutil / Driver.cs
blob315d461d11e879610955c2538228298e438e8e5f
1 using System;
2 using System.CodeDom;
3 using System.CodeDom.Compiler;
4 using System.IO;
5 using System.Reflection;
6 using System.ServiceModel;
7 using System.ServiceModel.Channels;
8 using System.ServiceModel.Description;
9 using System.ServiceModel.Dispatcher;
10 using System.Collections.ObjectModel;
11 using System.Xml;
12 using System.Xml.Schema;
13 using System.Xml.Serialization;
14 using System.Web.Services;
15 using System.Web.Services.Discovery;
17 using System.Collections.Generic;
18 using System.Runtime.Serialization;
20 using WSServiceDescrition = System.Web.Services.Description.ServiceDescription;
22 namespace Mono.ServiceContractTool
24 public class Driver
26 public static void Main (string [] args)
28 new Driver ().Run (args);
31 CommandLineOptions co = new CommandLineOptions ();
32 ServiceContractGenerator generator;
33 CodeDomProvider code_provider;
35 void Run (string [] args)
37 co.ProcessArgs (args);
38 if (co.Usage) {
39 co.DoUsage ();
40 return;
43 if (co.Version) {
44 co.DoVersion ();
45 return;
48 if (co.Help || co.RemainingArguments.Count == 0) {
49 co.DoHelp ();
50 return;
52 if (!co.NoLogo)
53 co.ShowBanner ();
55 CodeCompileUnit ccu = new CodeCompileUnit ();
56 CodeNamespace cns = new CodeNamespace (co.Namespace);
57 ccu.Namespaces.Add (cns);
59 generator = new ServiceContractGenerator (ccu);
60 generator.Options = GetGenerationOption ();
61 generator.Options |=ServiceContractGenerationOptions.ChannelInterface;
63 code_provider = GetCodeProvider ();
64 MetadataSet metadata = null;
66 // For now only assemblyPath is supported.
67 foreach (string arg in co.RemainingArguments) {
68 Uri uri = null;
69 if (Uri.TryCreate (arg, UriKind.Absolute, out uri)) {
70 metadata = ResolveWithDisco (arg);
71 if (metadata == null)
72 metadata = ResolveWithWSMex (arg);
74 continue;
77 FileInfo fi = new FileInfo (arg);
78 if (!fi.Exists)
79 switch (fi.Extension) {
80 case ".exe":
81 case ".dll":
82 GenerateContractType (fi.FullName);
83 break;
84 default:
85 throw new NotSupportedException ("Not supported file extension: " + fi.Extension);
89 if (metadata == null)
90 return;
92 List<IWsdlImportExtension> list = new List<IWsdlImportExtension> ();
93 list.Add (new TransportBindingElementImporter ());
94 //list.Add (new DataContractSerializerMessageContractImporter ());
95 list.Add (new XmlSerializerMessageContractImporter ());
97 //WsdlImporter importer = new WsdlImporter (metadata, null, list);
98 WsdlImporter importer = new WsdlImporter (metadata);
99 //ServiceEndpointCollection endpoints = importer.ImportAllEndpoints ();
101 Console.WriteLine ("Generating files..");
102 /*foreach (ServiceEndpoint se in endpoints)
103 generator.GenerateServiceContractType (se.Contract);*/
105 Collection<ContractDescription> contracts = importer.ImportAllContracts ();
106 foreach (ContractDescription cd in contracts) {
107 if (co.GenerateMoonlightProxy) {
108 var moonctx = new MoonlightChannelBaseContext ();
109 cd.Behaviors.Add (new MoonlightChannelBaseContractExtension (moonctx, co.GenerateMonoTouchProxy));
110 foreach (var od in cd.Operations)
111 od.Behaviors.Add (new MoonlightChannelBaseOperationExtension (moonctx, co.GenerateMonoTouchProxy));
112 generator.GenerateServiceContractType (cd);
113 moonctx.Fixup ();
115 else
116 generator.GenerateServiceContractType (cd);
119 /*if (cns.Types.Count == 0) {
120 Console.Error.WriteLine ("Argument assemblies have no types.");
121 Environment.Exit (1);
124 //FIXME: Generate .config
126 Console.WriteLine (GetOutputFilename ());
127 using (TextWriter w = File.CreateText (GetOutputFilename ())) {
128 code_provider.GenerateCodeFromCompileUnit (ccu, w, null);
132 MetadataSet ResolveWithDisco (string url)
134 DiscoveryClientProtocol prot = null;
135 Console.WriteLine ("\nAttempting to download metadata from '{0}' using DISCO..", url);
136 try {
137 prot = new DiscoveryClientProtocol ();
138 prot.DiscoverAny (url);
139 prot.ResolveAll ();
140 } catch (Exception e) {
141 Console.WriteLine ("Disco failed for the url '{0}' with exception :\n {1}", url, e.Message);
142 return null;
145 if (prot.References.Count > 0)
147 Console.WriteLine ("Disco found documents at the following URLs:");
148 foreach (DiscoveryReference refe in prot.References.Values)
150 if (refe is ContractReference) Console.Write ("- WSDL document at ");
151 else if (refe is DiscoveryDocumentReference) Console.Write ("- DISCO document at ");
152 else Console.Write ("- Xml Schema at ");
153 Console.WriteLine (refe.Url);
155 } else {
156 Console.WriteLine ("Disco didn't find any document at the specified URL");
157 return null;
160 MetadataSet metadata = new MetadataSet ();
161 foreach (object o in prot.Documents.Values) {
162 if (o is WSServiceDescrition) {
163 metadata.MetadataSections.Add (
164 new MetadataSection (MetadataSection.ServiceDescriptionDialect, "", (WSServiceDescrition) o));
166 if (o is XmlSchema) {
167 metadata.MetadataSections.Add (
168 new MetadataSection (MetadataSection.XmlSchemaDialect, "", (XmlSchema) o));
172 return metadata;
175 MetadataSet ResolveWithWSMex (string url)
177 MetadataSet metadata = null;
178 try {
179 MetadataExchangeClient client = new MetadataExchangeClient (new EndpointAddress (url));
181 Console.WriteLine ("\nAttempting to download metadata from {0} using WS-MetadataExchange..", url);
182 metadata = client.GetMetadata ();
183 } catch (InvalidOperationException e) {
184 //MetadataExchangeClient wraps exceptions, thrown while
185 //fetching the metadata, in an InvalidOperationException
186 string msg;
187 if (e.InnerException == null)
188 msg = e.Message;
189 else
190 msg = e.InnerException.ToString ();
192 Console.WriteLine ("WS-MetadataExchange query failed for the url '{0}' with exception :\n {1}",
193 url, msg);
196 return metadata;
199 CodeDomProvider GetCodeProvider ()
201 switch (co.Language) {
202 case "csharp":
203 case "cs":
204 return new Microsoft.CSharp.CSharpCodeProvider ();
205 case "vb":
206 return new Microsoft.VisualBasic.VBCodeProvider ();
207 default:
208 throw new NotSupportedException ();
212 void GenerateContractType (string file)
214 Assembly ass = Assembly.LoadFile (file);
215 foreach (Module m in ass.GetModules ())
216 foreach (Type t in m.GetTypes ())
217 ProcessType (t);
220 void ProcessType (Type type)
222 object [] a = type.GetCustomAttributes (
223 typeof (ServiceContractAttribute), true);
224 if (a.Length > 0)
225 generator.GenerateServiceContractType (
226 ContractDescription.GetContract (type));
229 ServiceContractGenerationOptions GetGenerationOption ()
231 ServiceContractGenerationOptions go =
232 ServiceContractGenerationOptions.ClientClass;
233 if (co.GenerateAsync)
234 go |= ServiceContractGenerationOptions.AsynchronousMethods;
235 if (co.ChannelInterface)
236 go |= ServiceContractGenerationOptions.ChannelInterface;
237 if (co.GenerateTypesAsInternal)
238 go |= ServiceContractGenerationOptions.InternalTypes;
239 if (co.GenerateProxy)
240 go |= ServiceContractGenerationOptions.ClientClass;
241 if (co.GenerateTypedMessages)
242 go |= ServiceContractGenerationOptions.TypedMessages;
243 if ((co.TargetClientVersion35 && co.GenerateAsync) || co.GenerateMoonlightProxy)
244 go |= ServiceContractGenerationOptions.EventBasedAsynchronousMethods;
246 return go;
249 string GetOutputFilename ()
251 if (co.OutputFilename != null)
252 return co.OutputFilename;
253 return "output." + code_provider.FileExtension;