MetadataExchangeClient.cs 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Description
  5. {
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Diagnostics;
  10. using System.Globalization;
  11. using System.IO;
  12. using System.Net;
  13. using System.Net.Mime;
  14. using System.Runtime;
  15. using System.Runtime.Diagnostics;
  16. using System.Security;
  17. using System.ServiceModel;
  18. using System.ServiceModel.Channels;
  19. using System.ServiceModel.Configuration;
  20. using System.ServiceModel.Diagnostics;
  21. using System.Text;
  22. using System.Threading;
  23. using System.Threading.Tasks;
  24. using System.Xml;
  25. using WsdlNS = System.Web.Services.Description;
  26. using XsdNS = System.Xml.Schema;
  27. public class MetadataExchangeClient
  28. {
  29. ChannelFactory<IMetadataExchange> factory;
  30. ICredentials webRequestCredentials;
  31. TimeSpan resolveTimeout = TimeSpan.FromMinutes(1);
  32. int maximumResolvedReferences = 10;
  33. bool resolveMetadataReferences = true;
  34. long maxMessageSize;
  35. XmlDictionaryReaderQuotas readerQuotas;
  36. EndpointAddress ctorEndpointAddress = null;
  37. Uri ctorUri = null;
  38. object thisLock = new object();
  39. internal const string MetadataExchangeClientKey = "MetadataExchangeClientKey";
  40. public MetadataExchangeClient()
  41. {
  42. this.factory = new ChannelFactory<IMetadataExchange>("*");
  43. this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
  44. }
  45. public MetadataExchangeClient(Uri address, MetadataExchangeClientMode mode)
  46. {
  47. Validate(address, mode);
  48. if (mode == MetadataExchangeClientMode.HttpGet)
  49. {
  50. this.ctorUri = address;
  51. }
  52. else
  53. {
  54. this.ctorEndpointAddress = new EndpointAddress(address);
  55. }
  56. CreateChannelFactory(address.Scheme);
  57. }
  58. public MetadataExchangeClient(EndpointAddress address)
  59. {
  60. if (address == null)
  61. {
  62. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  63. }
  64. this.ctorEndpointAddress = address;
  65. CreateChannelFactory(address.Uri.Scheme);
  66. }
  67. public MetadataExchangeClient(string endpointConfigurationName)
  68. {
  69. if (endpointConfigurationName == null)
  70. {
  71. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
  72. }
  73. this.factory = new ChannelFactory<IMetadataExchange>(endpointConfigurationName);
  74. this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
  75. }
  76. public MetadataExchangeClient(Binding mexBinding)
  77. {
  78. if (mexBinding == null)
  79. {
  80. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("mexBinding");
  81. }
  82. this.factory = new ChannelFactory<IMetadataExchange>(mexBinding);
  83. this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
  84. }
  85. //Configuration for credentials
  86. public ClientCredentials SoapCredentials
  87. {
  88. get { return this.factory.Credentials; }
  89. set
  90. {
  91. if (value == null)
  92. {
  93. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  94. }
  95. this.factory.Endpoint.Behaviors.RemoveAll<ClientCredentials>();
  96. this.factory.Endpoint.Behaviors.Add(value);
  97. }
  98. }
  99. public ICredentials HttpCredentials
  100. {
  101. get { return this.webRequestCredentials; }
  102. set { this.webRequestCredentials = value; }
  103. }
  104. // Configuration options for the entire MetadataResolver
  105. public TimeSpan OperationTimeout
  106. {
  107. get { return this.resolveTimeout; }
  108. set
  109. {
  110. if (value < TimeSpan.Zero)
  111. {
  112. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
  113. SR.GetString(SR.SFxTimeoutOutOfRange0)));
  114. }
  115. if (TimeoutHelper.IsTooLarge(value))
  116. {
  117. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
  118. SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
  119. }
  120. this.resolveTimeout = value;
  121. }
  122. }
  123. public int MaximumResolvedReferences
  124. {
  125. get { return this.maximumResolvedReferences; }
  126. set
  127. {
  128. if (value < 1)
  129. {
  130. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxMaximumResolvedReferencesOutOfRange, value)));
  131. }
  132. this.maximumResolvedReferences = value;
  133. }
  134. }
  135. public bool ResolveMetadataReferences
  136. {
  137. get { return this.resolveMetadataReferences; }
  138. set { this.resolveMetadataReferences = value; }
  139. }
  140. internal object ThisLock
  141. {
  142. get { return this.thisLock; }
  143. }
  144. internal long MaxMessageSize
  145. {
  146. get { return this.maxMessageSize; }
  147. set { this.maxMessageSize = value; }
  148. }
  149. internal XmlDictionaryReaderQuotas ReaderQuotas
  150. {
  151. get
  152. {
  153. if (this.readerQuotas == null)
  154. {
  155. if (this.factory != null)
  156. {
  157. BindingElementCollection bindingElementCollection = this.factory.Endpoint.Binding.CreateBindingElements();
  158. if (bindingElementCollection != null)
  159. {
  160. MessageEncodingBindingElement bindingElement = bindingElementCollection.Find<MessageEncodingBindingElement>();
  161. if (bindingElement != null)
  162. {
  163. this.readerQuotas = bindingElement.GetIndividualProperty<XmlDictionaryReaderQuotas>();
  164. }
  165. }
  166. }
  167. this.readerQuotas = this.readerQuotas ?? EncoderDefaults.ReaderQuotas;
  168. }
  169. return this.readerQuotas;
  170. }
  171. }
  172. [Fx.Tag.SecurityNote(Critical = "Uses ClientSection.UnsafeGetSection to get config in PT.",
  173. Safe = "Does not leak config object, just calculates a bool.")]
  174. [SecuritySafeCritical]
  175. bool ClientEndpointExists(string name)
  176. {
  177. ClientSection clientSection = ClientSection.UnsafeGetSection();
  178. if (clientSection == null)
  179. return false;
  180. foreach (ChannelEndpointElement endpoint in clientSection.Endpoints)
  181. {
  182. if (endpoint.Name == name && endpoint.Contract == ServiceMetadataBehavior.MexContractName)
  183. return true;
  184. }
  185. return false;
  186. }
  187. bool IsHttpOrHttps(Uri address)
  188. {
  189. return address.Scheme == Uri.UriSchemeHttp || address.Scheme == Uri.UriSchemeHttps;
  190. }
  191. void CreateChannelFactory(string scheme)
  192. {
  193. if (ClientEndpointExists(scheme))
  194. {
  195. this.factory = new ChannelFactory<IMetadataExchange>(scheme);
  196. }
  197. else
  198. {
  199. Binding mexBinding = null;
  200. if (MetadataExchangeBindings.TryGetBindingForScheme(scheme, out mexBinding))
  201. {
  202. this.factory = new ChannelFactory<IMetadataExchange>(mexBinding);
  203. }
  204. else
  205. {
  206. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("scheme", SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactoryBadScheme, scheme));
  207. }
  208. }
  209. this.maxMessageSize = GetMaxMessageSize(this.factory.Endpoint.Binding);
  210. }
  211. void Validate(Uri address, MetadataExchangeClientMode mode)
  212. {
  213. if (address == null)
  214. {
  215. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  216. }
  217. if (!address.IsAbsoluteUri)
  218. {
  219. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("address", SR.GetString(SR.SFxCannotGetMetadataFromRelativeAddress, address));
  220. }
  221. if (mode == MetadataExchangeClientMode.HttpGet && !IsHttpOrHttps(address))
  222. {
  223. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("address", SR.GetString(SR.SFxCannotHttpGetMetadataFromAddress, address));
  224. }
  225. MetadataExchangeClientModeHelper.Validate(mode);
  226. }
  227. public IAsyncResult BeginGetMetadata(AsyncCallback callback, object asyncState)
  228. {
  229. if (ctorUri != null)
  230. return BeginGetMetadata(ctorUri, MetadataExchangeClientMode.HttpGet, callback, asyncState);
  231. if (ctorEndpointAddress != null)
  232. return BeginGetMetadata(ctorEndpointAddress, callback, asyncState);
  233. else
  234. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
  235. }
  236. public IAsyncResult BeginGetMetadata(Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
  237. {
  238. Validate(address, mode);
  239. if (mode == MetadataExchangeClientMode.HttpGet)
  240. {
  241. return this.BeginGetMetadata(new MetadataLocationRetriever(address, this), callback, asyncState);
  242. }
  243. else
  244. {
  245. return this.BeginGetMetadata(new MetadataReferenceRetriever(new EndpointAddress(address), this), callback, asyncState);
  246. }
  247. }
  248. public IAsyncResult BeginGetMetadata(EndpointAddress address, AsyncCallback callback, object asyncState)
  249. {
  250. if (address == null)
  251. {
  252. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  253. }
  254. return this.BeginGetMetadata(new MetadataReferenceRetriever(address, this), callback, asyncState);
  255. }
  256. IAsyncResult BeginGetMetadata(MetadataRetriever retriever, AsyncCallback callback, object asyncState)
  257. {
  258. ResolveCallState state = new ResolveCallState(this.maximumResolvedReferences, this.resolveMetadataReferences, new TimeoutHelper(this.OperationTimeout), this);
  259. state.StackedRetrievers.Push(retriever);
  260. return new AsyncMetadataResolver(state, callback, asyncState);
  261. }
  262. public MetadataSet EndGetMetadata(IAsyncResult result)
  263. {
  264. return AsyncMetadataResolver.End(result);
  265. }
  266. public Task<MetadataSet> GetMetadataAsync()
  267. {
  268. if (ctorUri != null)
  269. return GetMetadataAsync(ctorUri, MetadataExchangeClientMode.HttpGet);
  270. if (ctorEndpointAddress != null)
  271. return GetMetadataAsync(ctorEndpointAddress);
  272. else
  273. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
  274. }
  275. public Task<MetadataSet> GetMetadataAsync(Uri address, MetadataExchangeClientMode mode)
  276. {
  277. Validate(address, mode);
  278. MetadataRetriever retriever = (mode == MetadataExchangeClientMode.HttpGet)
  279. ? (MetadataRetriever) new MetadataLocationRetriever(address, this)
  280. : (MetadataRetriever) new MetadataReferenceRetriever(new EndpointAddress(address), this);
  281. return Task.Factory.FromAsync<MetadataRetriever, MetadataSet>(this.BeginGetMetadata, this.EndGetMetadata, retriever, /* state */ null);
  282. }
  283. public Task<MetadataSet> GetMetadataAsync(EndpointAddress address)
  284. {
  285. if (address == null)
  286. {
  287. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  288. }
  289. return Task.Factory.FromAsync<MetadataRetriever, MetadataSet>(this.BeginGetMetadata, this.EndGetMetadata, new MetadataReferenceRetriever(address, this), /* state */ null);
  290. }
  291. public Task<MetadataSet> GetMetadataAsync(EndpointAddress address, Uri via)
  292. {
  293. if (address == null)
  294. {
  295. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  296. }
  297. if (via == null)
  298. {
  299. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("via");
  300. }
  301. return Task.Factory.FromAsync<MetadataRetriever, MetadataSet>(this.BeginGetMetadata, this.EndGetMetadata, new MetadataReferenceRetriever(address, via, this), /* state */ null);
  302. }
  303. public MetadataSet GetMetadata()
  304. {
  305. if (ctorUri != null)
  306. return GetMetadata(ctorUri, MetadataExchangeClientMode.HttpGet);
  307. if (ctorEndpointAddress != null)
  308. return GetMetadata(ctorEndpointAddress);
  309. else
  310. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMetadataExchangeClientNoMetadataAddress)));
  311. }
  312. public MetadataSet GetMetadata(Uri address, MetadataExchangeClientMode mode)
  313. {
  314. Validate(address, mode);
  315. MetadataRetriever retriever;
  316. if (mode == MetadataExchangeClientMode.HttpGet)
  317. {
  318. retriever = new MetadataLocationRetriever(address, this);
  319. }
  320. else
  321. {
  322. retriever = new MetadataReferenceRetriever(new EndpointAddress(address), this);
  323. }
  324. return GetMetadata(retriever);
  325. }
  326. public MetadataSet GetMetadata(EndpointAddress address)
  327. {
  328. if (address == null)
  329. {
  330. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  331. }
  332. MetadataReferenceRetriever retriever = new MetadataReferenceRetriever(address, this);
  333. return GetMetadata(retriever);
  334. }
  335. public MetadataSet GetMetadata(EndpointAddress address, Uri via)
  336. {
  337. if (address == null)
  338. {
  339. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  340. }
  341. if (via == null)
  342. {
  343. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("via");
  344. }
  345. MetadataReferenceRetriever retriever = new MetadataReferenceRetriever(address, via, this);
  346. return GetMetadata(retriever);
  347. }
  348. MetadataSet GetMetadata(MetadataRetriever retriever)
  349. {
  350. ResolveCallState resolveCallState = new ResolveCallState(this.maximumResolvedReferences, this.resolveMetadataReferences, new TimeoutHelper(this.OperationTimeout), this);
  351. resolveCallState.StackedRetrievers.Push(retriever);
  352. this.ResolveNext(resolveCallState);
  353. return resolveCallState.MetadataSet;
  354. }
  355. void ResolveNext(ResolveCallState resolveCallState)
  356. {
  357. if (resolveCallState.StackedRetrievers.Count > 0)
  358. {
  359. MetadataRetriever retriever = resolveCallState.StackedRetrievers.Pop();
  360. if (resolveCallState.HasBeenUsed(retriever))
  361. {
  362. this.ResolveNext(resolveCallState);
  363. }
  364. else
  365. {
  366. if (resolveCallState.ResolvedMaxResolvedReferences)
  367. {
  368. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxResolvedMaxResolvedReferences)));
  369. }
  370. resolveCallState.LogUse(retriever);
  371. resolveCallState.HandleSection(retriever.Retrieve(resolveCallState.TimeoutHelper));
  372. this.ResolveNext(resolveCallState);
  373. }
  374. }
  375. }
  376. protected internal virtual ChannelFactory<IMetadataExchange> GetChannelFactory(EndpointAddress metadataAddress, string dialect, string identifier)
  377. {
  378. return this.factory;
  379. }
  380. static long GetMaxMessageSize(Binding mexBinding)
  381. {
  382. BindingElementCollection bindingElementCollection = mexBinding.CreateBindingElements();
  383. TransportBindingElement bindingElement = bindingElementCollection.Find<TransportBindingElement>();
  384. if (bindingElement == null)
  385. {
  386. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBindingDoesNotHaveATransportBindingElement)));
  387. }
  388. return bindingElement.MaxReceivedMessageSize;
  389. }
  390. protected internal virtual HttpWebRequest GetWebRequest(Uri location, string dialect, string identifier)
  391. {
  392. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location);
  393. request.Method = "GET";
  394. request.Credentials = this.HttpCredentials;
  395. return request;
  396. }
  397. internal static void TraceSendRequest(Uri address)
  398. {
  399. TraceSendRequest(TraceCode.MetadataExchangeClientSendRequest, SR.GetString(SR.TraceCodeMetadataExchangeClientSendRequest),
  400. address.ToString(), MetadataExchangeClientMode.HttpGet.ToString());
  401. }
  402. internal static void TraceSendRequest(EndpointAddress address)
  403. {
  404. TraceSendRequest(TraceCode.MetadataExchangeClientSendRequest, SR.GetString(SR.TraceCodeMetadataExchangeClientSendRequest),
  405. address.ToString(), MetadataExchangeClientMode.MetadataExchange.ToString());
  406. }
  407. static void TraceSendRequest(int traceCode, string traceDescription, string address, string mode)
  408. {
  409. if (DiagnosticUtility.ShouldTraceInformation)
  410. {
  411. Hashtable h = new Hashtable(2)
  412. {
  413. { "Address", address },
  414. { "Mode", mode }
  415. };
  416. TraceUtility.TraceEvent(TraceEventType.Information, traceCode, traceDescription, new DictionaryTraceRecord(h), null, null);
  417. }
  418. }
  419. internal static void TraceReceiveReply(string sourceUrl, Type metadataType)
  420. {
  421. if (DiagnosticUtility.ShouldTraceInformation)
  422. {
  423. Hashtable h = new Hashtable(2);
  424. h.Add("SourceUrl", sourceUrl);
  425. h.Add("MetadataType", metadataType.ToString());
  426. TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.MetadataExchangeClientReceiveReply, SR.GetString(SR.TraceCodeMetadataExchangeClientReceiveReply),
  427. new DictionaryTraceRecord(h), null, null);
  428. }
  429. }
  430. class ResolveCallState
  431. {
  432. Dictionary<MetadataRetriever, MetadataRetriever> usedRetrievers; // to prevent looping when chasing MetadataReferences
  433. MetadataSet metadataSet;
  434. int maxResolvedReferences;
  435. bool resolveMetadataReferences;
  436. Stack<MetadataRetriever> stackedRetrievers;
  437. MetadataExchangeClient resolver;
  438. TimeoutHelper timeoutHelper;
  439. internal ResolveCallState(int maxResolvedReferences, bool resolveMetadataReferences,
  440. TimeoutHelper timeoutHelper, MetadataExchangeClient resolver)
  441. {
  442. this.maxResolvedReferences = maxResolvedReferences;
  443. this.resolveMetadataReferences = resolveMetadataReferences;
  444. this.resolver = resolver;
  445. this.timeoutHelper = timeoutHelper;
  446. this.metadataSet = new MetadataSet();
  447. this.usedRetrievers = new Dictionary<MetadataRetriever, MetadataRetriever>();
  448. this.stackedRetrievers = new Stack<MetadataRetriever>();
  449. }
  450. internal MetadataSet MetadataSet
  451. {
  452. get { return this.metadataSet; }
  453. }
  454. internal Stack<MetadataRetriever> StackedRetrievers
  455. {
  456. get { return this.stackedRetrievers; }
  457. }
  458. internal bool ResolvedMaxResolvedReferences
  459. {
  460. get { return this.usedRetrievers.Count == this.maxResolvedReferences; }
  461. }
  462. internal TimeoutHelper TimeoutHelper
  463. {
  464. get { return this.timeoutHelper; }
  465. }
  466. internal void HandleSection(MetadataSection section)
  467. {
  468. if (section.Metadata is MetadataSet)
  469. {
  470. foreach (MetadataSection innerSection in ((MetadataSet)section.Metadata).MetadataSections)
  471. {
  472. innerSection.SourceUrl = section.SourceUrl;
  473. this.HandleSection(innerSection);
  474. }
  475. }
  476. else if (section.Metadata is MetadataReference)
  477. {
  478. if (this.resolveMetadataReferences)
  479. {
  480. EndpointAddress address = ((MetadataReference)section.Metadata).Address;
  481. MetadataRetriever retriever = new MetadataReferenceRetriever(address, this.resolver, section.Dialect, section.Identifier);
  482. this.stackedRetrievers.Push(retriever);
  483. }
  484. else
  485. {
  486. this.metadataSet.MetadataSections.Add(section);
  487. }
  488. }
  489. else if (section.Metadata is MetadataLocation)
  490. {
  491. if (this.resolveMetadataReferences)
  492. {
  493. string location = ((MetadataLocation)section.Metadata).Location;
  494. MetadataRetriever retriever = new MetadataLocationRetriever(this.CreateUri(section.SourceUrl, location), this.resolver, section.Dialect, section.Identifier);
  495. this.stackedRetrievers.Push(retriever);
  496. }
  497. else
  498. {
  499. this.metadataSet.MetadataSections.Add(section);
  500. }
  501. }
  502. else if (section.Metadata is WsdlNS.ServiceDescription)
  503. {
  504. if (this.resolveMetadataReferences)
  505. {
  506. this.HandleWsdlImports(section);
  507. }
  508. this.metadataSet.MetadataSections.Add(section);
  509. }
  510. else if (section.Metadata is XsdNS.XmlSchema)
  511. {
  512. if (this.resolveMetadataReferences)
  513. {
  514. this.HandleSchemaImports(section);
  515. }
  516. this.metadataSet.MetadataSections.Add(section);
  517. }
  518. else
  519. {
  520. this.metadataSet.MetadataSections.Add(section);
  521. }
  522. }
  523. void HandleSchemaImports(MetadataSection section)
  524. {
  525. XsdNS.XmlSchema schema = (XsdNS.XmlSchema)section.Metadata;
  526. foreach (XsdNS.XmlSchemaExternal external in schema.Includes)
  527. {
  528. if (!String.IsNullOrEmpty(external.SchemaLocation))
  529. {
  530. EnqueueRetrieverIfShouldResolve(
  531. new MetadataLocationRetriever(
  532. this.CreateUri(section.SourceUrl, external.SchemaLocation),
  533. this.resolver));
  534. }
  535. }
  536. }
  537. void HandleWsdlImports(MetadataSection section)
  538. {
  539. WsdlNS.ServiceDescription wsdl = (WsdlNS.ServiceDescription)section.Metadata;
  540. foreach (WsdlNS.Import import in wsdl.Imports)
  541. {
  542. if (!String.IsNullOrEmpty(import.Location))
  543. {
  544. EnqueueRetrieverIfShouldResolve(new MetadataLocationRetriever(this.CreateUri(section.SourceUrl, import.Location), this.resolver));
  545. }
  546. }
  547. foreach (XsdNS.XmlSchema schema in wsdl.Types.Schemas)
  548. {
  549. MetadataSection schemaSection = new MetadataSection(null, null, schema);
  550. schemaSection.SourceUrl = section.SourceUrl;
  551. this.HandleSchemaImports(schemaSection);
  552. }
  553. }
  554. Uri CreateUri(string baseUri, string relativeUri)
  555. {
  556. return new Uri(new Uri(baseUri), relativeUri);
  557. }
  558. void EnqueueRetrieverIfShouldResolve(MetadataRetriever retriever)
  559. {
  560. if (this.resolveMetadataReferences)
  561. {
  562. this.stackedRetrievers.Push(retriever);
  563. }
  564. }
  565. internal bool HasBeenUsed(MetadataRetriever retriever)
  566. {
  567. return this.usedRetrievers.ContainsKey(retriever);
  568. }
  569. internal void LogUse(MetadataRetriever retriever)
  570. {
  571. this.usedRetrievers.Add(retriever, retriever);
  572. }
  573. }
  574. abstract class MetadataRetriever
  575. {
  576. protected MetadataExchangeClient resolver;
  577. protected string dialect;
  578. protected string identifier;
  579. public MetadataRetriever(MetadataExchangeClient resolver, string dialect, string identifier)
  580. {
  581. this.resolver = resolver;
  582. this.dialect = dialect;
  583. this.identifier = identifier;
  584. }
  585. internal MetadataSection Retrieve(TimeoutHelper timeoutHelper)
  586. {
  587. try
  588. {
  589. using (XmlReader reader = this.DownloadMetadata(timeoutHelper))
  590. {
  591. return MetadataRetriever.CreateMetadataSection(reader, this.SourceUrl);
  592. }
  593. }
  594. #pragma warning suppress 56500 // covered by FxCOP
  595. catch (Exception e)
  596. {
  597. if (Fx.IsFatal(e))
  598. throw;
  599. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  600. SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
  601. }
  602. }
  603. internal abstract IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state);
  604. internal abstract MetadataSection EndRetrieve(IAsyncResult result);
  605. static internal MetadataSection CreateMetadataSection(XmlReader reader, string sourceUrl)
  606. {
  607. MetadataSection section = null;
  608. Type metadataType = null;
  609. if (CanReadMetadataSet(reader))
  610. {
  611. MetadataSet newSet = MetadataSet.ReadFrom(reader);
  612. section = new MetadataSection(MetadataSection.MetadataExchangeDialect, null, newSet);
  613. metadataType = typeof(MetadataSet);
  614. }
  615. else if (WsdlNS.ServiceDescription.CanRead(reader))
  616. {
  617. WsdlNS.ServiceDescription wsdl = WsdlNS.ServiceDescription.Read(reader);
  618. section = MetadataSection.CreateFromServiceDescription(wsdl);
  619. metadataType = typeof(WsdlNS.ServiceDescription);
  620. }
  621. else if (CanReadSchema(reader))
  622. {
  623. XsdNS.XmlSchema schema = XsdNS.XmlSchema.Read(reader, null);
  624. section = MetadataSection.CreateFromSchema(schema);
  625. metadataType = typeof(XsdNS.XmlSchema);
  626. }
  627. else
  628. {
  629. XmlDocument doc = new XmlDocument();
  630. doc.Load(reader);
  631. section = new MetadataSection(null, null, doc.DocumentElement);
  632. metadataType = typeof(XmlElement);
  633. }
  634. section.SourceUrl = sourceUrl;
  635. TraceReceiveReply(sourceUrl, metadataType);
  636. return section;
  637. }
  638. protected abstract XmlReader DownloadMetadata(TimeoutHelper timeoutHelper);
  639. protected abstract string SourceUrl { get; }
  640. static bool CanReadSchema(XmlReader reader)
  641. {
  642. return reader.LocalName == MetadataStrings.XmlSchema.Schema
  643. && reader.NamespaceURI == XsdNS.XmlSchema.Namespace;
  644. }
  645. static bool CanReadMetadataSet(XmlReader reader)
  646. {
  647. return reader.LocalName == MetadataStrings.MetadataExchangeStrings.Metadata
  648. && reader.NamespaceURI == MetadataStrings.MetadataExchangeStrings.Namespace;
  649. }
  650. }
  651. class MetadataLocationRetriever : MetadataRetriever
  652. {
  653. Uri location;
  654. Uri responseLocation;
  655. internal MetadataLocationRetriever(Uri location, MetadataExchangeClient resolver)
  656. : this(location, resolver, null, null)
  657. {
  658. }
  659. internal MetadataLocationRetriever(Uri location, MetadataExchangeClient resolver, string dialect, string identifier)
  660. : base(resolver, dialect, identifier)
  661. {
  662. ValidateLocation(location);
  663. this.location = location;
  664. this.responseLocation = location;
  665. }
  666. internal static void ValidateLocation(Uri location)
  667. {
  668. if (location == null)
  669. {
  670. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("location");
  671. }
  672. if (location.Scheme != Uri.UriSchemeHttp && location.Scheme != Uri.UriSchemeHttps)
  673. {
  674. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("location", SR.GetString(SR.SFxCannotGetMetadataFromLocation, location.ToString()));
  675. }
  676. }
  677. public override bool Equals(object obj)
  678. {
  679. return obj is MetadataLocationRetriever && ((MetadataLocationRetriever)obj).location == this.location;
  680. }
  681. public override int GetHashCode()
  682. {
  683. return location.GetHashCode();
  684. }
  685. protected override XmlReader DownloadMetadata(TimeoutHelper timeoutHelper)
  686. {
  687. HttpWebResponse response;
  688. HttpWebRequest request;
  689. try
  690. {
  691. request = this.resolver.GetWebRequest(this.location, this.dialect, this.identifier);
  692. }
  693. #pragma warning suppress 56500 // covered by FxCOP
  694. catch (Exception e)
  695. {
  696. if (Fx.IsFatal(e))
  697. throw;
  698. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  699. SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateWebRequest, this.location, this.dialect, this.identifier), e));
  700. }
  701. TraceSendRequest(this.location);
  702. request.Timeout = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());
  703. response = (HttpWebResponse)request.GetResponse();
  704. responseLocation = request.Address;
  705. return MetadataLocationRetriever.GetXmlReader(response, this.resolver.MaxMessageSize, this.resolver.ReaderQuotas);
  706. }
  707. internal static XmlReader GetXmlReader(HttpWebResponse response, long maxMessageSize, XmlDictionaryReaderQuotas readerQuotas)
  708. {
  709. readerQuotas = readerQuotas ?? EncoderDefaults.ReaderQuotas;
  710. XmlReader reader = XmlDictionaryReader.CreateTextReader(
  711. new MaxMessageSizeStream(response.GetResponseStream(), maxMessageSize),
  712. EncodingHelper.GetDictionaryReaderEncoding(response.ContentType),
  713. readerQuotas,
  714. null);
  715. reader.Read();
  716. reader.MoveToContent();
  717. return reader;
  718. }
  719. internal override IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
  720. {
  721. AsyncMetadataLocationRetriever result;
  722. try
  723. {
  724. HttpWebRequest request;
  725. try
  726. {
  727. request = this.resolver.GetWebRequest(this.location, this.dialect, this.identifier);
  728. }
  729. #pragma warning suppress 56500 // covered by FxCOP
  730. catch (Exception e)
  731. {
  732. if (Fx.IsFatal(e))
  733. throw;
  734. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  735. SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateWebRequest, this.location, this.dialect, this.identifier), e));
  736. }
  737. TraceSendRequest(this.location);
  738. result = new AsyncMetadataLocationRetriever(request, this.resolver.MaxMessageSize, this.resolver.ReaderQuotas, timeoutHelper, callback, state);
  739. }
  740. #pragma warning suppress 56500 // covered by FxCOP
  741. catch (Exception e)
  742. {
  743. if (Fx.IsFatal(e))
  744. throw;
  745. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  746. SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
  747. }
  748. return result;
  749. }
  750. internal override MetadataSection EndRetrieve(IAsyncResult result)
  751. {
  752. try
  753. {
  754. return AsyncMetadataLocationRetriever.End(result);
  755. }
  756. #pragma warning suppress 56500 // covered by FxCOP
  757. catch (Exception e)
  758. {
  759. if (Fx.IsFatal(e))
  760. throw;
  761. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  762. SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
  763. }
  764. }
  765. protected override string SourceUrl
  766. {
  767. get { return this.responseLocation.ToString(); }
  768. }
  769. class AsyncMetadataLocationRetriever : AsyncResult
  770. {
  771. MetadataSection section;
  772. long maxMessageSize;
  773. XmlDictionaryReaderQuotas readerQuotas;
  774. internal AsyncMetadataLocationRetriever(WebRequest request, long maxMessageSize, XmlDictionaryReaderQuotas readerQuotas, TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
  775. : base(callback, state)
  776. {
  777. this.maxMessageSize = maxMessageSize;
  778. this.readerQuotas = readerQuotas;
  779. IAsyncResult result = request.BeginGetResponse(Fx.ThunkCallback(new AsyncCallback(this.GetResponseCallback)), request);
  780. //Register a callback to abort the request if we hit the timeout.
  781. ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
  782. Fx.ThunkCallback(new WaitOrTimerCallback(RetrieveTimeout)), request,
  783. TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime()), /* executeOnlyOnce */ true);
  784. if (result.CompletedSynchronously)
  785. {
  786. HandleResult(result);
  787. this.Complete(true);
  788. }
  789. }
  790. static void RetrieveTimeout(object state, bool timedOut)
  791. {
  792. if (timedOut)
  793. {
  794. HttpWebRequest request = state as HttpWebRequest;
  795. if (request != null)
  796. {
  797. request.Abort();
  798. }
  799. }
  800. }
  801. internal static MetadataSection End(IAsyncResult result)
  802. {
  803. AsyncMetadataLocationRetriever retrieverResult = AsyncResult.End<AsyncMetadataLocationRetriever>(result);
  804. return retrieverResult.section;
  805. }
  806. internal void GetResponseCallback(IAsyncResult result)
  807. {
  808. if (result.CompletedSynchronously)
  809. return;
  810. Exception exception = null;
  811. try
  812. {
  813. HandleResult(result);
  814. }
  815. #pragma warning suppress 56500 // covered by FxCOP
  816. catch (Exception e)
  817. {
  818. if (Fx.IsFatal(e))
  819. throw;
  820. exception = e;
  821. }
  822. this.Complete(false, exception);
  823. }
  824. void HandleResult(IAsyncResult result)
  825. {
  826. HttpWebRequest request = (HttpWebRequest)result.AsyncState;
  827. using (XmlReader reader =
  828. MetadataLocationRetriever.GetXmlReader((HttpWebResponse)request.EndGetResponse(result), this.maxMessageSize, this.readerQuotas))
  829. {
  830. section = MetadataRetriever.CreateMetadataSection(reader, request.Address.ToString());
  831. }
  832. }
  833. }
  834. }
  835. class MetadataReferenceRetriever : MetadataRetriever
  836. {
  837. EndpointAddress address;
  838. Uri via;
  839. public MetadataReferenceRetriever(EndpointAddress address, MetadataExchangeClient resolver)
  840. : this(address, null, resolver, null, null)
  841. {
  842. }
  843. public MetadataReferenceRetriever(EndpointAddress address, Uri via, MetadataExchangeClient resolver)
  844. : this(address, via, resolver, null, null)
  845. {
  846. }
  847. public MetadataReferenceRetriever(EndpointAddress address, MetadataExchangeClient resolver, string dialect, string identifier)
  848. : this(address, null, resolver, dialect, identifier)
  849. {
  850. }
  851. MetadataReferenceRetriever(EndpointAddress address, Uri via, MetadataExchangeClient resolver, string dialect, string identifier)
  852. : base(resolver, dialect, identifier)
  853. {
  854. if (address == null)
  855. {
  856. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  857. }
  858. this.address = address;
  859. this.via = via;
  860. }
  861. protected override string SourceUrl
  862. {
  863. get { return this.address.Uri.ToString(); }
  864. }
  865. internal override IAsyncResult BeginRetrieve(TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
  866. {
  867. try
  868. {
  869. IMetadataExchange metadataClient;
  870. MessageVersion messageVersion;
  871. lock (this.resolver.ThisLock)
  872. {
  873. ChannelFactory<IMetadataExchange> channelFactory;
  874. try
  875. {
  876. channelFactory = this.resolver.GetChannelFactory(this.address, this.dialect, this.identifier);
  877. }
  878. #pragma warning suppress 56500 // covered by FxCOP
  879. catch (Exception e)
  880. {
  881. if (Fx.IsFatal(e))
  882. throw;
  883. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  884. SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactory, this.address, this.dialect, this.identifier), e));
  885. }
  886. metadataClient = CreateChannel(channelFactory);
  887. messageVersion = channelFactory.Endpoint.Binding.MessageVersion;
  888. }
  889. TraceSendRequest(this.address);
  890. return new AsyncMetadataReferenceRetriever(metadataClient, messageVersion, timeoutHelper, callback, state);
  891. }
  892. #pragma warning suppress 56500 // covered by FxCOP
  893. catch (Exception e)
  894. {
  895. if (Fx.IsFatal(e))
  896. throw;
  897. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  898. SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
  899. }
  900. }
  901. IMetadataExchange CreateChannel(ChannelFactory<IMetadataExchange> channelFactory)
  902. {
  903. if (this.via != null)
  904. {
  905. return channelFactory.CreateChannel(this.address, this.via);
  906. }
  907. else
  908. {
  909. return channelFactory.CreateChannel(this.address);
  910. }
  911. }
  912. static Message CreateGetMessage(MessageVersion messageVersion)
  913. {
  914. return Message.CreateMessage(messageVersion, MetadataStrings.WSTransfer.GetAction);
  915. }
  916. protected override XmlReader DownloadMetadata(TimeoutHelper timeoutHelper)
  917. {
  918. IMetadataExchange metadataClient;
  919. MessageVersion messageVersion;
  920. lock (this.resolver.ThisLock)
  921. {
  922. ChannelFactory<IMetadataExchange> channelFactory;
  923. try
  924. {
  925. channelFactory = this.resolver.GetChannelFactory(this.address, this.dialect, this.identifier);
  926. }
  927. #pragma warning suppress 56500 // covered by FxCOP
  928. catch (Exception e)
  929. {
  930. if (Fx.IsFatal(e))
  931. throw;
  932. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  933. SR.GetString(SR.SFxMetadataExchangeClientCouldNotCreateChannelFactory, this.address, this.dialect, this.identifier), e));
  934. }
  935. metadataClient = CreateChannel(channelFactory);
  936. messageVersion = channelFactory.Endpoint.Binding.MessageVersion;
  937. }
  938. Message response;
  939. TraceSendRequest(this.address);
  940. try
  941. {
  942. using (Message getMessage = CreateGetMessage(messageVersion))
  943. {
  944. ((IClientChannel)metadataClient).OperationTimeout = timeoutHelper.RemainingTime();
  945. response = metadataClient.Get(getMessage);
  946. }
  947. ((IClientChannel)metadataClient).Close();
  948. }
  949. finally
  950. {
  951. ((IClientChannel)metadataClient).Abort();
  952. }
  953. if (response.IsFault)
  954. {
  955. MessageFault fault = MessageFault.CreateFault(response, 64 * 1024);
  956. StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
  957. XmlWriter xmlWriter = XmlWriter.Create(stringWriter);
  958. fault.WriteTo(xmlWriter, response.Version.Envelope);
  959. xmlWriter.Flush();
  960. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(stringWriter.ToString()));
  961. }
  962. return response.GetReaderAtBodyContents();
  963. }
  964. internal override MetadataSection EndRetrieve(IAsyncResult result)
  965. {
  966. try
  967. {
  968. return AsyncMetadataReferenceRetriever.End(result);
  969. }
  970. #pragma warning suppress 56500 // covered by FxCOP
  971. catch (Exception e)
  972. {
  973. if (Fx.IsFatal(e))
  974. throw;
  975. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  976. SR.GetString(SR.SFxBadMetadataReference, this.SourceUrl), e));
  977. }
  978. }
  979. public override bool Equals(object obj)
  980. {
  981. return obj is MetadataReferenceRetriever && ((MetadataReferenceRetriever)obj).address == this.address;
  982. }
  983. public override int GetHashCode()
  984. {
  985. return address.GetHashCode();
  986. }
  987. class AsyncMetadataReferenceRetriever : AsyncResult
  988. {
  989. MetadataSection section;
  990. Message message;
  991. internal AsyncMetadataReferenceRetriever(IMetadataExchange metadataClient, MessageVersion messageVersion, TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
  992. : base(callback, state)
  993. {
  994. message = MetadataReferenceRetriever.CreateGetMessage(messageVersion);
  995. ((IClientChannel)metadataClient).OperationTimeout = timeoutHelper.RemainingTime();
  996. IAsyncResult result = metadataClient.BeginGet(message, Fx.ThunkCallback(new AsyncCallback(this.RequestCallback)), metadataClient);
  997. if (result.CompletedSynchronously)
  998. {
  999. HandleResult(result);
  1000. this.Complete(true);
  1001. }
  1002. }
  1003. internal static MetadataSection End(IAsyncResult result)
  1004. {
  1005. AsyncMetadataReferenceRetriever retrieverResult = AsyncResult.End<AsyncMetadataReferenceRetriever>(result);
  1006. return retrieverResult.section;
  1007. }
  1008. internal void RequestCallback(IAsyncResult result)
  1009. {
  1010. if (result.CompletedSynchronously)
  1011. return;
  1012. Exception exception = null;
  1013. try
  1014. {
  1015. HandleResult(result);
  1016. }
  1017. #pragma warning suppress 56500 // covered by FxCOP
  1018. catch (Exception e)
  1019. {
  1020. if (Fx.IsFatal(e))
  1021. throw;
  1022. exception = e;
  1023. }
  1024. this.Complete(false, exception);
  1025. }
  1026. void HandleResult(IAsyncResult result)
  1027. {
  1028. IMetadataExchange metadataClient = (IMetadataExchange)result.AsyncState;
  1029. Message response = metadataClient.EndGet(result);
  1030. using (this.message)
  1031. {
  1032. if (response.IsFault)
  1033. {
  1034. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBadMetadataReference,
  1035. ((IClientChannel)metadataClient).RemoteAddress.Uri.ToString())));
  1036. }
  1037. else
  1038. {
  1039. using (XmlReader reader = response.GetReaderAtBodyContents())
  1040. {
  1041. section = MetadataRetriever.CreateMetadataSection(reader, ((IClientChannel)metadataClient).RemoteAddress.Uri.ToString());
  1042. }
  1043. }
  1044. }
  1045. }
  1046. }
  1047. }
  1048. class AsyncMetadataResolver : AsyncResult
  1049. {
  1050. ResolveCallState resolveCallState;
  1051. internal AsyncMetadataResolver(ResolveCallState resolveCallState, AsyncCallback callerCallback, object callerAsyncState)
  1052. : base(callerCallback, callerAsyncState)
  1053. {
  1054. if (resolveCallState == null)
  1055. {
  1056. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("resolveCallState");
  1057. }
  1058. this.resolveCallState = resolveCallState;
  1059. Exception exception = null;
  1060. bool doneResolving = false;
  1061. try
  1062. {
  1063. doneResolving = this.ResolveNext();
  1064. }
  1065. #pragma warning suppress 56500 // covered by FxCOP
  1066. catch (Exception e)
  1067. {
  1068. if (Fx.IsFatal(e))
  1069. throw;
  1070. exception = e;
  1071. doneResolving = true;
  1072. }
  1073. if (doneResolving)
  1074. {
  1075. this.Complete(true, exception);
  1076. }
  1077. }
  1078. bool ResolveNext()
  1079. {
  1080. bool doneResolving = false;
  1081. if (this.resolveCallState.StackedRetrievers.Count > 0)
  1082. {
  1083. MetadataRetriever retriever = this.resolveCallState.StackedRetrievers.Pop();
  1084. if (resolveCallState.HasBeenUsed(retriever))
  1085. {
  1086. doneResolving = this.ResolveNext();
  1087. }
  1088. else
  1089. {
  1090. if (resolveCallState.ResolvedMaxResolvedReferences)
  1091. {
  1092. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxResolvedMaxResolvedReferences)));
  1093. }
  1094. else
  1095. {
  1096. resolveCallState.LogUse(retriever);
  1097. IAsyncResult result = retriever.BeginRetrieve(this.resolveCallState.TimeoutHelper, Fx.ThunkCallback(new AsyncCallback(this.RetrieveCallback)), retriever);
  1098. if (result.CompletedSynchronously)
  1099. {
  1100. doneResolving = HandleResult(result);
  1101. }
  1102. }
  1103. }
  1104. }
  1105. else
  1106. {
  1107. doneResolving = true;
  1108. }
  1109. return doneResolving;
  1110. }
  1111. internal static MetadataSet End(IAsyncResult result)
  1112. {
  1113. AsyncMetadataResolver resolverResult = AsyncResult.End<AsyncMetadataResolver>(result);
  1114. return resolverResult.resolveCallState.MetadataSet;
  1115. }
  1116. internal void RetrieveCallback(IAsyncResult result)
  1117. {
  1118. if (result.CompletedSynchronously)
  1119. return;
  1120. Exception exception = null;
  1121. bool doneResolving = false;
  1122. try
  1123. {
  1124. doneResolving = HandleResult(result);
  1125. }
  1126. #pragma warning suppress 56500 // covered by FxCOP
  1127. catch (Exception e)
  1128. {
  1129. if (Fx.IsFatal(e))
  1130. throw;
  1131. exception = e;
  1132. doneResolving = true;
  1133. }
  1134. if (doneResolving)
  1135. {
  1136. this.Complete(false, exception);
  1137. }
  1138. }
  1139. bool HandleResult(IAsyncResult result)
  1140. {
  1141. MetadataRetriever retriever = (MetadataRetriever)result.AsyncState;
  1142. MetadataSection section = retriever.EndRetrieve(result);
  1143. this.resolveCallState.HandleSection(section);
  1144. return this.ResolveNext();
  1145. }
  1146. }
  1147. internal class EncodingHelper
  1148. {
  1149. internal const string ApplicationBase = "application";
  1150. internal static Encoding GetRfcEncoding(string contentTypeStr)
  1151. {
  1152. Encoding e = null;
  1153. ContentType contentType = null;
  1154. try
  1155. {
  1156. contentType = new ContentType(contentTypeStr);
  1157. string charset = contentType == null ? string.Empty : contentType.CharSet;
  1158. if (charset != null && charset.Length > 0)
  1159. e = Encoding.GetEncoding(charset);
  1160. }
  1161. #pragma warning suppress 56500 // covered by FxCOP
  1162. catch (Exception ex)
  1163. {
  1164. if (Fx.IsFatal(ex))
  1165. throw;
  1166. }
  1167. // default to ASCII encoding per RFC 2376/3023
  1168. if (IsApplication(contentType))
  1169. return e == null ? new ASCIIEncoding() : e;
  1170. else
  1171. return e;
  1172. }
  1173. internal static bool IsApplication(ContentType contentType)
  1174. {
  1175. return string.Compare(contentType == null ? string.Empty : contentType.MediaType,
  1176. ApplicationBase, StringComparison.OrdinalIgnoreCase) == 0;
  1177. }
  1178. internal static Encoding GetDictionaryReaderEncoding(string contentTypeStr)
  1179. {
  1180. if (String.IsNullOrEmpty(contentTypeStr))
  1181. return TextEncoderDefaults.Encoding;
  1182. Encoding encoding = GetRfcEncoding(contentTypeStr);
  1183. if (encoding == null)
  1184. return TextEncoderDefaults.Encoding;
  1185. string charSet = encoding.WebName;
  1186. Encoding[] supportedEncodings = TextEncoderDefaults.SupportedEncodings;
  1187. for (int i = 0; i < supportedEncodings.Length; i++)
  1188. {
  1189. if (charSet == supportedEncodings[i].WebName)
  1190. return encoding;
  1191. }
  1192. return TextEncoderDefaults.Encoding;
  1193. }
  1194. }
  1195. }
  1196. public enum MetadataExchangeClientMode
  1197. {
  1198. MetadataExchange,
  1199. HttpGet,
  1200. }
  1201. static class MetadataExchangeClientModeHelper
  1202. {
  1203. static public bool IsDefined(MetadataExchangeClientMode x)
  1204. {
  1205. return
  1206. x == MetadataExchangeClientMode.MetadataExchange ||
  1207. x == MetadataExchangeClientMode.HttpGet ||
  1208. false;
  1209. }
  1210. public static void Validate(MetadataExchangeClientMode value)
  1211. {
  1212. if (!IsDefined(value))
  1213. {
  1214. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value,
  1215. typeof(MetadataExchangeClientMode)));
  1216. }
  1217. }
  1218. }
  1219. }