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