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