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 */
017package org.apache.camel.reifier;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.camel.ErrorHandlerFactory;
023import org.apache.camel.Predicate;
024import org.apache.camel.Processor;
025import org.apache.camel.Route;
026import org.apache.camel.model.OnExceptionDefinition;
027import org.apache.camel.model.ProcessorDefinition;
028import org.apache.camel.processor.CatchProcessor;
029import org.apache.camel.processor.FatalFallbackErrorHandler;
030import org.apache.camel.spi.ClassResolver;
031
032public class OnExceptionReifier extends ProcessorReifier<OnExceptionDefinition> {
033
034    public OnExceptionReifier(Route route, ProcessorDefinition<?> definition) {
035        super(route, (OnExceptionDefinition)definition);
036    }
037
038    @Override
039    public void addRoutes() throws Exception {
040        // must validate configuration before creating processor
041        definition.validateConfiguration();
042
043        if (parseBoolean(definition.getUseOriginalMessage(), false)) {
044            // ensure allow original is turned on
045            route.setAllowUseOriginalMessage(true);
046        }
047
048        // lets attach this on exception to the route error handler
049        Processor child = createOutputsProcessor();
050        if (child != null) {
051            // wrap in our special safe fallback error handler if OnException
052            // have child output
053            Processor errorHandler = new FatalFallbackErrorHandler(child, false);
054            String id = getId(definition);
055            route.setOnException(id, errorHandler);
056        }
057        // lookup the error handler builder
058        ErrorHandlerFactory builder = route.getErrorHandlerFactory();
059        // and add this as error handlers
060        route.addErrorHandler(builder, definition);
061    }
062
063    @Override
064    public CatchProcessor createProcessor() throws Exception {
065        // load exception classes
066        List<Class<? extends Throwable>> classes = null;
067        if (definition.getExceptions() != null && !definition.getExceptions().isEmpty()) {
068            classes = createExceptionClasses(camelContext.getClassResolver());
069        }
070
071        if (parseBoolean(definition.getUseOriginalMessage(), false)) {
072            // ensure allow original is turned on
073            route.setAllowUseOriginalMessage(true);
074        }
075
076        // must validate configuration before creating processor
077        definition.validateConfiguration();
078
079        Processor childProcessor = this.createChildProcessor(false);
080
081        Predicate when = null;
082        if (definition.getOnWhen() != null) {
083            when = createPredicate(definition.getOnWhen().getExpression());
084        }
085
086        Predicate handle = null;
087        if (definition.getHandled() != null) {
088            handle = createPredicate(definition.getHandled());
089        }
090
091        return new CatchProcessor(classes, childProcessor, when, handle);
092    }
093
094    protected List<Class<? extends Throwable>> createExceptionClasses(ClassResolver resolver) throws ClassNotFoundException {
095        List<String> list = definition.getExceptions();
096        List<Class<? extends Throwable>> answer = new ArrayList<>(list.size());
097        for (String name : list) {
098            Class<? extends Throwable> type = resolver.resolveMandatoryClass(name, Throwable.class);
099            answer.add(type);
100        }
101        return answer;
102    }
103
104}