Coverage Report - org.mule.construct.Validator
 
Classes in this File Line Coverage Branch Coverage Complexity
Validator
0%
0/71
0%
0/18
0
Validator$1
N/A
N/A
0
Validator$ErrorAwareEventReturningMessageProcessor
0%
0/11
0%
0/2
0
Validator$ErrorExpressionTransformerMessageProcessor
0%
0/8
0%
0/2
0
 
 1  
 /*
 2  
  * $Id: Validator.java 20320 2010-11-24 15:03:31Z dfeist $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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  
 package org.mule.construct;
 12  
 
 13  
 import org.mule.MessageExchangePattern;
 14  
 import org.mule.RequestContext;
 15  
 import org.mule.api.ExceptionPayload;
 16  
 import org.mule.api.MuleContext;
 17  
 import org.mule.api.MuleEvent;
 18  
 import org.mule.api.MuleException;
 19  
 import org.mule.api.MuleMessage;
 20  
 import org.mule.api.MuleRuntimeException;
 21  
 import org.mule.api.construct.FlowConstructInvalidException;
 22  
 import org.mule.api.endpoint.InboundEndpoint;
 23  
 import org.mule.api.endpoint.OutboundEndpoint;
 24  
 import org.mule.api.lifecycle.InitialisationException;
 25  
 import org.mule.api.processor.MessageProcessor;
 26  
 import org.mule.api.processor.MessageProcessorChainBuilder;
 27  
 import org.mule.api.routing.filter.Filter;
 28  
 import org.mule.api.source.MessageSource;
 29  
 import org.mule.config.i18n.MessageFactory;
 30  
 import org.mule.construct.processor.FlowConstructStatisticsMessageProcessor;
 31  
 import org.mule.expression.ExpressionConfig;
 32  
 import org.mule.expression.transformers.ExpressionArgument;
 33  
 import org.mule.expression.transformers.ExpressionTransformer;
 34  
 import org.mule.interceptor.LoggingInterceptor;
 35  
 import org.mule.interceptor.ProcessingTimeInterceptor;
 36  
 import org.mule.message.DefaultExceptionPayload;
 37  
 import org.mule.processor.AbstractInterceptingMessageProcessor;
 38  
 import org.mule.processor.ResponseMessageProcessorAdapter;
 39  
 import org.mule.routing.ChoiceRouter;
 40  
 import org.mule.util.StringUtils;
 41  
 
 42  
 import org.apache.commons.lang.Validate;
 43  
 
 44  0
 public class Validator extends AbstractFlowConstruct
 45  
 {
 46  
     private final OutboundEndpoint outboundEndpoint;
 47  
     private final Filter validationFilter;
 48  
     private final String ackExpression;
 49  
     private final String nackExpression;
 50  
     private final String errorExpression;
 51  
 
 52  
     public Validator(String name,
 53  
                      MuleContext muleContext,
 54  
                      MessageSource messageSource,
 55  
                      OutboundEndpoint outboundEndpoint,
 56  
                      Filter validationFilter,
 57  
                      String ackExpression,
 58  
                      String nackExpression)
 59  
     {
 60  0
         this(name, muleContext, messageSource, outboundEndpoint, validationFilter, ackExpression,
 61  
             nackExpression, null);
 62  0
     }
 63  
 
 64  
     public Validator(String name,
 65  
                      MuleContext muleContext,
 66  
                      MessageSource messageSource,
 67  
                      OutboundEndpoint outboundEndpoint,
 68  
                      Filter validationFilter,
 69  
                      String ackExpression,
 70  
                      String nackExpression,
 71  
                      String errorExpression)
 72  
     {
 73  0
         super(name, muleContext);
 74  
 
 75  0
         Validate.notNull(messageSource, "messageSource can't be null");
 76  0
         Validate.notNull(outboundEndpoint, "outboundEndpoint can't be null");
 77  0
         Validate.notNull(validationFilter, "validationFilter can't be null");
 78  0
         Validate.notEmpty(ackExpression, "ackExpression can't be empty");
 79  0
         Validate.notEmpty(nackExpression, "nackExpression can't be empty");
 80  
 
 81  0
         this.messageSource = messageSource;
 82  0
         this.outboundEndpoint = outboundEndpoint;
 83  0
         this.validationFilter = validationFilter;
 84  0
         this.ackExpression = ackExpression;
 85  0
         this.nackExpression = nackExpression;
 86  0
         this.errorExpression = errorExpression;
 87  0
     }
 88  
 
 89  
     @Override
 90  
     protected void configureMessageProcessors(MessageProcessorChainBuilder builder)
 91  
     {
 92  0
         builder.chain(new ProcessingTimeInterceptor());
 93  0
         builder.chain(new LoggingInterceptor());
 94  0
         builder.chain(new FlowConstructStatisticsMessageProcessor());
 95  
 
 96  0
         final ErrorAwareEventReturningMessageProcessor outboundMessageProcessor = new ErrorAwareEventReturningMessageProcessor();
 97  0
         outboundMessageProcessor.setListener(outboundEndpoint);
 98  
 
 99  0
         final ResponseMessageProcessorAdapter ackResponseMessageProcessor = new ResponseMessageProcessorAdapter();
 100  0
         ackResponseMessageProcessor.setListener(outboundMessageProcessor);
 101  0
         ackResponseMessageProcessor.setProcessor(getExpressionTransformer(getName() + "-ack-expression",
 102  
             ackExpression));
 103  
 
 104  0
         MessageProcessor validRouteMessageProcessor = ackResponseMessageProcessor;
 105  
 
 106  0
         if (hasErrorExpression())
 107  
         {
 108  0
             final ErrorExpressionTransformerMessageProcessor errorResponseMessageProcessor = new ErrorExpressionTransformerMessageProcessor(
 109  
                 getExpressionTransformer(getName() + "-error-expression", errorExpression));
 110  0
             errorResponseMessageProcessor.setListener(ackResponseMessageProcessor);
 111  0
             validRouteMessageProcessor = errorResponseMessageProcessor;
 112  
         }
 113  
 
 114  
         // a simple success/failure choice router determines which response to return
 115  0
         final ChoiceRouter choiceRouter = new ChoiceRouter();
 116  0
         choiceRouter.addRoute(validRouteMessageProcessor, validationFilter);
 117  0
         choiceRouter.setDefaultRoute(getExpressionTransformer(getName() + "-nack-expression", nackExpression));
 118  0
         builder.chain(choiceRouter);
 119  0
     }
 120  
 
 121  
     @Override
 122  
     protected void validateConstruct() throws FlowConstructInvalidException
 123  
     {
 124  0
         super.validateConstruct();
 125  
 
 126  0
         validateMessageSource();
 127  0
         validateOutboundEndpoint();
 128  0
         validateExpression(ackExpression);
 129  0
         validateExpression(nackExpression);
 130  
 
 131  0
         if (hasErrorExpression())
 132  
         {
 133  0
             validateExpression(errorExpression);
 134  
         }
 135  0
     }
 136  
 
 137  
     private void validateMessageSource() throws FlowConstructInvalidException
 138  
     {
 139  0
         if ((messageSource instanceof InboundEndpoint)
 140  
             && (!((InboundEndpoint) messageSource).getExchangePattern().equals(
 141  
                 MessageExchangePattern.REQUEST_RESPONSE)))
 142  
         {
 143  0
             throw new FlowConstructInvalidException(
 144  
                 MessageFactory.createStaticMessage("Validator only works with a request-response inbound endpoint."),
 145  
                 this);
 146  
         }
 147  0
     }
 148  
 
 149  
     private void validateOutboundEndpoint() throws FlowConstructInvalidException
 150  
     {
 151  0
         if ((hasErrorExpression())
 152  
             && (!outboundEndpoint.getExchangePattern().equals(MessageExchangePattern.REQUEST_RESPONSE)))
 153  
         {
 154  0
             throw new FlowConstructInvalidException(
 155  
                 MessageFactory.createStaticMessage("Validator with an error expression only works with a request-response outbound endpoint."),
 156  
                 this);
 157  
         }
 158  0
     }
 159  
 
 160  
     protected boolean hasErrorExpression()
 161  
     {
 162  0
         return StringUtils.isNotBlank(errorExpression);
 163  
     }
 164  
 
 165  
     private void validateExpression(String expression) throws FlowConstructInvalidException
 166  
     {
 167  0
         if (!muleContext.getExpressionManager().isExpression(expression))
 168  
         {
 169  0
             throw new FlowConstructInvalidException(
 170  
                 MessageFactory.createStaticMessage("Invalid expression in Validator: " + expression), this);
 171  
         }
 172  0
     }
 173  
 
 174  
     private ExpressionTransformer getExpressionTransformer(String name, String expression)
 175  
     {
 176  0
         final ExpressionConfig expressionConfig = new ExpressionConfig();
 177  0
         expressionConfig.parse(expression);
 178  
 
 179  0
         final ExpressionArgument expressionArgument = new ExpressionArgument(name, expressionConfig, false);
 180  0
         expressionArgument.setMuleContext(muleContext);
 181  
 
 182  0
         final ExpressionTransformer expressionTransformer = new ExpressionTransformer();
 183  0
         expressionTransformer.setMuleContext(muleContext);
 184  0
         expressionTransformer.addArgument(expressionArgument);
 185  
 
 186  
         try
 187  
         {
 188  0
             expressionTransformer.initialise();
 189  
         }
 190  0
         catch (final InitialisationException ie)
 191  
         {
 192  0
             throw new MuleRuntimeException(ie);
 193  0
         }
 194  
 
 195  0
         return expressionTransformer;
 196  
     }
 197  
 
 198  
     private static class ErrorExpressionTransformerMessageProcessor extends
 199  
         AbstractInterceptingMessageProcessor
 200  
     {
 201  
         private final ExpressionTransformer errorExpressionTransformer;
 202  
 
 203  
         public ErrorExpressionTransformerMessageProcessor(ExpressionTransformer errorExpressionTransformer)
 204  0
         {
 205  0
             this.errorExpressionTransformer = errorExpressionTransformer;
 206  0
         }
 207  
 
 208  
         public MuleEvent process(MuleEvent event) throws MuleException
 209  
         {
 210  0
             final MuleEvent nextResult = super.processNext(event);
 211  
 
 212  0
             final ExceptionPayload nextResultMessageExceptionPayload = getExceptionPayload(nextResult);
 213  
 
 214  0
             if (nextResultMessageExceptionPayload != null)
 215  
             {
 216  0
                 return errorExpressionTransformer.process(event);
 217  
             }
 218  
 
 219  0
             return nextResult;
 220  
         }
 221  
     }
 222  
 
 223  0
     private static class ErrorAwareEventReturningMessageProcessor extends
 224  
         AbstractInterceptingMessageProcessor
 225  
     {
 226  
         /*
 227  
          * Returns the incoming event whatever the outcome of the rest of the chain
 228  
          * maybe. Sets an exception payload on the incoming event if an error
 229  
          * occurred downstream.
 230  
          */
 231  
         public MuleEvent process(MuleEvent event) throws MuleException
 232  
         {
 233  0
             final MuleEvent result = RequestContext.cloneAndUpdateEventEndpoint(event, this);
 234  
 
 235  
             try
 236  
             {
 237  0
                 final MuleEvent nextResult = super.processNext(event);
 238  
 
 239  0
                 final ExceptionPayload nextResultMessageExceptionPayload = getExceptionPayload(nextResult);
 240  
 
 241  0
                 if (nextResultMessageExceptionPayload != null)
 242  
                 {
 243  0
                     result.getMessage().setExceptionPayload(nextResultMessageExceptionPayload);
 244  
                 }
 245  
             }
 246  0
             catch (final MuleException me)
 247  
             {
 248  0
                 logger.error(me);
 249  0
                 result.getMessage().setExceptionPayload(new DefaultExceptionPayload(me));
 250  0
             }
 251  
 
 252  0
             return result;
 253  
         }
 254  
     }
 255  
 
 256  
     private static ExceptionPayload getExceptionPayload(MuleEvent event)
 257  
     {
 258  0
         if (event == null)
 259  
         {
 260  0
             return null;
 261  
         }
 262  
 
 263  0
         final MuleMessage message = event.getMessage();
 264  0
         if (message == null)
 265  
         {
 266  0
             return null;
 267  
         }
 268  
 
 269  0
         return message.getExceptionPayload();
 270  
     }
 271  
 
 272  
     @Override
 273  
     public String getConstructType()
 274  
     {
 275  0
         return "Validator";
 276  
     }
 277  
 }