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 }