using System; using System.IO; using System.Diagnostics; using System.Net; using System.Web.Services; using System.Web.Services.Description; using System.Web.Services.Protocols; using System.Xml; using System.Xml.Serialization; using System.Xml.Xsl; using System.Xml.XPath; using System.Text; using Microsoft.Uddi; using Microsoft.Uddi.Authentication; using Microsoft.Uddi.VersionSupport; namespace Microsoft.Uddi.Web { /// /// UddiWebResponse allows us to return our own Stream object. /// internal class UddiWebResponse : WebResponse { private WebResponse innerWebResponse; private UddiResponseStream uddiResponseStream; private UddiVersion uddiVersion; /// /// Constructor /// /// This object should come from the WebResponse created by HttpSoapClientProtocol. public UddiWebResponse( WebResponse innerWebResponse ) { this.innerWebResponse = innerWebResponse; this.uddiVersion = uddiVersion; } /// /// Return our response stream (UddiResponseStream) instead of the Stream associated with our inner response. /// /// public override Stream GetResponseStream() { if( null == uddiResponseStream ) { uddiResponseStream = new UddiResponseStream( innerWebResponse.GetResponseStream() ); } return uddiResponseStream; } /// /// Delegates to the inner web response. /// public override void Close() { innerWebResponse.Close(); } /// /// Delegates to the inner web response. /// public override long ContentLength { get { return innerWebResponse.ContentLength; } set { innerWebResponse.ContentLength = value; } } /// /// Delegates to the inner web response. /// public override string ContentType { get { return innerWebResponse.ContentType; } set { innerWebResponse.ContentType = value; } } /// /// Delegates to the inner web response. /// public override Uri ResponseUri { get { return innerWebResponse.ResponseUri; } } /// /// Delegates to the inner web response. /// public override WebHeaderCollection Headers { get { return innerWebResponse.Headers; } } } /// /// UddiResponseStream allows us to manipulate the XML sent back from the web service. /// internal class UddiResponseStream : MemoryStream { // // TODO: at some point it may be necessary to pass in the current version as a parameter if the transforms become // more complicated. // /// /// Constructor. We read all the XML sent from the server, do our version manipulation, then write the new XML /// into our inner responseStream object. /// /// This object should be the responseStream from a WebResponse object. public UddiResponseStream( Stream responseStream ) { try { // // Get the XML the server sent to us. // StreamReader reader = new StreamReader( responseStream ); string responseXml = reader.ReadToEnd(); reader.Close(); // // TODO: Consider making this class more generic, ie. have a IUddiResponseHandler interface: // IUddiResponseHandler // string HandleResponse( string xml ); // // // Translate the incoming XML into the current version. // string transformedXml = UddiVersionSupport.Translate( responseXml, UddiVersionSupport.CurrentVersion ); // // Write this transformed XML into the 'real' stream. // StreamUtility.WriteStringToStream( this, transformedXml ); } finally { this.Position = 0; } } } /// /// UddiWebRequest allows us to return our own request and response objects. /// internal class UddiWebRequest : WebRequest { private WebRequest innerWebRequest; private UddiRequestStream uddiRequestStream; private UddiWebResponse uddiWebResponse; private UddiVersion uddiVersion; /// /// Constructor /// /// Uri to the web service we are calling /// Uddi version to use for requests public UddiWebRequest( WebRequest innerWebRequest, UddiVersion uddiVersion ) { this.innerWebRequest = innerWebRequest; this.uddiVersion = uddiVersion; } /// /// Return a UddiRequestStream object instead of the default one. /// /// UddiRequestStream object public override Stream GetRequestStream() { if( null == uddiRequestStream ) { uddiRequestStream = new UddiRequestStream( innerWebRequest.GetRequestStream(), uddiVersion ); } return uddiRequestStream; } /// /// Return a UddiWebRequest object instead of the default one. /// /// UddiWebResponse object public override WebResponse GetResponse() { if( null == uddiWebResponse ) { uddiWebResponse = new UddiWebResponse( innerWebRequest.GetResponse() ); } return uddiWebResponse; } /// /// Delegates to our inner WebRequest /// public override string Method { get { return innerWebRequest.Method; } set { innerWebRequest.Method = value; } } /// /// Delegates to our inner WebRequest /// public override Uri RequestUri { get { return innerWebRequest.RequestUri; } } /// /// Delegates to our inner WebRequest /// public override string ConnectionGroupName { get { return innerWebRequest.ConnectionGroupName; } set { innerWebRequest.ConnectionGroupName = value; } } /// /// Delegates to our inner WebRequest /// public override WebHeaderCollection Headers { get { return innerWebRequest.Headers; } set { innerWebRequest.Headers = value; } } /// /// Delegates to our inner WebRequest /// public override long ContentLength { get { return innerWebRequest.ContentLength; } set { innerWebRequest.ContentLength = value; } } /// /// Delegates to our inner WebRequest /// public override string ContentType { get { return innerWebRequest.ContentType; } set { innerWebRequest.ContentType = value; } } /// /// Delegates to our inner WebRequest /// public override ICredentials Credentials { get { return innerWebRequest.Credentials; } set { innerWebRequest.Credentials = value; } } /// /// Delegates to our inner WebRequest /// public override IWebProxy Proxy { get { return innerWebRequest.Proxy; } set { innerWebRequest.Proxy = value; } } /// /// Delegates to our inner WebRequest /// public override bool PreAuthenticate { get { return innerWebRequest.PreAuthenticate; } set { innerWebRequest.PreAuthenticate = value; } } /// /// Delegates to our inner WebRequest /// public override int Timeout { get { return innerWebRequest.Timeout; } set { innerWebRequest.Timeout = value; } } /// /// Delegates to our inner WebRequest /// public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state) { return innerWebRequest.BeginGetResponse( callback, state ); } /// /// Delegates to our inner WebRequest /// public override WebResponse EndGetResponse(IAsyncResult asyncResult) { return innerWebRequest.EndGetResponse( asyncResult ); } /// /// Delegates to our inner WebRequest /// public override IAsyncResult BeginGetRequestStream(AsyncCallback callback, Object state) { return innerWebRequest.BeginGetRequestStream( callback, state ); } /// /// Delegates to our inner WebRequest /// public override Stream EndGetRequestStream(IAsyncResult asyncResult) { return innerWebRequest.EndGetRequestStream( asyncResult ); } /// /// Delegates to our inner WebRequest /// public override void Abort() { innerWebRequest.Abort(); } } /// /// UddiRequestStream allows us to manipulate the XML before we send it to the client. This class will accept all data that /// is written to it from the ASP.NET web service framework. When the framework closes the stream (ie. wants to send the data), we /// will manipulate this XML so that it has the right Uddi version, then send it out using our innerStream object. /// internal class UddiRequestStream : MemoryStream { private Stream innerStream; private UddiVersion uddiVersion; /// /// Constructor /// /// Should be from a WebRequest object. /// The UDD version we should use to send to the server public UddiRequestStream( Stream innerStream, UddiVersion uddiVersion ) { this.innerStream = innerStream; this.uddiVersion = uddiVersion; } /// /// Before we actually close the request stream, we want to manipulate the XML. /// public override void Close() { try { // // Rewind ourselves. // this.Position = 0; // // Read the XML that was written; this is the XML request that will be sent to the Uddi server. // StreamReader reader = new StreamReader( this ); string requestXml = reader.ReadToEnd(); // // TODO: Consider making this class more generic, ie. have a IUddiRequestHandler interface: // IUddiResponseHandler // string HandleRequest( string xml ); // // // Transform the content to a correct version on the server if we are not using the current version. // string transformedXml = requestXml; if( uddiVersion != UddiVersionSupport.CurrentVersion ) { transformedXml = UddiVersionSupport.Translate( requestXml, uddiVersion ); } // // Write the transformed data to the 'real' stream. // StreamUtility.WriteStringToStream( innerStream, transformedXml ); } finally { // // Make sure we clean up properly. // innerStream.Close(); base.Close(); } } } /// /// Simple utility class to help us write string data to Stream objects. /// internal sealed class StreamUtility { public static void WriteStringToStream( Stream stream, string stringToWrite ) { for ( int i = 0; i < stringToWrite.Length; i++ ) { stream.WriteByte( Convert.ToByte( stringToWrite[ i ] ) ); } } private StreamUtility() { // // Don't let anyone instantiate this class // } } }