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.component.bean;
018
019 import java.lang.reflect.InvocationTargetException;
020 import java.lang.reflect.Method;
021
022 import org.apache.camel.CamelContext;
023 import org.apache.camel.Exchange;
024 import org.apache.camel.Message;
025 import org.apache.camel.Processor;
026 import org.apache.camel.impl.ServiceSupport;
027 import org.apache.camel.util.CamelContextHelper;
028 import org.apache.camel.util.ObjectHelper;
029 import org.apache.camel.util.ServiceHelper;
030 import org.apache.commons.logging.Log;
031 import org.apache.commons.logging.LogFactory;
032 import static org.apache.camel.util.ObjectHelper.isNullOrBlank;
033
034 /**
035 * A {@link Processor} which converts the inbound exchange to a method
036 * invocation on a POJO
037 *
038 * @version $Revision: 36321 $
039 */
040 public class BeanProcessor extends ServiceSupport implements Processor {
041 public static final String METHOD_NAME = "org.apache.camel.MethodName";
042 private static final Log LOG = LogFactory.getLog(BeanProcessor.class);
043
044 private Method methodObject;
045 private String method;
046 private BeanHolder beanHolder;
047
048 public BeanProcessor(Object pojo, BeanInfo beanInfo) {
049 this(new ConstantBeanHolder(pojo, beanInfo));
050 }
051
052 public BeanProcessor(Object pojo, CamelContext camelContext, ParameterMappingStrategy parameterMappingStrategy) {
053 this(pojo, new BeanInfo(camelContext, pojo.getClass(), parameterMappingStrategy));
054 }
055
056 public BeanProcessor(Object pojo, CamelContext camelContext) {
057 this(pojo, camelContext, BeanInfo.createParameterMappingStrategy(camelContext));
058 }
059
060 public BeanProcessor(BeanHolder beanHolder) {
061 this.beanHolder = beanHolder;
062 }
063
064 @Override
065 public String toString() {
066 String description = methodObject != null ? " " + methodObject : "";
067 return "BeanProcessor[" + beanHolder + description + "]";
068 }
069
070 public void process(Exchange exchange) throws Exception {
071 if (LOG.isDebugEnabled()) {
072 LOG.debug(">>>> invoking method for: " + exchange);
073 }
074
075 Object bean = beanHolder.getBean();
076 exchange.setProperty("CamelBean", bean);
077
078 Processor processor = getProcessor();
079 BeanInfo beanInfo = beanHolder.getBeanInfo();
080
081 // do we have a custom adapter for this POJO to a Processor
082 if (processor != null) {
083 processor.process(exchange);
084 return;
085 }
086 Message in = exchange.getIn();
087 BeanInvocation beanInvoke = in.getBody(BeanInvocation.class);
088 if (beanInvoke != null) {
089 beanInvoke.invoke(bean, exchange);
090 return;
091 }
092
093 boolean isExplicitMethod = false;
094 String prevMethod = null;
095 MethodInvocation invocation;
096 if (methodObject != null) {
097 invocation = beanInfo.createInvocation(methodObject, bean, exchange);
098 } else {
099 // we just override the bean's invocation method name here
100 if (ObjectHelper.isNotNullAndNonEmpty(method)) {
101 prevMethod = in.getHeader(METHOD_NAME, String.class);
102 in.setHeader(METHOD_NAME, method);
103 isExplicitMethod = true;
104 }
105 invocation = beanInfo.createInvocation(bean, exchange);
106 }
107 if (invocation == null) {
108 throw new IllegalStateException("No method invocation could be created, "
109 + "no maching method could be found on: " + bean);
110 }
111 try {
112 Object value = invocation.proceed();
113 if (value != null) {
114 exchange.getOut().setBody(value);
115 }
116 } catch (InvocationTargetException e) {
117 // lets unwrap the exception
118 Throwable cause = e.getCause();
119 if (cause instanceof Exception) {
120 throw (Exception) cause;
121 } else {
122 // do not handle errors!
123 throw e;
124 }
125 } catch (Exception e) {
126 throw e;
127 } catch (Throwable throwable) {
128 throw new Exception(throwable);
129 } finally {
130 if (isExplicitMethod) {
131 in.setHeader(METHOD_NAME, prevMethod);
132 }
133 }
134 }
135
136 protected Processor getProcessor() {
137 return beanHolder.getProcessor();
138 }
139
140 // Properties
141 // -----------------------------------------------------------------------
142
143 public Method getMethodObject() {
144 return methodObject;
145 }
146
147 public void setMethodObject(Method methodObject) {
148 this.methodObject = methodObject;
149 }
150
151 public String getMethod() {
152 return method;
153 }
154
155 /**
156 * Sets the method name to use
157 */
158 public void setMethod(String method) {
159 this.method = method;
160 }
161
162 /**
163 * Kept around for backwards compatibility, please use {@link #setMethod(String)}
164 * in future instead.
165 *
166 * @deprecated
167 * @see #setMethod(String)
168 * @param method
169 */
170 public void setMethodName(String method) {
171 setMethod(method);
172 }
173
174 // Implementation methods
175 //-------------------------------------------------------------------------
176 protected void doStart() throws Exception {
177 ServiceHelper.startService(getProcessor());
178 }
179
180 protected void doStop() throws Exception {
181 ServiceHelper.stopService(getProcessor());
182 }
183 }