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.Collection;
021 import java.util.List;
022
023 import javax.xml.bind.annotation.XmlAccessType;
024 import javax.xml.bind.annotation.XmlAccessorType;
025 import javax.xml.bind.annotation.XmlElement;
026 import javax.xml.bind.annotation.XmlElementRef;
027 import javax.xml.bind.annotation.XmlRootElement;
028 import javax.xml.bind.annotation.XmlTransient;
029
030 import org.apache.camel.CamelContext;
031 import org.apache.camel.Expression;
032 import org.apache.camel.Predicate;
033 import org.apache.camel.Processor;
034 import org.apache.camel.Route;
035 import org.apache.camel.builder.ErrorHandlerBuilder;
036 import org.apache.camel.builder.ExpressionClause;
037 import org.apache.camel.language.constant.ConstantLanguage;
038 import org.apache.camel.processor.CatchProcessor;
039 import org.apache.camel.processor.RedeliveryPolicy;
040 import org.apache.camel.spi.RouteContext;
041 import org.apache.camel.util.ObjectHelper;
042
043 import static org.apache.camel.builder.PredicateBuilder.toPredicate;
044
045 /**
046 * Represents an XML <onException/> element
047 *
048 * @version $Revision: 719980 $
049 */
050 @XmlRootElement(name = "onException")
051 @XmlAccessorType(XmlAccessType.FIELD)
052 public class ExceptionType extends ProcessorType<ProcessorType> {
053
054 @XmlElement(name = "exception")
055 private List<String> exceptions = new ArrayList<String>();
056 @XmlElement(name = "onWhen", required = false)
057 private WhenType onWhen;
058 @XmlElement(name = "redeliveryPolicy", required = false)
059 private RedeliveryPolicyType redeliveryPolicy;
060 @XmlElement(name = "handled", required = false)
061 private ExpressionSubElementType handled;
062 @XmlElementRef
063 private List<ProcessorType<?>> outputs = new ArrayList<ProcessorType<?>>();
064 @XmlTransient
065 private List<Class> exceptionClasses;
066 @XmlTransient
067 private Processor errorHandler;
068 @XmlTransient
069 private Predicate handledPolicy;
070
071 public ExceptionType() {
072 }
073
074 public ExceptionType(List<Class> exceptionClasses) {
075 this.exceptionClasses = exceptionClasses;
076 }
077
078 public ExceptionType(Class exceptionType) {
079 exceptionClasses = new ArrayList<Class>();
080 exceptionClasses.add(exceptionType);
081 }
082
083 @Override
084 public String toString() {
085 return "Exception[" + getExceptionClasses() + (onWhen != null ? " " + onWhen : "") + " -> " + getOutputs() + "]";
086 }
087
088 /**
089 * Catches an exception type.
090 */
091 @Override
092 public ExceptionType onException(Class exceptionType) {
093 getExceptionClasses().add(exceptionType);
094 return this;
095 }
096
097 /**
098 * Allows an exception handler to create a new redelivery policy for this exception type
099 * @param context the camel context
100 * @param parentPolicy the current redelivery policy
101 * @return a newly created redelivery policy, or return the original policy if no customization is required
102 * for this exception handler.
103 */
104 public RedeliveryPolicy createRedeliveryPolicy(CamelContext context, RedeliveryPolicy parentPolicy) {
105 if (redeliveryPolicy != null) {
106 return redeliveryPolicy.createRedeliveryPolicy(context, parentPolicy);
107 } else if (errorHandler != null) {
108 // lets create a new error handler that has no retries
109 RedeliveryPolicy answer = parentPolicy.copy();
110 answer.setMaximumRedeliveries(0);
111 return answer;
112 }
113 return parentPolicy;
114 }
115
116 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
117 setHandledFromExpressionType(routeContext);
118 // lets attach a processor to an error handler
119 errorHandler = routeContext.createProcessor(this);
120 ErrorHandlerBuilder builder = routeContext.getRoute().getErrorHandlerBuilder();
121 builder.addErrorHandlers(this);
122 }
123
124 @Override
125 public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
126 Processor childProcessor = routeContext.createProcessor(this);
127 return new CatchProcessor(getExceptionClasses(), childProcessor);
128 }
129
130
131 // Fluent API
132 //-------------------------------------------------------------------------
133 public ExceptionType handled(boolean handled) {
134 ConstantLanguage constant = new ConstantLanguage();
135 return handled(constant.createPredicate(Boolean.toString(handled)));
136 }
137
138 public ExceptionType handled(Predicate handled) {
139 setHandledPolicy(handled);
140 return this;
141 }
142
143 public ExceptionType handled(Expression handled) {
144 setHandledPolicy(toPredicate(handled));
145 return this;
146 }
147
148 public ExceptionType onWhen(Predicate predicate) {
149 setOnWhen(new WhenType(predicate));
150 return this;
151 }
152
153 public ExpressionClause<ExceptionType> onWhen() {
154 onWhen = new WhenType();
155 ExpressionClause<ExceptionType> clause = new ExpressionClause<ExceptionType>(this);
156 onWhen.setExpression(clause);
157 return clause;
158 }
159
160 public ExceptionType backOffMultiplier(double backOffMultiplier) {
161 getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
162 return this;
163 }
164
165 public ExceptionType collisionAvoidanceFactor(double collisionAvoidanceFactor) {
166 getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor);
167 return this;
168 }
169
170 public ExceptionType collisionAvoidancePercent(short collisionAvoidancePercent) {
171 getOrCreateRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
172 return this;
173 }
174
175 public ExceptionType initialRedeliveryDelay(long initialRedeliveryDelay) {
176 getOrCreateRedeliveryPolicy().initialRedeliveryDelay(initialRedeliveryDelay);
177 return this;
178 }
179
180 public ExceptionType retriesExhaustedLogLevel(LoggingLevel retriesExhaustedLogLevel) {
181 getOrCreateRedeliveryPolicy().retriesExhaustedLogLevel(retriesExhaustedLogLevel);
182 return this;
183 }
184
185 public ExceptionType retryAttemptedLogLevel(LoggingLevel retryAttemptedLogLevel) {
186 getOrCreateRedeliveryPolicy().retryAttemptedLogLevel(retryAttemptedLogLevel);
187 return this;
188 }
189
190 public ExceptionType maximumRedeliveries(int maximumRedeliveries) {
191 getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
192 return this;
193 }
194
195 public ExceptionType useCollisionAvoidance() {
196 getOrCreateRedeliveryPolicy().useCollisionAvoidance();
197 return this;
198 }
199
200 public ExceptionType useExponentialBackOff() {
201 getOrCreateRedeliveryPolicy().useExponentialBackOff();
202 return this;
203 }
204
205 public ExceptionType maximumRedeliveryDelay(long maximumRedeliveryDelay) {
206 getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
207 return this;
208 }
209
210 // Properties
211 //-------------------------------------------------------------------------
212 public List<ProcessorType<?>> getOutputs() {
213 return outputs;
214 }
215
216 public void setOutputs(List<ProcessorType<?>> outputs) {
217 this.outputs = outputs;
218 }
219
220 public List<Class> getExceptionClasses() {
221 if (exceptionClasses == null) {
222 exceptionClasses = createExceptionClasses();
223 }
224 return exceptionClasses;
225 }
226
227 public void setExceptionClasses(List<Class> exceptionClasses) {
228 this.exceptionClasses = exceptionClasses;
229 }
230
231 public List<String> getExceptions() {
232 return exceptions;
233 }
234
235 public void setExceptions(List<String> exceptions) {
236 this.exceptions = exceptions;
237 }
238
239 public Processor getErrorHandler() {
240 return errorHandler;
241 }
242
243 public RedeliveryPolicyType getRedeliveryPolicy() {
244 return redeliveryPolicy;
245 }
246
247 public void setRedeliveryPolicy(RedeliveryPolicyType redeliveryPolicy) {
248 this.redeliveryPolicy = redeliveryPolicy;
249 }
250
251 public Predicate getHandledPolicy() {
252 return handledPolicy;
253 }
254
255 public void setHandled(ExpressionSubElementType handled) {
256 this.handled = handled;
257 }
258
259 public ExpressionSubElementType getHandled() {
260 return handled;
261 }
262
263 private void setHandledFromExpressionType(RouteContext routeContext) {
264 if (getHandled() != null && handledPolicy == null && routeContext != null) {
265 handled(getHandled().createPredicate(routeContext));
266 }
267 }
268
269 public void setHandledPolicy(Predicate handledPolicy) {
270 this.handledPolicy = handledPolicy;
271 }
272
273 public WhenType getOnWhen() {
274 return onWhen;
275 }
276
277 public void setOnWhen(WhenType onWhen) {
278 this.onWhen = onWhen;
279 }
280
281 // Implementation methods
282 //-------------------------------------------------------------------------
283 protected RedeliveryPolicyType getOrCreateRedeliveryPolicy() {
284 if (redeliveryPolicy == null) {
285 redeliveryPolicy = new RedeliveryPolicyType();
286 }
287 return redeliveryPolicy;
288 }
289
290 protected List<Class> createExceptionClasses() {
291 List<String> list = getExceptions();
292 List<Class> answer = new ArrayList<Class>(list.size());
293 for (String name : list) {
294 Class type = ObjectHelper.loadClass(name, getClass().getClassLoader());
295 answer.add(type);
296 }
297 return answer;
298 }
299 }