SPRNET-936 - Add message converter to/from XML (NMS)

This commit is contained in:
markpollack
2008-10-14 03:02:58 +00:00
parent 06edbc653d
commit 2116d744ae
4 changed files with 325 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
#region License
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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.
*/
#endregion
using System;
namespace Spring.Messaging.Nms.Support.Converter
{
/// <summary>
/// Provides a layer of indirection when adding the 'type' of the object as a message property.
/// </summary>
/// <author>Mark Pollack</author>
public interface ITypeMapper
{
string TypeIdFieldName
{
get;
}
string FromType(Type typeOfObjectToConvert);
Type ToType(string typeId);
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections;
using Spring.Core.TypeResolution;
namespace Spring.Messaging.Nms.Support.Converter
{
public class TypeMapper : ITypeMapper
{
private string defaultNamespace;
private string defaultAssemblyName;
//Generics not used to support both 1.1 and 2.0
private IDictionary idTypeMapping;
private IDictionary typeIdMapping;
//TODO generalize?
private string defaultHashtableTypeId = "Hashtable";
private Type defaultHashtableClass = typeof(Hashtable);
public TypeMapper()
{
idTypeMapping = new Hashtable();
typeIdMapping = new Hashtable();
}
public IDictionary IdTypeMapping
{
get { return idTypeMapping; }
set { idTypeMapping = value; }
}
public string TypeIdFieldName
{
get { return "__TypeId__"; }
}
public Type DefaultHashtableClass
{
set { defaultHashtableClass = value; }
}
public string FromType(Type typeOfObjectToConvert)
{
if (typeIdMapping.Contains(typeOfObjectToConvert))
{
return typeIdMapping[typeOfObjectToConvert] as string;
}
else
{
if ( typeof (IDictionary).IsAssignableFrom(typeOfObjectToConvert))
{
return defaultHashtableTypeId;
}
return typeOfObjectToConvert.Name;
}
}
public Type ToType(string typeId)
{
if (idTypeMapping.Contains(typeId))
{
return idTypeMapping[typeId] as Type;
}
else
{
if (typeId.Equals(defaultHashtableTypeId))
{
return defaultHashtableClass;
}
string fullyQualifiedTypeName = defaultNamespace + "." +
typeId + ", " +
DefaultAssemblyName;
return TypeResolutionUtils.ResolveType(fullyQualifiedTypeName);
}
}
public string DefaultNamespace
{
get
{
return defaultNamespace;
}
set
{
defaultNamespace = value;
}
}
public string DefaultAssemblyName
{
get
{
return defaultAssemblyName;
}
set
{
defaultAssemblyName = value;
}
}
public void AfterPropertiesSet()
{
ValidateIdTypeMapping();
if (DefaultAssemblyName != null && DefaultNamespace == null)
{
throw new ArgumentException("Default Namespace required when DefaultAssemblyName is set.");
}
if (DefaultNamespace != null && DefaultAssemblyName == null)
{
throw new ArgumentException("Default Assembly Name required when DefaultNamespace is set.");
}
}
private void ValidateIdTypeMapping()
{
IDictionary finalIdTypeMapping = new Hashtable();
foreach (DictionaryEntry entry in idTypeMapping)
{
string id = entry.Key.ToString();
Type t = entry.Value as Type;
if (t == null)
{
//convert from string value.
string typeName = entry.Value.ToString();
t = TypeResolutionUtils.ResolveType(typeName);
}
finalIdTypeMapping.Add(id,t);
typeIdMapping.Add(t,id);
}
idTypeMapping = finalIdTypeMapping;
}
}
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Apache.NMS;
using Spring.Messaging.Nms.Support.Converter;
namespace Spring.Messaging.Nms.Support.Converter
{
public class XmlMessageConverter : IMessageConverter
{
private IMessageConverter defaultMessageConverter = new SimpleMessageConverter();
private ITypeMapper typeMapper;
public ITypeMapper TypeMapper
{
set { typeMapper = value; }
}
public IMessage ToMessage(object objectToConvert, ISession session)
{
if (objectToConvert == null)
{
throw new MessageConversionException("Can't convert null object");
}
try
{
if (objectToConvert.GetType().Equals(typeof (string)) ||
typeof (IDictionary).IsAssignableFrom(objectToConvert.GetType()) ||
objectToConvert.GetType().Equals(typeof (Byte[])))
{
return defaultMessageConverter.ToMessage(objectToConvert, session);
}
else
{
string xmlString = GetXmlString(objectToConvert);
IMessage msg = session.CreateTextMessage(xmlString);
msg.Properties.SetString(typeMapper.TypeIdFieldName, typeMapper.FromType(objectToConvert.GetType()));
return msg;
}
} catch (Exception e)
{
throw new MessageConversionException("Can't convert object of type " + objectToConvert.GetType(), e);
}
}
private string GetXmlString(object objectToConvert)
{
string xmlString;
XmlTextWriter xmlTextWriter = null;
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream();
xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
XmlSerializer xs = new XmlSerializer(objectToConvert.GetType());
xs.Serialize(xmlTextWriter, objectToConvert);
xmlString = UTF8ByteArrayToString(((MemoryStream) xmlTextWriter.BaseStream).ToArray());
} catch (Exception e)
{
throw new MessageConversionException("Can't convert object of type " + objectToConvert.GetType(), e);
} finally
{
if (memoryStream != null) memoryStream.Close();
if (xmlTextWriter != null) xmlTextWriter.Close();
}
return xmlString;
}
public object FromMessage(IMessage messageToConvert)
{
if (messageToConvert == null)
{
throw new MessageConversionException("Can't convert null message");
}
try
{
string converterId = messageToConvert.Properties.GetString(typeMapper.TypeIdFieldName);
if (converterId == null)
{
return defaultMessageConverter.FromMessage(messageToConvert);
}
else
{
ITextMessage textMessage = messageToConvert as ITextMessage;
if (textMessage == null)
{
throw new MessageConversionException("Can't convert message of type " +
messageToConvert.GetType());
}
using (MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(textMessage.Text)))
{
XmlSerializer xs = new XmlSerializer(GetTargetType(textMessage));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
return xs.Deserialize(memoryStream);
}
}
} catch (Exception e)
{
throw new MessageConversionException("Can't convert message of type " + messageToConvert.GetType(), e);
}
}
private Type GetTargetType(ITextMessage message)
{
return typeMapper.ToType(message.Properties.GetString(typeMapper.TypeIdFieldName));
}
private String UTF8ByteArrayToString(Byte[] characters)
{
UTF8Encoding encoding = new UTF8Encoding();
String constructedString = encoding.GetString(characters);
return (constructedString);
}
private Byte[] StringToUTF8ByteArray(String pXmlString)
{
UTF8Encoding encoding = new UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(pXmlString);
return byteArray;
}
}
}

View File

@@ -84,8 +84,11 @@
<Compile Include="Messaging\Nms\Listener\RecoveryTimeExceededException.cs" />
<Compile Include="Messaging\Nms\Listener\SimpleMessageListenerContainer.cs" />
<Compile Include="Messaging\Nms\Support\Converter\IMessageConverter.cs" />
<Compile Include="Messaging\Nms\Support\Converter\ITypeMapper.cs" />
<Compile Include="Messaging\Nms\Support\Converter\MessageConversionException.cs" />
<Compile Include="Messaging\Nms\Support\Converter\SimpleMessageConverter.cs" />
<Compile Include="Messaging\Nms\Support\Converter\TypeMapper.cs" />
<Compile Include="Messaging\Nms\Support\Converter\XmlMessageConverter.cs" />
<Compile Include="Messaging\Nms\Support\Destinations\DynamicDestinationResolver.cs" />
<Compile Include="Messaging\Nms\Support\Destinations\IDestinationResolver.cs" />
<Compile Include="Messaging\Nms\Support\Destinations\NmsDestinationAccessor.cs" />