Clover coverage report - Lingo - 1.0-SNAPSHOT
Coverage timestamp: Fri May 13 2005 08:50:34 BST
file stats: LOC: 207   Methods: 14
NCLOC: 127   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
JmsServiceExporterSupport.java 62.5% 75.9% 57.1% 69.6%
coverage coverage
 1   
 /**
 2   
  * 
 3   
  * Copyright 2005 LogicBlaze, Inc.
 4   
  * 
 5   
  * Licensed under the Apache License, Version 2.0 (the "License"); 
 6   
  * you may not use this file except in compliance with the License. 
 7   
  * You may obtain a copy of the License at 
 8   
  * 
 9   
  * http://www.apache.org/licenses/LICENSE-2.0
 10   
  * 
 11   
  * Unless required by applicable law or agreed to in writing, software
 12   
  * distributed under the License is distributed on an "AS IS" BASIS, 
 13   
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14   
  * See the License for the specific language governing permissions and 
 15   
  * limitations under the License. 
 16   
  * 
 17   
  **/
 18   
 package org.logicblaze.lingo.jms;
 19   
 
 20   
 import org.logicblaze.lingo.LingoInvocation;
 21   
 import org.logicblaze.lingo.LingoRemoteInvocationFactory;
 22   
 import org.logicblaze.lingo.MetadataStrategy;
 23   
 import org.logicblaze.lingo.MethodMetadata;
 24   
 import org.logicblaze.lingo.SimpleMetadataStrategy;
 25   
 import org.logicblaze.lingo.jms.marshall.DefaultMarshaller;
 26   
 import org.logicblaze.lingo.jms.marshall.Marshaller;
 27   
 import org.apache.commons.logging.Log;
 28   
 import org.apache.commons.logging.LogFactory;
 29   
 import org.springframework.beans.factory.InitializingBean;
 30   
 import org.springframework.remoting.support.RemoteInvocation;
 31   
 import org.springframework.remoting.support.RemoteInvocationBasedExporter;
 32   
 import org.springframework.remoting.support.RemoteInvocationFactory;
 33   
 import org.springframework.remoting.support.RemoteInvocationResult;
 34   
 
 35   
 import javax.jms.JMSException;
 36   
 import javax.jms.Message;
 37   
 import javax.jms.MessageListener;
 38   
 import javax.jms.ObjectMessage;
 39   
 import javax.jms.Session;
 40   
 
 41   
 /**
 42   
  * @version $Revision: 1.1 $
 43   
  */
 44   
 public abstract class JmsServiceExporterSupport extends RemoteInvocationBasedExporter implements MessageListener, InitializingBean {
 45   
     private static final Log log = LogFactory.getLog(JmsServiceExporterSupport.class);
 46   
 
 47   
     protected Object proxy;
 48   
     private boolean ignoreFailures;
 49   
     private Marshaller marshaller;
 50   
     private MetadataStrategy metadataStrategy;
 51   
     private RemoteInvocationFactory responseInvocationFactory;
 52   
     private Requestor responseRequestor;
 53   
 
 54  21
     public void afterPropertiesSet() throws Exception {
 55  21
         this.proxy = getProxyForService();
 56  21
         if (proxy == null) {
 57  0
             throw new IllegalArgumentException("proxy is required");
 58   
         }
 59  21
         if (responseRequestor == null) {
 60  0
             throw new IllegalArgumentException("responseRequestor is required");
 61   
         }
 62  21
         if (marshaller == null) {
 63  14
             marshaller = new DefaultMarshaller();
 64   
         }
 65  21
         if (metadataStrategy == null) {
 66  21
             metadataStrategy = new SimpleMetadataStrategy(true);
 67   
         }
 68  21
         if (responseInvocationFactory == null) {
 69  21
             responseInvocationFactory = new LingoRemoteInvocationFactory(metadataStrategy);
 70   
         }
 71   
     }
 72   
 
 73  92
     public void onMessage(Message message) {
 74  92
         try {
 75  92
             RemoteInvocation invocation = marshaller.readRemoteInvocation(message);
 76  92
             if (invocation != null) {
 77  92
                 boolean oneway = false;
 78  92
                 if (invocation instanceof LingoInvocation) {
 79  92
                     LingoInvocation lingoInvocation = (LingoInvocation) invocation;
 80  92
                     oneway = lingoInvocation.getMetadata().isOneWay();
 81  92
                     introduceRemoteReferences(lingoInvocation, message);
 82   
                 }
 83  92
                 RemoteInvocationResult result = invokeAndCreateResult(invocation, this.proxy);
 84  92
                 if (!oneway) {
 85  87
                     writeRemoteInvocationResult(message, result);
 86   
                 }
 87   
             }
 88   
         }
 89   
         catch (JMSException e) {
 90  0
             onException(message, e);
 91   
         }
 92   
     }
 93   
 
 94   
     // Properties
 95   
     //-------------------------------------------------------------------------
 96  21
     public Requestor getResponseRequestor() {
 97  21
         return responseRequestor;
 98   
     }
 99   
 
 100  21
     public void setResponseRequestor(Requestor responseRequestor) {
 101  21
         this.responseRequestor = responseRequestor;
 102   
     }
 103   
 
 104  0
     public Marshaller getMarshaller() {
 105  0
         return marshaller;
 106   
     }
 107   
 
 108  7
     public void setMarshaller(Marshaller marshaller) {
 109  7
         this.marshaller = marshaller;
 110   
     }
 111   
 
 112  0
     public RemoteInvocationFactory getResponseInvocationFactory() {
 113  0
         return responseInvocationFactory;
 114   
     }
 115   
 
 116  0
     public void setResponseInvocationFactory(RemoteInvocationFactory responseInvocationFactory) {
 117  0
         this.responseInvocationFactory = responseInvocationFactory;
 118   
     }
 119   
 
 120  0
     public boolean isIgnoreFailures() {
 121  0
         return ignoreFailures;
 122   
     }
 123   
 
 124   
     /**
 125   
      * Sets whether or not failures should be ignored (and just logged) or thrown as
 126   
      * runtime exceptions into the JMS provider
 127   
      */
 128  0
     public void setIgnoreFailures(boolean ignoreFailures) {
 129  0
         this.ignoreFailures = ignoreFailures;
 130   
     }
 131   
 
 132   
 
 133   
     // Implementation methods
 134   
     //-------------------------------------------------------------------------
 135   
 
 136   
     /**
 137   
      * Send the given RemoteInvocationResult as a JMS message to the originator
 138   
      *
 139   
      * @param message current HTTP message
 140   
      * @param result  the RemoteInvocationResult object
 141   
      * @throws javax.jms.JMSException if thrown by trying to send the message
 142   
      */
 143   
     protected abstract void writeRemoteInvocationResult(Message message, RemoteInvocationResult result) throws JMSException;
 144   
 
 145   
     /**
 146   
      * Creates the invocation result response message
 147   
      *
 148   
      * @param session the JMS session to use
 149   
      * @param message the original request message, in case we want to attach any properties etc.
 150   
      * @param result  the invocation result
 151   
      * @return the message response to send
 152   
      * @throws javax.jms.JMSException if creating the messsage failed
 153   
      */
 154  87
     protected Message createResponseMessage(Session session, Message message, RemoteInvocationResult result) throws JMSException {
 155   
         // an alternative strategy could be to use XStream and text messages
 156   
         // though some JMS providers, like ActiveMQ, might do this kind of thing for us under the covers
 157  87
         if (result == null) {
 158  0
             throw new IllegalArgumentException("result cannot be null");
 159   
         }
 160  87
         ObjectMessage answer = session.createObjectMessage(result);
 161   
 
 162   
         // lets preserve the correlation ID
 163  87
         answer.setJMSCorrelationID(message.getJMSCorrelationID());
 164  87
         return answer;
 165   
     }
 166   
 
 167   
     /**
 168   
      * Lets replace any remote object correlation IDs with dynamic proxies
 169   
      *
 170   
      * @param invocation
 171   
      * @param requestMessage
 172   
      */
 173  92
     protected void introduceRemoteReferences(LingoInvocation invocation, Message requestMessage) throws JMSException {
 174  92
         MethodMetadata metadata = invocation.getMetadata();
 175  92
         Object[] arguments = invocation.getArguments();
 176  92
         Class[] parameterTypes = invocation.getParameterTypes();
 177  92
         for (int i = 0; i < parameterTypes.length; i++) {
 178  30
             if (metadata.isRemoteParameter(i)) {
 179  3
                 arguments[i] = createRemoteProxy(requestMessage, parameterTypes[i], arguments[i]);
 180   
             }
 181   
         }
 182   
     }
 183   
 
 184  3
     protected Object createRemoteProxy(Message message, Class parameterType, Object argument) throws JMSException {
 185  3
         JmsProxyFactoryBean factory = new JmsProxyFactoryBean();
 186  3
         factory.setDestination(message.getJMSReplyTo());
 187  3
         factory.setCorrelationID((String) argument);
 188  3
         factory.setRemoteInvocationFactory(responseInvocationFactory);
 189  3
         factory.setServiceInterface(parameterType);
 190  3
         factory.setRequestor(responseRequestor);
 191  3
         factory.afterPropertiesSet();
 192  3
         return factory.getObject();
 193   
     }
 194   
 
 195   
 
 196   
     /**
 197   
      * Handle the processing of an exception when processing an inbound messsage
 198   
      */
 199  0
     protected void onException(Message message, JMSException e) {
 200  0
         String text = "Failed to process inbound message due to: " + e + ". Message will be discarded: " + message;
 201  0
         log.info(text, e);
 202  0
         if (!ignoreFailures) {
 203  0
             throw new RuntimeException(text, e);
 204   
         }
 205   
     }
 206   
 }
 207