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.builder;
018
019 import java.util.List;
020
021 import org.apache.camel.ErrorHandlerFactory;
022 import org.apache.camel.Processor;
023 import org.apache.camel.model.ModelCamelContext;
024 import org.apache.camel.model.OnExceptionDefinition;
025 import org.apache.camel.spi.RouteContext;
026 import org.apache.camel.util.ObjectHelper;
027
028 /**
029 * Represents a proxy to an error handler builder which is resolved by named reference
030 *
031 * @version
032 */
033 public class ErrorHandlerBuilderRef extends ErrorHandlerBuilderSupport {
034 public static final String DEFAULT_ERROR_HANDLER_BUILDER = "CamelDefaultErrorHandlerBuilder";
035 private final String ref;
036 private ErrorHandlerBuilder handler;
037 private boolean supportTransacted;
038
039 public ErrorHandlerBuilderRef(String ref) {
040 this.ref = ref;
041 }
042
043 @Override
044 public void addErrorHandlers(OnExceptionDefinition exception) {
045 if (handler != null) {
046 handler.addErrorHandlers(exception);
047 }
048 super.addErrorHandlers(exception);
049 }
050
051 public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
052 if (handler == null) {
053 handler = createErrorHandler(routeContext);
054 }
055 return handler.createErrorHandler(routeContext, processor);
056 }
057
058 public boolean supportTransacted() {
059 return supportTransacted;
060 }
061
062 /**
063 * Lookup the error handler by the given ref
064 *
065 * @param routeContext the route context
066 * @param ref reference id for the error handler
067 * @return the error handler
068 */
069 public static ErrorHandlerFactory lookupErrorHandlerBuilder(RouteContext routeContext, String ref) {
070 ErrorHandlerFactory answer;
071
072 // if the ref is the default then we do not have any explicit error handler configured
073 // if that is the case then use error handlers configured on the route, as for instance
074 // the transacted error handler could have been configured on the route so we should use that one
075 if (!isErrorHandlerBuilderConfigured(ref)) {
076 // see if there has been configured a route builder on the route
077 answer = routeContext.getRoute().getErrorHandlerBuilder();
078 if (answer == null && routeContext.getRoute().getErrorHandlerRef() != null) {
079 answer = routeContext.lookup(routeContext.getRoute().getErrorHandlerRef(), ErrorHandlerBuilder.class);
080 }
081 if (answer == null) {
082 // fallback to the default error handler if none configured on the route
083 answer = new DefaultErrorHandlerBuilder();
084 }
085 // check if its also a ref with no error handler configuration like me
086 if (answer instanceof ErrorHandlerBuilderRef) {
087 ErrorHandlerBuilderRef other = (ErrorHandlerBuilderRef) answer;
088 String otherRef = other.getRef();
089 if (!isErrorHandlerBuilderConfigured(otherRef)) {
090 // the other has also no explicit error handler configured then fallback to the handler
091 // configured on the parent camel context
092 answer = lookupErrorHandlerBuilder((ModelCamelContext)routeContext.getCamelContext());
093 }
094 if (answer == null) {
095 // the other has also no explicit error handler configured then fallback to the default error handler
096 // otherwise we could recursive loop forever (triggered by createErrorHandler method)
097 answer = new DefaultErrorHandlerBuilder();
098 }
099 // inherit the error handlers from the other as they are to be shared
100 // this is needed by camel-spring when none error handler has been explicit configured
101 ((ErrorHandlerBuilder)answer).setErrorHandlers(other.getErrorHandlers());
102 }
103 } else {
104 // use specific configured error handler
105 answer = routeContext.lookup(ref, ErrorHandlerBuilder.class);
106 if (answer == null) {
107 throw new IllegalArgumentException("ErrorHandlerBuilder with id " + ref + " not found in registry.");
108 }
109 }
110
111 return answer;
112 }
113
114 protected static ErrorHandlerFactory lookupErrorHandlerBuilder(ModelCamelContext camelContext) {
115 @SuppressWarnings("deprecation")
116 ErrorHandlerFactory answer = camelContext.getErrorHandlerBuilder();
117 if (answer instanceof ErrorHandlerBuilderRef) {
118 ErrorHandlerBuilderRef other = (ErrorHandlerBuilderRef) answer;
119 String otherRef = other.getRef();
120 if (isErrorHandlerBuilderConfigured(otherRef)) {
121 answer = camelContext.getRegistry().lookup(otherRef, ErrorHandlerBuilder.class);
122 if (answer == null) {
123 throw new IllegalArgumentException("ErrorHandlerBuilder with id " + otherRef + " not found in registry.");
124 }
125 }
126 }
127
128 return answer;
129 }
130
131 /**
132 * Returns whether a specific error handler builder has been configured or not.
133 * <p/>
134 * Can be used to test if none has been configured and then install a custom error handler builder
135 * replacing the default error handler (that would have been used as fallback otherwise).
136 * <br/>
137 * This is for instance used by the transacted policy to setup a TransactedErrorHandlerBuilder
138 * in camel-spring.
139 */
140 public static boolean isErrorHandlerBuilderConfigured(String ref) {
141 return !DEFAULT_ERROR_HANDLER_BUILDER.equals(ref);
142 }
143
144 public String getRef() {
145 return ref;
146 }
147
148 public ErrorHandlerFactory getHandler() {
149 return handler;
150 }
151
152 private ErrorHandlerBuilder createErrorHandler(RouteContext routeContext) {
153 handler = (ErrorHandlerBuilder)lookupErrorHandlerBuilder(routeContext, getRef());
154 ObjectHelper.notNull(handler, "error handler '" + ref + "'");
155
156 // configure if the handler support transacted
157 supportTransacted = handler.supportTransacted();
158
159 List<OnExceptionDefinition> list = getErrorHandlers();
160 for (OnExceptionDefinition exceptionType : list) {
161 handler.addErrorHandlers(exceptionType);
162 }
163 return handler;
164 }
165
166 @Override
167 public String toString() {
168 return "ErrorHandlerBuilderRef[" + ref + "]";
169 }
170 }