2 // MetadataExchangeClient.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Ankit Jain <jankit@novell.com>
8 // Copyright (C) 2005 Novell, Inc. http://www.novell.com
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.ServiceModel.Description;
35 using System.Web.Services.Description;
36 using System.Web.Services.Discovery;
37 using System.Web.Services.Protocols;
39 using System.Xml.Serialization;
44 using SMBinding = System.ServiceModel.Channels.Binding;
45 using SMMessage = System.ServiceModel.Channels.Message;
47 namespace System.ServiceModel.Description
49 public class MetadataExchangeClient
53 EndpointAddress address;
55 MetadataExchangeClientMode mode = MetadataExchangeClientMode.MetadataExchange;
56 TimeSpan? operation_timeout = null;
60 [MonoTODO ("use empty configuration")]
61 public MetadataExchangeClient ()
65 public MetadataExchangeClient (SMBinding mexBinding)
70 public MetadataExchangeClient (EndpointAddress address)
72 this.address = address;
75 public MetadataExchangeClient (string endpointConfigurationName)
77 throw new NotImplementedException ();
80 [MonoTODO ("MetadataExchangeClientMode is not considered")]
81 public MetadataExchangeClient (Uri address, MetadataExchangeClientMode mode)
83 this.address = new EndpointAddress (address.AbsoluteUri);
88 public ICredentials HttpCredentials { get; set; }
90 public int MaximumResolvedReferences { get; set; }
92 public TimeSpan OperationTimeout {
94 if (!this.operation_timeout.HasValue) {
95 this.operation_timeout = DefaultCommunicationTimeouts.Instance.ReceiveTimeout;
97 return this.operation_timeout.Value;
100 this.operation_timeout = value;
105 public bool ResolveMetadataReferences { get; set; }
107 public ClientCredentials SoapCredentials { get; set; }
109 [MonoTODO ("use dialect and identifier (but how?)")]
110 protected internal virtual ChannelFactory<IMetadataExchange> GetChannelFactory (EndpointAddress metadataAddress, string dialect, string identifier)
112 if (metadataAddress == null)
113 throw new ArgumentNullException ("metadataAddress");
115 var se = new ServiceEndpoint (ContractDescription.GetContract (typeof (IMetadataExchange)), CreateBinding (metadataAddress), metadataAddress);
116 if (SoapCredentials != null) {
117 se.Behaviors.RemoveAll<ClientCredentials> ();
118 se.Behaviors.Add (SoapCredentials);
120 return new ChannelFactory<IMetadataExchange> (se);
124 protected internal virtual HttpWebRequest GetWebRequest (Uri location, string dialect, string identifier)
126 throw new NotImplementedException ();
129 SMBinding CreateBinding (EndpointAddress address)
131 return address.Uri.Scheme == Uri.UriSchemeHttps ?
132 MetadataExchangeBindings.CreateMexHttpsBinding () :
133 MetadataExchangeBindings.CreateMexHttpBinding ();
138 public MetadataSet GetMetadata ()
140 return GetMetadata (address);
143 public MetadataSet GetMetadata (EndpointAddress address)
145 //FIXME: default mode?
146 return GetMetadataInternal (address, mode);
149 public MetadataSet GetMetadata (Uri address, MetadataExchangeClientMode mode)
151 return GetMetadataInternal (new EndpointAddress (address.AbsoluteUri), mode);
154 internal MetadataSet GetMetadataInternal (EndpointAddress address, MetadataExchangeClientMode mode)
156 // FIXME: give dialect and identifier
157 var cf = GetChannelFactory (address, null, null);
159 var proxy = cf.CreateChannel ();
160 var asClientChannel = proxy as IClientChannel;
161 if (asClientChannel == null)
162 throw new InvalidOperationException ("The channel factory must return an IClientChannel implementation");
163 asClientChannel.OperationTimeout = OperationTimeout;
164 asClientChannel.Open ();
166 SMMessage msg = SMMessage.CreateMessage (
167 MessageVersion.Soap12WSAddressing10,
168 "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get");
170 msg.Headers.ReplyTo = new EndpointAddress (
171 "http://www.w3.org/2005/08/addressing/anonymous");
172 //msg.Headers.From = new EndpointAddress ("http://localhost");
173 msg.Headers.To = address.Uri;
174 msg.Headers.MessageId = new UniqueId ();
178 ret = proxy.Get (msg);
179 } catch (Exception e) {
180 throw new InvalidOperationException (
181 "Metadata contains a reference that cannot be resolved : " + address.Uri.AbsoluteUri, e);
184 return MetadataSet.ReadFrom (ret.GetReaderAtBodyContents ());
189 Func<Func<MetadataSet>,MetadataSet> getter;
191 void PrepareGetter ()
194 getter = new Func<Func<MetadataSet>,MetadataSet> (GetMetadata);
197 public MetadataSet EndGetMetadata (IAsyncResult result)
199 return getter.EndInvoke (result);
202 MetadataSet GetMetadata (Func<MetadataSet> func)
207 public IAsyncResult BeginGetMetadata (AsyncCallback callback, object asyncState)
210 return getter.BeginInvoke (() => GetMetadata (), callback, asyncState);
213 public IAsyncResult BeginGetMetadata (EndpointAddress address, AsyncCallback callback, object asyncState)
216 return getter.BeginInvoke (() => GetMetadata (address), callback, asyncState);
219 public IAsyncResult BeginGetMetadata (Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
222 return getter.BeginInvoke (() => GetMetadata (address, mode), callback, asyncState);
226 interface IMetadataExchangeClient : IMetadataExchange, IClientChannel