001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.model;
018
019 import java.util.ArrayList;
020 import java.util.Arrays;
021 import java.util.Collection;
022 import java.util.List;
023
024 import javax.xml.bind.annotation.XmlAccessType;
025 import javax.xml.bind.annotation.XmlAccessorType;
026 import javax.xml.bind.annotation.XmlAttribute;
027 import javax.xml.bind.annotation.XmlElement;
028 import javax.xml.bind.annotation.XmlElementRef;
029 import javax.xml.bind.annotation.XmlElements;
030 import javax.xml.bind.annotation.XmlRootElement;
031
032 import org.apache.camel.Expression;
033 import org.apache.camel.Processor;
034 import org.apache.camel.model.loadbalancer.FailoverLoadBalancerDefinition;
035 import org.apache.camel.model.loadbalancer.RandomLoadBalancerDefinition;
036 import org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition;
037 import org.apache.camel.model.loadbalancer.StickyLoadBalancerDefinition;
038 import org.apache.camel.model.loadbalancer.TopicLoadBalancerDefinition;
039 import org.apache.camel.processor.SendProcessor;
040 import org.apache.camel.processor.loadbalancer.FailOverLoadBalancer;
041 import org.apache.camel.processor.loadbalancer.LoadBalancer;
042 import org.apache.camel.processor.loadbalancer.RandomLoadBalancer;
043 import org.apache.camel.processor.loadbalancer.RoundRobinLoadBalancer;
044 import org.apache.camel.processor.loadbalancer.StickyLoadBalancer;
045 import org.apache.camel.processor.loadbalancer.TopicLoadBalancer;
046 import org.apache.camel.spi.RouteContext;
047 import org.apache.camel.util.CollectionStringBuffer;
048
049 /**
050 * Represents an XML <loadBalance/> element
051 */
052 @XmlRootElement(name = "loadBalance")
053 @XmlAccessorType(XmlAccessType.FIELD)
054 public class LoadBalanceDefinition extends ProcessorDefinition<LoadBalanceDefinition> {
055 @XmlAttribute(required = false)
056 private String ref;
057
058 @XmlElements({
059 @XmlElement(required = false, name = "failover", type = FailoverLoadBalancerDefinition.class),
060 @XmlElement(required = false, name = "random", type = RandomLoadBalancerDefinition.class),
061 @XmlElement(required = false, name = "roundRobin", type = RoundRobinLoadBalancerDefinition.class),
062 @XmlElement(required = false, name = "sticky", type = StickyLoadBalancerDefinition.class),
063 @XmlElement(required = false, name = "topic", type = TopicLoadBalancerDefinition.class)}
064 )
065 private LoadBalancerDefinition loadBalancerType;
066
067 @XmlElementRef
068 private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
069
070 public LoadBalanceDefinition() {
071 }
072
073 @Override
074 public String getShortName() {
075 return "loadbalance";
076 }
077
078 public List<ProcessorDefinition> getOutputs() {
079 return outputs;
080 }
081
082 public void setOutputs(List<ProcessorDefinition> outputs) {
083 this.outputs = outputs;
084 if (outputs != null) {
085 for (ProcessorDefinition output : outputs) {
086 configureChild(output);
087 }
088 }
089 }
090
091 public String getRef() {
092 return ref;
093 }
094
095 public void setRef(String ref) {
096 this.ref = ref;
097 }
098
099 public LoadBalancerDefinition getLoadBalancerType() {
100 return loadBalancerType;
101 }
102
103 public void setLoadBalancerType(LoadBalancerDefinition loadbalancer) {
104 loadBalancerType = loadbalancer;
105 }
106
107 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition> outputs)
108 throws Exception {
109 LoadBalancer loadBalancer = LoadBalancerDefinition.getLoadBalancer(routeContext, loadBalancerType, ref);
110 for (ProcessorDefinition processorType : outputs) {
111 // The outputs should be the SendProcessor
112 SendProcessor processor = (SendProcessor) processorType.createProcessor(routeContext);
113 loadBalancer.addProcessor(processor);
114 }
115 return loadBalancer;
116 }
117
118 @Override
119 public Processor createProcessor(RouteContext routeContext) throws Exception {
120 LoadBalancer loadBalancer = LoadBalancerDefinition.getLoadBalancer(routeContext, loadBalancerType, ref);
121 for (ProcessorDefinition processorType : getOutputs()) {
122 Processor processor = processorType.createProcessor(routeContext);
123 processor = wrapProcessor(routeContext, processor);
124 loadBalancer.addProcessor(processor);
125 }
126
127 return loadBalancer;
128 }
129
130 // Fluent API
131 // -------------------------------------------------------------------------
132
133 /**
134 * Uses a custom load balancer
135 *
136 * @param loadBalancer the load balancer
137 * @return the builder
138 */
139 public LoadBalanceDefinition loadBalance(LoadBalancer loadBalancer) {
140 loadBalancerType = new LoadBalancerDefinition(loadBalancer);
141 return this;
142 }
143
144 /**
145 * Uses fail over load balancer
146 *
147 * @return the builder
148 */
149 public LoadBalanceDefinition failover() {
150 loadBalancerType = new LoadBalancerDefinition(new FailOverLoadBalancer());
151 return this;
152 }
153
154 /**
155 * Uses fail over load balancer
156 *
157 * @param exceptions exception classes which we want to failover if one of them was thrown
158 * @return the builder
159 */
160 public LoadBalanceDefinition failover(Class... exceptions) {
161 loadBalancerType = new LoadBalancerDefinition(new FailOverLoadBalancer(Arrays.asList(exceptions)));
162 return this;
163 }
164
165 /**
166 * Uses round robin load balancer
167 *
168 * @return the builder
169 */
170 public LoadBalanceDefinition roundRobin() {
171 loadBalancerType = new LoadBalancerDefinition(new RoundRobinLoadBalancer());
172 return this;
173 }
174
175 /**
176 * Uses random load balancer
177 * @return the builder
178 */
179 public LoadBalanceDefinition random() {
180 loadBalancerType = new LoadBalancerDefinition(new RandomLoadBalancer());
181 return this;
182 }
183
184 /**
185 * Uses sticky load balancer
186 *
187 * @param correlationExpression the expression for correlation
188 * @return the builder
189 */
190 public LoadBalanceDefinition sticky(Expression correlationExpression) {
191 loadBalancerType = new LoadBalancerDefinition(new StickyLoadBalancer(correlationExpression));
192 return this;
193 }
194
195 /**
196 * Uses topic load balancer
197 *
198 * @return the builder
199 */
200 public LoadBalanceDefinition topic() {
201 loadBalancerType = new LoadBalancerDefinition(new TopicLoadBalancer());
202 return this;
203 }
204
205 @Override
206 public String getLabel() {
207 CollectionStringBuffer buffer = new CollectionStringBuffer();
208 List<ProcessorDefinition> list = getOutputs();
209 for (ProcessorDefinition processorType : list) {
210 buffer.append(processorType.getLabel());
211 }
212 return buffer.toString();
213 }
214
215 @Override
216 public String toString() {
217 if (loadBalancerType != null) {
218 return "LoadBalanceType[" + loadBalancerType + ", " + getOutputs() + "]";
219 } else {
220 return "LoadBalanceType[ref:" + ref + ", " + getOutputs() + "]";
221 }
222 }
223
224 }