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 }