001 package com.mockrunner.mock.jms; 002 003 import java.util.Arrays; 004 import java.util.Enumeration; 005 import java.util.HashMap; 006 import java.util.Iterator; 007 import java.util.Map; 008 import java.util.Vector; 009 010 import javax.jms.JMSException; 011 import javax.jms.MapMessage; 012 import javax.jms.MessageFormatException; 013 import javax.jms.MessageNotWriteableException; 014 015 import com.mockrunner.util.common.ArrayUtil; 016 017 /** 018 * Mock implementation of JMS <code>MapMessage</code>. 019 */ 020 public class MockMapMessage extends MockMessage implements MapMessage 021 { 022 private Map data; 023 024 public MockMapMessage() 025 { 026 data = new HashMap(); 027 } 028 029 public boolean getBoolean(String name) throws JMSException 030 { 031 Object value = getObject(name); 032 if(null == value) 033 { 034 return Boolean.valueOf(null).booleanValue(); 035 } 036 if(value instanceof Boolean) 037 { 038 return ((Boolean)value).booleanValue(); 039 } 040 if(value instanceof String) 041 { 042 return Boolean.valueOf((String)value).booleanValue(); 043 } 044 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to boolean"); 045 } 046 047 public byte getByte(String name) throws JMSException 048 { 049 Object value = getObject(name); 050 if(null == value) 051 { 052 return Byte.valueOf(null).byteValue(); 053 } 054 if(value instanceof Byte) 055 { 056 return ((Byte)value).byteValue(); 057 } 058 if(value instanceof String) 059 { 060 return Byte.valueOf((String)value).byteValue(); 061 } 062 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to byte"); 063 } 064 065 public short getShort(String name) throws JMSException 066 { 067 Object value = getObject(name); 068 if(null == value) 069 { 070 return Short.valueOf(null).shortValue(); 071 } 072 if((value instanceof Byte) || (value instanceof Short)) 073 { 074 return ((Number)value).shortValue(); 075 } 076 if(value instanceof String) 077 { 078 return Short.valueOf((String)value).shortValue(); 079 } 080 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to short"); 081 } 082 083 public char getChar(String name) throws JMSException 084 { 085 Object value = getObject(name); 086 if(null == value) 087 { 088 throw new NullPointerException(); 089 } 090 if(!(value instanceof Character)) 091 { 092 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to char"); 093 } 094 return ((Character)value).charValue(); 095 } 096 097 public int getInt(String name) throws JMSException 098 { 099 Object value = getObject(name); 100 if(null == value) 101 { 102 return Integer.valueOf(null).intValue(); 103 } 104 if((value instanceof Byte) || (value instanceof Short) || (value instanceof Integer)) 105 { 106 return ((Number)value).intValue(); 107 } 108 if(value instanceof String) 109 { 110 return Integer.valueOf((String)value).intValue(); 111 } 112 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to int"); 113 } 114 115 public long getLong(String name) throws JMSException 116 { 117 Object value = getObject(name); 118 if(null == value) 119 { 120 return Long.valueOf(null).longValue(); 121 } 122 if((value instanceof Byte) || (value instanceof Short) || (value instanceof Integer) || (value instanceof Long)) 123 { 124 return ((Number)value).longValue(); 125 } 126 if(value instanceof String) 127 { 128 return Long.valueOf((String)value).longValue(); 129 } 130 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to long"); 131 } 132 133 public float getFloat(String name) throws JMSException 134 { 135 Object value = getObject(name); 136 if(null == value) 137 { 138 return Float.valueOf(null).floatValue(); 139 } 140 if(value instanceof Float) 141 { 142 return ((Float)value).floatValue(); 143 } 144 if(value instanceof String) 145 { 146 return Float.valueOf((String)value).floatValue(); 147 } 148 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to float"); 149 } 150 151 public double getDouble(String name) throws JMSException 152 { 153 Object value = getObject(name); 154 if(null == value) 155 { 156 return Double.valueOf(null).doubleValue(); 157 } 158 if((value instanceof Double) || (value instanceof Float)) 159 { 160 return ((Number)value).doubleValue(); 161 } 162 if(value instanceof String) 163 { 164 return Double.valueOf((String)value).doubleValue(); 165 } 166 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to double"); 167 } 168 169 public String getString(String name) throws JMSException 170 { 171 Object value = getObject(name); 172 if(null == value) 173 { 174 return null; 175 } 176 if(value instanceof byte[]) 177 { 178 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to String"); 179 } 180 return value.toString(); 181 } 182 183 public byte[] getBytes(String name) throws JMSException 184 { 185 Object value = getObject(name); 186 if(null == value) 187 { 188 throw new NullPointerException(); 189 } 190 if(!(value instanceof byte[])) 191 { 192 throw new MessageFormatException(value.getClass().getName() + " cannot be converted to byte[]"); 193 } 194 return (byte[])value; 195 } 196 197 public Object getObject(String name) throws JMSException 198 { 199 return data.get(name); 200 } 201 202 public Enumeration getMapNames() throws JMSException 203 { 204 return new Vector(data.keySet()).elements(); 205 } 206 207 public void setBoolean(String name, boolean value) throws JMSException 208 { 209 setObject(name, new Boolean(value)); 210 } 211 212 public void setByte(String name, byte value) throws JMSException 213 { 214 setObject(name, new Byte(value)); 215 } 216 217 public void setShort(String name, short value) throws JMSException 218 { 219 setObject(name, new Short(value)); 220 } 221 222 public void setChar(String name, char value) throws JMSException 223 { 224 setObject(name, new Character(value)); 225 } 226 227 public void setInt(String name, int value) throws JMSException 228 { 229 setObject(name, new Integer(value)); 230 } 231 232 public void setLong(String name, long value) throws JMSException 233 { 234 setObject(name, new Long(value)); 235 } 236 237 public void setFloat(String name, float value) throws JMSException 238 { 239 setObject(name, new Float(value)); 240 } 241 242 public void setDouble(String name, double value) throws JMSException 243 { 244 setObject(name, new Double(value)); 245 } 246 247 public void setString(String name, String value) throws JMSException 248 { 249 setObject(name, value); 250 } 251 252 public void setBytes(String name, byte[] byteData) throws JMSException 253 { 254 byte[] copy = (byte[])byteData.clone(); 255 setObject(name, copy); 256 } 257 258 public void setBytes(String name, byte[] byteData, int offset, int length) throws JMSException 259 { 260 if(null == byteData) 261 { 262 setObject(name, null); 263 return; 264 } 265 setBytes(name, (byte[])ArrayUtil.truncateArray(byteData, offset, length)); 266 } 267 268 public void setObject(String name, Object object) throws JMSException 269 { 270 if(!isInWriteMode()) 271 { 272 throw new MessageNotWriteableException("Message is in read mode"); 273 } 274 if(null == name || name.length() <= 0) 275 { 276 throw new IllegalArgumentException("Property names must not be null or empty strings"); 277 } 278 if(null == object) return; 279 if((object instanceof Number) || (object instanceof Boolean) || (object instanceof Character) || (object instanceof String) || (object instanceof byte[])) 280 { 281 data.put(name, object); 282 return; 283 } 284 throw new MessageFormatException(object.getClass().getName() + " not a valid type"); 285 } 286 287 public boolean itemExists(String name) throws JMSException 288 { 289 return data.containsKey(name); 290 } 291 292 public void clearBody() throws JMSException 293 { 294 super.clearBody(); 295 data.clear(); 296 } 297 298 /** 299 * Returns a copy of the underlying data as a <code>Map</code> 300 * regardless if the message is in read or write mode. Primitives 301 * are wrapped into their corresponding type. 302 * @return the <code>Map</code> data 303 */ 304 public Map getMap() 305 { 306 Map map = new HashMap(); 307 copyDataToMap(map); 308 return map; 309 } 310 311 /** 312 * Compares the underlying map data. 313 */ 314 public boolean equals(Object otherObject) 315 { 316 if(null == otherObject) return false; 317 if(!(otherObject instanceof MockMapMessage)) return false; 318 MockMapMessage otherMessage = (MockMapMessage)otherObject; 319 if(data.size() != otherMessage.data.size()) return false; 320 Iterator keys = data.keySet().iterator(); 321 while(keys.hasNext()) 322 { 323 Object nextKey = keys.next(); 324 Object nextValue = data.get(nextKey); 325 Object otherValue = otherMessage.data.get(nextKey); 326 if(null == nextValue) 327 { 328 if(null != otherValue) return false; 329 } 330 else if(nextValue instanceof byte[]) 331 { 332 if(null == otherValue) return false; 333 if(!(otherValue instanceof byte[])) return false; 334 if(!Arrays.equals((byte[])nextValue, (byte[])otherValue)) return false; 335 } 336 else 337 { 338 if(!nextValue.equals(otherValue)) return false; 339 } 340 } 341 return true; 342 } 343 344 public int hashCode() 345 { 346 int value = 17; 347 Iterator values = data.values().iterator(); 348 while(values.hasNext()) 349 { 350 Object nextValue = values.next(); 351 if(nextValue instanceof byte[]) 352 { 353 for(int ii = 0; ii < ((byte[])nextValue).length; ii++) 354 { 355 value = (31 * value) + ((byte[])nextValue)[ii]; 356 } 357 } 358 else if(nextValue != null) 359 { 360 value = (31 * value) + nextValue.hashCode(); 361 } 362 } 363 return value; 364 } 365 366 public Object clone() 367 { 368 MockMapMessage message = (MockMapMessage)super.clone(); 369 message.data = new HashMap(data.size()); 370 copyDataToMap(message.data); 371 return message; 372 } 373 374 private void copyDataToMap(Map target) 375 { 376 Iterator keys = data.keySet().iterator(); 377 while(keys.hasNext()) 378 { 379 Object nextKey = keys.next(); 380 Object nextValue = data.get(nextKey); 381 if(nextValue instanceof byte[]) 382 { 383 target.put(nextKey, ((byte[])nextValue).clone()); 384 } 385 else 386 { 387 target.put(nextKey, nextValue); 388 } 389 } 390 } 391 392 public String toString() 393 { 394 return this.getClass().getName() + ": " + data.toString(); 395 } 396 }