/*
* 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();
}
}
}
}