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.builder; 018 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Set; 022 023import org.apache.camel.NamedNode; 024import org.apache.camel.Predicate; 025import org.apache.camel.Processor; 026import org.apache.camel.RuntimeCamelException; 027import org.apache.camel.model.OnExceptionDefinition; 028import org.apache.camel.model.ProcessorDefinitionHelper; 029import org.apache.camel.model.RouteDefinition; 030import org.apache.camel.processor.ErrorHandler; 031import org.apache.camel.processor.errorhandler.ErrorHandlerSupport; 032import org.apache.camel.processor.errorhandler.ExceptionPolicy; 033import org.apache.camel.processor.errorhandler.ExceptionPolicyKey; 034import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy; 035import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler; 036import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier; 037import org.apache.camel.spi.ClassResolver; 038import org.apache.camel.spi.RouteContext; 039import org.apache.camel.util.ObjectHelper; 040 041/** 042 * Base class for builders of error handling. 043 */ 044public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder { 045 private ExceptionPolicyStrategy exceptionPolicyStrategy; 046 047 protected void cloneBuilder(ErrorHandlerBuilderSupport other) { 048 other.exceptionPolicyStrategy = exceptionPolicyStrategy; 049 } 050 051 /** 052 * Configures the other error handler based on this error handler. 053 * 054 * @param routeContext the route context 055 * @param handler the other error handler 056 */ 057 public void configure(RouteContext routeContext, ErrorHandler handler) { 058 if (handler instanceof ErrorHandlerSupport) { 059 ErrorHandlerSupport handlerSupport = (ErrorHandlerSupport)handler; 060 061 Set<NamedNode> list = routeContext.getErrorHandlers(this); 062 for (NamedNode exception : list) { 063 addExceptionPolicy(handlerSupport, routeContext, (OnExceptionDefinition)exception); 064 } 065 } 066 if (handler instanceof RedeliveryErrorHandler) { 067 RedeliveryErrorHandler reh = (RedeliveryErrorHandler)handler; 068 boolean original = reh.isUseOriginalMessagePolicy() || reh.isUseOriginalBodyPolicy(); 069 if (original) { 070 if (reh.isUseOriginalMessagePolicy() && reh.isUseOriginalBodyPolicy()) { 071 throw new IllegalArgumentException("Cannot set both useOriginalMessage and useOriginalBody on the error handler"); 072 } 073 // ensure allow original is turned on 074 routeContext.setAllowUseOriginalMessage(true); 075 } 076 } 077 } 078 079 public static void addExceptionPolicy(ErrorHandlerSupport handlerSupport, RouteContext routeContext, OnExceptionDefinition exceptionType) { 080 if (routeContext != null) { 081 // add error handler as child service so they get lifecycle handled 082 Processor errorHandler = routeContext.getOnException(exceptionType.getId()); 083 handlerSupport.addErrorHandler(errorHandler); 084 085 // load exception classes 086 List<Class<? extends Throwable>> list; 087 if (ObjectHelper.isNotEmpty(exceptionType.getExceptions())) { 088 list = createExceptionClasses(exceptionType, routeContext.getCamelContext().getClassResolver()); 089 for (Class<? extends Throwable> clazz : list) { 090 String routeId = null; 091 // only get the route id, if the exception type is route 092 // scoped 093 if (exceptionType.isRouteScoped()) { 094 RouteDefinition route = ProcessorDefinitionHelper.getRoute(exceptionType); 095 if (route != null) { 096 routeId = route.getId(); 097 } 098 } 099 Predicate when = exceptionType.getOnWhen() != null ? exceptionType.getOnWhen().getExpression() : null; 100 ExceptionPolicyKey key = new ExceptionPolicyKey(routeId, clazz, when); 101 ExceptionPolicy policy = toExceptionPolicy(exceptionType, routeContext); 102 handlerSupport.addExceptionPolicy(key, policy); 103 } 104 } 105 } 106 } 107 108 protected static ExceptionPolicy toExceptionPolicy(OnExceptionDefinition exceptionType, RouteContext routeContext) { 109 return ErrorHandlerReifier.createExceptionPolicy(exceptionType, routeContext); 110 } 111 112 protected static List<Class<? extends Throwable>> createExceptionClasses(OnExceptionDefinition exceptionType, ClassResolver resolver) { 113 List<String> list = exceptionType.getExceptions(); 114 List<Class<? extends Throwable>> answer = new ArrayList<>(list.size()); 115 for (String name : list) { 116 try { 117 Class<? extends Throwable> type = resolver.resolveMandatoryClass(name, Throwable.class); 118 answer.add(type); 119 } catch (ClassNotFoundException e) { 120 throw RuntimeCamelException.wrapRuntimeCamelException(e); 121 } 122 } 123 return answer; 124 } 125 126 /** 127 * Sets the exception policy to use 128 */ 129 public ErrorHandlerBuilderSupport exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) { 130 setExceptionPolicyStrategy(exceptionPolicyStrategy); 131 return this; 132 } 133 134 /** 135 * Gets the exception policy strategy 136 */ 137 public ExceptionPolicyStrategy getExceptionPolicyStrategy() { 138 return exceptionPolicyStrategy; 139 } 140 141 /** 142 * Sets the exception policy strategy to use for resolving the 143 * {@link org.apache.camel.model.OnExceptionDefinition} to use for a given 144 * thrown exception 145 * 146 * @param exceptionPolicyStrategy the exception policy strategy 147 */ 148 public void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) { 149 ObjectHelper.notNull(exceptionPolicyStrategy, "ExceptionPolicyStrategy"); 150 this.exceptionPolicyStrategy = exceptionPolicyStrategy; 151 } 152 153}