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