001 /** 002 * 003 * Copyright 2004 Protique Ltd 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 **/ 018 019 package org.activemq.message; 020 021 022 import java.io.DataInput; 023 import java.io.DataOutput; 024 import java.io.IOException; 025 import java.io.InputStream; 026 import java.io.OutputStream; 027 import java.io.Serializable; 028 029 import javax.jms.JMSException; 030 import javax.jms.MessageFormatException; 031 import javax.jms.MessageNotWriteableException; 032 import javax.jms.ObjectMessage; 033 034 import org.activemq.util.SerializationHelper; 035 036 /** 037 * An <CODE>ObjectMessage</CODE> object is used to send a message that contains 038 * a serializable object in the Java programming language ("Java object"). 039 * It inherits from the <CODE>Message</CODE> interface and adds a body 040 * containing a single reference to an object. Only <CODE>Serializable</CODE> 041 * Java objects can be used. 042 * <p/> 043 * <P>If a collection of Java objects must be sent, one of the 044 * <CODE>Collection</CODE> classes provided since JDK 1.2 can be used. 045 * <p/> 046 * <P>When a client receives an <CODE>ObjectMessage</CODE>, it is in read-only 047 * mode. If a client attempts to write to the message at this point, a 048 * <CODE>MessageNotWriteableException</CODE> is thrown. If 049 * <CODE>clearBody</CODE> is called, the message can now be both read from and 050 * written to. 051 * 052 * @see javax.jms.Session#createObjectMessage() 053 * @see javax.jms.Session#createObjectMessage(Serializable) 054 * @see javax.jms.BytesMessage 055 * @see javax.jms.MapMessage 056 * @see javax.jms.Message 057 * @see javax.jms.StreamMessage 058 * @see javax.jms.TextMessage 059 */ 060 061 public class ActiveMQObjectMessage extends ActiveMQMessage implements ObjectMessage { 062 063 private Serializable object; 064 065 066 /** 067 * Return the type of Packet 068 * 069 * @return integer representation of the type of Packet 070 */ 071 072 public int getPacketType() { 073 return ACTIVEMQ_OBJECT_MESSAGE; 074 } 075 076 /** 077 * @return Returns a shallow copy of the message instance 078 * @throws JMSException 079 */ 080 081 public ActiveMQMessage shallowCopy() throws JMSException { 082 ActiveMQObjectMessage other = new ActiveMQObjectMessage(); 083 this.initializeOther(other); 084 other.object = this.object; 085 return other; 086 } 087 088 /** 089 * @return Returns a deep copy of the message - note the header fields are only shallow copied 090 * @throws JMSException 091 */ 092 093 public ActiveMQMessage deepCopy() throws JMSException { 094 return shallowCopy(); 095 } 096 097 /** 098 * Clears out the message body. Clearing a message's body does not clear 099 * its header values or property entries. 100 * <p/> 101 * <P>If this message body was read-only, calling this method leaves 102 * the message body in the same state as an empty body in a newly 103 * created message. 104 * 105 * @throws JMSException if the JMS provider fails to clear the message 106 * body due to some internal error. 107 */ 108 109 public void clearBody() throws JMSException { 110 super.clearBody(); 111 this.object = null; 112 } 113 114 115 /** 116 * Sets the serializable object containing this message's data. 117 * It is important to note that an <CODE>ObjectMessage</CODE> 118 * contains a snapshot of the object at the time <CODE>setObject()</CODE> 119 * is called; subsequent modifications of the object will have no 120 * effect on the <CODE>ObjectMessage</CODE> body. 121 * 122 * @param newObject the message's data 123 * @throws JMSException if the JMS provider fails to set the object 124 * due to some internal error. 125 * @throws javax.jms.MessageFormatException 126 * if object serialization fails. 127 * @throws javax.jms.MessageNotWriteableException 128 * if the message is in read-only 129 * mode. 130 */ 131 132 public void setObject(Serializable newObject) throws JMSException { 133 if (super.readOnlyMessage) { 134 throw new MessageNotWriteableException("The message is read-only"); 135 } 136 try { 137 setBodyAsBytes(null); 138 this.object = newObject; 139 getBodyAsBytes(); // This serializes the object. 140 } catch (IOException e) { 141 throw (MessageFormatException)new MessageFormatException("Could not serialize the object: "+e.getMessage()).initCause(e); 142 } 143 } 144 145 public void setObjectPayload(Object newObject) { 146 this.object = (Serializable) newObject; 147 } 148 149 150 /** 151 * Gets the serializable object containing this message's data. The 152 * default value is null. 153 * 154 * @return the serializable object containing this message's data 155 * @throws JMSException 156 */ 157 158 public Serializable getObject() throws JMSException { 159 if (this.object == null) { 160 try { 161 super.buildBodyFromBytes(); 162 } 163 catch (IOException ioe) { 164 throw createFailedToBuildBodyException(ioe); 165 } 166 } 167 return this.object; 168 } 169 170 /** 171 * Prepare a message body for delivery 172 * @throws JMSException 173 */ 174 public void prepareMessageBody() throws JMSException{ 175 try { 176 convertBodyToBytes(); 177 this.object = null; 178 } 179 catch (IOException ioe) { 180 throw createFailedToBuildBodyException(ioe); 181 } 182 } 183 184 /** 185 * Used serialize the message body to an output stream 186 * 187 * @param dataOut 188 * @throws IOException 189 */ 190 191 public void writeBody(DataOutput dataOut) throws IOException { 192 SerializationHelper.writeObject((OutputStream)dataOut,this.object); 193 } 194 195 /** 196 * Used to help build the body from an input stream 197 * 198 * @param dataIn 199 * @throws IOException 200 */ 201 202 public void readBody(DataInput dataIn) throws IOException { 203 try { 204 this.object = (Serializable) SerializationHelper.readObject((InputStream)dataIn); 205 } 206 catch (ClassNotFoundException ex) { 207 throw new IOException(ex.getMessage()); 208 } 209 } 210 211 public String toString() { 212 String objValue = "null"; 213 try { 214 if (!isMessagePart()){ 215 Object obj = getObject(); 216 if (obj != null){ 217 objValue = obj.toString(); 218 } 219 }else { 220 objValue = "message part"; 221 } 222 } 223 catch (JMSException e) { 224 object = e; 225 } 226 return super.toString() + " ActiveMQObjectMessage{ " + 227 "object = " + objValue + 228 " }"; 229 } 230 231 protected JMSException createFailedToBuildBodyException(IOException ioe) { 232 JMSException jmsEx = new JMSException("Failed to build body from bytes. Reason: " + ioe); 233 jmsEx.setLinkedException(ioe); 234 return jmsEx; 235 } 236 }