/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace Apache.Qpid.Test.Channel.WcfPerftest { using System; using System.Collections; using System.IO; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.Threading; using System.Text; using System.Xml; using Apache.Qpid.Channel; /// /// A sample interface for populating and extracting message body content. /// Just enough methods to handle basic Interop text and raw byte messages. /// public interface IRawBodyUtility { Message CreateMessage(byte[] body, int offset, int len); Message CreateMessage(byte[] body); byte[] GetBytes(Message m, byte[] recyclableBuffer); Message CreateMessage(string body); string GetText(Message m); } // an implementation of IRawBodyUtility that expects a RawMessageEncoder based channel public class RawEncoderUtility : IRawBodyUtility { public Message CreateMessage(byte[] body, int offset, int count) { return Message.CreateMessage(MessageVersion.None, "", new RawEncoderBodyWriter(body, offset, count)); } public Message CreateMessage(byte[] body) { return CreateMessage(body, 0, body.Length); } public byte[] GetBytes(Message message, byte[] recyclableBuffer) { XmlDictionaryReader reader = message.GetReaderAtBodyContents(); int length; while (!reader.HasValue) { reader.Read(); if (reader.EOF) { throw new InvalidDataException("empty XmlDictionaryReader"); } } if (reader.TryGetBase64ContentLength(out length)) { byte[] bytes = null; if (recyclableBuffer != null) { if (recyclableBuffer.Length == length) { // reuse bytes = recyclableBuffer; } } if (bytes == null) { bytes = new byte[length]; } // this is the single copy mechanism from native to managed space with no intervening // buffers. One could also write a method GetBytes(msg, myBuf, offset)... reader.ReadContentAsBase64(bytes, 0, length); reader.Close(); return bytes; } else { // uses whatever default buffering mechanism is used by the base XmlDictionaryReader class return reader.ReadContentAsBase64(); } } public Message CreateMessage(string body) { return Message.CreateMessage(MessageVersion.None, "", new RawEncoderBodyWriter(body)); } public string GetText(Message message) { byte[] rawBuffer = GetBytes(message, null); return Encoding.UTF8.GetString(rawBuffer, 0, rawBuffer.Length); } internal class RawEncoderBodyWriter : BodyWriter { // works only with the Raw Encoder; the "body" is either a single string or byte[] segment String bodyAsString; byte[] bodyAsBytes; int offset; int count; public RawEncoderBodyWriter(string body) : base(false) // isBuffered { this.bodyAsString = body; } public RawEncoderBodyWriter(byte[] body, int offset, int count) : base(false) // isBuffered { this.bodyAsBytes = body; this.offset = offset; this.count = count; } protected override void OnWriteBodyContents(System.Xml.XmlDictionaryWriter writer) { // TODO: RawMessageEncoder.StreamElementName should be public. writer.WriteStartElement("Binary"); // the expected Raw encoder "" virtual xml tag if (bodyAsString != null) { byte[] buf = Encoding.UTF8.GetBytes(bodyAsString); writer.WriteBase64(buf, 0, buf.Length); } else { writer.WriteBase64(this.bodyAsBytes, this.offset, this.count); } writer.WriteEndElement(); } } } }