Clover coverage report - Lingo - 1.0-SNAPSHOT
Coverage timestamp: Fri May 13 2005 08:50:34 BST
file stats: LOC: 243   Methods: 21
NCLOC: 157   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
JmsClientInterceptor.java 79.2% 80% 71.4% 78.1%
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   
 
 19   
 package org.logicblaze.lingo.jms;
 20   
 
 21   
 import org.logicblaze.lingo.LingoInvocation;
 22   
 import org.logicblaze.lingo.LingoRemoteInvocationFactory;
 23   
 import org.logicblaze.lingo.MetadataStrategy;
 24   
 import org.logicblaze.lingo.MethodMetadata;
 25   
 import org.logicblaze.lingo.SimpleMetadataStrategy;
 26   
 import org.logicblaze.lingo.jms.impl.AsyncReplyHandler;
 27   
 import org.logicblaze.lingo.jms.impl.MultiplexingRequestor;
 28   
 import org.logicblaze.lingo.jms.marshall.DefaultMarshaller;
 29   
 import org.logicblaze.lingo.jms.marshall.Marshaller;
 30   
 import org.aopalliance.intercept.MethodInterceptor;
 31   
 import org.aopalliance.intercept.MethodInvocation;
 32   
 import org.springframework.aop.support.AopUtils;
 33   
 import org.springframework.beans.factory.DisposableBean;
 34   
 import org.springframework.beans.factory.InitializingBean;
 35   
 import org.springframework.remoting.RemoteAccessException;
 36   
 import org.springframework.remoting.support.RemoteInvocationBasedAccessor;
 37   
 import org.springframework.remoting.support.RemoteInvocationFactory;
 38   
 import org.springframework.remoting.support.RemoteInvocationResult;
 39   
 
 40   
 import javax.jms.ConnectionFactory;
 41   
 import javax.jms.Destination;
 42   
 import javax.jms.JMSException;
 43   
 import javax.jms.Message;
 44   
 import java.util.Map;
 45   
 import java.util.WeakHashMap;
 46   
 
 47   
 /**
 48   
  * Interceptor for accessing a JMS based service which must be configured with a
 49   
  * {@link org.logicblaze.lingo.LingoRemoteInvocationFactory} instance.
 50   
  *
 51   
  * @author James Strachan
 52   
  * @see #setServiceInterface
 53   
  * @see #setServiceUrl
 54   
  * @see JmsServiceExporter
 55   
  * @see JmsProxyFactoryBean
 56   
  */
 57   
 public class JmsClientInterceptor extends RemoteInvocationBasedAccessor
 58   
         implements MethodInterceptor, InitializingBean, DisposableBean {
 59   
 
 60   
     private Map remoteObjects = new WeakHashMap();
 61   
     private Requestor requestor;
 62   
     private Destination destination;
 63   
     private String correlationID;
 64   
     private Marshaller marshaller;
 65   
     private ConnectionFactory connectionFactory;
 66   
 
 67  27
     public JmsClientInterceptor() {
 68  27
         setRemoteInvocationFactory(createRemoteInvocationFactory());
 69   
     }
 70   
 
 71  0
     public JmsClientInterceptor(Requestor requestor) {
 72  0
         this.requestor = requestor;
 73  0
         setRemoteInvocationFactory(createRemoteInvocationFactory());
 74   
     }
 75   
 
 76  0
     public JmsClientInterceptor(Requestor requestor, LingoRemoteInvocationFactory factory) {
 77  0
         this.requestor = requestor;
 78  0
         setRemoteInvocationFactory(factory);
 79   
     }
 80   
 
 81  116
     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
 82  116
         if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
 83  9
             return "JMS invoker proxy for service URL [" + getServiceUrl() + "]";
 84   
         }
 85  107
         LingoInvocation invocation = (LingoInvocation) createRemoteInvocation(methodInvocation);
 86  107
         MethodMetadata metadata = invocation.getMetadata();
 87  107
         replaceRemoteReferences(invocation, metadata);
 88  107
         try {
 89  107
             Message requestMessage = marshaller.createRequestMessage(requestor, invocation);
 90  101
             populateHeaders(requestMessage);
 91  101
             if (metadata.isOneWay()) {
 92  14
                 requestor.oneWay(destination, requestMessage);
 93  14
                 return null;
 94   
             }
 95   
             else {
 96  87
                 Message response = requestor.request(destination, requestMessage);
 97  87
                 RemoteInvocationResult result = marshaller.extractInvocationResult(response);
 98  87
                 return recreateRemoteInvocationResult(result);
 99   
             }
 100   
         }
 101   
         catch (JMSException ex) {
 102  6
             throw new RemoteAccessException("Cannot access JMS invoker remote service at [" + getServiceUrl() + "]", ex);
 103   
         }
 104   
     }
 105   
 
 106  27
     public void afterPropertiesSet() throws JMSException {
 107  27
         RemoteInvocationFactory factory = getRemoteInvocationFactory();
 108  27
         if (!(factory instanceof LingoRemoteInvocationFactory)) {
 109  0
             throw new IllegalArgumentException("remoteInvocationFactory must be an instance of LingoRemoteInvocationFactory but was: " + factory);
 110   
 
 111   
         }
 112  27
         if (requestor == null) {
 113  4
             if (connectionFactory == null) {
 114  0
                 throw new IllegalArgumentException("requestor or connectionFactory is required");
 115   
             }
 116   
             else {
 117  4
                 requestor = MultiplexingRequestor.newInstance(connectionFactory, destination);
 118   
             }
 119   
         }
 120  27
         if (marshaller == null) {
 121   
             // default to standard JMS marshalling
 122  20
             marshaller = new DefaultMarshaller();
 123   
         }
 124   
     }
 125   
 
 126  0
     public void destroy() throws Exception {
 127  0
         requestor.close();
 128   
     }
 129   
 
 130   
     // Properties
 131   
     //-------------------------------------------------------------------------
 132  6
     public Requestor getRequestor() {
 133  6
         return requestor;
 134   
     }
 135   
 
 136  23
     public void setRequestor(Requestor requestor) {
 137  23
         this.requestor = requestor;
 138   
     }
 139   
 
 140  0
     public Destination getDestination() {
 141  0
         return destination;
 142   
     }
 143   
 
 144  7
     public void setDestination(Destination destination) {
 145  7
         this.destination = destination;
 146   
     }
 147   
 
 148  3
     public void setCorrelationID(String correlationID) {
 149  3
         this.correlationID = correlationID;
 150   
     }
 151   
 
 152  0
     public Marshaller getMarshaller() {
 153  0
         return marshaller;
 154   
     }
 155   
 
 156  7
     public void setMarshaller(Marshaller marshaller) {
 157  7
         this.marshaller = marshaller;
 158   
     }
 159   
 
 160  0
     public ConnectionFactory getConnectionFactory() {
 161  0
         return connectionFactory;
 162   
     }
 163   
 
 164   
     /**
 165   
      * Used to create a default {@link Requestor} if no requestor is explicitly
 166   
      * configured.
 167   
      */
 168  4
     public void setConnectionFactory(ConnectionFactory connectionFactory) {
 169  4
         this.connectionFactory = connectionFactory;
 170   
     }
 171   
 
 172   
     // Implementation methods
 173   
     //-------------------------------------------------------------------------
 174   
 
 175  101
     protected void populateHeaders(Message requestMessage) throws JMSException {
 176  101
         if (correlationID != null) {
 177  9
             requestMessage.setJMSCorrelationID(correlationID);
 178   
         }
 179   
     }
 180   
 
 181   
 
 182   
     /**
 183   
      * Recreate the invocation result contained in the given RemoteInvocationResult
 184   
      * object. The default implementation calls the default recreate method.
 185   
      * <p>Can be overridden in subclass to provide custom recreation, potentially
 186   
      * processing the returned result object.
 187   
      *
 188   
      * @param result the RemoteInvocationResult to recreate
 189   
      * @return a return value if the invocation result is a successful return
 190   
      * @throws Throwable if the invocation result is an exception
 191   
      * @see org.springframework.remoting.support.RemoteInvocationResult#recreate
 192   
      */
 193  87
     protected Object recreateRemoteInvocationResult(RemoteInvocationResult result) throws Throwable {
 194  87
         return result.recreate();
 195   
     }
 196   
 
 197  107
     protected void replaceRemoteReferences(LingoInvocation invocation, MethodMetadata metadata) {
 198  107
         Object[] arguments = invocation.getArguments();
 199  107
         Class[] parameterTypes = invocation.getParameterTypes();
 200  107
         for (int i = 0; i < parameterTypes.length; i++) {
 201  42
             if (metadata.isRemoteParameter(i)) {
 202  3
                 arguments[i] = remoteReference(parameterTypes[i], arguments[i]);
 203   
             }
 204   
         }
 205   
     }
 206   
 
 207  3
     protected Object remoteReference(Class type, Object value) {
 208  3
         if (value == null) {
 209  0
             return null;
 210   
         }
 211  3
         String correlationID = (String) remoteObjects.get(value);
 212  3
         if (correlationID == null) {
 213  3
             correlationID = requestor.createCorrelationID();
 214  3
             remoteObjects.put(value, correlationID);
 215   
         }
 216  3
         if (requestor instanceof MultiplexingRequestor) {
 217  3
             MultiplexingRequestor multiplexingRequestor = (MultiplexingRequestor) requestor;
 218  3
             multiplexingRequestor.registerHandler(correlationID, new AsyncReplyHandler(value, marshaller));
 219   
         }
 220   
         else {
 221  0
             throw new IllegalArgumentException("You can only pass remote references with a MultiplexingRequestor");
 222   
         }
 223  3
         return correlationID;
 224   
     }
 225   
 
 226   
     /**
 227   
      * Factory method to create a default lingo based invocation factory if none is configured
 228   
      */
 229  27
     protected LingoRemoteInvocationFactory createRemoteInvocationFactory() {
 230  27
         return new LingoRemoteInvocationFactory(createMetadataStrategy());
 231   
     }
 232   
 
 233   
     /**
 234   
      * Factory method to create a default metadata strategy if none is configured
 235   
      *
 236   
      * @return
 237   
      */
 238  27
     protected MetadataStrategy createMetadataStrategy() {
 239  27
         return new SimpleMetadataStrategy();
 240   
     }
 241   
 
 242   
 }
 243