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