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 "JMSTransport.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.Destination; 034 import javax.jms.JMSException; 035 import javax.jms.Message; 036 import javax.jms.Queue; 037 import javax.jms.TextMessage; 038 import javax.jms.Topic; 039 040 import ca.uhn.hl7v2.protocol.JMSDestination; 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 class JMSTransport extends AbstractTransport implements TransportLayer { 054 055 private static final HapiLog log = HapiLogFactory.getHapiLog(URLTransport.class); 056 057 public static final String INBOUND_DESTINATION_NAME_KEY = "INBOUND_DESTINATION_NAME"; 058 public static final String INBOUND_CLIENT_ID_KEY = "INBOUND_CLIENT_ID"; 059 public static final String INBOUND_CONNECTION_METADATA_KEY = "INBOUND_CONNECTION_METADATA"; 060 public static final String OUTBOUND_DESTINATION_NAME_KEY = "OUTBOUND_DESTINATION_NAME"; 061 public static final String OUTBOUND_CLIENT_ID_KEY = "OUTBOUND_CLIENT_ID"; 062 public static final String OUTBOUND_CONNECTION_METADATA_KEY = "OUTBOUND_CONNECTION_METADATA"; 063 064 private JMSDestination myInbound; 065 private JMSDestination myOutbound; 066 private Map myMetadata; 067 068 /** 069 * @param theInboundDestination wrapper around the Queue or Topic to which outgoing messages 070 * are to be sent 071 * @param theOutboundDestination wrapper around the Queue or Topic from which incoming messages 072 * are to be retrieved 073 */ 074 public JMSTransport(JMSDestination theInboundDestination, JMSDestination theOutboundDestination) { 075 myInbound = theInboundDestination; 076 myOutbound = theOutboundDestination; 077 } 078 079 /** 080 * @param theConnection JMS connection over which messages are exchanged 081 * @param theDestination JMS destination to which messages are produced and 082 * from which messages are consumed 083 */ 084 public JMSTransport() { 085 myMetadata = makeMetadata(); 086 } 087 088 /** 089 * Sets common metadata on the basis of connection and destination. 090 */ 091 private Map makeMetadata() { 092 Map md = new HashMap(); 093 try { 094 md.put(INBOUND_CLIENT_ID_KEY, myInbound.getConnection().getClientID()); 095 md.put(INBOUND_CONNECTION_METADATA_KEY, myInbound.getConnection().getMetaData()); 096 md.put(INBOUND_DESTINATION_NAME_KEY, myInbound.getName()); 097 md.put(OUTBOUND_CLIENT_ID_KEY, myOutbound.getConnection().getClientID()); 098 md.put(OUTBOUND_CONNECTION_METADATA_KEY, myOutbound.getConnection().getMetaData()); 099 md.put(OUTBOUND_DESTINATION_NAME_KEY, myOutbound.getName()); 100 } catch (JMSException e) { 101 log.error("Error setting JMSTransport metadata", e); 102 } 103 return md; 104 } 105 106 /** 107 * @param theDestination a Queue or Topic 108 * @return either getQueueName() or getTopicName() 109 */ 110 private static String getName(Destination theDestination) throws JMSException { 111 String name = null; 112 113 if (theDestination instanceof Queue) { 114 name = ((Queue) theDestination).getQueueName(); 115 } else if (theDestination instanceof Topic) { 116 name = ((Topic) theDestination).getTopicName(); 117 } else { 118 throw new IllegalArgumentException("We don't support Destinations of type " 119 + theDestination.getClass().getName()); 120 } 121 return name; 122 } 123 124 /** 125 * @see ca.uhn.hl7v2.protocol.Transport#doSend(ca.uhn.hl7v2.protocol.Transportable) 126 */ 127 public void doSend(Transportable theMessage) throws TransportException { 128 try { 129 Message message = toMessage(theMessage); 130 myOutbound.send(message); 131 } catch (JMSException e) { 132 throw new TransportException(e); 133 } 134 } 135 136 /** 137 * Fills a JMS message object with text and metadata from the given 138 * <code>Transportable</code>. The default implementation obtains a 139 * the Message from getMessage(), and expects this to be a TextMessage. 140 * Override this method if you want to use a different message type. 141 * 142 * @param theSource a Transportable from which to obtain data for filling the 143 * given Message 144 * @return a Message containing data from the given Transportable 145 */ 146 protected Message toMessage(Transportable theSource) throws TransportException { 147 Message message; 148 try { 149 message = myOutbound.createMessage(); 150 151 if ( !(message instanceof TextMessage)) { 152 throw new TransportException("This implementation expects getMessage() to return " 153 + " a TextMessage. Override this method if another message type is to be used"); 154 } 155 156 ((TextMessage) message).setText(theSource.getMessage()); 157 158 Iterator it = theSource.getMetadata().keySet().iterator(); 159 while (it.hasNext()) { 160 Object key = it.next(); 161 Object val = theSource.getMetadata().get(key); 162 message.setObjectProperty(key.toString(), val); 163 } 164 } catch (JMSException e) { 165 throw new TransportException(e); 166 } 167 168 return message; 169 } 170 171 /** 172 * Copies data from the given Message into a Transportable. The default 173 * implementation expects a TextMessage, but this can be overridden. 174 * 175 * @param theMessage a JMS Message from which to obtain data 176 * @return a Transportable containing data from the given Message 177 */ 178 protected Transportable toTransportable(Message theMessage) throws TransportException { 179 if ( !(theMessage instanceof TextMessage)) { 180 throw new TransportException("This implementation expects getMessage() to return " 181 + " a TextMessage. Override this method if another message type is to be used"); 182 } 183 184 Transportable result = null; 185 try { 186 String text = ((TextMessage) theMessage).getText(); 187 result = new TransportableImpl(text); 188 result.getMetadata().putAll(getCommonMetadata()); 189 } catch (JMSException e) { 190 throw new TransportException(e); 191 } 192 193 return result; 194 } 195 196 /** 197 * @see ca.uhn.hl7v2.protocol.AbstractTransport#doReceive() 198 */ 199 public Transportable doReceive() throws TransportException { 200 Transportable result = null; 201 try { 202 Message message = myInbound.receive(); 203 result = toTransportable(message); 204 } catch (JMSException e) { 205 throw new TransportException(e); 206 } 207 return result; 208 } 209 210 /** 211 * Returns metadata under the static keys defined by this class. 212 * 213 * @see ca.uhn.hl7v2.protocol.TransportLayer#getCommonMetadata() 214 */ 215 public Map getCommonMetadata() { 216 return myMetadata; 217 } 218 219 /** 220 * @see ca.uhn.hl7v2.protocol.impl.AbstractTransport#doConnect() 221 */ 222 public void doConnect() throws TransportException { 223 try { 224 myInbound.connect(); 225 if (myInbound != myOutbound) { 226 myOutbound.connect(); 227 } 228 } catch (JMSException e) { 229 throw new TransportException(e); 230 } 231 } 232 233 /** 234 * @see ca.uhn.hl7v2.protocol.impl.AbstractTransport#doDisconnect() 235 */ 236 public void doDisconnect() throws TransportException { 237 try { 238 myInbound.disconnect(); 239 if (myInbound != myOutbound) { 240 myOutbound.disconnect(); 241 } 242 } catch (JMSException e) { 243 throw new TransportException(e); 244 } 245 } 246 247 }