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    
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.Expression;
030    import org.apache.camel.Predicate;
031    import org.apache.camel.Processor;
032    import org.apache.camel.builder.ExpressionBuilder;
033    import org.apache.camel.builder.ExpressionClause;
034    import org.apache.camel.processor.CatchProcessor;
035    import org.apache.camel.spi.RouteContext;
036    import org.apache.camel.util.ObjectHelper;
037    import static org.apache.camel.builder.PredicateBuilder.toPredicate;
038    
039    /**
040     * Represents an XML <catch/> element
041     *
042     * @version $Revision: 766610 $
043     */
044    @XmlRootElement(name = "doCatch")
045    @XmlAccessorType(XmlAccessType.FIELD)
046    public class CatchDefinition extends ProcessorDefinition<CatchDefinition> {
047        @XmlElement(name = "exception")
048        private List<String> exceptions = new ArrayList<String>();
049        @XmlElement(name = "onWhen", required = false)
050        private WhenDefinition onWhen;
051        @XmlElement(name = "handled", required = false)
052        private ExpressionSubElementDefinition handled;
053        @XmlElementRef
054        private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
055        @XmlTransient
056        private List<Class> exceptionClasses;
057        @XmlTransient
058        private Predicate handledPolicy;
059    
060        public CatchDefinition() {
061        }
062    
063        public CatchDefinition(List<Class> exceptionClasses) {
064            this.exceptionClasses = exceptionClasses;
065        }
066    
067        public CatchDefinition(Class exceptionType) {
068            exceptionClasses = new ArrayList<Class>();
069            exceptionClasses.add(exceptionType);
070        }
071    
072        @Override
073        public String toString() {
074            return "DoCatch[ " + getExceptionClasses() + " -> " + getOutputs() + "]";
075        }
076    
077        @Override
078        public String getShortName() {
079            return "doCatch";
080        }
081    
082        @Override
083        public String getLabel() {
084            return getExceptionClasses().toString();
085        }
086    
087        @Override
088        public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
089            Processor childProcessor = routeContext.createProcessor(this);
090    
091            Predicate when = null;
092            if (onWhen != null) {
093                when = onWhen.getExpression().createPredicate(routeContext);
094            }
095    
096            Predicate handle = handledPolicy;
097            if (handled != null) {
098                handle = handled.createPredicate(routeContext);
099            }
100    
101            return new CatchProcessor(getExceptionClasses(), childProcessor, when, handle);
102        }
103    
104        public List<ProcessorDefinition> getOutputs() {
105            return outputs;
106        }
107    
108        public void setOutputs(List<ProcessorDefinition> outputs) {
109            this.outputs = outputs;
110        }
111    
112        public List<Class> getExceptionClasses() {
113            if (exceptionClasses == null) {
114                exceptionClasses = createExceptionClasses();
115            }
116            return exceptionClasses;
117        }
118    
119        public void setExceptionClasses(List<Class> exceptionClasses) {
120            this.exceptionClasses = exceptionClasses;
121        }
122        
123        // Fluent API
124        //-------------------------------------------------------------------------
125        /**
126         * Sets the exceptionClasses of the CatchType
127         *
128         * @param exceptionClasses  a list of the exception classes
129         * @return the builder
130         */
131        public CatchDefinition exceptionClasses(List<Class> exceptionClasses) {
132            setExceptionClasses(exceptionClasses);
133            return this;
134        }
135        
136        /**
137         * Sets an additional predicate that should be true before the onCatch is triggered.
138         * <p/>
139         * To be used for fine grained controlling whether a thrown exception should be intercepted
140         * by this exception type or not.
141         *
142         * @param predicate  predicate that determines true or false
143         * @return the builder
144         */
145        public CatchDefinition onWhen(Predicate predicate) {
146            setOnWhen(new WhenDefinition(predicate));
147            return this;
148        }
149    
150        /**
151         * Creates an expression to configure an additional predicate that should be true before the
152         * onCatch is triggered.
153         * <p/>
154         * To be used for fine grained controlling whether a thrown exception should be intercepted
155         * by this exception type or not.
156         *
157         * @return the expression clause to configure
158         */
159        public ExpressionClause<CatchDefinition> onWhen() {
160            onWhen = new WhenDefinition();
161            ExpressionClause<CatchDefinition> clause = new ExpressionClause<CatchDefinition>(this);
162            onWhen.setExpression(clause);
163            return clause;
164        }
165    
166        /**
167         * Sets whether the exchange should be marked as handled or not.
168         *
169         * @param handled  handled or not
170         * @return the builder
171         */
172        public CatchDefinition handled(boolean handled) {
173            Expression expression = ExpressionBuilder.constantExpression(Boolean.toString(handled));
174            return handled(expression);
175        }
176    
177        /**
178         * Sets whether the exchange should be marked as handled or not.
179         *
180         * @param handled  predicate that determines true or false
181         * @return the builder
182         */
183        public CatchDefinition handled(Predicate handled) {
184            setHandledPolicy(handled);
185            return this;
186        }
187    
188        /**
189         * Sets whether the exchange should be marked as handled or not.
190         *
191         * @param handled  expression that determines true or false
192         * @return the builder
193         */
194        public CatchDefinition handled(Expression handled) {
195            setHandledPolicy(toPredicate(handled));
196            return this;
197        }
198    
199        /**
200         * Sets the exception class that the CatchType want to catch
201         *
202         * @param exception  the exception of class
203         * @return the builder
204         */
205        public CatchDefinition exceptionClasses(Class exception) {
206            List<Class> list = getExceptionClasses();
207            list.add(exception);
208            return this;
209        }
210    
211        public List<String> getExceptions() {
212            return exceptions;
213        }
214    
215        public void setExceptions(List<String> exceptions) {
216            this.exceptions = exceptions;
217        }
218    
219        public WhenDefinition getOnWhen() {
220            return onWhen;
221        }
222    
223        public void setOnWhen(WhenDefinition onWhen) {
224            this.onWhen = onWhen;
225        }
226    
227        public Predicate getHandledPolicy() {
228            return handledPolicy;
229        }
230    
231        public void setHandledPolicy(Predicate handledPolicy) {
232            this.handledPolicy = handledPolicy;
233        }
234    
235        protected List<Class> createExceptionClasses() {
236            List<String> list = getExceptions();
237            List<Class> answer = new ArrayList<Class>(list.size());
238            for (String name : list) {
239                Class type = ObjectHelper.loadClass(name, getClass().getClassLoader());
240                answer.add(type);
241            }
242            return answer;
243        }
244    }