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: 660266 $
042     */
043    @XmlRootElement(name = "onException")
044    @XmlAccessorType(XmlAccessType.FIELD)
045    public class ExceptionType extends ProcessorType<ProcessorType> {
046    
047    /*
048        @XmlElementRef
049        private List<InterceptorType> interceptors = new ArrayList<InterceptorType>();
050    */
051        @XmlElement(name = "exception")
052        private List<String> exceptions = new ArrayList<String>();
053        @XmlElement(name = "redeliveryPolicy", required = false)
054        private RedeliveryPolicyType redeliveryPolicy;
055        @XmlElementRef
056        private List<ProcessorType<?>> outputs = new ArrayList<ProcessorType<?>>();
057        @XmlTransient
058        private List<Class> exceptionClasses;
059        @XmlTransient
060        private Processor errorHandler;
061    
062        public ExceptionType() {
063        }
064    
065        public ExceptionType(List<Class> exceptionClasses) {
066            this.exceptionClasses = exceptionClasses;
067        }
068    
069        public ExceptionType(Class exceptionType) {
070            exceptionClasses = new ArrayList<Class>();
071            exceptionClasses.add(exceptionType);
072        }
073    
074        @Override
075        public String toString() {
076            return "Exception[ " + getExceptionClasses() + " -> " + getOutputs() + "]";
077        }
078    
079        /**
080         * Allows an exception handler to create a new redelivery policy for this exception type
081         * @param parentPolicy the current redelivery policy
082         * @return a newly created redelivery policy, or return the original policy if no customization is required
083         * for this exception handler.
084         */
085        public RedeliveryPolicy createRedeliveryPolicy(RedeliveryPolicy parentPolicy) {
086            if (redeliveryPolicy != null) {
087                return redeliveryPolicy.createRedeliveryPolicy(parentPolicy);
088            } else if (errorHandler != null) {
089                // lets create a new error handler that has no retries
090                RedeliveryPolicy answer = parentPolicy.copy();
091                answer.setMaximumRedeliveries(0);
092                return answer;
093            }
094            return parentPolicy;
095        }
096    
097        public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
098            // lets attach a processor to an error handler
099            errorHandler = routeContext.createProcessor(this);
100            ErrorHandlerBuilder builder = routeContext.getRoute().getErrorHandlerBuilder();
101            builder.addErrorHandlers(this);
102        }
103    
104        @Override
105        public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
106            Processor childProcessor = routeContext.createProcessor(this);
107            return new CatchProcessor(getExceptionClasses(), childProcessor);
108        }
109    
110    
111        // Fluent API
112        //-------------------------------------------------------------------------
113        public ExceptionType backOffMultiplier(double backOffMultiplier) {
114            getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
115            return this;
116        }
117    
118        public ExceptionType collisionAvoidanceFactor(double collisionAvoidanceFactor) {
119            getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor);
120            return this;
121        }
122    
123        public ExceptionType collisionAvoidancePercent(short collisionAvoidancePercent) {
124            getOrCreateRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
125            return this;
126        }
127    
128        public ExceptionType initialRedeliveryDelay(long initialRedeliveryDelay) {
129            getOrCreateRedeliveryPolicy().initialRedeliveryDelay(initialRedeliveryDelay);
130            return this;
131        }
132    
133        public ExceptionType maximumRedeliveries(int maximumRedeliveries) {
134            getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
135            return this;
136        }
137    
138        public ExceptionType useCollisionAvoidance() {
139            getOrCreateRedeliveryPolicy().useCollisionAvoidance();
140            return this;
141        }
142    
143        public ExceptionType useExponentialBackOff() {
144            getOrCreateRedeliveryPolicy().useExponentialBackOff();
145            return this;
146        }
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    }