1 /*** 2 * 3 * Copyright 2004 Protique Ltd 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 **/ 18 19 package org.codehaus.activemq.message; 20 21 22 import javax.jms.JMSException; 23 import javax.jms.MessageNotWriteableException; 24 import javax.jms.ObjectMessage; 25 import java.io.DataInput; 26 import java.io.DataOutput; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.ObjectInputStream; 30 import java.io.ObjectOutputStream; 31 import java.io.OutputStream; 32 import java.io.Serializable; 33 34 /*** 35 * An <CODE>ObjectMessage</CODE> object is used to send a message that contains 36 * a serializable object in the Java programming language ("Java object"). 37 * It inherits from the <CODE>Message</CODE> interface and adds a body 38 * containing a single reference to an object. Only <CODE>Serializable</CODE> 39 * Java objects can be used. 40 * <p/> 41 * <P>If a collection of Java objects must be sent, one of the 42 * <CODE>Collection</CODE> classes provided since JDK 1.2 can be used. 43 * <p/> 44 * <P>When a client receives an <CODE>ObjectMessage</CODE>, it is in read-only 45 * mode. If a client attempts to write to the message at this point, a 46 * <CODE>MessageNotWriteableException</CODE> is thrown. If 47 * <CODE>clearBody</CODE> is called, the message can now be both read from and 48 * written to. 49 * 50 * @see javax.jms.Session#createObjectMessage() 51 * @see javax.jms.Session#createObjectMessage(Serializable) 52 * @see javax.jms.BytesMessage 53 * @see javax.jms.MapMessage 54 * @see javax.jms.Message 55 * @see javax.jms.StreamMessage 56 * @see javax.jms.TextMessage 57 */ 58 59 public class ActiveMQObjectMessage extends ActiveMQMessage implements ObjectMessage { 60 61 private Serializable object; 62 63 64 /*** 65 * Return the type of Packet 66 * 67 * @return integer representation of the type of Packet 68 */ 69 70 public int getPacketType() { 71 return ACTIVEMQ_OBJECT_MESSAGE; 72 } 73 74 /*** 75 * @return Returns a shallow copy of the message instance 76 * @throws JMSException 77 */ 78 79 public ActiveMQMessage shallowCopy() throws JMSException { 80 ActiveMQObjectMessage other = new ActiveMQObjectMessage(); 81 this.initializeOther(other); 82 other.object = this.object; 83 return other; 84 } 85 86 /*** 87 * @return Returns a deep copy of the message - note the header fields are only shallow copied 88 * @throws JMSException 89 */ 90 91 public ActiveMQMessage deepCopy() throws JMSException { 92 return shallowCopy(); 93 } 94 95 /*** 96 * Clears out the message body. Clearing a message's body does not clear 97 * its header values or property entries. 98 * <p/> 99 * <P>If this message body was read-only, calling this method leaves 100 * the message body in the same state as an empty body in a newly 101 * created message. 102 * 103 * @throws JMSException if the JMS provider fails to clear the message 104 * body due to some internal error. 105 */ 106 107 public void clearBody() throws JMSException { 108 super.clearBody(); 109 this.object = null; 110 } 111 112 113 /*** 114 * Sets the serializable object containing this message's data. 115 * It is important to note that an <CODE>ObjectMessage</CODE> 116 * contains a snapshot of the object at the time <CODE>setObject()</CODE> 117 * is called; subsequent modifications of the object will have no 118 * effect on the <CODE>ObjectMessage</CODE> body. 119 * 120 * @param newObject the message's data 121 * @throws JMSException if the JMS provider fails to set the object 122 * due to some internal error. 123 * @throws javax.jms.MessageFormatException 124 * if object serialization fails. 125 * @throws javax.jms.MessageNotWriteableException 126 * if the message is in read-only 127 * mode. 128 */ 129 130 public void setObject(Serializable newObject) throws JMSException { 131 if (super.readOnlyMessage) { 132 throw new MessageNotWriteableException("The message is read-only"); 133 } 134 this.object = newObject; 135 } 136 137 void setObjectPayload(Object newObject) { 138 this.object = (Serializable) newObject; 139 } 140 141 142 /*** 143 * Gets the serializable object containing this message's data. The 144 * default value is null. 145 * 146 * @return the serializable object containing this message's data 147 * @throws JMSException 148 */ 149 150 public Serializable getObject() throws JMSException { 151 if (this.object == null) { 152 try { 153 super.buildBodyFromBytes(); 154 } 155 catch (IOException ioe) { 156 JMSException jmsEx = new JMSException("failed to build body from bytes"); 157 jmsEx.setLinkedException(ioe); 158 throw jmsEx; 159 } 160 } 161 return this.object; 162 } 163 164 /*** 165 * Prepare a message body for delivery 166 * @throws JMSException 167 */ 168 public void prepareMessageBody() throws JMSException{ 169 try { 170 convertBodyToBytes(); 171 this.object = null; 172 } 173 catch (IOException ioe) { 174 JMSException jmsEx = new JMSException("failed to convert body to bytes"); 175 jmsEx.setLinkedException(ioe); 176 throw jmsEx; 177 } 178 } 179 180 /*** 181 * Used serialize the message body to an output stream 182 * 183 * @param dataOut 184 * @throws IOException 185 */ 186 187 protected void writeBody(DataOutput dataOut) throws IOException { 188 ObjectOutputStream objOut = new ObjectOutputStream((OutputStream) dataOut); 189 objOut.writeObject(this.object); 190 objOut.flush(); 191 } 192 193 /*** 194 * Used to help build the body from an input stream 195 * 196 * @param dataIn 197 * @throws IOException 198 */ 199 200 protected void readBody(DataInput dataIn) throws IOException { 201 ObjectInputStream objIn = new ObjectInputStream((InputStream) dataIn); 202 try { 203 this.object = (Serializable) objIn.readObject(); 204 objIn.close(); 205 } 206 catch (ClassNotFoundException ex) { 207 throw new IOException(ex.getMessage()); 208 } 209 } 210 }