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