001 /* 002 The contents of this file are subject to the Mozilla Public License Version 1.1 003 (the "License"); you may not use this file except in compliance with the License. 004 You may obtain a copy of the License at http://www.mozilla.org/MPL/ 005 Software distributed under the License is distributed on an "AS IS" basis, 006 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 007 specific language governing rights and limitations under the License. 008 009 The Original Code is "AbstractJMSTransport.java". Description: 010 "A TransportLayer that exchanges messages through JMS destinations." 011 012 The Initial Developer of the Original Code is University Health Network. Copyright (C) 013 2004. All Rights Reserved. 014 015 Contributor(s): ______________________________________. 016 017 Alternatively, the contents of this file may be used under the terms of the 018 GNU General Public License (the ?GPL?), in which case the provisions of the GPL are 019 applicable instead of those above. If you wish to allow use of your version of this 020 file only under the terms of the GPL and not to allow others to use your version 021 of this file under the MPL, indicate your decision by deleting the provisions above 022 and replace them with the notice and other provisions required by the GPL License. 023 If you do not delete the provisions above, a recipient may use your version of 024 this file under either the MPL or the GPL. 025 */ 026 027 package ca.uhn.hl7v2.protocol.impl; 028 029 import java.util.HashMap; 030 import java.util.Iterator; 031 import java.util.Map; 032 033 import javax.jms.Connection; 034 import javax.jms.Destination; 035 import javax.jms.JMSException; 036 import javax.jms.Message; 037 import javax.jms.Queue; 038 import javax.jms.TextMessage; 039 import javax.jms.Topic; 040 041 import ca.uhn.hl7v2.protocol.TransportException; 042 import ca.uhn.hl7v2.protocol.TransportLayer; 043 import ca.uhn.hl7v2.protocol.Transportable; 044 import ca.uhn.log.HapiLog; 045 import ca.uhn.log.HapiLogFactory; 046 047 /** 048 * A <code>TransportLayer</code> that exchanges messages through JMS destinations. 049 * 050 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 051 * @version $Revision: 1.1 $ updated on $Date: 2007/02/19 02:24:26 $ by $Author: jamesagnew $ 052 */ 053 public abstract class AbstractJMSTransport extends AbstractTransport implements TransportLayer { 054 055 private static final HapiLog log = HapiLogFactory.getHapiLog(URLTransport.class); 056 057 public static final String CLIENT_ID_KEY = "CLIENT_ID"; 058 public static final String CONNECTION_METADATA_KEY = "CONNECTION_METADATA"; 059 public static final String DESTINATION_NAME_KEY = "DESTINATION_NAME"; 060 061 private Map myMetadata; 062 063 /** 064 * @param theConnection JMS connection over which messages are exchanged 065 * @param theDestination JMS destination to which messages are produced and 066 * from which messages are consumed 067 */ 068 public AbstractJMSTransport() { 069 myMetadata = makeMetadata(); 070 } 071 072 /** 073 * Sets common metadata on the basis of connection and destination. 074 */ 075 private Map makeMetadata() { 076 Map md = new HashMap(); 077 try { 078 md.put(CLIENT_ID_KEY, getConnection().getClientID()); 079 } catch (JMSException e) { 080 log.error("Error setting JMSTransport metadata", e); 081 } 082 083 try { 084 md.put(CONNECTION_METADATA_KEY, getConnection().getMetaData()); 085 } catch (JMSException e) { 086 log.error("Error setting JMSTransport metadata", e); 087 } 088 089 try { 090 md.put(DESTINATION_NAME_KEY, getDestinationName()); 091 } catch (JMSException e) { 092 log.error("Error setting JMSTransport metadata", e); 093 } 094 return md; 095 } 096 097 /** 098 * @return the name of the destination at which messages are 099 * written and read 100 */ 101 protected abstract String getDestinationName() throws JMSException; 102 103 /** 104 * @return the QueueConnection or TopicConnection over which messages 105 * are transported 106 */ 107 public abstract Connection getConnection(); 108 109 /** 110 * @return a new JMS Message created on the sending Session. 111 * @throws JMSException 112 */ 113 protected abstract Message getMessage() throws JMSException; 114 115 /** 116 * Sends a message to the underlying Destination 117 * 118 * @param theMessage 119 * @throws JMSException 120 */ 121 protected abstract void sendJMS(Message theMessage) throws JMSException; 122 123 /** 124 * @return the next available message from the underlying Destination 125 * @throws JMSException 126 */ 127 protected abstract Message receiveJMS() throws JMSException; 128 129 /** 130 * @param theDestination a Queue or Topic 131 * @return either getQueueName() or getTopicName() 132 */ 133 private static String getName(Destination theDestination) throws JMSException { 134 String name = null; 135 136 if (theDestination instanceof Queue) { 137 name = ((Queue) theDestination).getQueueName(); 138 } else if (theDestination instanceof Topic) { 139 name = ((Topic) theDestination).getTopicName(); 140 } else { 141 throw new IllegalArgumentException("We don't support Destinations of type " 142 + theDestination.getClass().getName()); 143 } 144 return name; 145 } 146 147 /** 148 * @see ca.uhn.hl7v2.protocol.Transport#doSend(ca.uhn.hl7v2.protocol.Transportable) 149 */ 150 public void doSend(Transportable theMessage) throws TransportException { 151 try { 152 Message message = toMessage(theMessage); 153 sendJMS(message); 154 } catch (JMSException e) { 155 throw new TransportException(e); 156 } 157 } 158 159 /** 160 * Fills a JMS message object with text and metadata from the given 161 * <code>Transportable</code>. The default implementation obtains a 162 * the Message from getMessage(), and expects this to be a TextMessage. 163 * Override this method if you want to use a different message type. 164 * 165 * @param theSource a Transportable from which to obtain data for filling the 166 * given Message 167 * @return a Message containing data from the given Transportable 168 */ 169 protected Message toMessage(Transportable theSource) throws TransportException { 170 Message message; 171 try { 172 message = getMessage(); 173 174 if ( !(message instanceof TextMessage)) { 175 throw new TransportException("This implementation expects getMessage() to return " 176 + " a TextMessage. Override this method if another message type is to be used"); 177 } 178 179 ((TextMessage) message).setText(theSource.getMessage()); 180 181 Iterator it = theSource.getMetadata().keySet().iterator(); 182 while (it.hasNext()) { 183 Object key = it.next(); 184 Object val = theSource.getMetadata().get(key); 185 message.setObjectProperty(key.toString(), val); 186 } 187 } catch (JMSException e) { 188 throw new TransportException(e); 189 } 190 191 return message; 192 } 193 194 /** 195 * Copies data from the given Message into a Transportable. The default 196 * implementation expects a TextMessage, but this can be overridden. 197 * 198 * @param theMessage a JMS Message from which to obtain data 199 * @return a Transportable containing data from the given Message 200 */ 201 protected Transportable toTransportable(Message theMessage) throws TransportException { 202 if ( !(theMessage instanceof TextMessage)) { 203 throw new TransportException("This implementation expects getMessage() to return " 204 + " a TextMessage. Override this method if another message type is to be used"); 205 } 206 207 Transportable result = null; 208 try { 209 String text = ((TextMessage) theMessage).getText(); 210 result = new TransportableImpl(text); 211 result.getMetadata().putAll(getCommonMetadata()); 212 } catch (JMSException e) { 213 throw new TransportException(e); 214 } 215 216 return result; 217 } 218 219 /** 220 * @see ca.uhn.hl7v2.protocol.AbstractTransport#doReceive() 221 */ 222 public Transportable doReceive() throws TransportException { 223 Transportable result = null; 224 try { 225 Message message = receiveJMS(); 226 result = toTransportable(message); 227 } catch (JMSException e) { 228 throw new TransportException(e); 229 } 230 return result; 231 } 232 233 /** 234 * Returns metadata under the static keys defined by this class. 235 * 236 * @see ca.uhn.hl7v2.protocol.TransportLayer#getCommonMetadata() 237 */ 238 public Map getCommonMetadata() { 239 return myMetadata; 240 } 241 242 }