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 }