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.model;
018
019 import javax.xml.bind.annotation.XmlAccessType;
020 import javax.xml.bind.annotation.XmlAccessorType;
021 import javax.xml.bind.annotation.XmlAttribute;
022 import javax.xml.bind.annotation.XmlRootElement;
023 import javax.xml.bind.annotation.XmlTransient;
024
025 import org.apache.camel.Processor;
026 import org.apache.camel.component.bean.BeanHolder;
027 import org.apache.camel.component.bean.BeanInfo;
028 import org.apache.camel.component.bean.BeanProcessor;
029 import org.apache.camel.component.bean.ConstantBeanHolder;
030 import org.apache.camel.component.bean.ConstantTypeBeanHolder;
031 import org.apache.camel.component.bean.MethodNotFoundException;
032 import org.apache.camel.component.bean.RegistryBean;
033 import org.apache.camel.spi.RouteContext;
034 import org.apache.camel.util.CamelContextHelper;
035 import org.apache.camel.util.ObjectHelper;
036
037 /**
038 * Represents an XML <bean/> element
039 *
040 * @version
041 */
042 @XmlRootElement(name = "bean")
043 @XmlAccessorType(XmlAccessType.FIELD)
044 public class BeanDefinition extends NoOutputDefinition<BeanDefinition> {
045 @XmlAttribute
046 private String ref;
047 @XmlAttribute
048 private String method;
049 @XmlAttribute
050 private String beanType;
051 @XmlTransient
052 private Class<?> beanClass;
053 @XmlTransient
054 private Object bean;
055
056 public BeanDefinition() {
057 }
058
059 public BeanDefinition(String ref) {
060 this.ref = ref;
061 }
062
063 public BeanDefinition(String ref, String method) {
064 this.ref = ref;
065 this.method = method;
066 }
067
068 @Override
069 public String toString() {
070 return "Bean[" + description() + "]";
071 }
072
073 public String description() {
074 if (ref != null) {
075 String methodText = "";
076 if (method != null) {
077 methodText = " method: " + method;
078 }
079 return "ref:" + ref + methodText;
080 } else if (bean != null) {
081 return bean.toString();
082 } else if (beanClass != null) {
083 return beanClass.getName();
084 } else if (beanType != null) {
085 return beanType;
086 } else {
087 return "";
088 }
089 }
090
091 @Override
092 public String getLabel() {
093 return "bean[" + description() + "]";
094 }
095
096 @Override
097 public String getShortName() {
098 return "bean";
099 }
100
101 public String getRef() {
102 return ref;
103 }
104
105 public void setRef(String ref) {
106 this.ref = ref;
107 }
108
109 public String getMethod() {
110 return method;
111 }
112
113 public void setMethod(String method) {
114 this.method = method;
115 }
116
117 public void setBean(Object bean) {
118 this.bean = bean;
119 }
120
121 public String getBeanType() {
122 return beanType;
123 }
124
125 public void setBeanType(String beanType) {
126 this.beanType = beanType;
127 }
128
129 public void setBeanType(Class<?> beanType) {
130 this.beanClass = beanType;
131 }
132
133 // Fluent API
134 //-------------------------------------------------------------------------
135 /**
136 * Sets the ref String on camel bean
137 *
138 * @param ref the bean's id in the registry
139 * @return the builder
140 * @deprecated not in use, will be removed in next Camel release
141 */
142 @Deprecated
143 public BeanDefinition ref(String ref) {
144 setRef(ref);
145 return this;
146 }
147
148 /**
149 * Sets the calling method name of camel bean
150 *
151 * @param method the bean's method name which wants camel to call
152 * @return the builder
153 * @deprecated not in use, will be removed in next Camel release
154 */
155 @Deprecated
156 public BeanDefinition method(String method) {
157 setMethod(method);
158 return this;
159 }
160
161 /**
162 * Sets the bean's instance that camel to call
163 *
164 * @param bean the instance of the bean
165 * @return the builder
166 * @deprecated not in use, will be removed in next Camel release
167 */
168 @Deprecated
169 public BeanDefinition bean(Object bean) {
170 setBean(bean);
171 return this;
172 }
173
174 /**
175 * Sets the Class of the bean
176 *
177 * @param beanType the Class of the bean
178 * @return the builder
179 * @deprecated not in use, will be removed in next Camel release
180 */
181 @Deprecated
182 public BeanDefinition beanType(Class<?> beanType) {
183 setBeanType(beanType);
184 return this;
185 }
186
187 @Override
188 public Processor createProcessor(RouteContext routeContext) {
189 BeanProcessor answer;
190 Class<?> clazz = bean != null ? bean.getClass() : null;
191 BeanHolder beanHolder;
192
193 if (ObjectHelper.isNotEmpty(ref)) {
194 beanHolder = new RegistryBean(routeContext.getCamelContext(), ref);
195 // bean holder will check if the bean exists
196 bean = beanHolder.getBean();
197 answer = new BeanProcessor(beanHolder);
198 } else {
199 if (bean == null) {
200
201 if (beanType == null && beanClass == null) {
202 throw new IllegalArgumentException("bean, ref or beanType must be provided");
203 }
204
205 // the clazz is either from beanType or beanClass
206 if (beanType != null) {
207 try {
208 clazz = routeContext.getCamelContext().getClassResolver().resolveMandatoryClass(beanType);
209 } catch (ClassNotFoundException e) {
210 throw ObjectHelper.wrapRuntimeCamelException(e);
211 }
212 } else {
213 clazz = beanClass;
214 }
215
216 // create a bean if there is a default public no-arg constructor
217 if (ObjectHelper.hasDefaultPublicNoArgConstructor(clazz)) {
218 bean = CamelContextHelper.newInstance(routeContext.getCamelContext(), clazz);
219 ObjectHelper.notNull(bean, "bean", this);
220 }
221 }
222
223 // validate the bean type is not from java so you by mistake think its a reference
224 // to a bean name but the String is being invoke instead
225 if (bean instanceof String) {
226 throw new IllegalArgumentException("The bean instance is a java.lang.String type: " + bean
227 + ". We suppose you want to refer to a bean instance by its id instead. Please use beanRef.");
228 }
229
230 // the holder should either be bean or type based
231 beanHolder = bean != null ? new ConstantBeanHolder(bean, routeContext.getCamelContext()) : new ConstantTypeBeanHolder(clazz, routeContext.getCamelContext());
232 answer = new BeanProcessor(beanHolder);
233 }
234
235 // check for method exists
236 if (method != null) {
237 answer.setMethod(method);
238
239 // check there is a method with the given name, and leverage BeanInfo for that
240 BeanInfo beanInfo = beanHolder.getBeanInfo();
241 if (bean != null) {
242 // there is a bean instance, so check for any methods
243 if (!beanInfo.hasMethod(method)) {
244 throw ObjectHelper.wrapRuntimeCamelException(new MethodNotFoundException(null, bean, method));
245 }
246 } else if (clazz != null) {
247 // there is no bean instance, so check for static methods only
248 if (!beanInfo.hasStaticMethod(method)) {
249 throw ObjectHelper.wrapRuntimeCamelException(new MethodNotFoundException(null, clazz, method, true));
250 }
251 }
252 }
253
254 return answer;
255 }
256
257 }