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.Predicate; 023import org.apache.camel.Processor; 024import org.apache.camel.builder.ErrorHandlerBuilder; 025import org.apache.camel.model.OnExceptionDefinition; 026import org.apache.camel.model.ProcessorDefinition; 027import org.apache.camel.processor.CatchProcessor; 028import org.apache.camel.processor.FatalFallbackErrorHandler; 029import org.apache.camel.spi.ClassResolver; 030import org.apache.camel.spi.RouteContext; 031 032public class OnExceptionReifier extends ProcessorReifier<OnExceptionDefinition> { 033 034 public OnExceptionReifier(RouteContext routeContext, ProcessorDefinition<?> definition) { 035 super(routeContext, (OnExceptionDefinition)definition); 036 } 037 038 @Override 039 public void addRoutes() throws Exception { 040 // assign whether this was a route scoped onException or not 041 // we need to know this later when setting the parent, as only route 042 // scoped should have parent 043 // Note: this logic can possible be removed when the Camel routing 044 // engine decides at runtime 045 // to apply onException in a more dynamic fashion than current code base 046 // and therefore is in a better position to decide among context/route 047 // scoped OnException at runtime 048 if (definition.getRouteScoped() == null) { 049 definition.setRouteScoped(definition.getParent() != null); 050 } 051 052 // must validate configuration before creating processor 053 definition.validateConfiguration(); 054 055 if (parseBoolean(definition.getUseOriginalMessage(), false)) { 056 // ensure allow original is turned on 057 routeContext.setAllowUseOriginalMessage(true); 058 } 059 060 // lets attach this on exception to the route error handler 061 Processor child = createOutputsProcessor(); 062 if (child != null) { 063 // wrap in our special safe fallback error handler if OnException 064 // have child output 065 Processor errorHandler = new FatalFallbackErrorHandler(child); 066 String id = getId(definition, routeContext); 067 routeContext.setOnException(id, errorHandler); 068 } 069 // lookup the error handler builder 070 ErrorHandlerBuilder builder = (ErrorHandlerBuilder)routeContext.getErrorHandlerFactory(); 071 // and add this as error handlers 072 routeContext.addErrorHandler(builder, definition); 073 } 074 075 @Override 076 public CatchProcessor createProcessor() throws Exception { 077 // load exception classes 078 List<Class<? extends Throwable>> classes = null; 079 if (definition.getExceptions() != null && !definition.getExceptions().isEmpty()) { 080 classes = createExceptionClasses(camelContext.getClassResolver()); 081 } 082 083 if (parseBoolean(definition.getUseOriginalMessage(), false)) { 084 // ensure allow original is turned on 085 routeContext.setAllowUseOriginalMessage(true); 086 } 087 088 // must validate configuration before creating processor 089 definition.validateConfiguration(); 090 091 Processor childProcessor = this.createChildProcessor(false); 092 093 Predicate when = null; 094 if (definition.getOnWhen() != null) { 095 when = createPredicate(definition.getOnWhen().getExpression()); 096 } 097 098 Predicate handle = null; 099 if (definition.getHandled() != null) { 100 handle = createPredicate(definition.getHandled()); 101 } 102 103 return new CatchProcessor(classes, childProcessor, when, handle); 104 } 105 106 protected List<Class<? extends Throwable>> createExceptionClasses(ClassResolver resolver) throws ClassNotFoundException { 107 List<String> list = definition.getExceptions(); 108 List<Class<? extends Throwable>> answer = new ArrayList<>(list.size()); 109 for (String name : list) { 110 Class<? extends Throwable> type = resolver.resolveMandatoryClass(name, Throwable.class); 111 answer.add(type); 112 } 113 return answer; 114 } 115 116}