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: 56884 $
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 maximumRedeliveries(int maximumRedeliveries) {
164 getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
165 return this;
166 }
167
168 public ExceptionType useCollisionAvoidance() {
169 getOrCreateRedeliveryPolicy().useCollisionAvoidance();
170 return this;
171 }
172
173 public ExceptionType useExponentialBackOff() {
174 getOrCreateRedeliveryPolicy().useExponentialBackOff();
175 return this;
176 }
177
178 public ExceptionType maximumRedeliveryDelay(long maximumRedeliveryDelay) {
179 getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
180 return this;
181 }
182
183 // Properties
184 //-------------------------------------------------------------------------
185 public List<ProcessorType<?>> getOutputs() {
186 return outputs;
187 }
188
189 public void setOutputs(List<ProcessorType<?>> outputs) {
190 this.outputs = outputs;
191 }
192
193 public List<Class> getExceptionClasses() {
194 if (exceptionClasses == null) {
195 exceptionClasses = createExceptionClasses();
196 }
197 return exceptionClasses;
198 }
199
200 public void setExceptionClasses(List<Class> exceptionClasses) {
201 this.exceptionClasses = exceptionClasses;
202 }
203
204 public List<String> getExceptions() {
205 return exceptions;
206 }
207
208 public void setExceptions(List<String> exceptions) {
209 this.exceptions = exceptions;
210 }
211
212 public Processor getErrorHandler() {
213 return errorHandler;
214 }
215
216 public RedeliveryPolicyType getRedeliveryPolicy() {
217 return redeliveryPolicy;
218 }
219
220 public void setRedeliveryPolicy(RedeliveryPolicyType redeliveryPolicy) {
221 this.redeliveryPolicy = redeliveryPolicy;
222 }
223
224 public Predicate getHandledPolicy() {
225 return handledPolicy;
226 }
227
228 public void setHandled(ExpressionSubElementType handled) {
229 this.handled = handled;
230 }
231
232 public ExpressionSubElementType getHandled() {
233 return handled;
234 }
235
236 private void setHandledFromExpressionType(RouteContext routeContext) {
237 if (getHandled() != null && handledPolicy == null && routeContext != null) {
238 handled(getHandled().createPredicate(routeContext));
239 }
240 }
241
242 public void setHandledPolicy(Predicate handledPolicy) {
243 this.handledPolicy = handledPolicy;
244 }
245
246 // Implementation methods
247 //-------------------------------------------------------------------------
248 protected RedeliveryPolicyType getOrCreateRedeliveryPolicy() {
249 if (redeliveryPolicy == null) {
250 redeliveryPolicy = new RedeliveryPolicyType();
251 }
252 return redeliveryPolicy;
253 }
254
255 protected List<Class> createExceptionClasses() {
256 List<String> list = getExceptions();
257 List<Class> answer = new ArrayList<Class>(list.size());
258 for (String name : list) {
259 Class type = ObjectHelper.loadClass(name, getClass().getClassLoader());
260 answer.add(type);
261 }
262 return answer;
263 }
264 }