View Javadoc

1   /*
2    * $Id: AbstractMessageSplitter.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.config.MuleProperties;
14  import org.mule.umo.UMOException;
15  import org.mule.umo.UMOMessage;
16  import org.mule.umo.UMOSession;
17  import org.mule.umo.endpoint.UMOEndpoint;
18  import org.mule.umo.routing.CouldNotRouteOutboundMessageException;
19  import org.mule.umo.routing.RoutingException;
20  
21  import java.util.Iterator;
22  import java.util.List;
23  
24  /**
25   * <code>AbstractMessageSplitter</code> is an outbound Message Splitter used to
26   * split the contents of a received message into sub parts that can be processed by
27   * other components. Each Part is fired as a separate event to each endpoint on the
28   * router. The endpoints can have filters on them to receive only certain message
29   * parts.
30   */
31  public abstract class AbstractMessageSplitter extends FilteringOutboundRouter
32  {
33      // Determines if the same endpoint will be matched multiple times until a
34      // match is not found. This should be set by overriding classes.
35      protected boolean multimatch = true;
36  
37      // flag which, if true, makes the splitter honour settings such as remoteSync and
38      // synchronous on the endpoint
39      protected boolean honorSynchronicity = false;
40  
41      public UMOMessage route(UMOMessage message, UMOSession session, boolean synchronous)
42          throws RoutingException
43      {
44          String correlationId = (String) propertyExtractor.getProperty(
45              MuleProperties.MULE_CORRELATION_ID_PROPERTY, message);
46  
47          this.initialise(message);
48  
49          UMOEndpoint endpoint;
50          UMOMessage result = null;
51          List list = getEndpoints();
52          int correlationSequence = 1;
53          for (Iterator iterator = list.iterator(); iterator.hasNext();)
54          {
55              endpoint = (UMOEndpoint) iterator.next();
56              message = getMessagePart(message, endpoint);
57              // TODO MULE-1378
58              if (message == null)
59              {
60                  // Log a warning if there are no messages for a given endpoint
61                  logger.warn("Message part is null for endpoint: " + endpoint.getEndpointURI().toString());
62              }
63  
64              // We'll keep looping to get all messages for the current endpoint
65              // before moving to the next endpoint
66              // This can be turned off by setting the multimatch flag to false
67              while (message != null)
68              {
69                  if (honorSynchronicity)
70                  {
71                      synchronous = endpoint.isSynchronous();
72                  }
73                  try
74                  {
75                      if (enableCorrelation != ENABLE_CORRELATION_NEVER)
76                      {
77                          boolean correlationSet = message.getCorrelationId() != null;
78                          if (!correlationSet && (enableCorrelation == ENABLE_CORRELATION_IF_NOT_SET))
79                          {
80                              message.setCorrelationId(correlationId);
81                          }
82  
83                          // take correlation group size from the message
84                          // properties, set by concrete message splitter
85                          // implementations
86                          final int groupSize = message.getCorrelationGroupSize();
87                          message.setCorrelationGroupSize(groupSize);
88                          message.setCorrelationSequence(correlationSequence++);
89                      }
90                      if (honorSynchronicity)
91                      {
92                          message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY,
93                              endpoint.isRemoteSync());
94                      }
95                      if (synchronous)
96                      {
97                          result = send(session, message, endpoint);
98                      }
99                      else
100                     {
101                         dispatch(session, message, endpoint);
102                     }
103                 }
104                 catch (UMOException e)
105                 {
106                     throw new CouldNotRouteOutboundMessageException(message, endpoint, e);
107                 }
108                 if (!multimatch)
109                 {
110                     break;
111                 }
112                 message = getMessagePart(message, endpoint);
113             }
114         }
115         return result;
116     }
117 
118     /**
119      * Template method that can be used to split the message up before the
120      * getMessagePart method is called .
121      * 
122      * @param message the message being routed
123      */
124     protected void initialise(UMOMessage message)
125     {
126         // nothing to do
127     }
128 
129     public boolean isHonorSynchronicity()
130     {
131         return honorSynchronicity;
132     }
133 
134     /**
135      * Sets the flag indicating whether the splitter honurs endpoint settings
136      * 
137      * @param honorSynchronicity flag setting
138      */
139     public void setHonorSynchronicity(boolean honorSynchronicity)
140     {
141         this.honorSynchronicity = honorSynchronicity;
142     }
143 
144     /**
145      * Retrieves a specific message part for the given endpoint. the message will
146      * then be routed via the provider. <p/> <strong>NOTE:</strong>Implementations
147      * must provide proper synchronization for shared state (payload, properties,
148      * etc.)
149      * 
150      * @param message the current message being processed
151      * @param endpoint the endpoint that will be used to route the resulting message
152      *            part
153      * @return the message part to dispatch
154      */
155     protected abstract UMOMessage getMessagePart(UMOMessage message, UMOEndpoint endpoint);
156 }