Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DefaultMessageProcessorChainBuilder |
|
| 0.0;0 |
1 | /* | |
2 | * $Id: DefaultMessageProcessorChainBuilder.java 20781 2010-12-16 13:19:09Z dfeist $ | |
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.processor.chain; | |
12 | ||
13 | import org.mule.api.MuleException; | |
14 | import org.mule.api.construct.FlowConstruct; | |
15 | import org.mule.api.processor.InterceptingMessageProcessor; | |
16 | import org.mule.api.processor.MessageProcessor; | |
17 | import org.mule.api.processor.MessageProcessorBuilder; | |
18 | import org.mule.api.processor.MessageProcessorChain; | |
19 | ||
20 | import java.util.ArrayList; | |
21 | import java.util.Collections; | |
22 | import java.util.LinkedList; | |
23 | import java.util.List; | |
24 | ||
25 | /** | |
26 | * <p> | |
27 | * Constructs a chain of {@link MessageProcessor}s and wraps the invocation of the chain in a composite | |
28 | * MessageProcessor. Both MessageProcessors and InterceptingMessageProcessor's can be chained together | |
29 | * arbitrarily in a single chain. InterceptingMessageProcessors simply intercept the next MessageProcessor in | |
30 | * the chain. When other non-intercepting MessageProcessors are used an adapter is used internally to chain | |
31 | * the MessageProcessor with the next in the chain. | |
32 | * </p> | |
33 | * <p> | |
34 | * The MessageProcessor instance that this builder builds can be nested in other chains as required. | |
35 | * </p> | |
36 | */ | |
37 | 0 | public class DefaultMessageProcessorChainBuilder extends AbstractMessageProcessorChainBuilder |
38 | { | |
39 | ||
40 | public DefaultMessageProcessorChainBuilder() | |
41 | 0 | { |
42 | // empty | |
43 | 0 | } |
44 | ||
45 | public DefaultMessageProcessorChainBuilder(FlowConstruct flowConstruct) | |
46 | 0 | { |
47 | 0 | this.flowConstruct = flowConstruct; |
48 | 0 | } |
49 | ||
50 | /** | |
51 | * This builder supports the chaining together of message processors that intercept and also those that | |
52 | * don't. While one can iterate over message processor intercepting message processors need to be chained | |
53 | * together. One solution is make all message processors intercepting (via adaption) and chain them all | |
54 | * together, this results in huge stack traces and recursive calls with adaptor. The alternative is to | |
55 | * build the chain in such a way that we iterate when we can and chain where we need to. <br> | |
56 | * We iterate over the list of message processor to be chained together in reverse order collecting up | |
57 | * those that can be iterated over in a temporary list, as soon as we have an intercepting message | |
58 | * processor we create a DefaultMessageProcessorChain using the temporary list and set it as a listener of | |
59 | * the intercepting message processor and then we continue with the algorithm | |
60 | */ | |
61 | public MessageProcessorChain build() throws MuleException | |
62 | { | |
63 | 0 | LinkedList<MessageProcessor> tempList = new LinkedList<MessageProcessor>(); |
64 | ||
65 | // Start from last but one message processor and work backwards | |
66 | 0 | for (int i = processors.size() - 1; i >= 0; i--) |
67 | { | |
68 | 0 | MessageProcessor processor = initializeMessageProcessor(processors.get(i)); |
69 | 0 | if (processor instanceof InterceptingMessageProcessor) |
70 | { | |
71 | 0 | InterceptingMessageProcessor interceptingProcessor = (InterceptingMessageProcessor) processor; |
72 | // Processor is intercepting so we can't simply iterate | |
73 | 0 | if (i + 1 < processors.size()) |
74 | { | |
75 | // The current processor is not the last in the list | |
76 | 0 | if (tempList.isEmpty()) |
77 | { | |
78 | 0 | interceptingProcessor.setListener(initializeMessageProcessor(processors.get(i + 1))); |
79 | } | |
80 | 0 | else if (tempList.size() == 1) |
81 | { | |
82 | 0 | interceptingProcessor.setListener(tempList.get(0)); |
83 | } | |
84 | else | |
85 | { | |
86 | 0 | final DefaultMessageProcessorChain chain = new DefaultMessageProcessorChain( |
87 | "(inner iterating chain) of " + name, new ArrayList<MessageProcessor>(tempList)); | |
88 | 0 | interceptingProcessor.setListener(chain); |
89 | } | |
90 | } | |
91 | 0 | tempList = new LinkedList<MessageProcessor>(Collections.singletonList(processor)); |
92 | 0 | } |
93 | else | |
94 | { | |
95 | // Processor is not intercepting so we can invoke it using iteration | |
96 | // (add to temp list) | |
97 | 0 | tempList.addFirst(initializeMessageProcessor(processor)); |
98 | } | |
99 | } | |
100 | // Create the final chain using the current tempList after reserve iteration is complete. This temp | |
101 | // list contains the first n processors in the chain that are not intercepting.. with processor n+1 | |
102 | // having been injected as the listener of processor n | |
103 | 0 | final DefaultMessageProcessorChain chain = new DefaultMessageProcessorChain(name, |
104 | new ArrayList<MessageProcessor>(tempList)); | |
105 | ||
106 | // Wrap with something that can apply lifecycle to all processors which are otherwise not visable from | |
107 | // DefaultMessageProcessorChain | |
108 | 0 | return new InterceptingChainLifecycleWrapper(chain, processors, "wrapper for " + name); |
109 | } | |
110 | ||
111 | public DefaultMessageProcessorChainBuilder chain(MessageProcessor... processors) | |
112 | { | |
113 | 0 | for (MessageProcessor messageProcessor : processors) |
114 | { | |
115 | 0 | this.processors.add(messageProcessor); |
116 | } | |
117 | 0 | return this; |
118 | } | |
119 | ||
120 | public DefaultMessageProcessorChainBuilder chain(List<MessageProcessor> processors) | |
121 | { | |
122 | 0 | if (processors != null) |
123 | { | |
124 | 0 | this.processors.addAll(processors); |
125 | } | |
126 | 0 | return this; |
127 | } | |
128 | ||
129 | public DefaultMessageProcessorChainBuilder chain(MessageProcessorBuilder... builders) | |
130 | { | |
131 | 0 | for (MessageProcessorBuilder messageProcessorBuilder : builders) |
132 | { | |
133 | 0 | this.processors.add(messageProcessorBuilder); |
134 | } | |
135 | 0 | return this; |
136 | } | |
137 | ||
138 | public DefaultMessageProcessorChainBuilder chainBefore(MessageProcessor processor) | |
139 | { | |
140 | 0 | this.processors.add(0, processor); |
141 | 0 | return this; |
142 | } | |
143 | ||
144 | public DefaultMessageProcessorChainBuilder chainBefore(MessageProcessorBuilder builder) | |
145 | { | |
146 | 0 | this.processors.add(0, builder); |
147 | 0 | return this; |
148 | } | |
149 | } |