Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

264 lines
7.6 KiB
C#

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Collections.ObjectModel;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Web.Services;
using System.Web.Services.Discovery;
using System.Collections.Generic;
using System.Runtime.Serialization;
using WSServiceDescrition = System.Web.Services.Description.ServiceDescription;
namespace Mono.ServiceContractTool
{
public class Driver
{
public static void Main (string [] args)
{
new Driver ().Run (args);
}
CommandLineOptions co = new CommandLineOptions ();
ServiceContractGenerator generator;
CodeDomProvider code_provider;
void Run (string [] args)
{
co.ProcessArgs (args);
if (co.Usage) {
co.DoUsage ();
return;
}
if (co.Version) {
co.DoVersion ();
return;
}
if (co.Help || co.RemainingArguments.Count == 0) {
co.DoHelp ();
return;
}
if (!co.NoLogo)
co.ShowBanner ();
CodeCompileUnit ccu = new CodeCompileUnit ();
CodeNamespace cns = new CodeNamespace (co.Namespace);
ccu.Namespaces.Add (cns);
generator = new ServiceContractGenerator (ccu);
generator.Options = GetGenerationOption ();
generator.Options |=ServiceContractGenerationOptions.ChannelInterface;
code_provider = GetCodeProvider ();
MetadataSet metadata = null;
// For now only assemblyPath is supported.
foreach (string arg in co.RemainingArguments) {
if (!File.Exists (arg)) {
Uri uri = null;
if (Uri.TryCreate (arg, UriKind.Absolute, out uri)) {
metadata = ResolveWithDisco (arg);
if (metadata == null)
metadata = ResolveWithWSMex (arg);
continue;
}
} else {
FileInfo fi = new FileInfo (arg);
switch (fi.Extension) {
case ".exe":
case ".dll":
GenerateContractType (fi.FullName);
break;
default:
throw new NotSupportedException ("Not supported file extension: " + fi.Extension);
}
}
}
if (metadata != null)
{
List<IWsdlImportExtension> list = new List<IWsdlImportExtension> ();
list.Add (new TransportBindingElementImporter ());
//list.Add (new DataContractSerializerMessageContractImporter ());
list.Add (new XmlSerializerMessageContractImporter ());
//WsdlImporter importer = new WsdlImporter (metadata, null, list);
WsdlImporter importer = new WsdlImporter (metadata);
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints ();
Collection<ContractDescription> contracts = new Collection<ContractDescription> ();
if (endpoints.Count > 0) {
foreach (var se in endpoints)
contracts.Add (se.Contract);
} else {
foreach (var cd in importer.ImportAllContracts ())
contracts.Add (cd);
}
Console.WriteLine ("Generating files..");
// FIXME: could better become IWsdlExportExtension
foreach (ContractDescription cd in contracts) {
if (co.GenerateMoonlightProxy) {
var moonctx = new MoonlightChannelBaseContext ();
cd.Behaviors.Add (new MoonlightChannelBaseContractExtension (moonctx, co.GenerateMonoTouchProxy));
foreach (var od in cd.Operations)
od.Behaviors.Add (new MoonlightChannelBaseOperationExtension (moonctx, co.GenerateMonoTouchProxy));
generator.GenerateServiceContractType (cd);
moonctx.Fixup ();
}
else
generator.GenerateServiceContractType (cd);
}
}
/*if (cns.Types.Count == 0) {
Console.Error.WriteLine ("Argument assemblies have no types.");
Environment.Exit (1);
}*/
//FIXME: Generate .config
Console.WriteLine (GetOutputFilename ());
using (TextWriter w = File.CreateText (GetOutputFilename ())) {
code_provider.GenerateCodeFromCompileUnit (ccu, w, null);
}
}
MetadataSet ResolveWithDisco (string url)
{
DiscoveryClientProtocol prot = null;
Console.WriteLine ("\nAttempting to download metadata from '{0}' using DISCO..", url);
try {
prot = new DiscoveryClientProtocol ();
prot.DiscoverAny (url);
prot.ResolveAll ();
} catch (Exception e) {
Console.WriteLine ("Disco failed for the url '{0}' with exception :\n {1}", url, e.Message);
return null;
}
if (prot.References.Count > 0)
{
Console.WriteLine ("Disco found documents at the following URLs:");
foreach (DiscoveryReference refe in prot.References.Values)
{
if (refe is ContractReference) Console.Write ("- WSDL document at ");
else if (refe is DiscoveryDocumentReference) Console.Write ("- DISCO document at ");
else Console.Write ("- Xml Schema at ");
Console.WriteLine (refe.Url);
}
} else {
Console.WriteLine ("Disco didn't find any document at the specified URL");
return null;
}
MetadataSet metadata = new MetadataSet ();
foreach (object o in prot.Documents.Values) {
if (o is WSServiceDescrition) {
metadata.MetadataSections.Add (
new MetadataSection (MetadataSection.ServiceDescriptionDialect, "", (WSServiceDescrition) o));
}
if (o is XmlSchema) {
metadata.MetadataSections.Add (
new MetadataSection (MetadataSection.XmlSchemaDialect, "", (XmlSchema) o));
}
}
return metadata;
}
MetadataSet ResolveWithWSMex (string url)
{
MetadataSet metadata = null;
try {
MetadataExchangeClient client = new MetadataExchangeClient (new EndpointAddress (url));
Console.WriteLine ("\nAttempting to download metadata from {0} using WS-MetadataExchange..", url);
metadata = client.GetMetadata ();
} catch (InvalidOperationException e) {
//MetadataExchangeClient wraps exceptions, thrown while
//fetching the metadata, in an InvalidOperationException
string msg;
if (e.InnerException == null)
msg = e.Message;
else
msg = e.InnerException.ToString ();
Console.WriteLine ("WS-MetadataExchange query failed for the url '{0}' with exception :\n {1}",
url, msg);
}
return metadata;
}
CodeDomProvider GetCodeProvider ()
{
switch (co.Language) {
case "csharp":
case "cs":
return new Microsoft.CSharp.CSharpCodeProvider ();
case "vb":
return new Microsoft.VisualBasic.VBCodeProvider ();
default:
throw new NotSupportedException ();
}
}
void GenerateContractType (string file)
{
Assembly ass = Assembly.LoadFile (file);
foreach (Module m in ass.GetModules ())
foreach (Type t in m.GetTypes ())
ProcessType (t);
}
void ProcessType (Type type)
{
object [] a = type.GetCustomAttributes (
typeof (ServiceContractAttribute), true);
if (a.Length > 0)
generator.GenerateServiceContractType (
ContractDescription.GetContract (type));
}
ServiceContractGenerationOptions GetGenerationOption ()
{
ServiceContractGenerationOptions go =
ServiceContractGenerationOptions.ClientClass;
if (co.GenerateAsync)
go |= ServiceContractGenerationOptions.AsynchronousMethods;
if (co.ChannelInterface)
go |= ServiceContractGenerationOptions.ChannelInterface;
if (co.GenerateTypesAsInternal)
go |= ServiceContractGenerationOptions.InternalTypes;
if (co.GenerateProxy)
go |= ServiceContractGenerationOptions.ClientClass;
if (co.GenerateTypedMessages)
go |= ServiceContractGenerationOptions.TypedMessages;
if ((co.TargetClientVersion35 && co.GenerateAsync) || co.GenerateMoonlightProxy)
go |= ServiceContractGenerationOptions.EventBasedAsynchronousMethods;
return go;
}
string GetOutputFilename ()
{
if (co.OutputFilename != null)
return co.OutputFilename;
return "output." + code_provider.FileExtension;
}
}
}