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