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.processor;
018    
019    import java.util.Iterator;
020    import java.util.List;
021    
022    import org.apache.camel.Exchange;
023    import org.apache.camel.Predicate;
024    import org.apache.camel.Processor;
025    import org.apache.camel.util.ObjectHelper;
026    
027    /**
028     * A processor which catches exceptions.
029     *
030     * @version $Revision: 788621 $
031     */
032    public class CatchProcessor extends DelegateProcessor implements Traceable {
033        private final List<Class> exceptions;
034        private final Predicate onWhen;
035        private final Predicate handled;
036    
037        public CatchProcessor(List<Class> exceptions, Processor processor, Predicate onWhen, Predicate handled) {
038            super(processor);
039            this.exceptions = exceptions;
040            this.onWhen = onWhen;
041            this.handled = handled;
042        }
043    
044        @Override
045        public String toString() {
046            return "Catch[" + exceptions + " -> " + getProcessor() + "]";
047        }
048    
049        public String getTraceLabel() {
050            return "Catch";
051        }
052    
053        /**
054         * Whether this catch processor catch the given thrown exception
055         *
056         * @param exchange  the current exchange
057         * @param exception the thrown exception
058         * @return <tt>true</tt> if this processor catches it, <tt>false</tt> otherwise.
059         */
060        public boolean catches(Exchange exchange, Throwable exception) {
061            // use the exception iterator to walk the caused by hierachy
062            Iterator<Throwable> it = ObjectHelper.createExceptionIterator(exception);
063            while (it.hasNext()) {
064                Throwable e = it.next();
065                // see if we catch this type
066                for (Class type : exceptions) {
067                    if (type.isInstance(e) && matchesWhen(exchange)) {
068                        return true;
069                    }
070                }
071            }
072    
073            // not found
074            return false;
075        }
076    
077    
078        /**
079         * Whether this catch processor handles the exception it have caught
080         *
081         * @param exchange  the current exchange
082         * @return <tt>true</tt> if this processor handles it, <tt>false</tt> otherwise.
083         */
084        public boolean handles(Exchange exchange) {
085            if (handled == null) {
086                // handle by default
087                return true;
088            }
089    
090            return handled.matches(exchange);
091        }
092    
093        public List<Class> getExceptions() {
094            return exceptions;
095        }
096    
097        /**
098         * Strategy method for matching the exception type with the current exchange.
099         * <p/>
100         * This default implementation will match as:
101         * <ul>
102         * <li>Always true if no when predicate on the exception type
103         * <li>Otherwise the when predicate is matches against the current exchange
104         * </ul>
105         *
106         * @param exchange the current {@link org.apache.camel.Exchange}
107         * @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
108         */
109        protected boolean matchesWhen(Exchange exchange) {
110            if (onWhen == null) {
111                // if no predicate then it's always a match
112                return true;
113            }
114            return onWhen.matches(exchange);
115        }
116    
117    }