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: 766610 $
031     */
032    public class CatchProcessor extends DelegateProcessor {
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        /**
050         * Whether this catch processor catch the given thrown exception
051         *
052         * @param exchange  the current exchange
053         * @param exception the thrown exception
054         * @return <tt>true</tt> if this processor catches it, <tt>false</tt> otherwise.
055         */
056        public boolean catches(Exchange exchange, Throwable exception) {
057            // use the exception iterator to walk the caused by hierachy
058            Iterator<Throwable> it = ObjectHelper.createExceptionIterator(exception);
059            while (it.hasNext()) {
060                Throwable e = it.next();
061                // see if we catch this type
062                for (Class type : exceptions) {
063                    if (type.isInstance(e) && matchesWhen(exchange)) {
064                        return true;
065                    }
066                }
067            }
068    
069            // not found
070            return false;
071        }
072    
073    
074        /**
075         * Whether this catch processor handles the exception it have caught
076         *
077         * @param exchange  the current exchange
078         * @return <tt>true</tt> if this processor handles it, <tt>false</tt> otherwise.
079         */
080        public boolean handles(Exchange exchange) {
081            if (handled == null) {
082                // handle by default
083                return true;
084            }
085    
086            return handled.matches(exchange);
087        }
088    
089        public List<Class> getExceptions() {
090            return exceptions;
091        }
092    
093        /**
094         * Strategy method for matching the exception type with the current exchange.
095         * <p/>
096         * This default implementation will match as:
097         * <ul>
098         * <li>Always true if no when predicate on the exception type
099         * <li>Otherwise the when predicate is matches against the current exchange
100         * </ul>
101         *
102         * @param exchange the current {@link org.apache.camel.Exchange}
103         * @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
104         */
105        protected boolean matchesWhen(Exchange exchange) {
106            if (onWhen == null) {
107                // if no predicate then it's always a match
108                return true;
109            }
110            return onWhen.matches(exchange);
111        }
112    
113    }