Coverage Report - org.mule.providers.oracle.jms.AbstractOracleJmsConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractOracleJmsConnector
19%
12/64
7%
2/30
2.571
 
 1  
 /*
 2  
  * $Id: AbstractOracleJmsConnector.java 9032 2007-10-10 14:11:38Z aperepel $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 
 12  
 package org.mule.providers.oracle.jms;
 13  
 
 14  
 import org.mule.config.i18n.CoreMessages;
 15  
 import org.mule.providers.ConnectException;
 16  
 import org.mule.providers.jms.JmsConnector;
 17  
 import org.mule.providers.jms.JmsConstants;
 18  
 import org.mule.providers.jms.JmsMessageUtils;
 19  
 import org.mule.transaction.TransactionCoordination;
 20  
 import org.mule.umo.TransactionException;
 21  
 import org.mule.umo.UMOTransaction;
 22  
 import org.mule.umo.lifecycle.InitialisationException;
 23  
 
 24  
 import java.io.Serializable;
 25  
 import java.sql.SQLException;
 26  
 
 27  
 import javax.jms.Connection;
 28  
 import javax.jms.ConnectionFactory;
 29  
 import javax.jms.JMSException;
 30  
 import javax.jms.Session;
 31  
 import javax.naming.NamingException;
 32  
 
 33  
 import oracle.jms.AQjmsSession;
 34  
 import oracle.jms.AdtMessage;
 35  
 import oracle.xdb.XMLType;
 36  
 
 37  
 public abstract class AbstractOracleJmsConnector extends JmsConnector
 38  
 {
 39  
     /**
 40  
      * If a queue's payload is an ADT (Oracle Advanced Data Type), the appropriate
 41  
      * payload factory must be specified in the endpoint's properties. Note: if
 42  
      * <u>all</u> queues are of the same payload type, this property may be set
 43  
      * globally for the connector instead of for each endpoint.
 44  
      */
 45  
     public static final String PAYLOADFACTORY_PROPERTY = "payloadFactory";
 46  
 
 47  30
     protected String payloadFactory = null;
 48  
     
 49  
     /**
 50  
      * Some versions of Oracle do not support more than one JMS session per
 51  
      * connection. In this case we need to open a new connection for each session,
 52  
      * otherwise we will get the following error:
 53  
      * {@code JMS-106: Cannot have more than one open Session on a JMSConnection.}
 54  
      */
 55  30
     private boolean multipleSessionsPerConnection = false;
 56  
 
 57  
     public AbstractOracleJmsConnector()
 58  
     {
 59  30
         super();
 60  30
         registerSupportedProtocol("jms");
 61  30
     }
 62  
 
 63  
     /**
 64  
      * The Oracle AQ connector supports both the oaq:// and the jms:// protocols.
 65  
      */
 66  
     public String getProtocol()
 67  
     {
 68  158
         return "oaq";
 69  
     }
 70  
 
 71  
     /**
 72  
      * The Oracle AQ connector supports both the oaq:// and the jms:// protocols.
 73  
      */
 74  
     public boolean supportsProtocol(String protocol)
 75  
     {
 76  
         // The oaq:// protocol handling breaks the model a bit; you do _not_ need to
 77  
         // qualify the jms protocol with oaq (oaq:jms://) hence we need to override
 78  
         // the
 79  
         // default supportsProtocol() method.
 80  4
         return getProtocol().equalsIgnoreCase(protocol) || super.getProtocol().equalsIgnoreCase(protocol);
 81  
     }
 82  
 
 83  
     protected void doConnect() throws ConnectException
 84  
     {
 85  
         try {
 86  
             // Set these to false so that the jndiContext will not be used by the
 87  
             // JmsSupport classes
 88  4
             setJndiDestinations(false);
 89  4
             setForceJndiDestinations(false);
 90  
 
 91  4
             setJmsSupport(new OracleJmsSupport(this, null, false, false));
 92  
         }
 93  0
         catch (Exception e) {
 94  0
             throw new ConnectException(CoreMessages.failedToCreate("Oracle Jms Connector"), 
 95  
                 e, this);
 96  4
         }
 97  
 
 98  
         // Note it doesn't make sense to start a connection at this point
 99  
         // (as the standard JMS Provider does) because a connection will be created
 100  
         // for
 101  
         // each session.
 102  4
     }
 103  
 
 104  
     /**
 105  
      * Some versions of Oracle do not support more than one JMS session per
 106  
      * connection. In this case we need to open a new connection for each session,
 107  
      * otherwise we will get the following error:
 108  
      * {@code JMS-106: Cannot have more than one open Session on a JMSConnection.}
 109  
      *
 110  
      * @see #multipleSessionsPerConnection
 111  
      */
 112  
     public Session getSession(boolean transacted, boolean topic) throws JMSException {
 113  
 
 114  0
         if (multipleSessionsPerConnection) {
 115  0
             return super.getSession(transacted, topic);
 116  
         } else {
 117  0
             UMOTransaction tx = TransactionCoordination.getInstance().getTransaction();
 118  
 
 119  
             // Check to see if we are already in a session.
 120  0
             Session session = getSessionFromTransaction();
 121  0
             if (session != null) {
 122  0
                 return session;
 123  
             }
 124  
 
 125  
             // Create a new database connection before creating a new session.
 126  
             Connection connection;
 127  
             try {
 128  0
                 connection = createConnection();
 129  
             }
 130  0
             catch (NamingException e) {
 131  0
                 throw new JMSException("Unable to open new database connection: " + e.getMessage());
 132  
             }
 133  0
             catch (InitialisationException e) {
 134  0
                 throw new JMSException("Unable to open new database connection: " + e.getMessage());
 135  0
             }
 136  
 
 137  
             // Create a new session.
 138  0
             logger.debug("Retrieving new jms session from connection");
 139  0
             session = getJmsSupport().createSession(connection, topic, transacted || tx != null,
 140  
                     getAcknowledgementMode(), isNoLocal());
 141  0
             if (tx != null) {
 142  0
                 logger.debug("Binding session " + session + " to current transaction " + tx);
 143  
                 try {
 144  0
                     tx.bindResource(connection, session);
 145  
                 }
 146  0
                 catch (TransactionException e) {
 147  0
                     throw new RuntimeException("Could not bind session to current transaction", e);
 148  0
                 }
 149  
             }
 150  0
             return session;
 151  
         }
 152  
     }
 153  
 
 154  
     /**
 155  
      * Oracle throws a "JMS-102: Feature not supported" error if any of these
 156  
      * "standard" properties are used.
 157  
      */
 158  
     public boolean supportsProperty(String property) {
 159  0
         return (!JmsConstants.JMS_REPLY_TO.equalsIgnoreCase(property) && !JmsConstants.JMS_TYPE.equalsIgnoreCase(property));
 160  
     }
 161  
 
 162  
     /**
 163  
      * If the incoming message is an XMLType, return it as a standard
 164  
      * {@code javax.jms.TextMessage}. If the incoming message is any other
 165  
      * AdtMessage, return it as a standard {@code javax.jms.ObjectMessage}.
 166  
      */
 167  
     public javax.jms.Message preProcessMessage(javax.jms.Message message, Session session) throws Exception {
 168  
         Object payload;
 169  
         javax.jms.Message newMessage;
 170  
 
 171  0
         if (message instanceof AdtMessage) {
 172  0
             payload = ((AdtMessage) message).getAdtPayload();
 173  
 
 174  0
             if (payload instanceof XMLType) {
 175  0
                 newMessage = session.createTextMessage(((XMLType) payload).getStringVal().trim());
 176  0
             } else if (payload instanceof Serializable) {
 177  0
                 newMessage = session.createObjectMessage((Serializable) payload);
 178  
             } else {
 179  0
                 throw new JMSException("The payload of the incoming AdtMessage must be serializable.");
 180  
             }
 181  
             // TODO Is there a better way to do this?
 182  0
             JmsMessageUtils.copyJMSProperties(message, newMessage, this);
 183  0
             return newMessage;
 184  
         } else {
 185  0
             return message;
 186  
         }
 187  
     }
 188  
 
 189  
     /**
 190  
      * Attempts to close the underlying JDBC connection before closing the JMS
 191  
      * session.
 192  
      *
 193  
      * @see org.mule.providers.jms.JmsConnector.close( javax.jms.Session)
 194  
      */
 195  
     public void close(Session session) throws JMSException {
 196  0
         if (session != null) {
 197  0
             java.sql.Connection conn = ((AQjmsSession) session).getDBConnection();
 198  
             try {
 199  0
                 if (conn != null && !conn.isClosed()) {
 200  0
                     conn.commit();
 201  0
                     conn.close();
 202  
                 }
 203  
             }
 204  0
             catch (SQLException e) {
 205  0
                 JMSException ex = new JMSException(e.getMessage());
 206  0
                 ex.setLinkedException(e);
 207  0
                 throw ex;
 208  0
             }
 209  
         }
 210  0
     }
 211  
 
 212  
     public abstract java.sql.Connection getJdbcConnection() throws JMSException;
 213  
 
 214  
     public boolean isMultipleSessionsPerConnection() {
 215  0
         return multipleSessionsPerConnection;
 216  
     }
 217  
 
 218  
     public void setMultipleSessionsPerConnection(boolean multipleSessionsPerConnection) {
 219  0
         this.multipleSessionsPerConnection = multipleSessionsPerConnection;
 220  0
     }
 221  
 
 222  
     /**
 223  
      * Oracle has two different factory classes: {@code AQjmsQueueConnectionFactory}
 224  
      * which implements {@code javax.jms.QueueConnectionFactory} and
 225  
      * {@code AQjmsTopicConnectionFactory} which implements
 226  
      * {@code javax.jms.TopicConnectionFactory} so there is no single class to return
 227  
      * in this method.
 228  
      *
 229  
      * @return null
 230  
      */
 231  
     protected ConnectionFactory createConnectionFactory() throws InitialisationException, NamingException {
 232  0
         return null;
 233  
     }
 234  
 
 235  
     public String getPayloadFactory()
 236  
     {
 237  0
         return payloadFactory;
 238  
     }
 239  
 
 240  
     public void setPayloadFactory(String payloadFactory)
 241  
     {
 242  0
         this.payloadFactory = payloadFactory;
 243  0
     }
 244  
 }