private void CheckSOAPHeaders(SoapMessage message)
        {
            // We want to check the following:
            //
            // - no SOAP Actor attribute exists
            // - no SOAP headers can have a must_understand attribute set to true
            //
            // Go through each header in our message
            //
            foreach (SoapHeader header in message.Headers)
            {
                if (header.MustUnderstand)
                {
                    //
                    // No headers can have this attribute set.
                    //
                    DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_SOAP_MUSTUNDERSTANDATT"));

                    return;
                }

                if (header.Actor.Length > 0)
                {
                    //
                    // Can't have a SOAP Actor attribute set, generate a SOAP fault with
                    // no detail element and a 'Client' fault code
                    //
                    DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_SOAP_ACTORATT"));

                    return;
                }
            }
        }
        //
        // TODO: see if there is a way to better modularize this method and rename it.
        //
        private void CheckForSingleRequest(Stream stream)
        {
            try
            {
                //
                // Move to the start of our stream
                //
                stream.Position = 0;
                XmlTextReader requestReader = new XmlTextReader(oldStream);
                requestReader.MoveToContent();

                //
                // TODO: should not hard-code SOAP names and namespaces
                //

                //
                // Move to the beginning of the SOAP envelope
                //
                requestReader.ReadStartElement("Envelope", "http://schemas.xmlsoap.org/soap/envelope/");

                //
                // Move to the SOAP body
                //
                while (!requestReader.IsStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/") && !requestReader.EOF)
                {
                    requestReader.Skip();
                }

                //
                // Advance the current node to the first child of Body.  This is presumably the UDDI message
                //
                requestReader.ReadStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/");
                requestReader.MoveToContent();

                //
                // This element MUST have a UDDI namespace
                //
                string uddiNamespace = requestReader.LookupNamespace(requestReader.Prefix);

                switch (uddiNamespace)
                {
                case "urn:uddi-org:api":
                {
                    Context.ApiVersionMajor = 1;
                    break;
                }

                case "urn:uddi-org:api_v2":
                {
                    Context.ApiVersionMajor = 2;
                    break;
                }

                case "urn:uddi-microsoft-com:api_v2_extensions":
                {
                    Context.ApiVersionMajor = 2;
                    break;
                }

                case "urn:uddi-org:repl":
                {
                    Context.ApiVersionMajor = 2;
                    break;
                }

                default:
                {
                    //
                    // This is a problem, we don't have a UDDI namespace.  Throw an exception and get out of here.  The
                    // exception will be caught in our outer catch and sent to our client using DispositionReport.ThrowFinal.
                    //

                    throw new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_MISSINGUDDINS");
                }
                }

                //
                // Skip the children of this node
                //
                requestReader.Skip();
                requestReader.MoveToContent();

                //
                // Reset our stream so someone else can use it.
                //
                stream.Position = 0;

                //
                // If we are not at the end of the Body tag, then we have multiple requests, we should reject the message.
                //
                if (false == requestReader.LocalName.Equals("Body"))
                {
                    DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_SOAP_MULTIPLEREQUEST"));
                }
            }
            catch (UDDIException uddiException)
            {
                DispositionReport.ThrowFinal(uddiException);
            }
            catch
            {
                //
                // We'll get this exception if the message contains any invalid elements
                //
                DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_SOAP_INVALIDELEMENT"));
            }
        }
        public override void ProcessMessage(SoapMessage message)
        {
            try
            {
                switch (message.Stage)
                {
                case SoapMessageStage.BeforeDeserialize:
                    //
                    // Check to see if the server has been manually stopped.
                    //
                    if (0 == Config.GetInt("Run", 1))
                    {
                        DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_busy, "UDDI_ERROR_BUSY_SERVICENOTAVAILABLE"));

                        //
                        // DispositionReport.ThrowFinal will close the HTTP stream so there is no point going on in this method
                        //
                        return;
                    }

                    try
                    {
                        //
                        // Validate against the UDDI schemas
                        //
                        SchemaCollection.Validate(oldStream);
                    }
                    catch (Exception e)
                    {
                        DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_SCHEMAVALIDATIONFAILED", e.Message));

                        //
                        // DispositionReport.ThrowFinal will close the HTTP stream so there is no point going on in this method
                        //
                        return;
                    }

                    //
                    // Make sure we only have 1 UDDI request in the SOAP body.  This method will also set the versionMajor
                    // member.
                    //
                    CheckForSingleRequest(oldStream);

                    //
                    // If this is a v1 message, we'll first map it to the v2
                    // namespace so that it can be processed by the new
                    // library.
                    //
                    if (1 == Context.ApiVersionMajor || 2 == Context.ApiVersionMajor)
                    {
                        TextReader reader = new StreamReader(oldStream);
                        TextWriter writer = new StreamWriter(newStream, new System.Text.UTF8Encoding(false));
                        string     xml    = reader.ReadToEnd();

                        if (1 == Context.ApiVersionMajor)
                        {
                            xml = xml.Replace("=\"urn:uddi-org:api\"", "=\"urn:uddi-org:api_v2\"");
                            xml = xml.Replace("='urn:uddi-org:api'", "=\"urn:uddi-org:api_v2\"");
                        }
                        writer.Write(xml);
                        writer.Flush();

                        newStream.Position = 0;
                    }

                    break;

                case SoapMessageStage.AfterDeserialize:
                    //
                    // After the message is deserialized is the earliest place where we
                    // have access to our SOAP headers.
                    //
                    CheckSOAPHeaders(message);

                    //
                    // Now that the message has been deserialized, make
                    // sure that the generic and xmlns attributes agree.
                    //
                    IMessage obj = message.GetInParameterValue(0) as IMessage;
                    if (null != obj)
                    {
                        //
                        // We only need to do this if the deserialized object supports IMessage
                        //
                        string expected = Context.ApiVersionMajor + ".0";
                        string actual   = obj.Generic.Trim();

                        if (expected != actual)
                        {
                            throw new UDDIException(ErrorType.E_unrecognizedVersion, "UDDI_ERROR_UNKNOWNVERSION_GENERICNAMESPACEMISMATCH");
                        }
                    }

                    break;

                case SoapMessageStage.BeforeSerialize:
                    break;

                case SoapMessageStage.AfterSerialize:

                    //
                    // There may have been exceptions thrown during serialization.
                    //
                    if (null != message.Exception &&
                        (null == message.Exception.Detail ||
                         0 == message.Exception.Detail.ChildNodes.Count))
                    {
                        DispositionReport.ThrowFinal(new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_FAILEDDESERIALIZATION"));

                        //
                        // DispositionReport.ThrowFinal will close the HTTP stream so there is no point going on in this method
                        //
                        return;
                    }

                    //
                    // If the original request was v1, then we'll need to
                    // remap the output to use the v1 namespace.
                    //
                    if (1 == Context.ApiVersionMajor || 2 == Context.ApiVersionMajor)
                    {
                        newStream.Position = 0;

                        TextReader reader = new StreamReader(newStream);
                        TextWriter writer = new StreamWriter(oldStream, new System.Text.UTF8Encoding(false));

                        string xml = reader.ReadToEnd();

                        //
                        // We don't have to use the same 'loose' replacement as we did on the incoming request
                        // because our response will be serialized such that the default namespace is our UDDI
                        // namespace.
                        //

                        if (1 == Context.ApiVersionMajor)
                        {
                            xml = xml.Replace("xmlns=\"urn:uddi-org:api_v2\"", "xmlns=\"urn:uddi-org:api\"");
                            xml = xml.Replace("generic=\"2.0\"", "generic=\"1.0\"");
                        }
                        writer.Write(xml);
                        writer.Flush();
                    }

                    break;

                default:
                    throw new UDDIException(ErrorType.E_fatalError, "UDDI_ERROR_FATALERROR_UNKNOWNEXTSTAGE");
                }
            }
            catch (Exception e)
            {
                DispositionReport.Throw(e);
            }
        }