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.Processor;
031    import org.apache.camel.Route;
032    import org.apache.camel.builder.ErrorHandlerBuilder;
033    import org.apache.camel.processor.CatchProcessor;
034    import org.apache.camel.processor.RedeliveryPolicy;
035    import org.apache.camel.spi.RouteContext;
036    import org.apache.camel.util.ObjectHelper;
037    
038    /**
039     * Represents an XML <onException/> element
040     *
041     * @version $Revision: 46235 $
042     */
043    @XmlRootElement(name = "onException")
044    @XmlAccessorType(XmlAccessType.FIELD)
045    public class ExceptionType extends ProcessorType<ProcessorType> {
046    
047        @XmlElement(name = "exception")
048        private List<String> exceptions = new ArrayList<String>();
049        @XmlElement(name = "redeliveryPolicy", required = false)
050        private RedeliveryPolicyType redeliveryPolicy;
051        @XmlElementRef
052        private List<ProcessorType<?>> outputs = new ArrayList<ProcessorType<?>>();
053        @XmlTransient
054        private List<Class> exceptionClasses;
055        @XmlTransient
056        private Processor errorHandler;
057    
058        public ExceptionType() {
059        }
060    
061        public ExceptionType(List<Class> exceptionClasses) {
062            this.exceptionClasses = exceptionClasses;
063        }
064    
065        public ExceptionType(Class exceptionType) {
066            exceptionClasses = new ArrayList<Class>();
067            exceptionClasses.add(exceptionType);
068        }
069    
070        @Override
071        public String toString() {
072            return "Exception[ " + getExceptionClasses() + " -> " + getOutputs() + "]";
073        }
074    
075        /**
076         * Allows an exception handler to create a new redelivery policy for this exception type
077         * @param parentPolicy the current redelivery policy
078         * @return a newly created redelivery policy, or return the original policy if no customization is required
079         * for this exception handler.
080         */
081        public RedeliveryPolicy createRedeliveryPolicy(RedeliveryPolicy parentPolicy) {
082            if (redeliveryPolicy != null) {
083                return redeliveryPolicy.createRedeliveryPolicy(parentPolicy);
084            } else if (errorHandler != null) {
085                // lets create a new error handler that has no retries
086                RedeliveryPolicy answer = parentPolicy.copy();
087                answer.setMaximumRedeliveries(0);
088                return answer;
089            }
090            return parentPolicy;
091        }
092    
093        public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
094            // lets attach a processor to an error handler
095            errorHandler = routeContext.createProcessor(this);
096            ErrorHandlerBuilder builder = routeContext.getRoute().getErrorHandlerBuilder();
097            builder.addErrorHandlers(this);
098        }
099    
100        @Override
101        public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
102            Processor childProcessor = routeContext.createProcessor(this);
103            return new CatchProcessor(getExceptionClasses(), childProcessor);
104        }
105    
106    
107        // Fluent API
108        //-------------------------------------------------------------------------
109        public ExceptionType backOffMultiplier(double backOffMultiplier) {
110            getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
111            return this;
112        }
113    
114        public ExceptionType collisionAvoidanceFactor(double collisionAvoidanceFactor) {
115            getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor);
116            return this;
117        }
118    
119        public ExceptionType collisionAvoidancePercent(short collisionAvoidancePercent) {
120            getOrCreateRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
121            return this;
122        }
123    
124        public ExceptionType initialRedeliveryDelay(long initialRedeliveryDelay) {
125            getOrCreateRedeliveryPolicy().initialRedeliveryDelay(initialRedeliveryDelay);
126            return this;
127        }
128    
129        public ExceptionType maximumRedeliveries(int maximumRedeliveries) {
130            getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
131            return this;
132        }
133    
134        public ExceptionType useCollisionAvoidance() {
135            getOrCreateRedeliveryPolicy().useCollisionAvoidance();
136            return this;
137        }
138    
139        public ExceptionType useExponentialBackOff() {
140            getOrCreateRedeliveryPolicy().useExponentialBackOff();
141            return this;
142        }
143    
144        public ExceptionType maximumRedeliveryDelay(long maximumRedeliveryDelay) {
145            getOrCreateRedeliveryPolicy().maximumRedeliveryDelay(maximumRedeliveryDelay);
146            return this;
147        }
148    
149        // Properties
150        //-------------------------------------------------------------------------
151        public List<ProcessorType<?>> getOutputs() {
152            return outputs;
153        }
154    
155        public void setOutputs(List<ProcessorType<?>> outputs) {
156            this.outputs = outputs;
157        }
158    
159        public List<Class> getExceptionClasses() {
160            if (exceptionClasses == null) {
161                exceptionClasses = createExceptionClasses();
162            }
163            return exceptionClasses;
164        }
165    
166        public void setExceptionClasses(List<Class> exceptionClasses) {
167            this.exceptionClasses = exceptionClasses;
168        }
169    
170        public List<String> getExceptions() {
171            return exceptions;
172        }
173    
174        public void setExceptions(List<String> exceptions) {
175            this.exceptions = exceptions;
176        }
177    
178        public Processor getErrorHandler() {
179            return errorHandler;
180        }
181    
182        public RedeliveryPolicyType getRedeliveryPolicy() {
183            return redeliveryPolicy;
184        }
185    
186        public void setRedeliveryPolicy(RedeliveryPolicyType redeliveryPolicy) {
187            this.redeliveryPolicy = redeliveryPolicy;
188        }
189    
190        // Implementation methods
191        //-------------------------------------------------------------------------
192        protected RedeliveryPolicyType getOrCreateRedeliveryPolicy() {
193            if (redeliveryPolicy == null) {
194                redeliveryPolicy = new RedeliveryPolicyType();
195            }
196            return redeliveryPolicy;
197        }
198    
199        protected List<Class> createExceptionClasses() {
200            List<String> list = getExceptions();
201            List<Class> answer = new ArrayList<Class>(list.size());
202            for (String name : list) {
203                Class type = ObjectHelper.loadClass(name, getClass().getClassLoader());
204                answer.add(type);
205            }
206            return answer;
207        }
208    }