| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Description
- {
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.IO;
- using System.Net;
- using System.Net.Mime;
- using System.Runtime;
- using System.Runtime.Diagnostics;
- using System.Security;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Configuration;
- using System.ServiceModel.Diagnostics;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Xml;
- using WsdlNS = System.Web.Services.Description;
- using XsdNS = System.Xml.Schema;
- public class MetadataExchangeClient
- {
- ChannelFactory<IMetadataExchange> factory;
- ICredentials webRequestCredentials;
- TimeSpan resolveTimeout = TimeSpan.FromMinutes(1);
- int maximumResolvedReferences = 10;
- bool resolveMetadataReferences = true;
- long maxMessageSize;
- XmlDictionaryReaderQuotas readerQuotas;
- EndpointAddress ctorEndpointAddress = null;
- Uri ctorUri = null;
- object thisLock = new object();
- internal const string MetadataExchangeClientKey = "MetadataExchangeClientKey";
- public MetadataExchangeClient()
- {
- this.factory = new ChannelFactory<IMetadataExchange>("*");
- this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
- }
- public MetadataExchangeClient(Uri address, MetadataExchangeClientMode mode)
- {
- Validate(address, mode);
- if (mode == MetadataExchangeClientMode.HttpGet)
- {
- this.ctorUri = address;
- }
- else
- {
- this.ctorEndpointAddress = new EndpointAddress(address);
- }
- CreateChannelFactory(address.Scheme);
- }
- public MetadataExchangeClient(EndpointAddress address)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- this.ctorEndpointAddress = address;
- CreateChannelFactory(address.Uri.Scheme);
- }
- public MetadataExchangeClient(string endpointConfigurationName)
- {
- if (endpointConfigurationName == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
- }
- this.factory = new ChannelFactory<IMetadataExchange>(endpointConfigurationName);
- this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
- }
- public MetadataExchangeClient(Binding mexBinding)
- {
- if (mexBinding == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("mexBinding");
- }
- this.factory = new ChannelFactory<IMetadataExchange>(mexBinding);
- this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
- }
- //Configuration for credentials
- public ClientCredentials SoapCredentials
- {
- get { return this.factory.Credentials; }
- set
- {
- if (value == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
- }
- this.factory.Endpoint.Behaviors.RemoveAll<ClientCredentials>();
- this.factory.Endpoint.Behaviors.Add(value);
- }
- }
- public ICredentials HttpCredentials
- {
- get { return this.webRequestCredentials; }
- set { this.webRequestCredentials = value; }
- }
- // Configuration options for the entire MetadataResolver
- public TimeSpan OperationTimeout
- {
- get { return this.resolveTimeout; }
- set
- {
- if (value < TimeSpan.Zero)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
- SR.GetString(SR.SFxTimeoutOutOfRange0)));
- }
- if (TimeoutHelper.IsTooLarge(value))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
- SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
- }
- this.resolveTimeout = value;
- }
- }
- public int MaximumResolvedReferences
- {
- get { return this.maximumResolvedReferences; }
- set
- {
- if (value < 1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxMaximumResolvedReferencesOutOfRange, value)));
- }
- this.maximumResolvedReferences = value;
- }
- }
- public bool ResolveMetadataReferences
- {
- get { return this.resolveMetadataReferences; }
- set { this.resolveMetadataReferences = value; }
- }
- internal object ThisLock
- {
- get { return this.thisLock; }
- }
- internal long MaxMessageSize
- {
- get { return this.maxMessageSize; }
- set { this.maxMessageSize = value; }
- }
- internal XmlDictionaryReaderQuotas ReaderQuotas
- {
- get
- {
- if (this.readerQuotas == null)
- {
- if (this.factory != null)
- {
- BindingElementCollection bindingElementCollection = this.factory.Endpoint.Binding.CreateBindingElements();
- if (bindingElementCollection != null)
- {
- MessageEncodingBindingElement bindingElement = bindingElementCollection.Find<MessageEncodingBindingElement>();
- if (bindingElement != null)
- {
- this.readerQuotas = bindingElement.GetIndividualProperty<XmlDictionaryReaderQuotas>();
- }
- }
- }
- this.readerQuotas = this.readerQuotas ?? EncoderDefaults.ReaderQuotas;
- }
- return this.readerQuotas;
- }
- }
- [Fx.Tag.SecurityNote(Critical = "Uses ClientSection.UnsafeGetSection to get config in PT.",
- Safe = "Does not leak config object, just calculates a bool.")]
- [SecuritySafeCritical]
- bool ClientEndpointExists(string name)
- {
- ClientSection clientSection = ClientSection.UnsafeGetSection();
- if (clientSection == null)
- return false;
- foreach (ChannelEndpointElement endpoint in clientSection.Endpoints)
- {
- if (endpoint.Name == name && endpoint.Contract == ServiceMetadataBehavior.MexContractName)
- return true;
- }
- return false;
- }
- bool IsHttpOrHttps(Uri address)
- {
- return address.Scheme == Uri.UriSchemeHttp || address.Scheme == Uri.UriSchemeHttps;
- }
- void CreateChannelFactory(string scheme)
- {
- if (ClientEndpointExists(scheme))
- {
- this.factory = new ChannelFactory<IMetadataExchange>(scheme);
- }
- else
- {
- Binding mexBinding = null;
- if (MetadataExchangeBindings.TryGetBindingForScheme(scheme, out mexBinding))
- {
- this.factory = new ChannelFactory<IMetadataExchange>(mexBinding);
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("scheme", SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactoryBadScheme, scheme));
- }
- }
- this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
- }
- void Validate(Uri address, MetadataExchangeClientMode mode)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- if (!address.IsAbsoluteUri)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("address", SR.GetString(SR.SFxCannotGetMetadataFromRelativeAddress, address));
- }
- if (mode == MetadataExchangeClientMode.HttpGet && !IsHttpOrHttps(address))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("address", SR.GetString(SR.SFxCannotHttpGetMetadataFromAddress, address));
- }
- MetadataExchangeClientModeHelper.Validate(mode);
- }
- public IAsyncResult BeginGetMetadata(AsyncCallback callback, object asyncState)
- {
- if (ctorUri != null)
- return BeginGetMetadata(ctorUri, MetadataExchangeClientMode.HttpGet, callback, asyncState);
- if (ctorEndpointAddress != null)
- return BeginGetMetadata(ctorEndpointAddress, callback, asyncState);
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
- }
- public IAsyncResult BeginGetMetadata(Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
- {
- Validate(address, mode);
- if (mode == MetadataExchangeClientMode.HttpGet)
- {
- return this.BeginGetMetadata(new MetadataLocationRetriever(address, this), callback, asyncState);
- }
- else
- {
- return this.BeginGetMetadata(new MetadataReferenceRetriever(new EndpointAddress(address), this), callback, asyncState);
- }
- }
- public IAsyncResult BeginGetMetadata(EndpointAddress address, AsyncCallback callback, object asyncState)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- return this.BeginGetMetadata(new MetadataReferenceRetriever(address, this), callback, asyncState);
- }
- IAsyncResult BeginGetMetadata(MetadataRetriever retriever, AsyncCallback callback, object asyncState)
- {
- ResolveCallState state = new ResolveCallState(this.maximumResolvedReferences, this.resolveMetadataReferences, new TimeoutHelper(this.OperationTimeout), this);
- state.StackedRetrievers.Push(retriever);
- return new AsyncMetadataResolver(state, callback, asyncState);
- }
- public MetadataSet EndGetMetadata(IAsyncResult result)
- {
- return AsyncMetadataResolver.End(result);
- }
- public Task<MetadataSet> GetMetadataAsync()
- {
- if (ctorUri != null)
- return GetMetadataAsync(ctorUri, MetadataExchangeClientMode.HttpGet);
- if (ctorEndpointAddress != null)
- return GetMetadataAsync(ctorEndpointAddress);
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
- }
- public Task<MetadataSet> GetMetadataAsync(Uri address, MetadataExchangeClientMode mode)
- {
- Validate(address, mode);
- MetadataRetriever retriever = (mode == MetadataExchangeClientMode.HttpGet)
- ? (MetadataRetriever) new MetadataLocationRetriever(address, this)
- : (MetadataRetriever) new MetadataReferenceRetriever(new EndpointAddress(address), this);
- return Task.Factory.FromAsync<MetadataRetriever, MetadataSet>(this.BeginGetMetadata, this.EndGetMetadata, retriever, /* state */ null);
- }
- public Task<MetadataSet> GetMetadataAsync(EndpointAddress address)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- return Task.Factory.FromAsync<MetadataRetriever, MetadataSet>(this.BeginGetMetadata, this.EndGetMetadata, new MetadataReferenceRetriever(address, this), /* state */ null);
- }
- public Task<MetadataSet> GetMetadataAsync(EndpointAddress address, Uri via)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- if (via == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("via");
- }
-
- return Task.Factory.FromAsync<MetadataRetriever, MetadataSet>(this.BeginGetMetadata, this.EndGetMetadata, new MetadataReferenceRetriever(address, via, this), /* state */ null);
- }
- public MetadataSet GetMetadata()
- {
- if (ctorUri != null)
- return GetMetadata(ctorUri, MetadataExchangeClientMode.HttpGet);
- if (ctorEndpointAddress != null)
- return GetMetadata(ctorEndpointAddress);
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
- }
- public MetadataSet GetMetadata(Uri address, MetadataExchangeClientMode mode)
- {
- Validate(address, mode);
- MetadataRetriever retriever;
- if (mode == MetadataExchangeClientMode.HttpGet)
- {
- retriever = new MetadataLocationRetriever(address, this);
- }
- else
- {
- retriever = new MetadataReferenceRetriever(new EndpointAddress(address), this);
- }
- return GetMetadata(retriever);
- }
- public MetadataSet GetMetadata(EndpointAddress address)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- MetadataReferenceRetriever retriever = new MetadataReferenceRetriever(address, this);
- return GetMetadata(retriever);
- }
- public MetadataSet GetMetadata(EndpointAddress address, Uri via)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- if (via == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("via");
- }
- MetadataReferenceRetriever retriever = new MetadataReferenceRetriever(address, via, this);
- return GetMetadata(retriever);
- }
- MetadataSet GetMetadata(MetadataRetriever retriever)
- {
- ResolveCallState resolveCallState = new ResolveCallState(this.maximumResolvedReferences, this.resolveMetadataReferences, new TimeoutHelper(this.OperationTimeout), this);
- resolveCallState.StackedRetrievers.Push(retriever);
- this.ResolveNext(resolveCallState);
- return resolveCallState.MetadataSet;
- }
- void ResolveNext(ResolveCallState resolveCallState)
- {
- if (resolveCallState.StackedRetrievers.Count > 0)
- {
- MetadataRetriever retriever = resolveCallState.StackedRetrievers.Pop();
- if (resolveCallState.HasBeenUsed(retriever))
- {
- this.ResolveNext(resolveCallState);
- }
- else
- {
- if (resolveCallState.ResolvedMaxResolvedReferences)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxResolvedMaxResolvedReferences)));
- }
- resolveCallState.LogUse(retriever);
- resolveCallState.HandleSection(retriever.Retrieve(resolveCallState.TimeoutHelper));
- this.ResolveNext(resolveCallState);
- }
- }
- }
- protected internal virtual ChannelFactory<IMetadataExchange> GetChannelFactory(EndpointAddress metadataAddress, string dialect, string identifier)
- {
- return this.factory;
- }
- static long GetMaxMessageSize(Binding mexBinding)
- {
- BindingElementCollection bindingElementCollection = mexBinding.CreateBindingElements();
- TransportBindingElement bindingElement = bindingElementCollection.Find<TransportBindingElement>();
- if (bindingElement == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBindingDoesNotHaveATransportBindingElement)));
- }
- return bindingElement.MaxReceivedMessageSize;
- }
- protected internal virtual HttpWebRequest GetWebRequest(Uri location, string dialect, string identifier)
- {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location);
- request.Method = "GET";
- request.Credentials = this.HttpCredentials;
- return request;
- }
- internal static void TraceSendRequest(Uri address)
- {
- TraceSendRequest(TraceCode.MetadataExchangeClientSendRequest, SR.GetString(SR.TraceCodeMetadataExchangeClientSendRequest),
- address.ToString(), MetadataExchangeClientMode.HttpGet.ToString());
- }
- internal static void TraceSendRequest(EndpointAddress address)
- {
- TraceSendRequest(TraceCode.MetadataExchangeClientSendRequest, SR.GetString(SR.TraceCodeMetadataExchangeClientSendRequest),
- address.ToString(), MetadataExchangeClientMode.MetadataExchange.ToString());
- }
- static void TraceSendRequest(int traceCode, string traceDescription, string address, string mode)
- {
- if (DiagnosticUtility.ShouldTraceInformation)
- {
- Hashtable h = new Hashtable(2)
- {
- { "Address", address },
- { "Mode", mode }
- };
- TraceUtility.TraceEvent(TraceEventType.Information, traceCode, traceDescription, new DictionaryTraceRecord(h), null, null);
- }
- }
- internal static void TraceReceiveReply(string sourceUrl, Type metadataType)
- {
- if (DiagnosticUtility.ShouldTraceInformation)
- {
- Hashtable h = new Hashtable(2);
- h.Add("SourceUrl", sourceUrl);
- h.Add("MetadataType", metadataType.ToString());
- TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.MetadataExchangeClientReceiveReply, SR.GetString(SR.TraceCodeMetadataExchangeClientReceiveReply),
- new DictionaryTraceRecord(h), null, null);
- }
- }
- class ResolveCallState
- {
- Dictionary<MetadataRetriever, MetadataRetriever> usedRetrievers; // to prevent looping when chasing MetadataReferences
- MetadataSet metadataSet;
- int maxResolvedReferences;
- bool resolveMetadataReferences;
- Stack<MetadataRetriever> stackedRetrievers;
- MetadataExchangeClient resolver;
- TimeoutHelper timeoutHelper;
- internal ResolveCallState(int maxResolvedReferences, bool resolveMetadataReferences,
- TimeoutHelper timeoutHelper, MetadataExchangeClient resolver)
- {
- this.maxResolvedReferences = maxResolvedReferences;
- this.resolveMetadataReferences = resolveMetadataReferences;
- this.resolver = resolver;
- this.timeoutHelper = timeoutHelper;
- this.metadataSet = new MetadataSet();
- this.usedRetrievers = new Dictionary<MetadataRetriever, MetadataRetriever>();
- this.stackedRetrievers = new Stack<MetadataRetriever>();
- }
- internal MetadataSet MetadataSet
- {
- get { return this.metadataSet; }
- }
- internal Stack<MetadataRetriever> StackedRetrievers
- {
- get { return this.stackedRetrievers; }
- }
- internal bool ResolvedMaxResolvedReferences
- {
- get { return this.usedRetrievers.Count == this.maxResolvedReferences; }
- }
- internal TimeoutHelper TimeoutHelper
- {
- get { return this.timeoutHelper; }
- }
- internal void HandleSection(MetadataSection section)
- {
- if (section.Metadata is MetadataSet)
- {
- foreach (MetadataSection innerSection in ((MetadataSet)section.Metadata).MetadataSections)
- {
- innerSection.SourceUrl = section.SourceUrl;
- this.HandleSection(innerSection);
- }
- }
- else if (section.Metadata is MetadataReference)
- {
- if (this.resolveMetadataReferences)
- {
- EndpointAddress address = ((MetadataReference)section.Metadata).Address;
- MetadataRetriever retriever = new MetadataReferenceRetriever(address, this.resolver, section.Dialect, section.Identifier);
- this.stackedRetrievers.Push(retriever);
- }
- else
- {
- this.metadataSet.MetadataSections.Add(section);
- }
- }
- else if (section.Metadata is MetadataLocation)
- {
- if (this.resolveMetadataReferences)
- {
- string location = ((MetadataLocation)section.Metadata).Location;
- MetadataRetriever retriever = new MetadataLocationRetriever(this.CreateUri(section.SourceUrl, location), this.resolver, section.Dialect, section.Identifier);
- this.stackedRetrievers.Push(retriever);
- }
- else
- {
- this.metadataSet.MetadataSections.Add(section);
- }
- }
- else if (section.Metadata is WsdlNS.ServiceDescription)
- {
- if (this.resolveMetadataReferences)
- {
- this.HandleWsdlImports(section);
- }
- this.metadataSet.MetadataSections.Add(section);
- }
- else if (section.Metadata is XsdNS.XmlSchema)
- {
- if (this.resolveMetadataReferences)
- {
- this.HandleSchemaImports(section);
- }
- this.metadataSet.MetadataSections.Add(section);
- }
- else
- {
- this.metadataSet.MetadataSections.Add(section);
- }
- }
- void HandleSchemaImports(MetadataSection section)
- {
- XsdNS.XmlSchema schema = (XsdNS.XmlSchema)section.Metadata;
- foreach (XsdNS.XmlSchemaExternal external in schema.Includes)
- {
- if (!String.IsNullOrEmpty(external.SchemaLocation))
- {
- EnqueueRetrieverIfShouldResolve(
- new MetadataLocationRetriever(
- this.CreateUri(section.SourceUrl, external.SchemaLocation),
- this.resolver));
- }
- }
- }
- void HandleWsdlImports(MetadataSection section)
- {
- WsdlNS.ServiceDescription wsdl = (WsdlNS.ServiceDescription)section.Metadata;
- foreach (WsdlNS.Import import in wsdl.Imports)
- {
- if (!String.IsNullOrEmpty(import.Location))
- {
- EnqueueRetrieverIfShouldResolve(new MetadataLocationRetriever(this.CreateUri(section.SourceUrl, import.Location), this.resolver));
- }
- }
- foreach (XsdNS.XmlSchema schema in wsdl.Types.Schemas)
- {
- MetadataSection schemaSection = new MetadataSection(null, null, schema);
- schemaSection.SourceUrl = section.SourceUrl;
- this.HandleSchemaImports(schemaSection);
- }
- }
- Uri CreateUri(string baseUri, string relativeUri)
- {
- return new Uri(new Uri(baseUri), relativeUri);
- }
- void EnqueueRetrieverIfShouldResolve(MetadataRetriever retriever)
- {
- if (this.resolveMetadataReferences)
- {
- this.stackedRetrievers.Push(retriever);
- }
- }
- internal bool HasBeenUsed(MetadataRetriever retriever)
- {
- return this.usedRetrievers.ContainsKey(retriever);
- }
- internal void LogUse(MetadataRetriever retriever)
- {
- this.usedRetrievers.Add(retriever, retriever);
- }
- }
- abstract class MetadataRetriever
- {
- protected MetadataExchangeClient resolver;
- protected string dialect;
- protected string identifier;
- public MetadataRetriever(MetadataExchangeClient resolver, string dialect, string identifier)
- {
- this.resolver = resolver;
- this.dialect = dialect;
- this.identifier = identifier;
- }
- internal MetadataSection Retrieve(TimeoutHelper timeoutHelper)
- {
- try
- {
- using (XmlReader reader = this.DownloadMetadata(timeoutHelper))
- {
- return MetadataRetriever.CreateMetadataSection(reader, this.SourceUrl);
- }
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
- }
- }
- internal abstract IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state);
- internal abstract MetadataSection EndRetrieve(IAsyncResult result);
- static internal MetadataSection CreateMetadataSection(XmlReader reader, string sourceUrl)
- {
- MetadataSection section = null;
- Type metadataType = null;
- if (CanReadMetadataSet(reader))
- {
- MetadataSet newSet = MetadataSet.ReadFrom(reader);
- section = new MetadataSection(MetadataSection.MetadataExchangeDialect, null, newSet);
- metadataType = typeof(MetadataSet);
- }
- else if (WsdlNS.ServiceDescription.CanRead(reader))
- {
- WsdlNS.ServiceDescription wsdl = WsdlNS.ServiceDescription.Read(reader);
- section = MetadataSection.CreateFromServiceDescription(wsdl);
- metadataType = typeof(WsdlNS.ServiceDescription);
- }
- else if (CanReadSchema(reader))
- {
- XsdNS.XmlSchema schema = XsdNS.XmlSchema.Read(reader, null);
- section = MetadataSection.CreateFromSchema(schema);
- metadataType = typeof(XsdNS.XmlSchema);
- }
- else
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(reader);
- section = new MetadataSection(null, null, doc.DocumentElement);
- metadataType = typeof(XmlElement);
- }
- section.SourceUrl = sourceUrl;
- TraceReceiveReply(sourceUrl, metadataType);
- return section;
- }
- protected abstract XmlReader DownloadMetadata(TimeoutHelper timeoutHelper);
- protected abstract string SourceUrl { get; }
- static bool CanReadSchema(XmlReader reader)
- {
- return reader.LocalName == MetadataStrings.XmlSchema.Schema
- && reader.NamespaceURI == XsdNS.XmlSchema.Namespace;
- }
- static bool CanReadMetadataSet(XmlReader reader)
- {
- return reader.LocalName == MetadataStrings.MetadataExchangeStrings.Metadata
- && reader.NamespaceURI == MetadataStrings.MetadataExchangeStrings.Namespace;
- }
- }
- class MetadataLocationRetriever : MetadataRetriever
- {
- Uri location;
- Uri responseLocation;
- internal MetadataLocationRetriever(Uri location, MetadataExchangeClient resolver)
- : this(location, resolver, null, null)
- {
- }
- internal MetadataLocationRetriever(Uri location, MetadataExchangeClient resolver, string dialect, string identifier)
- : base(resolver, dialect, identifier)
- {
- ValidateLocation(location);
- this.location = location;
- this.responseLocation = location;
- }
- internal static void ValidateLocation(Uri location)
- {
- if (location == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("location");
- }
- if (location.Scheme != Uri.UriSchemeHttp && location.Scheme != Uri.UriSchemeHttps)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("location", SR.GetString(SR.SFxCannotGetMetadataFromLocation, location.ToString()));
- }
- }
- public override bool Equals(object obj)
- {
- return obj is MetadataLocationRetriever && ((MetadataLocationRetriever)obj).location == this.location;
- }
- public override int GetHashCode()
- {
- return location.GetHashCode();
- }
- protected override XmlReader DownloadMetadata(TimeoutHelper timeoutHelper)
- {
- HttpWebResponse response;
- HttpWebRequest request;
- try
- {
- request = this.resolver.GetWebRequest(this.location, this.dialect, this.identifier);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateWebRequest, this.location, this.dialect, this.identifier), e));
- }
- TraceSendRequest(this.location);
- request.Timeout = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());
- response = (HttpWebResponse)request.GetResponse();
- responseLocation = request.Address;
- return MetadataLocationRetriever.GetXmlReader(response, this.resolver.MaxMessageSize, this.resolver.ReaderQuotas);
- }
- internal static XmlReader GetXmlReader(HttpWebResponse response, long maxMessageSize, XmlDictionaryReaderQuotas readerQuotas)
- {
- readerQuotas = readerQuotas ?? EncoderDefaults.ReaderQuotas;
- XmlReader reader = XmlDictionaryReader.CreateTextReader(
- new MaxMessageSizeStream(response.GetResponseStream(), maxMessageSize),
- EncodingHelper.GetDictionaryReaderEncoding(response.ContentType),
- readerQuotas,
- null);
- reader.Read();
- reader.MoveToContent();
- return reader;
- }
- internal override IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
- {
- AsyncMetadataLocationRetriever result;
- try
- {
- HttpWebRequest request;
- try
- {
- request = this.resolver.GetWebRequest(this.location, this.dialect, this.identifier);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateWebRequest, this.location, this.dialect, this.identifier), e));
- }
- TraceSendRequest(this.location);
- result = new AsyncMetadataLocationRetriever(request, this.resolver.MaxMessageSize, this.resolver.ReaderQuotas, timeoutHelper, callback, state);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
- }
- return result;
- }
- internal override MetadataSection EndRetrieve(IAsyncResult result)
- {
- try
- {
- return AsyncMetadataLocationRetriever.End(result);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
- }
- }
- protected override string SourceUrl
- {
- get { return this.responseLocation.ToString(); }
- }
- class AsyncMetadataLocationRetriever : AsyncResult
- {
- MetadataSection section;
- long maxMessageSize;
- XmlDictionaryReaderQuotas readerQuotas;
- internal AsyncMetadataLocationRetriever(WebRequest request, long maxMessageSize, XmlDictionaryReaderQuotas readerQuotas, TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.maxMessageSize = maxMessageSize;
- this.readerQuotas = readerQuotas;
- IAsyncResult result = request.BeginGetResponse(Fx.ThunkCallback(new AsyncCallback(this.GetResponseCallback)), request);
- //Register a callback to abort the request if we hit the timeout.
- ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
- Fx.ThunkCallback(new WaitOrTimerCallback(RetrieveTimeout)), request,
- TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime()), /* executeOnlyOnce */ true);
- if (result.CompletedSynchronously)
- {
- HandleResult(result);
- this.Complete(true);
- }
- }
- static void RetrieveTimeout(object state, bool timedOut)
- {
- if (timedOut)
- {
- HttpWebRequest request = state as HttpWebRequest;
- if (request != null)
- {
- request.Abort();
- }
- }
- }
- internal static MetadataSection End(IAsyncResult result)
- {
- AsyncMetadataLocationRetriever retrieverResult = AsyncResult.End<AsyncMetadataLocationRetriever>(result);
- return retrieverResult.section;
- }
- internal void GetResponseCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- return;
- Exception exception = null;
- try
- {
- HandleResult(result);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- exception = e;
- }
- this.Complete(false, exception);
- }
- void HandleResult(IAsyncResult result)
- {
- HttpWebRequest request = (HttpWebRequest)result.AsyncState;
- using (XmlReader reader =
- MetadataLocationRetriever.GetXmlReader((HttpWebResponse)request.EndGetResponse(result), this.maxMessageSize, this.readerQuotas))
- {
- section = MetadataRetriever.CreateMetadataSection(reader, request.Address.ToString());
- }
- }
- }
- }
- class MetadataReferenceRetriever : MetadataRetriever
- {
- EndpointAddress address;
- Uri via;
- public MetadataReferenceRetriever(EndpointAddress address, MetadataExchangeClient resolver)
- : this(address, null, resolver, null, null)
- {
- }
- public MetadataReferenceRetriever(EndpointAddress address, Uri via, MetadataExchangeClient resolver)
- : this(address, via, resolver, null, null)
- {
- }
- public MetadataReferenceRetriever(EndpointAddress address, MetadataExchangeClient resolver, string dialect, string identifier)
- : this(address, null, resolver, dialect, identifier)
- {
- }
- MetadataReferenceRetriever(EndpointAddress address, Uri via, MetadataExchangeClient resolver, string dialect, string identifier)
- : base(resolver, dialect, identifier)
- {
- if (address == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
- }
- this.address = address;
- this.via = via;
- }
- protected override string SourceUrl
- {
- get { return this.address.Uri.ToString(); }
- }
- internal override IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
- {
- try
- {
- IMetadataExchange metadataClient;
- MessageVersion messageVersion;
- lock (this.resolver.ThisLock)
- {
- ChannelFactory<IMetadataExchange> channelFactory;
- try
- {
- channelFactory = this.resolver.GetChannelFactory(this.address, this.dialect, this.identifier);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactory, this.address, this.dialect, this.identifier), e));
- }
- metadataClient = CreateChannel(channelFactory);
- messageVersion = channelFactory.Endpoint.Binding.MessageVersion;
- }
- TraceSendRequest(this.address);
- return new AsyncMetadataReferenceRetriever(metadataClient, messageVersion, timeoutHelper, callback, state);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
- }
- }
- IMetadataExchange CreateChannel(ChannelFactory<IMetadataExchange> channelFactory)
- {
- if (this.via != null)
- {
- return channelFactory.CreateChannel(this.address, this.via);
- }
- else
- {
- return channelFactory.CreateChannel(this.address);
- }
- }
- static Message CreateGetMessage(MessageVersion messageVersion)
- {
- return Message.CreateMessage(messageVersion, MetadataStrings.WSTransfer.GetAction);
- }
- protected override XmlReader DownloadMetadata(TimeoutHelper timeoutHelper)
- {
- IMetadataExchange metadataClient;
- MessageVersion messageVersion;
- lock (this.resolver.ThisLock)
- {
- ChannelFactory<IMetadataExchange> channelFactory;
- try
- {
- channelFactory = this.resolver.GetChannelFactory(this.address, this.dialect, this.identifier);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactory, this.address, this.dialect, this.identifier), e));
- }
- metadataClient = CreateChannel(channelFactory);
- messageVersion = channelFactory.Endpoint.Binding.MessageVersion;
- }
- Message response;
- TraceSendRequest(this.address);
- try
- {
- using (Message getMessage = CreateGetMessage(messageVersion))
- {
- ((IClientChannel)metadataClient).OperationTimeout = timeoutHelper.RemainingTime();
- response = metadataClient.Get(getMessage);
- }
- ((IClientChannel)metadataClient).Close();
- }
- finally
- {
- ((IClientChannel)metadataClient).Abort();
- }
- if (response.IsFault)
- {
- MessageFault fault = MessageFault.CreateFault(response, 64 * 1024);
- StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
- XmlWriter xmlWriter = XmlWriter.Create(stringWriter);
- fault.WriteTo(xmlWriter, response.Version.Envelope);
- xmlWriter.Flush();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(stringWriter.ToString()));
- }
- return response.GetReaderAtBodyContents();
- }
- internal override MetadataSection EndRetrieve(IAsyncResult result)
- {
- try
- {
- return AsyncMetadataReferenceRetriever.End(result);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
- }
- }
- public override bool Equals(object obj)
- {
- return obj is MetadataReferenceRetriever && ((MetadataReferenceRetriever)obj).address == this.address;
- }
- public override int GetHashCode()
- {
- return address.GetHashCode();
- }
- class AsyncMetadataReferenceRetriever : AsyncResult
- {
- MetadataSection section;
- Message message;
- internal AsyncMetadataReferenceRetriever(IMetadataExchange metadataClient, MessageVersion messageVersion, TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
- : base(callback, state)
- {
- message = MetadataReferenceRetriever.CreateGetMessage(messageVersion);
- ((IClientChannel)metadataClient).OperationTimeout = timeoutHelper.RemainingTime();
- IAsyncResult result = metadataClient.BeginGet(message, Fx.ThunkCallback(new AsyncCallback(this.RequestCallback)), metadataClient);
- if (result.CompletedSynchronously)
- {
- HandleResult(result);
- this.Complete(true);
- }
- }
- internal static MetadataSection End(IAsyncResult result)
- {
- AsyncMetadataReferenceRetriever retrieverResult = AsyncResult.End<AsyncMetadataReferenceRetriever>(result);
- return retrieverResult.section;
- }
- internal void RequestCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- return;
- Exception exception = null;
- try
- {
- HandleResult(result);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- exception = e;
- }
- this.Complete(false, exception);
- }
- void HandleResult(IAsyncResult result)
- {
- IMetadataExchange metadataClient = (IMetadataExchange)result.AsyncState;
- Message response = metadataClient.EndGet(result);
- using (this.message)
- {
- if (response.IsFault)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBadMetadataReference,
- ((IClientChannel)metadataClient).RemoteAddress.Uri.ToString())));
- }
- else
- {
- using (XmlReader reader = response.GetReaderAtBodyContents())
- {
- section = MetadataRetriever.CreateMetadataSection(reader, ((IClientChannel)metadataClient).RemoteAddress.Uri.ToString());
- }
- }
- }
- }
- }
- }
- class AsyncMetadataResolver : AsyncResult
- {
- ResolveCallState resolveCallState;
- internal AsyncMetadataResolver(ResolveCallState resolveCallState, AsyncCallback callerCallback, object callerAsyncState)
- : base(callerCallback, callerAsyncState)
- {
- if (resolveCallState == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("resolveCallState");
- }
- this.resolveCallState = resolveCallState;
- Exception exception = null;
- bool doneResolving = false;
- try
- {
- doneResolving = this.ResolveNext();
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- exception = e;
- doneResolving = true;
- }
- if (doneResolving)
- {
- this.Complete(true, exception);
- }
- }
- bool ResolveNext()
- {
- bool doneResolving = false;
- if (this.resolveCallState.StackedRetrievers.Count > 0)
- {
- MetadataRetriever retriever = this.resolveCallState.StackedRetrievers.Pop();
- if (resolveCallState.HasBeenUsed(retriever))
- {
- doneResolving = this.ResolveNext();
- }
- else
- {
- if (resolveCallState.ResolvedMaxResolvedReferences)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxResolvedMaxResolvedReferences)));
- }
- else
- {
- resolveCallState.LogUse(retriever);
- IAsyncResult result = retriever.BeginRetrieve(this.resolveCallState.TimeoutHelper, Fx.ThunkCallback(new AsyncCallback(this.RetrieveCallback)), retriever);
- if (result.CompletedSynchronously)
- {
- doneResolving = HandleResult(result);
- }
- }
- }
- }
- else
- {
- doneResolving = true;
- }
- return doneResolving;
- }
- internal static MetadataSet End(IAsyncResult result)
- {
- AsyncMetadataResolver resolverResult = AsyncResult.End<AsyncMetadataResolver>(result);
- return resolverResult.resolveCallState.MetadataSet;
- }
- internal void RetrieveCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- return;
- Exception exception = null;
- bool doneResolving = false;
- try
- {
- doneResolving = HandleResult(result);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- exception = e;
- doneResolving = true;
- }
- if (doneResolving)
- {
- this.Complete(false, exception);
- }
- }
- bool HandleResult(IAsyncResult result)
- {
- MetadataRetriever retriever = (MetadataRetriever)result.AsyncState;
- MetadataSection section = retriever.EndRetrieve(result);
- this.resolveCallState.HandleSection(section);
- return this.ResolveNext();
- }
- }
- internal class EncodingHelper
- {
- internal const string ApplicationBase = "application";
- internal static Encoding GetRfcEncoding(string contentTypeStr)
- {
- Encoding e = null;
- ContentType contentType = null;
- try
- {
- contentType = new ContentType(contentTypeStr);
- string charset = contentType == null ? string.Empty : contentType.CharSet;
- if (charset != null && charset.Length > 0)
- e = Encoding.GetEncoding(charset);
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception ex)
- {
- if (Fx.IsFatal(ex))
- throw;
- }
- // default to ASCII encoding per RFC 2376/3023
- if (IsApplication(contentType))
- return e == null ? new ASCIIEncoding() : e;
- else
- return e;
- }
- internal static bool IsApplication(ContentType contentType)
- {
- return string.Compare(contentType == null ? string.Empty : contentType.MediaType,
- ApplicationBase, StringComparison.OrdinalIgnoreCase) == 0;
- }
- internal static Encoding GetDictionaryReaderEncoding(string contentTypeStr)
- {
- if (String.IsNullOrEmpty(contentTypeStr))
- return TextEncoderDefaults.Encoding;
- Encoding encoding = GetRfcEncoding(contentTypeStr);
- if (encoding == null)
- return TextEncoderDefaults.Encoding;
- string charSet = encoding.WebName;
- Encoding[] supportedEncodings = TextEncoderDefaults.SupportedEncodings;
- for (int i = 0; i < supportedEncodings.Length; i++)
- {
- if (charSet == supportedEncodings[i].WebName)
- return encoding;
- }
- return TextEncoderDefaults.Encoding;
- }
- }
- }
- public enum MetadataExchangeClientMode
- {
- MetadataExchange,
- HttpGet,
- }
- static class MetadataExchangeClientModeHelper
- {
- static public bool IsDefined(MetadataExchangeClientMode x)
- {
- return
- x == MetadataExchangeClientMode.MetadataExchange ||
- x == MetadataExchangeClientMode.HttpGet ||
- false;
- }
- public static void Validate(MetadataExchangeClientMode value)
- {
- if (!IsDefined(value))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
- typeof(MetadataExchangeClientMode)));
- }
- }
- }
- }
|