View Javadoc

1   /*
2    * $Id: AbstractMessageSplitter.java 19191 2010-08-25 21:05:23Z tcarlson $
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.routing.outbound;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleException;
16  import org.mule.api.MuleMessage;
17  import org.mule.api.processor.MessageProcessor;
18  import org.mule.api.processor.MessageRouter;
19  import org.mule.api.routing.CouldNotRouteOutboundMessageException;
20  import org.mule.api.routing.RoutingException;
21  import org.mule.routing.CorrelationMode;
22  
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  /**
29   * <code>AbstractMessageSplitter</code> is an outbound Message Splitter used to split
30   * the contents of a received message into sub parts that can be processed by other
31   * components. Each Part is fired as a separate event to each endpoint on the router. The
32   * targets can have filters on them to receive only certain message parts.
33   */
34  public abstract class AbstractMessageSplitter extends FilteringOutboundRouter implements MessageRouter
35  {
36      @Override
37      public MuleEvent route(MuleEvent event) throws RoutingException
38      {
39          MuleMessage message = event.getMessage();
40  
41          String correlationId = event.getFlowConstruct().getMessageInfoMapping().getCorrelationId(message);
42  
43          List<MuleEvent> results = new ArrayList<MuleEvent>();
44          int correlationSequence = 1;
45          SplitMessage splitMessage = getMessageParts(message, getRoutes());
46  
47          // Cache the properties here because for some message types getting the
48          // properties can be expensive
49          Map props = new HashMap();
50          for (String propertyKey : message.getOutboundPropertyNames())
51          {
52              Object value = message.getOutboundProperty(propertyKey);
53              if (value != null)
54              {
55                  props.put(propertyKey, value);
56              }
57          }
58  
59          for (int i = 0; i < splitMessage.size(); i++)
60          {
61              SplitMessage.MessagePart part = splitMessage.getPart(i);
62  
63              MuleMessage sendMessage;
64              if (part.getPart() instanceof MuleMessage)
65              {
66                  sendMessage = (MuleMessage) part.getPart();
67              }
68              else
69              {
70                  sendMessage = new DefaultMuleMessage(part.getPart(), props, muleContext);
71              }
72  
73              try
74              {
75                  if (enableCorrelation != CorrelationMode.NEVER)
76                  {
77                      boolean correlationSet = message.getCorrelationId() != null;
78                      if (!correlationSet && (enableCorrelation == CorrelationMode.IF_NOT_SET))
79                      {
80                          sendMessage.setCorrelationId(correlationId);
81                      }
82  
83                      // take correlation group size from the message properties, set by concrete 
84                      // message splitter implementations
85                      sendMessage.setCorrelationGroupSize(splitMessage.size());
86                      sendMessage.setCorrelationSequence(correlationSequence++);
87                  }
88  
89                  if (part.getEndpoint().getExchangePattern().hasResponse())
90                  {
91                      results.add(sendRequest(event, sendMessage, part.getEndpoint(), true));
92                  }
93                  else
94                  {
95                      sendRequest(event, sendMessage, part.getEndpoint(), false);
96                  }
97              }
98              catch (MuleException e)
99              {
100                 throw new CouldNotRouteOutboundMessageException(event, part.getEndpoint(), e);
101             }
102         }
103 
104         return resultsHandler.aggregateResults(results, event, muleContext);
105     }
106 
107 
108     /**
109      * Implementing classes should create a {@link org.mule.routing.outbound.SplitMessage} instance and for
110      * each part can associate an endpoint.
111      * Note that No state should be stored on the router itself. The {@link SplitMessage} provides the parts and
112      * endpoint mapping info in order for the correct dispatching to occur.
113      * <p/>
114      * If users do not want to associate a message part with an endpoint, but just dispatch parts over the targets in
115      * a round-robin way, they should use the {@link org.mule.routing.outbound.AbstractRoundRobinMessageSplitter} instead.
116      *
117      * @param message   the current message being processed
118      * @param endpoints A list of {@link org.mule.api.endpoint.OutboundEndpoint} that will be used to dispatch each of the parts
119      * @return a {@link org.mule.routing.outbound.SplitMessage} instance that contains the message parts and the
120      *         endpoint to associate with the message part.
121      * @see org.mule.routing.outbound.SplitMessage
122      * @see org.mule.routing.outbound.AbstractRoundRobinMessageSplitter
123      */
124     protected abstract SplitMessage getMessageParts(MuleMessage message, List <MessageProcessor> endpoints);
125 
126 }