001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021
022 package org.apache.qpid.client.message;
023
024 import org.apache.commons.collections.map.ReferenceMap;
025 import org.apache.qpid.client.*;
026 import org.apache.qpid.framing.ContentHeaderProperties;
027 import org.apache.qpid.framing.BasicContentHeaderProperties;
028 import org.apache.qpid.framing.AMQShortString;
029 import org.apache.qpid.framing.FieldTable;
030 import org.apache.qpid.AMQException;
031 import org.apache.qpid.AMQPInvalidClassException;
032 import org.apache.qpid.jms.Message;
033 import org.apache.qpid.url.BindingURL;
034 import org.apache.qpid.url.AMQBindingURL;
035 import org.apache.mina.common.ByteBuffer;
036 import org.apache.qpid.transport.*;
037
038 import javax.jms.Destination;
039 import javax.jms.JMSException;
040 import javax.jms.MessageNotWriteableException;
041 import javax.jms.MessageFormatException;
042 import javax.jms.DeliveryMode;
043 import java.util.*;
044 import java.util.concurrent.ConcurrentHashMap;
045 import java.net.URISyntaxException;
046 import java.nio.charset.Charset;
047 import org.apache.qpid.exchange.ExchangeDefaults;
048
049 public class AMQMessageDelegate_0_10 implements AMQMessageDelegate
050 {
051 private static final Map<ReplyTo, Destination> _destinationCache = Collections.synchronizedMap(new ReferenceMap());
052
053 public static final String JMS_TYPE = "x-jms-type";
054
055
056 private boolean _readableProperties = false;
057
058 private Destination _destination;
059
060
061 private MessageProperties _messageProps;
062 private DeliveryProperties _deliveryProps;
063 /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
064 private AMQSession _session;
065 private final long _deliveryTag;
066
067 private static Map<AMQShortString,Integer> _exchangeTypeMap = new ConcurrentHashMap<AMQShortString, Integer>();
068 private static Map<String,Integer> _exchangeTypeStringMap = new ConcurrentHashMap<String, Integer>();
069 private static Map<String, Integer> _exchangeTypeToDestinationType = new ConcurrentHashMap<String, Integer>();;
070
071 static
072 {
073 _exchangeTypeMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME, AMQDestination.QUEUE_TYPE);
074 _exchangeTypeMap.put(AMQShortString.EMPTY_STRING, AMQDestination.QUEUE_TYPE);
075 _exchangeTypeMap.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME, AMQDestination.TOPIC_TYPE);
076 _exchangeTypeMap.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME, AMQDestination.TOPIC_TYPE);
077
078 _exchangeTypeStringMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME.toString(), AMQDestination.QUEUE_TYPE);
079 _exchangeTypeStringMap.put("", AMQDestination.QUEUE_TYPE);
080 _exchangeTypeStringMap.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
081 _exchangeTypeStringMap.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
082
083
084 _exchangeTypeToDestinationType.put(ExchangeDefaults.DIRECT_EXCHANGE_CLASS.toString(), AMQDestination.QUEUE_TYPE);
085 _exchangeTypeToDestinationType.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
086 _exchangeTypeToDestinationType.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
087 }
088
089 protected AMQMessageDelegate_0_10()
090 {
091 this(new MessageProperties(), new DeliveryProperties(), -1);
092 _readableProperties = false;
093 }
094
095 protected AMQMessageDelegate_0_10(long deliveryTag, MessageProperties messageProps, DeliveryProperties deliveryProps, AMQShortString exchange,
096 AMQShortString routingKey) throws AMQException
097 {
098 this(messageProps, deliveryProps, deliveryTag);
099
100
101 AMQDestination dest;
102
103 dest = generateDestination(exchange, routingKey);
104 setJMSDestination(dest);
105 }
106
107 private AMQDestination generateDestination(AMQShortString exchange, AMQShortString routingKey)
108 {
109 AMQDestination dest;
110 switch(getExchangeType(exchange))
111 {
112 case AMQDestination.QUEUE_TYPE:
113 dest = new AMQQueue(exchange, routingKey, routingKey);
114 break;
115 case AMQDestination.TOPIC_TYPE:
116 dest = new AMQTopic(exchange, routingKey, null);
117 break;
118 default:
119 dest = new AMQUndefinedDestination(exchange, routingKey, null);
120
121 }
122
123 return dest;
124 }
125
126 private int getExchangeType(AMQShortString exchange)
127 {
128 Integer type = _exchangeTypeMap.get(exchange == null ? AMQShortString.EMPTY_STRING : exchange);
129
130 if(type == null)
131 {
132 return AMQDestination.UNKNOWN_TYPE;
133 }
134
135
136 return type;
137 }
138
139
140 public static void updateExchangeTypeMapping(Header header, org.apache.qpid.transport.Session session)
141 {
142 DeliveryProperties deliveryProps = header.get(DeliveryProperties.class);
143 if(deliveryProps != null)
144 {
145 String exchange = deliveryProps.getExchange();
146
147 if(exchange != null && !_exchangeTypeStringMap.containsKey(exchange))
148 {
149
150 AMQShortString exchangeShortString = new AMQShortString(exchange);
151 Future<ExchangeQueryResult> future =
152 session.exchangeQuery(exchange.toString());
153 ExchangeQueryResult res = future.get();
154
155 Integer type = _exchangeTypeToDestinationType.get(res.getType());
156 if(type == null)
157 {
158 type = AMQDestination.UNKNOWN_TYPE;
159 }
160 _exchangeTypeStringMap.put(exchange, type);
161 _exchangeTypeMap.put(exchangeShortString, type);
162
163 }
164 }
165 }
166
167 protected AMQMessageDelegate_0_10(MessageProperties messageProps, DeliveryProperties deliveryProps, long deliveryTag)
168 {
169 _messageProps = messageProps;
170 _deliveryProps = deliveryProps;
171 _deliveryTag = deliveryTag;
172 _readableProperties = (_messageProps != null);
173
174 }
175
176
177 public String getJMSMessageID() throws JMSException
178 {
179 UUID id = _messageProps.getMessageId();
180 return id == null ? null : "ID:" + id;
181 }
182
183 public void setJMSMessageID(String messageId) throws JMSException
184 {
185 if(messageId == null)
186 {
187 _messageProps.clearMessageId();
188 }
189 else
190 {
191 if(messageId.startsWith("ID:"))
192 {
193 try
194 {
195 _messageProps.setMessageId(UUID.fromString(messageId.substring(3)));
196 }
197 catch(IllegalArgumentException ex)
198 {
199 throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be ID: followed by a UUID");
200 }
201 }
202 else
203 {
204 throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be ID: followed by a UUID");
205 }
206 }
207 }
208
209 public void setJMSMessageID(UUID messageId) throws JMSException
210 {
211 if(messageId == null)
212 {
213 _messageProps.clearMessageId();
214 }
215 else
216 {
217 _messageProps.setMessageId(messageId);
218 }
219 }
220
221
222 public long getJMSTimestamp() throws JMSException
223 {
224 return _deliveryProps.getTimestamp();
225 }
226
227 public void setJMSTimestamp(long timestamp) throws JMSException
228 {
229 _deliveryProps.setTimestamp(timestamp);
230 }
231
232 public byte[] getJMSCorrelationIDAsBytes() throws JMSException
233 {
234 return _messageProps.getCorrelationId();
235 }
236
237 public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException
238 {
239 _messageProps.setCorrelationId(bytes);
240 }
241
242 public void setJMSCorrelationID(String correlationId) throws JMSException
243 {
244
245 setJMSCorrelationIDAsBytes(correlationId == null ? null : correlationId.getBytes());
246 }
247
248 public String getJMSCorrelationID() throws JMSException
249 {
250
251 byte[] correlationIDAsBytes = getJMSCorrelationIDAsBytes();
252 return correlationIDAsBytes == null ? null : new String(correlationIDAsBytes);
253 }
254
255 public Destination getJMSReplyTo()
256 {
257 ReplyTo replyTo = _messageProps.getReplyTo();
258
259 if (replyTo == null)
260 {
261 return null;
262 }
263 else
264 {
265 Destination dest = _destinationCache.get(replyTo);
266 if (dest == null)
267 {
268 String exchange = replyTo.getExchange();
269 String routingKey = replyTo.getRoutingKey();
270
271 dest = generateDestination(exchange == null ? null : new AMQShortString(exchange),
272 routingKey == null ? null : new AMQShortString(routingKey));
273
274
275
276
277
278 _destinationCache.put(replyTo, dest);
279 }
280
281 return dest;
282 }
283 }
284
285 public void setJMSReplyTo(Destination destination) throws JMSException
286 {
287 if (destination == null)
288 {
289 _messageProps.setReplyTo(null);
290 return;
291 }
292
293 if (!(destination instanceof AMQDestination))
294 {
295 throw new IllegalArgumentException(
296 "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass());
297 }
298
299 final AMQDestination amqd = (AMQDestination) destination;
300
301 final ReplyTo replyTo = new ReplyTo(amqd.getExchangeName().toString(), amqd.getRoutingKey().toString());
302 _destinationCache.put(replyTo, destination);
303 _messageProps.setReplyTo(replyTo);
304
305 }
306
307 public Destination getJMSDestination() throws JMSException
308 {
309 return _destination;
310 }
311
312 public void setJMSDestination(Destination destination)
313 {
314 _destination = destination;
315 }
316
317 public void setContentType(String contentType)
318 {
319 _messageProps.setContentType(contentType);
320 }
321
322 public String getContentType()
323 {
324 return _messageProps.getContentType();
325 }
326
327 public void setEncoding(String encoding)
328 {
329 if(encoding == null || encoding.length() == 0)
330 {
331 _messageProps.clearContentEncoding();
332 }
333 else
334 {
335 _messageProps.setContentEncoding(encoding);
336 }
337 }
338
339 public String getEncoding()
340 {
341 return _messageProps.getContentEncoding();
342 }
343
344 public String getReplyToString()
345 {
346 Destination replyTo = getJMSReplyTo();
347 if(replyTo != null)
348 {
349 return ((AMQDestination)replyTo).toURL();
350 }
351 else
352 {
353 return null;
354 }
355
356 }
357
358 public int getJMSDeliveryMode() throws JMSException
359 {
360
361 MessageDeliveryMode deliveryMode = _deliveryProps.getDeliveryMode();
362 if(deliveryMode != null)
363 {
364 switch(deliveryMode)
365 {
366 case PERSISTENT :
367 return DeliveryMode.PERSISTENT;
368 case NON_PERSISTENT:
369 return DeliveryMode.NON_PERSISTENT;
370 default:
371 throw new JMSException("Unknown Message Delivery Mode: " + _deliveryProps.getDeliveryMode());
372 }
373 }
374 else
375 {
376 return Message.DEFAULT_DELIVERY_MODE;
377 }
378
379 }
380
381 public void setJMSDeliveryMode(int deliveryMode) throws JMSException
382 {
383 switch(deliveryMode)
384 {
385 case DeliveryMode.PERSISTENT:
386 _deliveryProps.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
387 break;
388 case DeliveryMode.NON_PERSISTENT:
389 _deliveryProps.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);
390 break;
391 default:
392 throw new JMSException("Unknown JMS Delivery Mode: " + deliveryMode);
393 }
394
395 }
396
397
398 public String getJMSType() throws JMSException
399 {
400 if(getApplicationHeaders().containsKey(JMS_TYPE))
401 {
402 return getStringProperty(JMS_TYPE);
403 }
404 else
405 {
406 return null;
407 }
408 }
409
410 private Map<String, Object> getApplicationHeaders()
411 {
412 Map<String, Object> map = _messageProps.getApplicationHeaders();
413 return map == null ? Collections.EMPTY_MAP : map;
414 }
415
416 public void setJMSType(String type) throws JMSException
417 {
418 Map<String, Object> headers = _messageProps.getApplicationHeaders();
419 if(type == null)
420 {
421 if(headers != null)
422 {
423 headers.remove(JMS_TYPE);
424 }
425 }
426 else
427 {
428 if(headers == null)
429 {
430 headers = new HashMap<String,Object>();
431 _messageProps.setApplicationHeaders(headers);
432
433 }
434 headers.put(JMS_TYPE, type);
435 }
436 }
437
438 public long getJMSExpiration() throws JMSException
439 {
440 return _deliveryProps.getExpiration();
441 }
442
443 public void setJMSExpiration(long l) throws JMSException
444 {
445 _deliveryProps.setExpiration(l);
446 }
447
448
449
450 public boolean propertyExists(String propertyName) throws JMSException
451 {
452 return getApplicationHeaders().containsKey(propertyName);
453 }
454
455 public boolean getBooleanProperty(String propertyName) throws JMSException
456 {
457 checkPropertyName(propertyName);
458
459 Object o = getApplicationHeaders().get(propertyName);
460
461 if(o instanceof Boolean)
462 {
463 return ((Boolean)o).booleanValue();
464 }
465 else if(o instanceof String)
466 {
467 return Boolean.valueOf((String) o).booleanValue();
468 }
469 else if(getApplicationHeaders().containsKey(propertyName))
470 {
471 throw new MessageFormatException("getBooleanProperty(\""+propertyName+"\") failed as value is not boolean: " + o);
472 }
473 else
474 {
475 return Boolean.valueOf(null);
476 }
477 }
478
479 public byte getByteProperty(String propertyName) throws JMSException
480 {
481 checkPropertyName(propertyName);
482
483 Map<String, Object> propertyMap = getApplicationHeaders();
484
485 Object o = propertyMap.get(propertyName);
486
487 if(o instanceof Byte)
488 {
489 return ((Byte)o).byteValue();
490 }
491 else if(o instanceof String)
492 {
493 return Byte.valueOf((String) o).byteValue();
494 }
495 else if(getApplicationHeaders().containsKey(propertyName))
496 {
497 throw new MessageFormatException("getByteProperty(\""+propertyName+"\") failed as value is not a byte: " + o);
498 }
499 else
500 {
501 return Byte.valueOf(null);
502 }
503 }
504
505 public short getShortProperty(String propertyName) throws JMSException
506 {
507 checkPropertyName(propertyName);
508
509 Map<String, Object> propertyMap = getApplicationHeaders();
510
511 Object o = propertyMap.get(propertyName);
512
513 if(o instanceof Short)
514 {
515 return ((Short)o).shortValue();
516 }
517 else
518 {
519 try
520 {
521 return Short.valueOf(getByteProperty(propertyName));
522 }
523 catch(MessageFormatException e)
524 {
525 throw new MessageFormatException("getShortProperty(\""+propertyName+"\") failed as value is not a short: " + o);
526 }
527 }
528
529
530 }
531
532 public int getIntProperty(String propertyName) throws JMSException
533 {
534 checkPropertyName(propertyName);
535
536 Map<String, Object> propertyMap = getApplicationHeaders();
537
538 Object o = propertyMap.get(propertyName);
539
540 if(o instanceof Integer)
541 {
542 return ((Integer)o).intValue();
543 }
544 else
545 {
546 try
547 {
548 return Integer.valueOf(getShortProperty(propertyName));
549 }
550 catch(MessageFormatException e)
551 {
552 throw new MessageFormatException("getIntProperty(\""+propertyName+"\") failed as value is not an int: " + o);
553 }
554
555 }
556 }
557
558 public long getLongProperty(String propertyName) throws JMSException
559 {
560 checkPropertyName(propertyName);
561
562 Map<String, Object> propertyMap = getApplicationHeaders();
563
564 Object o = propertyMap.get(propertyName);
565
566 if(o instanceof Long)
567 {
568 return ((Long)o).longValue();
569 }
570 else
571 {
572 try
573 {
574 return Long.valueOf(getIntProperty(propertyName));
575 }
576 catch(MessageFormatException e)
577 {
578 throw new MessageFormatException("getLongProperty(\""+propertyName+"\") failed as value is not a long: " + o);
579 }
580
581 }
582 }
583
584 public float getFloatProperty(String propertyName) throws JMSException
585 {
586 checkPropertyName(propertyName);
587 Map<String, Object> propertyMap = getApplicationHeaders();
588
589 Object o = propertyMap.get(propertyName);
590
591 if(o instanceof Float)
592 {
593 return ((Float)o).floatValue();
594 }
595 else if(o instanceof String)
596 {
597 return Float.valueOf((String) o).floatValue();
598 }
599 else if(getApplicationHeaders().containsKey(propertyName))
600 {
601 throw new MessageFormatException("getFloatProperty(\""+propertyName+"\") failed as value is not a float: " + o);
602 }
603 else
604 {
605 return Float.valueOf(null);
606 }
607
608 }
609
610 public double getDoubleProperty(String propertyName) throws JMSException
611 {
612 checkPropertyName(propertyName);
613
614 Map<String, Object> propertyMap = getApplicationHeaders();
615
616 Object o = propertyMap.get(propertyName);
617
618 if(o instanceof Double)
619 {
620 return ((Double)o).doubleValue();
621 }
622 else
623 {
624 try
625 {
626 return Double.valueOf(getFloatProperty(propertyName));
627 }
628 catch(MessageFormatException e)
629 {
630 throw new MessageFormatException("getDoubleProperty(\""+propertyName+"\") failed as value is not a double: " + o);
631 }
632
633 }
634 }
635
636 public String getStringProperty(String propertyName) throws JMSException
637 {
638 if (propertyName.equals(CustomJMSXProperty.JMSXUserID.toString()))
639 {
640 return new String(_messageProps.getUserId());
641 }
642 else
643 {
644 checkPropertyName(propertyName);
645 Map<String, Object> propertyMap = getApplicationHeaders();
646
647 Object o = propertyMap.get(propertyName);
648
649 if(o instanceof String)
650 {
651 return (String) o;
652 }
653 else if(o == null)
654 {
655 return null;
656 }
657 else if(o.getClass().isArray())
658 {
659 throw new MessageFormatException("getString(\""+propertyName+"\") failed as value of type " + o.getClass()+ " is an array.");
660 }
661 else
662 {
663 return String.valueOf(o);
664 }
665
666 }
667 }
668
669 public Object getObjectProperty(String propertyName) throws JMSException
670 {
671 checkPropertyName(propertyName);
672 Map<String, Object> propertyMap = getApplicationHeaders();
673
674 return propertyMap.get(propertyName);
675
676 }
677
678 public Enumeration getPropertyNames() throws JMSException
679 {
680 return java.util.Collections.enumeration(getApplicationHeaders().keySet());
681 }
682
683 public void setBooleanProperty(String propertyName, boolean b) throws JMSException
684 {
685 checkPropertyName(propertyName);
686 checkWritableProperties();
687 setApplicationHeader(propertyName, b);
688 }
689
690 public void setByteProperty(String propertyName, byte b) throws JMSException
691 {
692 checkPropertyName(propertyName);
693 checkWritableProperties();
694 setApplicationHeader(propertyName, b);
695 }
696
697 public void setShortProperty(String propertyName, short i) throws JMSException
698 {
699 checkPropertyName(propertyName);
700 checkWritableProperties();
701 setApplicationHeader(propertyName, i);
702 }
703
704 public void setIntProperty(String propertyName, int i) throws JMSException
705 {
706 checkPropertyName(propertyName);
707 checkWritableProperties();
708 setApplicationHeader(propertyName, i);
709 }
710
711 public void setLongProperty(String propertyName, long l) throws JMSException
712 {
713 checkPropertyName(propertyName);
714 checkWritableProperties();
715 setApplicationHeader(propertyName, l);
716 }
717
718 public void setFloatProperty(String propertyName, float f) throws JMSException
719 {
720 checkPropertyName(propertyName);
721 checkWritableProperties();
722 setApplicationHeader(propertyName, f);
723 }
724
725 public void setDoubleProperty(String propertyName, double v) throws JMSException
726 {
727 checkPropertyName(propertyName);
728 checkWritableProperties();
729 setApplicationHeader(propertyName, v);
730 }
731
732 public void setStringProperty(String propertyName, String value) throws JMSException
733 {
734 checkPropertyName(propertyName);
735 checkWritableProperties();
736 setApplicationHeader(propertyName, value);
737 }
738
739 private static final Set<Class> ALLOWED = new HashSet();
740 static
741 {
742 ALLOWED.add(Boolean.class);
743 ALLOWED.add(Byte.class);
744 ALLOWED.add(Short.class);
745 ALLOWED.add(Integer.class);
746 ALLOWED.add(Long.class);
747 ALLOWED.add(Float.class);
748 ALLOWED.add(Double.class);
749 ALLOWED.add(Character.class);
750 ALLOWED.add(String.class);
751 ALLOWED.add(byte[].class);
752 }
753
754 public void setObjectProperty(String propertyName, Object object) throws JMSException
755 {
756 checkPropertyName(propertyName);
757 checkWritableProperties();
758 if (object != null && !ALLOWED.contains(object.getClass()))
759 {
760 throw new MessageFormatException
761 (String.format
762 ("Cannot set a %s, allowed property types are: %s",
763 object.getClass(), ALLOWED));
764 }
765 setApplicationHeader(propertyName, object);
766 }
767
768 private void setApplicationHeader(String propertyName, Object object)
769 {
770 Map<String, Object> headers = _messageProps.getApplicationHeaders();
771 if(headers == null)
772 {
773 headers = new HashMap<String,Object>();
774 _messageProps.setApplicationHeaders(headers);
775 }
776 headers.put(propertyName, object);
777 }
778
779 public void removeProperty(String propertyName) throws JMSException
780 {
781 Map<String, Object> headers = _messageProps.getApplicationHeaders();
782 if(headers != null)
783 {
784 headers.remove(propertyName);
785 }
786 }
787
788
789
790 protected void checkWritableProperties() throws MessageNotWriteableException
791 {
792 if (_readableProperties)
793 {
794 throw new MessageNotWriteableException("You need to call clearProperties() to make the message writable");
795 }
796 }
797
798
799 public int getJMSPriority() throws JMSException
800 {
801 MessageDeliveryPriority messageDeliveryPriority = _deliveryProps.getPriority();
802 return messageDeliveryPriority == null ? Message.DEFAULT_PRIORITY : messageDeliveryPriority.getValue();
803 }
804
805 public void setJMSPriority(int i) throws JMSException
806 {
807 _deliveryProps.setPriority(MessageDeliveryPriority.get((short)i));
808 }
809
810 public void clearProperties() throws JMSException
811 {
812 if(!getApplicationHeaders().isEmpty())
813 {
814 getApplicationHeaders().clear();
815 }
816
817 _readableProperties = false;
818 }
819
820
821 public void acknowledgeThis() throws JMSException
822 {
823 // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
824 // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
825 if (_session != null)
826 {
827 if (_session.getAMQConnection().isClosed())
828 {
829 throw new javax.jms.IllegalStateException("Connection is already closed");
830 }
831
832 // we set multiple to true here since acknowledgement implies acknowledge of all previous messages
833 // received on the session
834 _session.acknowledgeMessage(_deliveryTag, true);
835 }
836 }
837
838 public void acknowledge() throws JMSException
839 {
840 if (_session != null)
841 {
842 _session.acknowledge();
843 }
844 }
845
846
847 /**
848 * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
849 * acknowledge()
850 *
851 * @param s the AMQ session that delivered this message
852 */
853 public void setAMQSession(AMQSession s)
854 {
855 _session = s;
856 }
857
858 public AMQSession getAMQSession()
859 {
860 return _session;
861 }
862
863 /**
864 * Get the AMQ message number assigned to this message
865 *
866 * @return the message number
867 */
868 public long getDeliveryTag()
869 {
870 return _deliveryTag;
871 }
872
873
874
875
876
877
878 protected void checkPropertyName(CharSequence propertyName)
879 {
880 if (propertyName == null)
881 {
882 throw new IllegalArgumentException("Property name must not be null");
883 }
884 else if (propertyName.length() == 0)
885 {
886 throw new IllegalArgumentException("Property name must not be the empty string");
887 }
888
889 checkIdentiferFormat(propertyName);
890 }
891
892 protected void checkIdentiferFormat(CharSequence propertyName)
893 {
894 // JMS requirements 3.5.1 Property Names
895 // Identifiers:
896 // - An identifier is an unlimited-length character sequence that must begin
897 // with a Java identifier start character; all following characters must be Java
898 // identifier part characters. An identifier start character is any character for
899 // which the method Character.isJavaIdentifierStart returns true. This includes
900 // '_' and '$'. An identifier part character is any character for which the
901 // method Character.isJavaIdentifierPart returns true.
902 // - Identifiers cannot be the names NULL, TRUE, or FALSE.
903 // Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
904 // ESCAPE.
905 // Identifiers are either header field references or property references. The
906 // type of a property value in a message selector corresponds to the type
907 // used to set the property. If a property that does not exist in a message is
908 // referenced, its value is NULL. The semantics of evaluating NULL values
909 // in a selector are described in Section 3.8.1.2, Null Values.
910 // The conversions that apply to the get methods for properties do not
911 // apply when a property is used in a message selector expression. For
912 // example, suppose you set a property as a string value, as in the
913 // following:
914 // myMessage.setStringProperty("NumberOfOrders", "2");
915 // The following expression in a message selector would evaluate to false,
916 // because a string cannot be used in an arithmetic expression:
917 // "NumberOfOrders > 1"
918 // Identifiers are case sensitive.
919 // Message header field references are restricted to JMSDeliveryMode,
920 // JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
921 // JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
922 // null and if so are treated as a NULL value.
923
924 if (Boolean.getBoolean("strict-jms"))
925 {
926 // JMS start character
927 if (!(Character.isJavaIdentifierStart(propertyName.charAt(0))))
928 {
929 throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character");
930 }
931
932 // JMS part character
933 int length = propertyName.length();
934 for (int c = 1; c < length; c++)
935 {
936 if (!(Character.isJavaIdentifierPart(propertyName.charAt(c))))
937 {
938 throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character");
939 }
940 }
941
942 // JMS invalid names
943 if ((propertyName.equals("NULL")
944 || propertyName.equals("TRUE")
945 || propertyName.equals("FALSE")
946 || propertyName.equals("NOT")
947 || propertyName.equals("AND")
948 || propertyName.equals("OR")
949 || propertyName.equals("BETWEEN")
950 || propertyName.equals("LIKE")
951 || propertyName.equals("IN")
952 || propertyName.equals("IS")
953 || propertyName.equals("ESCAPE")))
954 {
955 throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS");
956 }
957 }
958
959 }
960
961
962 public MessageProperties getMessageProperties()
963 {
964 return _messageProps;
965 }
966
967
968 public DeliveryProperties getDeliveryProperties()
969 {
970 return _deliveryProps;
971 }
972
973 }
|