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