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 @XmlAttribute 052 private Boolean cache; 053 @XmlTransient 054 private Class<?> beanClass; 055 @XmlTransient 056 private Object bean; 057 058 public BeanDefinition() { 059 } 060 061 public BeanDefinition(String ref) { 062 this.ref = ref; 063 } 064 065 public BeanDefinition(String ref, String method) { 066 this.ref = ref; 067 this.method = method; 068 } 069 070 @Override 071 public String toString() { 072 return "Bean[" + description() + "]"; 073 } 074 075 public String description() { 076 if (ref != null) { 077 String methodText = ""; 078 if (method != null) { 079 methodText = " method: " + method; 080 } 081 return "ref:" + ref + methodText; 082 } else if (bean != null) { 083 return bean.toString(); 084 } else if (beanClass != null) { 085 return beanClass.getName(); 086 } else if (beanType != null) { 087 return beanType; 088 } else { 089 return ""; 090 } 091 } 092 093 @Override 094 public String getLabel() { 095 return "bean[" + description() + "]"; 096 } 097 098 @Override 099 public String getShortName() { 100 return "bean"; 101 } 102 103 public String getRef() { 104 return ref; 105 } 106 107 public void setRef(String ref) { 108 this.ref = ref; 109 } 110 111 public String getMethod() { 112 return method; 113 } 114 115 public void setMethod(String method) { 116 this.method = method; 117 } 118 119 public void setBean(Object bean) { 120 this.bean = bean; 121 } 122 123 public String getBeanType() { 124 return beanType; 125 } 126 127 public void setBeanType(String beanType) { 128 this.beanType = beanType; 129 } 130 131 public void setBeanType(Class<?> beanType) { 132 this.beanClass = beanType; 133 } 134 135 public Boolean getCache() { 136 return cache; 137 } 138 139 public void setCache(Boolean cache) { 140 this.cache = cache; 141 } 142 143 // Fluent API 144 //------------------------------------------------------------------------- 145 /** 146 * Sets the ref String on camel bean 147 * 148 * @param ref the bean's id in the registry 149 * @return the builder 150 * @deprecated not in use, will be removed in next Camel release 151 */ 152 @Deprecated 153 public BeanDefinition ref(String ref) { 154 setRef(ref); 155 return this; 156 } 157 158 /** 159 * Sets the calling method name of camel bean 160 * 161 * @param method the bean's method name which wants camel to call 162 * @return the builder 163 * @deprecated not in use, will be removed in next Camel release 164 */ 165 @Deprecated 166 public BeanDefinition method(String method) { 167 setMethod(method); 168 return this; 169 } 170 171 /** 172 * Sets the bean's instance that camel to call 173 * 174 * @param bean the instance of the bean 175 * @return the builder 176 * @deprecated not in use, will be removed in next Camel release 177 */ 178 @Deprecated 179 public BeanDefinition bean(Object bean) { 180 setBean(bean); 181 return this; 182 } 183 184 /** 185 * Sets the Class of the bean 186 * 187 * @param beanType the Class of the bean 188 * @return the builder 189 * @deprecated not in use, will be removed in next Camel release 190 */ 191 @Deprecated 192 public BeanDefinition beanType(Class<?> beanType) { 193 setBeanType(beanType); 194 return this; 195 } 196 197 /** 198 * Caches the bean lookup, to avoid lookup up bean on every usage. 199 * 200 * @return the builder 201 */ 202 @Deprecated 203 public BeanDefinition cache() { 204 setCache(true); 205 return this; 206 } 207 208 @Override 209 public Processor createProcessor(RouteContext routeContext) throws Exception { 210 BeanProcessor answer; 211 Class<?> clazz = bean != null ? bean.getClass() : null; 212 BeanHolder beanHolder; 213 214 if (ObjectHelper.isNotEmpty(ref)) { 215 if (cache != null && cache) { 216 // cache the registry lookup which avoids repeat lookup in the registry 217 beanHolder = new RegistryBean(routeContext.getCamelContext(), ref).createCacheHolder(); 218 } else { 219 beanHolder = new RegistryBean(routeContext.getCamelContext(), ref); 220 } 221 // bean holder will check if the bean exists 222 bean = beanHolder.getBean(); 223 answer = new BeanProcessor(beanHolder); 224 } else { 225 if (bean == null) { 226 227 if (beanType == null && beanClass == null) { 228 throw new IllegalArgumentException("bean, ref or beanType must be provided"); 229 } 230 231 // the clazz is either from beanType or beanClass 232 if (beanType != null) { 233 try { 234 clazz = routeContext.getCamelContext().getClassResolver().resolveMandatoryClass(beanType); 235 } catch (ClassNotFoundException e) { 236 throw ObjectHelper.wrapRuntimeCamelException(e); 237 } 238 } else { 239 clazz = beanClass; 240 } 241 242 // create a bean if there is a default public no-arg constructor 243 if (ObjectHelper.hasDefaultPublicNoArgConstructor(clazz)) { 244 bean = CamelContextHelper.newInstance(routeContext.getCamelContext(), clazz); 245 ObjectHelper.notNull(bean, "bean", this); 246 } 247 } 248 249 // validate the bean type is not from java so you by mistake think its a reference 250 // to a bean name but the String is being invoke instead 251 if (bean instanceof String) { 252 throw new IllegalArgumentException("The bean instance is a java.lang.String type: " + bean 253 + ". We suppose you want to refer to a bean instance by its id instead. Please use beanRef."); 254 } 255 256 // the holder should either be bean or type based 257 beanHolder = bean != null ? new ConstantBeanHolder(bean, routeContext.getCamelContext()) : new ConstantTypeBeanHolder(clazz, routeContext.getCamelContext()); 258 answer = new BeanProcessor(beanHolder); 259 } 260 261 // check for method exists 262 if (method != null) { 263 answer.setMethod(method); 264 265 // check there is a method with the given name, and leverage BeanInfo for that 266 BeanInfo beanInfo = beanHolder.getBeanInfo(); 267 if (bean != null) { 268 // there is a bean instance, so check for any methods 269 if (!beanInfo.hasMethod(method)) { 270 throw ObjectHelper.wrapRuntimeCamelException(new MethodNotFoundException(null, bean, method)); 271 } 272 } else if (clazz != null) { 273 // there is no bean instance, so check for static methods only 274 if (!beanInfo.hasStaticMethod(method)) { 275 throw ObjectHelper.wrapRuntimeCamelException(new MethodNotFoundException(null, clazz, method, true)); 276 } 277 } 278 } 279 280 return answer; 281 } 282 283 }