View Javadoc

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