Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.component.bean; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; import org.apache.camel.impl.DefaultExchange; import org.apache.camel.util.ObjectHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * An {@link java.lang.reflect.InvocationHandler} which invokes a * message exchange on a camel {@link Endpoint} * * @version $Revision$ */ public class CamelInvocationHandler implements InvocationHandler { private static final transient Log LOG = LogFactory.getLog(CamelInvocationHandler.class); private final Endpoint endpoint; private final Producer producer; private final MethodInfoCache methodInfoCache; public CamelInvocationHandler(Endpoint endpoint, Producer producer, MethodInfoCache methodInfoCache) { this.endpoint = endpoint; this.producer = producer; this.methodInfoCache = methodInfoCache; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { BeanInvocation invocation = new BeanInvocation(method, args); ExchangePattern pattern = ExchangePattern.InOut; MethodInfo methodInfo = methodInfoCache.getMethodInfo(method); if (methodInfo != null) { pattern = methodInfo.getPattern(); } Exchange exchange = new DefaultExchange(endpoint, pattern); exchange.getIn().setBody(invocation); // process the exchange if (LOG.isTraceEnabled()) { LOG.trace("Proxied method call " + method.getName() + " invoking producer: " + producer); } producer.process(exchange); // check if we had an exception Throwable cause = exchange.getException(); if (cause != null) { Throwable found = findSuitableException(cause, method); if (found != null) { throw found; } // special for runtime camel exceptions as they can be nested if (cause instanceof RuntimeCamelException) { // if the inner cause is a runtime exception we can throw it directly if (cause.getCause() instanceof RuntimeException) { throw (RuntimeException) ((RuntimeCamelException) cause).getCause(); } throw (RuntimeCamelException) cause; } // okay just throw the exception as is throw cause; } // do not return a reply if the method is VOID or the MEP is not OUT capable Class<?> to = method.getReturnType(); if (to == Void.TYPE || !pattern.isOutCapable()) { return null; } // only convert if there is a body if (!exchange.hasOut() || exchange.getOut().getBody() == null) { // there is no body so return null return null; } // use type converter so we can convert output in the desired type defined by the method // and let it be mandatory so we know wont return null if we cant convert it to the defined type Object answer = exchange.getOut().getMandatoryBody(to); if (LOG.isTraceEnabled()) { LOG.trace("Proxied method call " + method.getName() + " returning: " + answer); } return answer; } /** * Tries to find the best suited exception to throw. * <p/> * It looks in the exception hierarchy from the caused exception and matches this against the declared exceptions * being thrown on the method. * * @param cause the caused exception * @param method the method * @return the exception to throw, or <tt>null</tt> if not possible to find a suitable exception */ protected Throwable findSuitableException(Throwable cause, Method method) { if (method.getExceptionTypes() == null || method.getExceptionTypes().length == 0) { return null; } // see if there is any exception which matches the declared exception on the method for (Class<?> type : method.getExceptionTypes()) { Object fault = ObjectHelper.getException(type, cause); if (fault != null) { return Throwable.class.cast(fault); } } return null; } }