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 * Used serialize the message body to an output stream
166 *
167 * @param dataOut
168 * @throws IOException
169 */
170
171 protected void writeBody(DataOutput dataOut) throws IOException {
172 ObjectOutputStream objOut = new ObjectOutputStream((OutputStream) dataOut);
173 objOut.writeObject(this.object);
174 objOut.flush();
175 }
176
177 /***
178 * Used to help build the body from an input stream
179 *
180 * @param dataIn
181 * @throws IOException
182 */
183
184 protected void readBody(DataInput dataIn) throws IOException {
185 ObjectInputStream objIn = new ObjectInputStream((InputStream) dataIn);
186 try {
187 this.object = (Serializable) objIn.readObject();
188 objIn.close();
189 }
190 catch (ClassNotFoundException ex) {
191 throw new IOException(ex.getMessage());
192 }
193 }
194 }