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