001 package com.mockrunner.mock.jms;
002
003 import java.util.Arrays;
004 import java.util.Collections;
005 import java.util.Stack;
006 import java.util.Vector;
007
008 import javax.jms.JMSException;
009 import javax.jms.MessageEOFException;
010 import javax.jms.MessageFormatException;
011 import javax.jms.MessageNotReadableException;
012 import javax.jms.MessageNotWriteableException;
013 import javax.jms.StreamMessage;
014
015 import com.mockrunner.util.common.ArrayUtil;
016
017 /**
018 * Mock implementation of JMS <code>StreamMessage</code>.
019 */
020 public class MockStreamMessage extends MockMessage implements StreamMessage
021 {
022 private Stack data;
023
024 public MockStreamMessage()
025 {
026 data = new Stack();
027 }
028
029 public boolean readBoolean() throws JMSException
030 {
031 if(isInWriteMode())
032 {
033 throw new MessageNotReadableException("Message is in write mode");
034 }
035 if(data.empty())
036 {
037 throw new MessageEOFException("No more data");
038 }
039 Object value = readObject();
040 if(null == value) return Boolean.valueOf(null).booleanValue();
041 if(value instanceof Boolean)
042 {
043 return ((Boolean)value).booleanValue();
044 }
045 if(value instanceof String)
046 {
047 return Boolean.valueOf((String)value).booleanValue();
048 }
049 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to boolean");
050 }
051
052 public byte readByte() throws JMSException
053 {
054 if(isInWriteMode())
055 {
056 throw new MessageNotReadableException("Message is in write mode");
057 }
058 if(data.empty())
059 {
060 throw new MessageEOFException("No more data");
061 }
062 Object value = readObject();
063 if(null == value) return Byte.valueOf(null).byteValue();
064 if(value instanceof Byte)
065 {
066 return ((Byte)value).byteValue();
067 }
068 if(value instanceof String)
069 {
070 return Byte.valueOf((String)value).byteValue();
071 }
072 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to byte");
073 }
074
075 public short readShort() throws JMSException
076 {
077 if(isInWriteMode())
078 {
079 throw new MessageNotReadableException("Message is in write mode");
080 }
081 if(data.empty())
082 {
083 throw new MessageEOFException("No more data");
084 }
085 Object value = readObject();
086 if(null == value) return Short.valueOf(null).shortValue();
087 if((value instanceof Byte) || (value instanceof Short))
088 {
089 return ((Number)value).shortValue();
090 }
091 if(value instanceof String)
092 {
093 return Short.valueOf((String)value).shortValue();
094 }
095 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to short");
096 }
097
098 public char readChar() throws JMSException
099 {
100 if(isInWriteMode())
101 {
102 throw new MessageNotReadableException("Message is in write mode");
103 }
104 if(data.empty())
105 {
106 throw new MessageEOFException("No more data");
107 }
108 Object value = readObject();
109 if(null == value)
110 {
111 throw new NullPointerException();
112 }
113 if(value instanceof Character)
114 {
115 return ((Character)value).charValue();
116 }
117 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to char");
118 }
119
120 public int readInt() throws JMSException
121 {
122 if(isInWriteMode())
123 {
124 throw new MessageNotReadableException("Message is in write mode");
125 }
126 if(data.empty())
127 {
128 throw new MessageEOFException("No more data");
129 }
130 Object value = readObject();
131 if(null == value) return Integer.valueOf(null).intValue();
132 if((value instanceof Byte) || (value instanceof Short) || (value instanceof Integer))
133 {
134 return ((Number)value).intValue();
135 }
136 if(value instanceof String)
137 {
138 return Integer.valueOf((String)value).intValue();
139 }
140 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to int");
141 }
142
143 public long readLong() throws JMSException
144 {
145 if(isInWriteMode())
146 {
147 throw new MessageNotReadableException("Message is in write mode");
148 }
149 if(data.empty())
150 {
151 throw new MessageEOFException("No more data");
152 }
153 Object value = readObject();
154 if(null == value) return Long.valueOf(null).longValue();
155 if((value instanceof Byte) || (value instanceof Short) || (value instanceof Integer) || (value instanceof Long))
156 {
157 return ((Number)value).longValue();
158 }
159 if(value instanceof String)
160 {
161 return Long.valueOf((String)value).longValue();
162 }
163 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to long");
164 }
165
166 public float readFloat() throws JMSException
167 {
168 if(isInWriteMode())
169 {
170 throw new MessageNotReadableException("Message is in write mode");
171 }
172 if(data.empty())
173 {
174 throw new MessageEOFException("No more data");
175 }
176 Object value = readObject();
177 if(null == value) return Float.valueOf(null).floatValue();
178 if(value instanceof Float)
179 {
180 return ((Float)value).floatValue();
181 }
182 if(value instanceof String)
183 {
184 return Float.valueOf((String)value).floatValue();
185 }
186 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to float");
187 }
188
189 public double readDouble() throws JMSException
190 {
191 if(isInWriteMode())
192 {
193 throw new MessageNotReadableException("Message is in write mode");
194 }
195 if(data.empty())
196 {
197 throw new MessageEOFException("No more data");
198 }
199 Object value = readObject();
200 if(null == value) return Double.valueOf(null).doubleValue();
201 if((value instanceof Float) || (value instanceof Double))
202 {
203 return ((Number)value).doubleValue();
204 }
205 if(value instanceof String)
206 {
207 return Double.valueOf((String)value).doubleValue();
208 }
209 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to double");
210 }
211
212 public String readString() throws JMSException
213 {
214 if(isInWriteMode())
215 {
216 throw new MessageNotReadableException("Message is in write mode");
217 }
218 if(data.empty())
219 {
220 throw new MessageEOFException("No more data");
221 }
222 Object value = readObject();
223 if(null == value) return null;
224 if(value instanceof byte[])
225 {
226 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to String");
227 }
228 return value.toString();
229 }
230
231 public int readBytes(byte[] byteData) throws JMSException
232 {
233 if(isInWriteMode())
234 {
235 throw new MessageNotReadableException("Message is in write mode");
236 }
237 if(data.empty())
238 {
239 throw new MessageEOFException("No more data");
240 }
241 if(null == byteData) return -1;
242 if(0 == byteData.length) return 0;
243 Object value = readObject();
244 if(null == value)
245 {
246 throw new NullPointerException();
247 }
248 if(!(value instanceof byte[]))
249 {
250 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to byte[]");
251 }
252 int length = Math.min(byteData.length, ((byte[])value).length);
253 System.arraycopy(value, 0, byteData, 0, length);
254 return length;
255 }
256
257 public Object readObject() throws JMSException
258 {
259 if(isInWriteMode())
260 {
261 throw new MessageNotReadableException("Message is in write mode");
262 }
263 if(data.empty())
264 {
265 throw new MessageEOFException("No more data");
266 }
267 return data.pop();
268 }
269
270 public void writeBoolean(boolean value) throws JMSException
271 {
272 if(!isInWriteMode())
273 {
274 throw new MessageNotWriteableException("Message is in read mode");
275 }
276 writeObject(new Boolean(value));
277 }
278
279 public void writeByte(byte value) throws JMSException
280 {
281 if(!isInWriteMode())
282 {
283 throw new MessageNotWriteableException("Message is in read mode");
284 }
285 writeObject(new Byte(value));
286 }
287
288 public void writeShort(short value) throws JMSException
289 {
290 if(!isInWriteMode())
291 {
292 throw new MessageNotWriteableException("Message is in read mode");
293 }
294 writeObject(new Short(value));
295 }
296
297 public void writeChar(char value) throws JMSException
298 {
299 if(!isInWriteMode())
300 {
301 throw new MessageNotWriteableException("Message is in read mode");
302 }
303 writeObject(new Character(value));
304 }
305
306 public void writeInt(int value) throws JMSException
307 {
308 if(!isInWriteMode())
309 {
310 throw new MessageNotWriteableException("Message is in read mode");
311 }
312 writeObject(new Integer(value));
313 }
314
315 public void writeLong(long value) throws JMSException
316 {
317 if(!isInWriteMode())
318 {
319 throw new MessageNotWriteableException("Message is in read mode");
320 }
321 writeObject(new Long(value));
322 }
323
324 public void writeFloat(float value) throws JMSException
325 {
326 if(!isInWriteMode())
327 {
328 throw new MessageNotWriteableException("Message is in read mode");
329 }
330 writeObject(new Float(value));
331 }
332
333 public void writeDouble(double value) throws JMSException
334 {
335 if(!isInWriteMode())
336 {
337 throw new MessageNotWriteableException("Message is in read mode");
338 }
339 writeObject(new Double(value));
340 }
341
342 public void writeString(String value) throws JMSException
343 {
344 if(!isInWriteMode())
345 {
346 throw new MessageNotWriteableException("Message is in read mode");
347 }
348 writeObject(value);
349 }
350
351 public void writeBytes(byte[] data) throws JMSException
352 {
353 if(!isInWriteMode())
354 {
355 throw new MessageNotWriteableException("Message is in read mode");
356 }
357 writeObject(data);
358 }
359
360 public void writeBytes(byte[] data, int offset, int length) throws JMSException
361 {
362 if(!isInWriteMode())
363 {
364 throw new MessageNotWriteableException("Message is in read mode");
365 }
366 if(null == data)
367 {
368 writeObject(null);
369 return;
370 }
371 writeObject(ArrayUtil.truncateArray(data, offset, length));
372 }
373
374 public void writeObject(Object object) throws JMSException
375 {
376 if(!isInWriteMode())
377 {
378 throw new MessageNotWriteableException("Message is in read mode");
379 }
380 if(null == object)
381 {
382 data.push(object);
383 return;
384 }
385 if((object instanceof String) || (object instanceof Number) || (object instanceof Character) || (object instanceof Boolean))
386 {
387 data.push(object);
388 return;
389 }
390 if(object instanceof byte[])
391 {
392 byte[] arrayData = (byte[])((byte[])object).clone();
393 data.push(arrayData);
394 return;
395 }
396 throw new MessageFormatException(object.getClass() + " not a valid type");
397 }
398
399 public void reset() throws JMSException
400 {
401 setReadOnly(true);
402 Collections.reverse(data);
403 }
404
405 public void clearBody() throws JMSException
406 {
407 super.clearBody();
408 data = new Stack();
409 }
410
411 /**
412 * Compares the underlying stream data.
413 */
414 public boolean equals(Object otherObject)
415 {
416 if(null == otherObject) return false;
417 if(!(otherObject instanceof MockStreamMessage)) return false;
418 MockStreamMessage otherMessage = (MockStreamMessage)otherObject;
419 if(data.size() != otherMessage.data.size()) return false;
420 Vector otherData = otherMessage.data;
421 if(isInWriteMode() != otherMessage.isInWriteMode())
422 {
423 otherData = new Vector(otherData);
424 Collections.reverse(otherData);
425 }
426 for(int ii = 0; ii < data.size(); ii++)
427 {
428 Object nextValue = data.get(ii);
429 Object otherValue = otherData.get(ii);
430 if(null == nextValue)
431 {
432 if(null != otherValue) return false;
433 }
434 else if(nextValue instanceof byte[])
435 {
436 if(null == otherValue) return false;
437 if(!(otherValue instanceof byte[])) return false;
438 if(!Arrays.equals((byte[])nextValue, (byte[])otherValue)) return false;
439 }
440 else
441 {
442 if(!nextValue.equals(otherValue)) return false;
443 }
444 }
445 return true;
446 }
447
448 public int hashCode()
449 {
450 int value = 17;
451 Vector theData = new Vector(data);
452 if(isInWriteMode())
453 {
454 Collections.reverse(theData);
455 }
456 for(int ii = 0; ii < theData.size(); ii++)
457 {
458 Object nextValue = theData.get(ii);
459 if(nextValue instanceof byte[])
460 {
461 for(int yy = 0; yy < ((byte[])nextValue).length; yy++)
462 {
463 value = (31 * value) + ((byte[])nextValue)[yy];
464 }
465 }
466 else if(nextValue != null)
467 {
468 value = (31 * value) + nextValue.hashCode();
469 }
470 }
471 return value;
472 }
473
474 public Object clone()
475 {
476 MockStreamMessage message = (MockStreamMessage)super.clone();
477 message.data = new Stack();
478 for(int ii = 0; ii < data.size(); ii++)
479 {
480 Object nextValue = data.get(ii);
481 if(nextValue instanceof byte[])
482 {
483 message.data.add(((byte[])nextValue).clone());
484 }
485 else
486 {
487 message.data.add(nextValue);
488 }
489 }
490 return message;
491 }
492
493 public String toString()
494 {
495 return this.getClass().getName() + ": " + data.toString();
496 }
497 }