Java tutorial
/* * Copyright 2004,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.synapse.transport.jms; import org.apache.axiom.om.OMOutputFormat; import org.apache.axiom.om.OMText; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.util.StAXUtils; import org.apache.axiom.om.impl.builder.StAXBuilder; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.axiom.om.impl.llom.OMTextImpl; import org.apache.axiom.soap.SOAP11Constants; import org.apache.axiom.soap.SOAP12Constants; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory; import org.apache.axiom.attachments.ByteArrayDataSource; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.builder.BuilderUtil; import org.apache.axis2.context.MessageContext; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.Parameter; import org.apache.axis2.description.AxisOperation; import org.apache.axis2.description.ParameterIncludeImpl; import org.apache.axis2.transport.http.HTTPTransportUtils; import org.apache.synapse.transport.base.BaseUtils; import org.apache.synapse.transport.base.BaseConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.jms.*; import javax.jms.Queue; import javax.xml.stream.XMLStreamException; import javax.xml.namespace.QName; import javax.activation.DataHandler; import javax.naming.Context; import java.io.*; import java.util.*; import java.nio.ByteBuffer; /** * Miscallaneous methods used for the JMS transport */ public class JMSUtils extends BaseUtils { private static final Log log = LogFactory.getLog(JMSUtils.class); private static BaseUtils _instance = new JMSUtils(); public static BaseUtils getInstace() { return _instance; } /** * Create a JMS Queue using the given connection with the JNDI destination name, and return the * JMS Destination name of the created queue * * @param con the JMS Connection to be used * @param destinationJNDIName the JNDI name of the Queue to be created * @return the JMS Destination name of the created Queue * @throws JMSException on error */ public static String createJMSQueue(Connection con, String destinationJNDIName) throws JMSException { try { QueueSession session = ((QueueConnection) con).createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(destinationJNDIName); log.info("JMS Queue with JNDI name : " + destinationJNDIName + " created"); return queue.getQueueName(); } finally { try { con.close(); } catch (JMSException ignore) { } } } /** * Create a JMS Topic using the given connection with the JNDI destination name, and return the * JMS Destination name of the created queue * * @param con the JMS Connection to be used * @param destinationJNDIName the JNDI name of the Topic to be created * @return the JMS Destination name of the created Topic * @throws JMSException on error */ public static String createJMSTopic(Connection con, String destinationJNDIName) throws JMSException { try { TopicSession session = ((TopicConnection) con).createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic topic = session.createTopic(destinationJNDIName); log.info("JMS Topic with JNDI name : " + destinationJNDIName + " created"); return topic.getTopicName(); } finally { try { con.close(); } catch (JMSException ignore) { } } } /** * Should this service be enabled over the JMS transport? * * @param service the Axis service * @return true if JMS should be enabled */ public static boolean isJMSService(AxisService service) { if (service.isEnableAllTransports()) { return true; } else { List transports = service.getExposedTransports(); for (int i = 0; i < transports.size(); i++) { if (JMSListener.TRANSPORT_NAME.equals(transports.get(i))) { return true; } } } return false; } /** * Get the JMS destination used by this service * * @param service the Axis Service * @return the name of the JMS destination */ public static String getJNDIDestinationNameForService(AxisService service) { Parameter destParam = service.getParameter(JMSConstants.DEST_PARAM); if (destParam != null) { return (String) destParam.getValue(); } else { return service.getName(); } } /** * Get the JMS destination type of this service * * @param service the Axis Service * @return the name of the JMS destination */ public static String getDestinationTypeForService(AxisService service) { Parameter destTypeParam = service.getParameter(JMSConstants.DEST_PARAM_TYPE); if (destTypeParam != null) { String paramValue = (String) destTypeParam.getValue(); if (JMSConstants.DESTINATION_TYPE_QUEUE.equals(paramValue) || JMSConstants.DESTINATION_TYPE_TOPIC.equals(paramValue)) { return paramValue; } else { handleException("Invalid destinaton type value " + paramValue); return null; } } else { log.debug("JMS destination type not given. default queue"); return JMSConstants.DESTINATION_TYPE_QUEUE; } } /** * Extract connection factory properties from a given URL * * @param url a JMS URL of the form jms:/<destination>?[<key>=<value>&]* * @return a Hashtable of extracted properties */ public static Hashtable getProperties(String url) { Hashtable h = new Hashtable(); int propPos = url.indexOf("?"); if (propPos != -1) { StringTokenizer st = new StringTokenizer(url.substring(propPos + 1), "&"); while (st.hasMoreTokens()) { String token = st.nextToken(); int sep = token.indexOf("="); if (sep != -1) { h.put(token.substring(0, sep), token.substring(sep + 1)); } else { continue; // ignore, what else can we do? } } } return h; } /** * Get the EPR for the given JMS connection factory and destination * the form of the URL is * jms:/<destination>?[<key>=<value>&]* * * @param cf the Axis2 JMS connection factory * @param destination the JNDI name of the destination * @return the EPR as a String */ static String getEPR(JMSConnectionFactory cf, String destination) { StringBuffer sb = new StringBuffer(); sb.append(JMSConstants.JMS_PREFIX).append(destination); sb.append("?").append(JMSConstants.CONFAC_JNDI_NAME_PARAM).append("=").append(cf.getConnFactoryJNDIName()); Iterator props = cf.getJndiProperties().keySet().iterator(); while (props.hasNext()) { String key = (String) props.next(); String value = (String) cf.getJndiProperties().get(key); sb.append("&").append(key).append("=").append(value); } return sb.toString(); } /** * Get a String property from the JMS message * * @param message JMS message * @param property property name * @return property value */ public String getProperty(Object message, String property) { try { return ((Message) message).getStringProperty(property); } catch (JMSException e) { return null; } } /** * Return the destination name from the given URL * * @param url the URL * @return the destination name */ public static String getDestination(String url) { String tempUrl = url.substring(JMSConstants.JMS_PREFIX.length()); int propPos = tempUrl.indexOf("?"); if (propPos == -1) { return tempUrl; } else { return tempUrl.substring(0, propPos); } } /** * Set JNDI properties and any other connection factory parameters to the connection factory * passed in, looing at the parameter in axis2.xml * @param param the axis parameter that holds the connection factory settings * @param jmsConFactory the JMS connection factory to which the parameters should be applied */ public static void setConnectionFactoryParameters(Parameter param, JMSConnectionFactory jmsConFactory) { ParameterIncludeImpl pi = new ParameterIncludeImpl(); try { pi.deserializeParameters((OMElement) param.getValue()); } catch (AxisFault axisFault) { log.error("Error reading parameters for JMS connection factory" + jmsConFactory.getName(), axisFault); } Iterator params = pi.getParameters().iterator(); while (params.hasNext()) { Parameter p = (Parameter) params.next(); if (JMSConstants.CONFAC_TYPE.equals(p.getName())) { String connectionFactoryType = (String) p.getValue(); jmsConFactory.setConnectionFactoryType(connectionFactoryType); } else if (JMSConstants.RECONNECT_TIMEOUT.equals(p.getName())) { String strTimeout = (String) p.getValue(); int reconnectTimeoutSeconds = Integer.parseInt(strTimeout); long reconnectTimeoutMillis = reconnectTimeoutSeconds * 1000; jmsConFactory.setReconnectTimeout(reconnectTimeoutMillis); } else if (Context.INITIAL_CONTEXT_FACTORY.equals(p.getName())) { jmsConFactory.addJNDIContextProperty(Context.INITIAL_CONTEXT_FACTORY, (String) p.getValue()); } else if (Context.PROVIDER_URL.equals(p.getName())) { jmsConFactory.addJNDIContextProperty(Context.PROVIDER_URL, (String) p.getValue()); } else if (Context.SECURITY_PRINCIPAL.equals(p.getName())) { jmsConFactory.addJNDIContextProperty(Context.SECURITY_PRINCIPAL, (String) p.getValue()); } else if (Context.SECURITY_CREDENTIALS.equals(p.getName())) { jmsConFactory.addJNDIContextProperty(Context.SECURITY_CREDENTIALS, (String) p.getValue()); } else if (JMSConstants.CONFAC_JNDI_NAME_PARAM.equals(p.getName())) { jmsConFactory.setConnFactoryJNDIName((String) p.getValue()); jmsConFactory.addJNDIContextProperty(JMSConstants.CONFAC_JNDI_NAME_PARAM, (String) p.getValue()); } } } /** * Get an InputStream to the JMS message payload * * @param message the JMS message * @return an InputStream to the payload */ public InputStream getInputStream(Object message) { try { if (message instanceof BytesMessage) { byte[] buffer = new byte[1024]; ByteArrayOutputStream out = new ByteArrayOutputStream(); BytesMessage byteMsg = (BytesMessage) message; for (int bytesRead = byteMsg.readBytes(buffer); bytesRead != -1; bytesRead = byteMsg .readBytes(buffer)) { out.write(buffer, 0, bytesRead); } return new ByteArrayInputStream(out.toByteArray()); } else if (message instanceof TextMessage) { TextMessage txtMsg = (TextMessage) message; String contentType = getProperty(txtMsg, BaseConstants.CONTENT_TYPE); if (contentType != null) { return new ByteArrayInputStream( txtMsg.getText().getBytes(BuilderUtil.getCharSetEncoding(contentType))); } else { return new ByteArrayInputStream(txtMsg.getText().getBytes()); } } else { handleException("Unsupported JMS message type : " + message.getClass().getName()); } } catch (JMSException e) { handleException("JMS Exception reading message payload", e); } catch (UnsupportedEncodingException e) { handleException("Encoding exception getting InputStream into message", e); } return null; } /** * Set the JMS ReplyTo for the message * * @param replyDestination the JMS Destination where the reply is expected * @param session the session to use to create a temp Queue if a response is expected * but a Destination has not been specified * @param message the JMS message where the final Destinatio would be set as the JMS ReplyTo * @return the JMS ReplyTo Destination for the message */ public static Destination setReplyDestination(Destination replyDestination, Session session, Message message) { if (replyDestination == null) { try { // create temporary queue to receive the reply replyDestination = createTemporaryDestination(session); } catch (JMSException e) { handleException("Error creating temporary queue for response"); } } try { message.setJMSReplyTo(replyDestination); } catch (JMSException e) { log.warn("Error setting JMS ReplyTo destination to : " + replyDestination, e); } if (log.isDebugEnabled()) { try { log.debug("Expecting a response to JMS Destination : " + (replyDestination instanceof Queue ? ((Queue) replyDestination).getQueueName() : ((Topic) replyDestination).getTopicName())); } catch (JMSException ignore) { } } return replyDestination; } /** * When trying to send a message to a destination, if it does not exist, try to create it * * @param destination the JMS destination to send messages * @param targetAddress the target JMS EPR to find the Destination to be created if required * @param session the JMS session to use * @return the JMS Destination where messages could be posted * @throws AxisFault if the target Destination does not exist and cannot be created */ public static Destination createDestinationIfRequired(Destination destination, String destinationType, String targetAddress, Session session) throws AxisFault { if (destination == null) { if (targetAddress != null) { String name = JMSUtils.getDestination(targetAddress); if (log.isDebugEnabled()) { log.debug("Creating JMS Destination : " + name); } try { destination = createDestination(session, name, destinationType); } catch (JMSException e) { handleException("Error creating destination Queue : " + name, e); } } else { handleException("Cannot send reply to null JMS Destination"); } } return destination; } /** * Send the given message to the Destination using the given session * @param session the session to use to send * @param destination the Destination * @param message the JMS Message * @throws AxisFault on error */ public static void sendMessageToJMSDestination(Session session, Destination destination, Message message) throws AxisFault { MessageProducer producer = null; try { if (log.isDebugEnabled()) { log.debug("Sending message to destination : " + destination); } if (destination instanceof Queue) { producer = ((QueueSession) session).createSender((Queue) destination); ((QueueSender) producer).send(message); } else { producer = ((TopicSession) session).createPublisher((Topic) destination); ((TopicPublisher) producer).publish(message); } if (log.isDebugEnabled()) { log.debug("Sent message to destination : " + destination + "\nMessage ID : " + message.getJMSMessageID() + "\nCorrelation ID : " + message.getJMSCorrelationID() + "\nReplyTo ID : " + message.getJMSReplyTo()); } } catch (JMSException e) { handleException("Error creating a producer or sending to : " + destination, e); } finally { if (producer != null) { try { producer.close(); } catch (JMSException ignore) { } } } } /** * Set transport headers from the axis message context, into the JMS message * * @param msgContext the axis message context * @param message the JMS Message * @throws JMSException on exception */ public static void setTransportHeaders(MessageContext msgContext, Message message) throws JMSException { Map headerMap = (Map) msgContext.getProperty(MessageContext.TRANSPORT_HEADERS); if (headerMap == null) { return; } Iterator iter = headerMap.keySet().iterator(); while (iter.hasNext()) { String name = (String) iter.next(); if (JMSConstants.JMS_COORELATION_ID.equals(name)) { message.setJMSCorrelationID((String) headerMap.get(JMSConstants.JMS_COORELATION_ID)); } else if (JMSConstants.JMS_DELIVERY_MODE.equals(name)) { Object o = headerMap.get(JMSConstants.JMS_DELIVERY_MODE); if (o instanceof Integer) { message.setJMSDeliveryMode(((Integer) o).intValue()); } else if (o instanceof String) { try { message.setJMSDeliveryMode(Integer.parseInt((String) o)); } catch (NumberFormatException nfe) { log.warn("Invalid delivery mode ignored : " + o, nfe); } } else { log.warn("Invalid delivery mode ignored : " + o); } } else if (JMSConstants.JMS_EXPIRATION.equals(name)) { message.setJMSExpiration(Long.parseLong((String) headerMap.get(JMSConstants.JMS_EXPIRATION))); } else if (JMSConstants.JMS_MESSAGE_ID.equals(name)) { message.setJMSMessageID((String) headerMap.get(JMSConstants.JMS_MESSAGE_ID)); } else if (JMSConstants.JMS_PRIORITY.equals(name)) { message.setJMSPriority(Integer.parseInt((String) headerMap.get(JMSConstants.JMS_PRIORITY))); } else if (JMSConstants.JMS_TIMESTAMP.equals(name)) { message.setJMSTimestamp(Long.parseLong((String) headerMap.get(JMSConstants.JMS_TIMESTAMP))); } else if (JMSConstants.JMS_MESSAGE_TYPE.equals(name)) { message.setJMSType((String) headerMap.get(JMSConstants.JMS_MESSAGE_TYPE)); } else { Object value = headerMap.get(name); if (value instanceof String) { message.setStringProperty(name, (String) value); } else if (value instanceof Boolean) { message.setBooleanProperty(name, ((Boolean) value).booleanValue()); } else if (value instanceof Integer) { message.setIntProperty(name, ((Integer) value).intValue()); } else if (value instanceof Long) { message.setLongProperty(name, ((Long) value).longValue()); } else if (value instanceof Double) { message.setDoubleProperty(name, ((Double) value).doubleValue()); } else if (value instanceof Float) { message.setFloatProperty(name, ((Float) value).floatValue()); } } } } /** * Read the transport headers from the JMS Message and set them to the axis2 message context * * @param message the JMS Message received * @param responseMsgCtx the axis message context * @throws AxisFault on error */ public static void loadTransportHeaders(Message message, MessageContext responseMsgCtx) throws AxisFault { responseMsgCtx.setProperty(MessageContext.TRANSPORT_HEADERS, getTransportHeaders(message)); } /** * Extract transport level headers for JMS from the given message into a Map * * @param message the JMS message * @return a Map of the transport headers */ public static Map getTransportHeaders(Message message) { // create a Map to hold transport headers Map map = new HashMap(); // correlation ID try { if (message.getJMSCorrelationID() != null) { map.put(JMSConstants.JMS_COORELATION_ID, message.getJMSCorrelationID()); } } catch (JMSException ignore) { } // set the delivery mode as persistent or not try { map.put(JMSConstants.JMS_DELIVERY_MODE, Integer.toString(message.getJMSDeliveryMode())); } catch (JMSException ignore) { } // destination name try { if (message.getJMSDestination() != null) { Destination dest = message.getJMSDestination(); map.put(JMSConstants.JMS_DESTINATION, dest instanceof Queue ? ((Queue) dest).getQueueName() : ((Topic) dest).getTopicName()); } } catch (JMSException ignore) { } // expiration try { map.put(JMSConstants.JMS_EXPIRATION, Long.toString(message.getJMSExpiration())); } catch (JMSException ignore) { } // if a JMS message ID is found try { if (message.getJMSMessageID() != null) { map.put(JMSConstants.JMS_MESSAGE_ID, message.getJMSMessageID()); } } catch (JMSException ignore) { } // priority try { map.put(JMSConstants.JMS_PRIORITY, Long.toString(message.getJMSPriority())); } catch (JMSException ignore) { } // redelivered try { map.put(JMSConstants.JMS_REDELIVERED, Boolean.toString(message.getJMSRedelivered())); } catch (JMSException ignore) { } // replyto destination name try { if (message.getJMSReplyTo() != null) { Destination dest = message.getJMSReplyTo(); map.put(JMSConstants.JMS_REPLY_TO, dest instanceof Queue ? ((Queue) dest).getQueueName() : ((Topic) dest).getTopicName()); } } catch (JMSException ignore) { } // priority try { map.put(JMSConstants.JMS_TIMESTAMP, Long.toString(message.getJMSTimestamp())); } catch (JMSException ignore) { } // message type try { if (message.getJMSType() != null) { map.put(JMSConstants.JMS_TYPE, message.getJMSType()); } } catch (JMSException ignore) { } // any other transport properties / headers Enumeration e = null; try { e = message.getPropertyNames(); } catch (JMSException ignore) { } if (e != null) { while (e.hasMoreElements()) { String headerName = (String) e.nextElement(); try { map.put(headerName, message.getStringProperty(headerName)); continue; } catch (JMSException ignore) { } try { map.put(headerName, Boolean.valueOf(message.getBooleanProperty(headerName))); continue; } catch (JMSException ignore) { } try { map.put(headerName, new Integer(message.getIntProperty(headerName))); continue; } catch (JMSException ignore) { } try { map.put(headerName, new Long(message.getLongProperty(headerName))); continue; } catch (JMSException ignore) { } try { map.put(headerName, new Double(message.getDoubleProperty(headerName))); continue; } catch (JMSException ignore) { } try { map.put(headerName, new Float(message.getFloatProperty(headerName))); continue; } catch (JMSException ignore) { } } } return map; } public String getMessageTextPayload(Object message) { if (message instanceof TextMessage) { try { return ((TextMessage) message).getText(); } catch (JMSException e) { handleException("Error reading JMS text message payload", e); } } return null; } public byte[] getMessageBinaryPayload(Object message) { if (message instanceof BytesMessage) { BytesMessage bytesMessage = (BytesMessage) message; try { bytesMessage.reset(); byte[] buffer = new byte[1024]; ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int bytesRead = bytesMessage.readBytes(buffer); bytesRead != -1; bytesRead = bytesMessage .readBytes(buffer)) { out.write(buffer, 0, bytesRead); } return out.toByteArray(); } catch (JMSException e) { handleException("Error reading JMS binary message payload", e); } } return null; } // ----------- JMS 1.0.2b compatibility methods ------------- public static Connection createConnection(ConnectionFactory conFactory, String user, String pass, String destinationType) throws JMSException { if (JMSConstants.DESTINATION_TYPE_QUEUE.equals(destinationType)) { if (user != null && pass != null) { return ((QueueConnectionFactory) conFactory).createQueueConnection(user, pass); } else { return ((QueueConnectionFactory) conFactory).createQueueConnection(); } } else if (JMSConstants.DESTINATION_TYPE_TOPIC.equals(destinationType)) { if (user != null && pass != null) { return ((TopicConnectionFactory) conFactory).createTopicConnection(user, pass); } else { return ((TopicConnectionFactory) conFactory).createTopicConnection(); } } else { handleException("Unable to determine type of JMS Connection Factory - i.e Queue/Topic"); } return null; } public static Session createSession(Connection con, boolean transacted, int acknowledgeMode, String destinationType) throws JMSException { if (JMSConstants.DESTINATION_TYPE_QUEUE.equals(destinationType)) { return ((QueueConnection) con).createQueueSession(transacted, acknowledgeMode); } else if (JMSConstants.DESTINATION_TYPE_TOPIC.equals(destinationType)) { return ((TopicConnection) con).createTopicSession(transacted, acknowledgeMode); } else { log.debug("JMS destination type not given or invalid. default queue. was " + destinationType); return ((QueueConnection) con).createQueueSession(transacted, acknowledgeMode); } } public static Destination createDestination(Session session, String destName, String destinationType) throws JMSException { if (JMSConstants.DESTINATION_TYPE_QUEUE.equals(destinationType)) { return ((QueueSession) session).createQueue(destName); } else if (JMSConstants.DESTINATION_TYPE_TOPIC.equals(destinationType)) { return ((TopicSession) session).createTopic(destName); } else { log.debug("JMS destination type not given or invalid. default queue. was " + destinationType); return ((QueueSession) session).createQueue(destName); } } public static void createDestination(ConnectionFactory conFactory, String destinationJNDIName, String destinationType) throws JMSException { if (JMSConstants.DESTINATION_TYPE_QUEUE.equals(destinationType)) { JMSUtils.createJMSQueue(((QueueConnectionFactory) conFactory).createQueueConnection(), destinationJNDIName); } else if (JMSConstants.DESTINATION_TYPE_TOPIC.equals(destinationType)) { JMSUtils.createJMSTopic(((TopicConnectionFactory) conFactory).createTopicConnection(), destinationJNDIName); } } public static MessageConsumer createConsumer(Session session, Destination dest) throws JMSException { if (dest instanceof Queue) { return ((QueueSession) session).createReceiver((Queue) dest); } else { return ((TopicSession) session).createSubscriber((Topic) dest); } } public static Destination createTemporaryDestination(Session session) throws JMSException { if (session instanceof QueueSession) { return ((QueueSession) session).createTemporaryQueue(); } else { return ((TopicSession) session).createTemporaryTopic(); } } }