/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author mark.little@jboss.com
*/
package org.jboss.internal.soa.esb.message.format.serialized;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.net.URI;
import org.jboss.soa.esb.addressing.Call;
import org.jboss.soa.esb.message.Attachment;
import org.jboss.soa.esb.message.Body;
import org.jboss.soa.esb.message.ByReferenceMessage;
import org.jboss.soa.esb.message.Context;
import org.jboss.soa.esb.message.Fault;
import org.jboss.soa.esb.message.Header;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.Properties;
import org.jboss.soa.esb.message.format.MessageType;
import org.jboss.soa.esb.util.ContextObjectInputStream;
/**
* This is the basic internal core message abstraction. A message consists of
* the following components:
*
* Header: the header information contains information such as the destination
* EPR, the sender EPR, where the reply goes etc, i.e., general message-level
* functional information. Context: additional information to contextualise the
* message; for example, transaction or security data, the identity of the
* ultimate receiver, or HTTP-cookie like information. Body: the actual payload
* of the message. Fault: any fault information associated with the message.
* Attachment: any attachments associated with the message.
*
* Each message, once created, has a corresponding element for these 5
* components. That element may be empty (<b>NOT NULL</b>). The object
* representing the element can then be used to act on the corresponding data
* item in the message.
*
* @author Mark Little
*
*/
public class MessageImpl implements ByReferenceMessage, Externalizable
{
private static final long serialVersionUID = 0x0;
public MessageImpl()
{
_theHeader = new HeaderImpl();
_theContext = new ContextImpl();
_theBody = new BodyImpl();
_theFault = new FaultImpl(_theBody);
_theAttachment = new AttachmentImpl();
_theProperties = new PropertiesImpl();
}
private MessageImpl(final MessageImpl message)
{
// Header and context are not by reference.
_theHeader = new HeaderImpl() ;
final Call origCall = message._theHeader.getCall() ;
final Call call = new Call(origCall.getTo()) ;
call.setAction(origCall.getAction()) ;
call.setFaultTo(origCall.getFaultTo()) ;
call.setFrom(origCall.getFrom()) ;
call.setMessageID(origCall.getMessageID()) ;
call.setRelatesTo(origCall.getRelatesTo()) ;
call.setReplyTo(origCall.getReplyTo()) ;
_theHeader.setCall(call) ;
_theContext = new ContextImpl(message._theContext) ;
_theBody = message._theBody ;
_theFault = message._theFault ;
_theAttachment = message._theAttachment ;
_theProperties = message._theProperties ;
}
/**
* @return get the header component of the message.
*/
public Header getHeader ()
{
return _theHeader;
}
/**
* @return get the context component of the message.
*/
public Context getContext ()
{
return _theContext;
}
/**
* @return get the body component of the message.
*/
public Body getBody ()
{
return _theBody;
}
/**
* @return get any faults associated with the message. These should not
* be application level faults, but comms level.
*/
public Fault getFault ()
{
return _theFault;
}
/**
* @return get any message attachments.
*/
public Attachment getAttachment ()
{
return _theAttachment;
}
/**
* @return the type of this message format.
*/
public URI getType ()
{
return MessageType.JAVA_SERIALIZED;
}
/**
* @return Map<String,Object> - any message properties.
*/
public Properties getProperties ()
{
return _theProperties;
}
/**
* Return a duplicate of this instance.
*
* Just serialize and then deserialize. Not the most efficient but
* a reasonable default.
*/
public Message copy () throws IOException
{
ByteArrayOutputStream bostream = new ByteArrayOutputStream();
ObjectOutputStream output = new ObjectOutputStream(bostream);
output.writeObject(this);
ByteArrayInputStream bistream = new ByteArrayInputStream(bostream.toByteArray());
ObjectInputStream input = new ContextObjectInputStream(bistream);
try
{
return (MessageImpl) input.readObject();
}
catch (final IOException ioe)
{
throw ioe ;
}
catch (Exception ex)
{
final IOException ioe = new IOException("Unexpected exception during copying");
ioe.initCause(ex) ;
throw ioe ;
}
}
public String toString ()
{
return "message: [ JAVA_SERIALIZED ]\n" + _theHeader.toString()
+ "\n" + _theContext.toString() + "\n" + _theBody.toString()
+ "\n" + _theFault.toString() + "\n"
+ _theAttachment.toString() + "\n" + _theProperties.toString();
}
public void writeExternal (ObjectOutput out) throws IOException
{
out.writeObject(_theHeader);
out.writeObject(_theContext);
out.writeObject(_theBody);
out.writeObject(_theFault);
out.writeObject(_theAttachment);
out.writeObject(_theProperties);
}
public void readExternal (ObjectInput in) throws IOException
{
try
{
_theHeader = (HeaderImpl) in.readObject();
_theContext = (ContextImpl) in.readObject();
_theBody = (BodyImpl) in.readObject();
_theFault = (FaultImpl) in.readObject();
_theAttachment = (AttachmentImpl) in.readObject();
_theProperties = (PropertiesImpl) in.readObject();
_theFault.setBody(_theBody);
}
catch (final IOException ioe)
{
throw ioe ;
}
catch (Exception ex)
{
final IOException ioe = new IOException("Unexpected exception during readExternal");
ioe.initCause(ex) ;
throw ioe ;
}
}
/**
* Create the message used for pass by reference semantics.
* @return the referencable message.
*/
public Message reference()
{
return new MessageImpl(this) ;
}
// should be a capability on the base interface, but no changes for 4.2
// ...
void replaceBody (BodyImpl body)
{
if (body == null)
throw new IllegalArgumentException();
_theBody = body;
}
private HeaderImpl _theHeader;
private ContextImpl _theContext;
private BodyImpl _theBody;
private FaultImpl _theFault;
private AttachmentImpl _theAttachment;
private Properties _theProperties;
}