Source code: org/activemq/message/ActiveMQTextMessage.java
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 package org.activemq.message;
19
20 import javax.jms.JMSException;
21 import javax.jms.MessageNotWriteableException;
22 import javax.jms.TextMessage;
23 import java.io.DataInput;
24 import java.io.DataOutput;
25 import java.io.IOException;
26 import java.io.UTFDataFormatException;
27
28 /**
29 * A <CODE>TextMessage</CODE> object is used to send a message containing a
30 * <CODE>java.lang.String</CODE>.
31 * It inherits from the <CODE>Message</CODE> interface and adds a text message
32 * body.
33 * <p/>
34 * <P>This message type can be used to transport text-based messages, including
35 * those with XML content.
36 * <p/>
37 * <P>When a client receives a <CODE>TextMessage</CODE>, it is in read-only
38 * mode. If a client attempts to write to the message at this point, a
39 * <CODE>MessageNotWriteableException</CODE> is thrown. If
40 * <CODE>clearBody</CODE> is
41 * called, the message can now be both read from and written to.
42 *
43 * @see javax.jms.Session#createTextMessage()
44 * @see javax.jms.Session#createTextMessage(String)
45 * @see javax.jms.BytesMessage
46 * @see javax.jms.MapMessage
47 * @see javax.jms.Message
48 * @see javax.jms.ObjectMessage
49 * @see javax.jms.StreamMessage
50 * @see java.lang.String
51 */
52
53 public class ActiveMQTextMessage extends ActiveMQMessage implements TextMessage {
54 private String text;
55
56
57 public String toString() {
58 String payload = null;
59 try {
60 if(!isMessagePart()){
61 payload = getText();
62 }else{
63 payload = "fragmented message";
64 }
65 }
66 catch (JMSException e) {
67 payload = "could not read payload: " + e.toString();
68 }
69 return super.toString() + ", text = " + payload;
70 }
71
72 /**
73 * Return the type of Packet
74 *
75 * @return integer representation of the type of Packet
76 */
77
78 public int getPacketType() {
79 return ACTIVEMQ_TEXT_MESSAGE;
80 }
81
82 /**
83 * @return Returns a shallow copy of the message instance
84 * @throws JMSException
85 */
86
87 public ActiveMQMessage shallowCopy() throws JMSException {
88 ActiveMQTextMessage other = new ActiveMQTextMessage();
89 this.initializeOther(other);
90 other.text = this.text;
91 return other;
92 }
93
94 /**
95 * @return Returns a deep copy of the message - note the header fields are only shallow copied
96 * @throws JMSException
97 */
98
99 public ActiveMQMessage deepCopy() throws JMSException {
100 return shallowCopy();
101 }
102
103 /**
104 * Clears out the message body. Clearing a message's body does not clear
105 * its header values or property entries.
106 * <p/>
107 * <P>If this message body was read-only, calling this method leaves
108 * the message body in the same state as an empty body in a newly
109 * created message.
110 *
111 * @throws JMSException if the JMS provider fails to clear the message
112 * body due to some internal error.
113 */
114
115 public void clearBody() throws JMSException {
116 super.clearBody();
117 this.text = null;
118 }
119
120 /**
121 * Sets the string containing this message's data.
122 *
123 * @param string the <CODE>String</CODE> containing the message's data
124 * @throws JMSException if the JMS provider fails to set the text due to
125 * some internal error.
126 * @throws MessageNotWriteableException if the message is in read-only
127 * mode.
128 */
129
130 public void setText(String string) throws JMSException {
131 if (super.readOnlyMessage) {
132 throw new MessageNotWriteableException("The message is read only");
133 }
134 // lets flush the byte memory if available
135 clearBody();
136 this.text = string;
137 }
138
139
140 /**
141 * Gets the string containing this message's data. The default
142 * value is null.
143 *
144 * @return the <CODE>String</CODE> containing the message's data
145 * @throws JMSException
146 */
147
148 public String getText() throws JMSException {
149 if (this.text == null) {
150 try {
151 super.buildBodyFromBytes();
152 }
153 catch (IOException ioe) {
154 JMSException jmsEx = new JMSException("failed to build body from bytes");
155 jmsEx.setLinkedException(ioe);
156 throw jmsEx;
157 }
158 }
159 return this.text;
160 }
161
162 /**
163 * Used serialize the message body to an output stream
164 *
165 * @param dataOut
166 * @throws IOException
167 */
168
169 public void writeBody(DataOutput dataOut) throws IOException {
170 if (text != null) {
171 int strlen = text.length();
172 int utflen = 0;
173 char[] charr = new char[strlen];
174 int c, count = 0;
175
176 text.getChars(0, strlen, charr, 0);
177
178 for (int i = 0; i < strlen; i++) {
179 c = charr[i];
180 if ((c >= 0x0001) && (c <= 0x007F)) {
181 utflen++;
182 }
183 else if (c > 0x07FF) {
184 utflen += 3;
185 }
186 else {
187 utflen += 2;
188 }
189 }
190
191 byte[] bytearr = new byte[utflen + 4];
192 bytearr[count++] = (byte) ((utflen >>> 24) & 0xFF);
193 bytearr[count++] = (byte) ((utflen >>> 16) & 0xFF);
194 bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
195 bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
196 for (int i = 0; i < strlen; i++) {
197 c = charr[i];
198 if ((c >= 0x0001) && (c <= 0x007F)) {
199 bytearr[count++] = (byte) c;
200 }
201 else if (c > 0x07FF) {
202 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
203 bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
204 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
205 }
206 else {
207 bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
208 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
209 }
210 }
211 dataOut.write(bytearr);
212
213 }
214 else {
215 dataOut.writeInt(-1);
216 }
217 }
218
219 /**
220 * Used to help build the body from an input stream
221 *
222 * @param dataIn
223 * @throws IOException
224 */
225
226 public void readBody(DataInput dataIn) throws IOException {
227 int utflen = dataIn.readInt();
228 if (utflen > -1) {
229 StringBuffer str = new StringBuffer(utflen);
230 byte bytearr[] = new byte[utflen];
231 int c, char2, char3;
232 int count = 0;
233
234 dataIn.readFully(bytearr, 0, utflen);
235
236 while (count < utflen) {
237 c = bytearr[count] & 0xff;
238 switch (c >> 4) {
239 case 0:
240 case 1:
241 case 2:
242 case 3:
243 case 4:
244 case 5:
245 case 6:
246 case 7:
247 /* 0xxxxxxx */
248 count++;
249 str.append((char) c);
250 break;
251 case 12:
252 case 13:
253 /* 110x xxxx 10xx xxxx */
254 count += 2;
255 if (count > utflen) {
256 throw new UTFDataFormatException();
257 }
258 char2 = bytearr[count - 1];
259 if ((char2 & 0xC0) != 0x80) {
260 throw new UTFDataFormatException();
261 }
262 str.append((char) (((c & 0x1F) << 6) | (char2 & 0x3F)));
263 break;
264 case 14:
265 /* 1110 xxxx 10xx xxxx 10xx xxxx */
266 count += 3;
267 if (count > utflen) {
268 throw new UTFDataFormatException();
269 }
270 char2 = bytearr[count - 2];
271 char3 = bytearr[count - 1];
272 if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
273 throw new UTFDataFormatException();
274 }
275 str.append((char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)));
276 break;
277 default :
278 /* 10xx xxxx, 1111 xxxx */
279 throw new UTFDataFormatException();
280 }
281 }
282 // The number of chars produced may be less than utflen
283 this.text = new String(str);
284 }
285 }
286
287 /**
288 * dumps the text body as UTF-8
289 * @param dataOut
290 * @throws IOException
291 */
292 public void writeText(DataOutput dataOut) throws IOException {
293 String theText = text != null ? text : "";
294 dataOut.writeUTF(theText);
295 }
296
297 /**
298 * read the text as UTF-8
299 * @param dataIn
300 * @throws IOException
301 */
302 public void readText(DataInput dataIn) throws IOException{
303 this.text = dataIn.readUTF();
304 }
305 }