MessageFactoryRegistry.java
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 package org.apache.qpid.client.message;
022 
023 import java.util.HashMap;
024 import java.util.List;
025 import java.util.Map;
026 import java.nio.ByteBuffer;
027 
028 import javax.jms.JMSException;
029 
030 import org.apache.qpid.AMQException;
031 import org.apache.qpid.framing.AMQShortString;
032 import org.apache.qpid.framing.BasicContentHeaderProperties;
033 import org.apache.qpid.framing.ContentHeaderBody;
034 import org.apache.qpid.transport.Struct;
035 import org.apache.qpid.transport.MessageProperties;
036 import org.apache.qpid.transport.MessageTransfer;
037 import org.apache.qpid.transport.DeliveryProperties;
038 import org.slf4j.Logger;
039 import org.slf4j.LoggerFactory;
040 
041 public class MessageFactoryRegistry
042 {
043     /**
044      * This class logger
045      */
046     protected final Logger _logger = LoggerFactory.getLogger(getClass());
047 
048     private final Map<String, MessageFactory> _mimeStringToFactoryMap = new HashMap<String, MessageFactory>();
049     private final Map<AMQShortString, MessageFactory> _mimeShortStringToFactoryMap =
050             new HashMap<AMQShortString, MessageFactory>();
051 
052     /**
053      * Construct a new registry with the default message factories registered
054      *
055      @return a message factory registry
056      */
057     public static MessageFactoryRegistry newDefaultRegistry()
058     {
059         MessageFactoryRegistry mf = new MessageFactoryRegistry();
060         mf.registerFactory(JMSMapMessage.MIME_TYPE, new JMSMapMessageFactory());
061         mf.registerFactory("text/plain"new JMSTextMessageFactory());
062         mf.registerFactory("text/xml"new JMSTextMessageFactory());
063         mf.registerFactory(JMSBytesMessage.MIME_TYPE, new JMSBytesMessageFactory());
064         mf.registerFactory(JMSObjectMessage.MIME_TYPE, new JMSObjectMessageFactory());
065         mf.registerFactory(JMSStreamMessage.MIME_TYPE, new JMSStreamMessageFactory());
066         mf.registerFactory(null, new JMSBytesMessageFactory());
067 
068         return mf;
069     }
070 
071 
072     public void registerFactory(String mimeType, MessageFactory mf)
073     {
074         if (mf == null)
075         {
076             throw new IllegalArgumentException("Message factory must not be null");
077         }
078 
079         _mimeStringToFactoryMap.put(mimeType, mf);
080         _mimeShortStringToFactoryMap.put(new AMQShortString(mimeType), mf);
081     }
082 
083     public MessageFactory deregisterFactory(String mimeType)
084     {
085         _mimeShortStringToFactoryMap.remove(new AMQShortString(mimeType));
086 
087         return _mimeStringToFactoryMap.remove(mimeType);
088     }
089 
090     /**
091      * Create a message. This looks up the MIME type from the content header and instantiates the appropriate
092      * concrete message type.
093      *
094      @param deliveryTag   the AMQ message id
095      @param redelivered   true if redelivered
096      @param contentHeader the content header that was received
097      @param bodies        a list of ContentBody instances @return the message.
098      @throws AMQException
099      @throws JMSException
100      */
101     public AbstractJMSMessage createMessage(long deliveryTag, boolean redelivered, AMQShortString exchange,
102                                             AMQShortString routingKey, ContentHeaderBody contentHeader, List bodies)
103             throws AMQException, JMSException
104     {
105         BasicContentHeaderProperties properties = (BasicContentHeaderPropertiescontentHeader.properties;
106 
107         // Get the message content type. This may be null for pure AMQP messages, but will always be set for JMS over
108         // AMQP. When the type is null, it can only be assumed that the message is a byte message.
109         AMQShortString contentTypeShortString = properties.getContentType();
110         contentTypeShortString = (contentTypeShortString == nullnew AMQShortString(
111                 JMSBytesMessage.MIME_TYPE: contentTypeShortString;
112 
113         MessageFactory mf = _mimeShortStringToFactoryMap.get(contentTypeShortString);
114         if (mf == null)
115         {
116             throw new AMQException(null, "Unsupport MIME type of " + properties.getContentTypeAsString()null);
117         }
118         else
119         {
120             return mf.createMessage(deliveryTag, redelivered, contentHeader, exchange, routingKey, bodies);
121         }
122     }
123 
124     public AbstractJMSMessage createMessage(MessageTransfer transferthrows AMQException, JMSException
125     {
126 
127         MessageProperties mprop = transfer.getHeader().get(MessageProperties.class);
128         String messageType = "";
129         if mprop == null || mprop.getContentType() == null)
130         {
131             _logger.debug("no message type specified, building a byte message");
132             messageType = JMSBytesMessage.MIME_TYPE;
133         }
134         else
135         {
136            messageType = mprop.getContentType();
137         }
138         MessageFactory mf = _mimeStringToFactoryMap.get(messageType);
139         if (mf == null)
140         {
141             throw new AMQException(null, "Unsupport MIME type of " + messageType, null);
142         }
143         else
144         {
145             boolean redelivered = false;
146             DeliveryProperties deliverProps;
147             if((deliverProps = transfer.getHeader().get(DeliveryProperties.class)) != null)
148             {
149                 redelivered = deliverProps.getRedelivered();
150             }
151             return mf.createMessage(transfer.getId()
152                                     redelivered, 
153                                     mprop == nullnew MessageProperties():mprop,
154                                     deliverProps == nullnew DeliveryProperties():deliverProps,
155                                     transfer.getBody());
156         }
157     }
158 
159 
160     public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory, String mimeTypethrows AMQException, JMSException
161     {
162         if (mimeType == null)
163         {
164             throw new IllegalArgumentException("Mime type must not be null");
165         }
166 
167         MessageFactory mf = _mimeStringToFactoryMap.get(mimeType);
168         if (mf == null)
169         {
170             throw new AMQException(null, "Unsupport MIME type of " + mimeType, null);
171         }
172         else
173         {
174             return mf.createMessage(delegateFactory);
175         }
176     }
177 }