001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 *
020 */
021 package org.apache.qpid.client.message;
022
023 import org.apache.mina.common.ByteBuffer;
024
025 import org.apache.qpid.AMQException;
026 import org.apache.qpid.framing.AMQShortString;
027 import org.apache.qpid.framing.BasicContentHeaderProperties;
028
029 import org.slf4j.Logger;
030 import org.slf4j.LoggerFactory;
031
032 import javax.jms.JMSException;
033 import javax.jms.MessageFormatException;
034
035 import java.nio.charset.CharacterCodingException;
036 import java.util.Collections;
037 import java.util.Enumeration;
038 import java.util.HashMap;
039 import java.util.Map;
040
041 public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jms.MapMessage
042 {
043 private static final Logger _logger = LoggerFactory.getLogger(JMSMapMessage.class);
044
045 public static final String MIME_TYPE = "jms/map-message";
046
047
048 private Map<String, Object> _map = new HashMap<String, Object>();
049
050 public JMSMapMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
051 {
052 this(delegateFactory, null);
053 }
054
055 JMSMapMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data) throws JMSException
056 {
057
058 super(delegateFactory, data); // this instantiates a content header
059 if(data != null)
060 {
061 populateMapFromData();
062 }
063
064 }
065
066 JMSMapMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
067 {
068
069 super(delegate, data);
070 try
071 {
072 populateMapFromData();
073 }
074 catch (JMSException je)
075 {
076 throw new AMQException(null, "Error populating MapMessage from ByteBuffer", je);
077
078 }
079
080 }
081
082
083 public String toBodyString() throws JMSException
084 {
085 return _map == null ? "" : _map.toString();
086 }
087
088 protected String getMimeType()
089 {
090 return MIME_TYPE;
091 }
092
093 public ByteBuffer getData()
094 {
095 // What if _data is null?
096 writeMapToData();
097
098 return super.getData();
099 }
100
101 @Override
102 public void clearBodyImpl() throws JMSException
103 {
104 super.clearBodyImpl();
105 _map.clear();
106 }
107
108 public boolean getBoolean(String propName) throws JMSException
109 {
110 Object value = _map.get(propName);
111
112 if (value instanceof Boolean)
113 {
114 return ((Boolean) value).booleanValue();
115 }
116 else if ((value instanceof String) || (value == null))
117 {
118 return Boolean.valueOf((String) value);
119 }
120 else
121 {
122 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
123 + " cannot be converted to boolean.");
124 }
125
126 }
127
128 public byte getByte(String propName) throws JMSException
129 {
130 Object value = _map.get(propName);
131
132 if (value instanceof Byte)
133 {
134 return ((Byte) value).byteValue();
135 }
136 else if ((value instanceof String) || (value == null))
137 {
138 return Byte.valueOf((String) value).byteValue();
139 }
140 else
141 {
142 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
143 + " cannot be converted to byte.");
144 }
145 }
146
147 public short getShort(String propName) throws JMSException
148 {
149 Object value = _map.get(propName);
150
151 if (value instanceof Short)
152 {
153 return ((Short) value).shortValue();
154 }
155 else if (value instanceof Byte)
156 {
157 return ((Byte) value).shortValue();
158 }
159 else if ((value instanceof String) || (value == null))
160 {
161 return Short.valueOf((String) value).shortValue();
162 }
163 else
164 {
165 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
166 + " cannot be converted to short.");
167 }
168
169 }
170
171 public int getInt(String propName) throws JMSException
172 {
173 Object value = _map.get(propName);
174
175 if (value instanceof Integer)
176 {
177 return ((Integer) value).intValue();
178 }
179 else if (value instanceof Short)
180 {
181 return ((Short) value).intValue();
182 }
183 else if (value instanceof Byte)
184 {
185 return ((Byte) value).intValue();
186 }
187 else if ((value instanceof String) || (value == null))
188 {
189 return Integer.valueOf((String) value).intValue();
190 }
191 else
192 {
193 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
194 + " cannot be converted to int.");
195 }
196
197 }
198
199 public long getLong(String propName) throws JMSException
200 {
201 Object value = _map.get(propName);
202
203 if (value instanceof Long)
204 {
205 return ((Long) value).longValue();
206 }
207 else if (value instanceof Integer)
208 {
209 return ((Integer) value).longValue();
210 }
211
212 if (value instanceof Short)
213 {
214 return ((Short) value).longValue();
215 }
216
217 if (value instanceof Byte)
218 {
219 return ((Byte) value).longValue();
220 }
221 else if ((value instanceof String) || (value == null))
222 {
223 return Long.valueOf((String) value).longValue();
224 }
225 else
226 {
227 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
228 + " cannot be converted to long.");
229 }
230
231 }
232
233 public char getChar(String propName) throws JMSException
234 {
235 Object value = _map.get(propName);
236
237 if (!_map.containsKey(propName))
238 {
239 throw new MessageFormatException("Property " + propName + " not present");
240 }
241 else if (value instanceof Character)
242 {
243 return ((Character) value).charValue();
244 }
245 else if (value == null)
246 {
247 throw new NullPointerException("Property " + propName + " has null value and therefore cannot "
248 + "be converted to char.");
249 }
250 else
251 {
252 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
253 + " cannot be converted to boolan.");
254 }
255
256 }
257
258 public float getFloat(String propName) throws JMSException
259 {
260 Object value = _map.get(propName);
261
262 if (value instanceof Float)
263 {
264 return ((Float) value).floatValue();
265 }
266 else if ((value instanceof String) || (value == null))
267 {
268 return Float.valueOf((String) value).floatValue();
269 }
270 else
271 {
272 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
273 + " cannot be converted to float.");
274 }
275 }
276
277 public double getDouble(String propName) throws JMSException
278 {
279 Object value = _map.get(propName);
280
281 if (value instanceof Double)
282 {
283 return ((Double) value).doubleValue();
284 }
285 else if (value instanceof Float)
286 {
287 return ((Float) value).doubleValue();
288 }
289 else if ((value instanceof String) || (value == null))
290 {
291 return Double.valueOf((String) value).doubleValue();
292 }
293 else
294 {
295 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
296 + " cannot be converted to double.");
297 }
298 }
299
300 public String getString(String propName) throws JMSException
301 {
302 Object value = _map.get(propName);
303
304 if ((value instanceof String) || (value == null))
305 {
306 return (String) value;
307 }
308 else if (value instanceof byte[])
309 {
310 throw new MessageFormatException("Property " + propName + " of type byte[] " + "cannot be converted to String.");
311 }
312 else
313 {
314 return value.toString();
315 }
316
317 }
318
319 public byte[] getBytes(String propName) throws JMSException
320 {
321 Object value = _map.get(propName);
322
323 if (!_map.containsKey(propName))
324 {
325 throw new MessageFormatException("Property " + propName + " not present");
326 }
327 else if ((value instanceof byte[]) || (value == null))
328 {
329 return (byte[]) value;
330 }
331 else
332 {
333 throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName()
334 + " cannot be converted to byte[].");
335 }
336 }
337
338 public Object getObject(String propName) throws JMSException
339 {
340 return _map.get(propName);
341 }
342
343 public Enumeration getMapNames() throws JMSException
344 {
345 return Collections.enumeration(_map.keySet());
346 }
347
348 public void setBoolean(String propName, boolean b) throws JMSException
349 {
350 checkWritable();
351 checkPropertyName(propName);
352 _map.put(propName, b);
353 }
354
355 public void setByte(String propName, byte b) throws JMSException
356 {
357 checkWritable();
358 checkPropertyName(propName);
359 _map.put(propName, b);
360 }
361
362 public void setShort(String propName, short i) throws JMSException
363 {
364 checkWritable();
365 checkPropertyName(propName);
366 _map.put(propName, i);
367 }
368
369 public void setChar(String propName, char c) throws JMSException
370 {
371 checkWritable();
372 checkPropertyName(propName);
373 _map.put(propName, c);
374 }
375
376 public void setInt(String propName, int i) throws JMSException
377 {
378 checkWritable();
379 checkPropertyName(propName);
380 _map.put(propName, i);
381 }
382
383 public void setLong(String propName, long l) throws JMSException
384 {
385 checkWritable();
386 checkPropertyName(propName);
387 _map.put(propName, l);
388 }
389
390 public void setFloat(String propName, float v) throws JMSException
391 {
392 checkWritable();
393 checkPropertyName(propName);
394 _map.put(propName, v);
395 }
396
397 public void setDouble(String propName, double v) throws JMSException
398 {
399 checkWritable();
400 checkPropertyName(propName);
401 _map.put(propName, v);
402 }
403
404 public void setString(String propName, String string1) throws JMSException
405 {
406 checkWritable();
407 checkPropertyName(propName);
408 _map.put(propName, string1);
409 }
410
411 public void setBytes(String propName, byte[] bytes) throws JMSException
412 {
413 checkWritable();
414 checkPropertyName(propName);
415 _map.put(propName, bytes);
416 }
417
418 public void setBytes(String propName, byte[] bytes, int offset, int length) throws JMSException
419 {
420 if ((offset == 0) && (length == bytes.length))
421 {
422 setBytes(propName, bytes);
423 }
424 else
425 {
426 byte[] newBytes = new byte[length];
427 System.arraycopy(bytes, offset, newBytes, 0, length);
428 setBytes(propName, newBytes);
429 }
430 }
431
432 public void setObject(String propName, Object value) throws JMSException
433 {
434 checkWritable();
435 checkPropertyName(propName);
436 if ((value instanceof Boolean) || (value instanceof Byte) || (value instanceof Short) || (value instanceof Integer)
437 || (value instanceof Long) || (value instanceof Character) || (value instanceof Float)
438 || (value instanceof Double) || (value instanceof String) || (value instanceof byte[]) || (value == null))
439 {
440 _map.put(propName, value);
441 }
442 else
443 {
444 throw new MessageFormatException("Cannot set property " + propName + " to value " + value + "of type "
445 + value.getClass().getName() + ".");
446 }
447 }
448
449 private void checkPropertyName(String propName)
450 {
451 if ((propName == null) || propName.equals(""))
452 {
453 throw new IllegalArgumentException("Property name cannot be null, or the empty String.");
454 }
455 }
456
457 public boolean itemExists(String propName) throws JMSException
458 {
459 return _map.containsKey(propName);
460 }
461
462 private void populateMapFromData() throws JMSException
463 {
464 if (_data != null)
465 {
466 _data.rewind();
467
468 final int entries = readIntImpl();
469 for (int i = 0; i < entries; i++)
470 {
471 String propName = readStringImpl();
472 Object value = readObject();
473 _map.put(propName, value);
474 }
475 }
476 else
477 {
478 _map.clear();
479 }
480 }
481
482 private void writeMapToData()
483 {
484 allocateInitialBuffer();
485 final int size = _map.size();
486 writeIntImpl(size);
487 for (Map.Entry<String, Object> entry : _map.entrySet())
488 {
489 try
490 {
491 writeStringImpl(entry.getKey());
492 }
493 catch (CharacterCodingException e)
494 {
495 throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey(), e);
496
497 }
498
499 try
500 {
501 writeObject(entry.getValue());
502 }
503 catch (JMSException e)
504 {
505 Object value = entry.getValue();
506 throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey() + " value : " + value
507 + " (type: " + value.getClass().getName() + ").", e);
508 }
509 }
510
511 }
512
513 }
|