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 }