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: 45097 $
037 */
038 public class BeanProcessor extends ServiceSupport implements Processor {
039 public static final String METHOD_NAME = "org.apache.camel.MethodName";
040 public static final String MULTI_PARAMETER_ARRAY = "org.apache.camel.MultiParameterArray";
041 private static final transient Log LOG = LogFactory.getLog(BeanProcessor.class);
042
043 private boolean multiParameterArray;
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("org.apache.camel.bean.BeanHolder", beanHolder);
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
088 if (in.getHeader(MULTI_PARAMETER_ARRAY) == null) {
089 in.setHeader(MULTI_PARAMETER_ARRAY, isMultiParameterArray());
090 }
091
092 BeanInvocation beanInvoke = in.getBody(BeanInvocation.class);
093 if (beanInvoke != null) {
094 beanInvoke.invoke(bean, exchange);
095 return;
096 }
097
098 boolean isExplicitMethod = false;
099 String prevMethod = null;
100 MethodInvocation invocation;
101 if (methodObject != null) {
102 invocation = beanInfo.createInvocation(methodObject, bean, exchange);
103 } else {
104 // we just override the bean's invocation method name here
105 if (ObjectHelper.isNotNullAndNonEmpty(method)) {
106 prevMethod = in.getHeader(METHOD_NAME, String.class);
107 in.setHeader(METHOD_NAME, method);
108 isExplicitMethod = true;
109 }
110 invocation = beanInfo.createInvocation(bean, exchange);
111 }
112 if (invocation == null) {
113 throw new IllegalStateException("No method invocation could be created, "
114 + "no maching method could be found on: " + bean);
115 }
116 try {
117 Object value = invocation.proceed();
118 if (value != null) {
119 if (exchange.getPattern().isOutCapable()) {
120 // force out creating if not already created (as its lazy)
121 if (LOG.isDebugEnabled()) {
122 LOG.debug("Setting bean invocation value on OUT message: " + value);
123 }
124 exchange.getOut(true).setBody(value);
125 } else {
126 // if not out then set it on the in
127 if (LOG.isDebugEnabled()) {
128 LOG.debug("Setting bean invocation value on IN message: " + value);
129 }
130 exchange.getIn().setBody(value);
131 }
132 }
133 } catch (InvocationTargetException e) {
134 // lets unwrap the exception
135 Throwable cause = e.getCause();
136 if (cause instanceof Exception) {
137 throw (Exception) cause;
138 } else {
139 // do not handle errors!
140 throw e;
141 }
142 } catch (Exception e) {
143 throw e;
144 } catch (Throwable throwable) {
145 throw new Exception(throwable);
146 } finally {
147 if (isExplicitMethod) {
148 in.setHeader(METHOD_NAME, prevMethod);
149 }
150 }
151 }
152
153 protected Processor getProcessor() {
154 return beanHolder.getProcessor();
155 }
156
157 // Properties
158 // -----------------------------------------------------------------------
159
160 public Method getMethodObject() {
161 return methodObject;
162 }
163
164 public void setMethodObject(Method methodObject) {
165 this.methodObject = methodObject;
166 }
167
168 public String getMethod() {
169 return method;
170 }
171
172 public boolean isMultiParameterArray() {
173 return multiParameterArray;
174 }
175
176 public void setMultiParameterArray(boolean mpArray) {
177 multiParameterArray = mpArray;
178 }
179
180 /**
181 * Sets the method name to use
182 */
183 public void setMethod(String method) {
184 this.method = method;
185 }
186
187 /**
188 * Kept around for backwards compatibility, please use {@link #setMethod(String)}
189 * in future instead.
190 *
191 * @deprecated use {@link #setMethod(String)}. Will be removed in Camel 2.0.
192 */
193 @Deprecated
194 public void setMethodName(String method) {
195 setMethod(method);
196 }
197
198 // Implementation methods
199 //-------------------------------------------------------------------------
200 protected void doStart() throws Exception {
201 ServiceHelper.startService(getProcessor());
202 }
203
204 protected void doStop() throws Exception {
205 ServiceHelper.stopService(getProcessor());
206 }
207 }