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    }