1 10 11 package org.mule.model; 12 13 import org.apache.commons.logging.Log; 14 import org.apache.commons.logging.LogFactory; 15 import org.mule.config.MuleProperties; 16 import org.mule.config.i18n.Message; 17 import org.mule.config.i18n.Messages; 18 import org.mule.impl.MuleMessage; 19 import org.mule.impl.RequestContext; 20 import org.mule.providers.NullPayload; 21 import org.mule.umo.UMOEventContext; 22 import org.mule.umo.lifecycle.Callable; 23 import org.mule.umo.model.UMOEntryPoint; 24 import org.mule.util.ClassUtils; 25 26 import java.lang.reflect.InvocationTargetException ; 27 import java.lang.reflect.Method ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 39 40 public class DynamicEntryPoint implements UMOEntryPoint 41 { 42 45 protected static final Log logger = LogFactory.getLog(DynamicEntryPoint.class); 46 47 private Map entryPoints = new HashMap (); 48 private Method currentMethod; 49 50 protected String [] ignoreMethods = new String []{"equals", "getInvocationHandler"}; 53 54 public Class [] getParameterTypes() 55 { 56 if (currentMethod == null) 57 { 58 return null; 59 } 60 return currentMethod.getParameterTypes(); 61 } 62 63 public synchronized Object invoke(Object component, UMOEventContext context) throws Exception 64 { 65 Object payload = null; 66 Method method = null; 67 68 Boolean ignoreMethod = (Boolean )context.getMessage().removeProperty( 70 MuleProperties.MULE_IGNORE_METHOD_PROPERTY); 71 boolean ignore = (ignoreMethod == null ? false : ignoreMethod.booleanValue()); 72 73 if (!ignore) 74 { 75 Object methodOverride = context.getMessage().removeProperty(MuleProperties.MULE_METHOD_PROPERTY); 77 if (methodOverride instanceof Method ) 78 { 79 method = (Method )methodOverride; 80 } 81 else if (methodOverride != null) 82 { 83 payload = context.getTransformedMessage(); 84 method = ClassUtils.getMethod(methodOverride.toString(), ClassUtils.getClassTypes(payload), 87 component.getClass()); 88 validateMethod(component, method, methodOverride.toString()); 89 } 90 } 91 92 if (method == null) 93 { 94 if (component instanceof Callable) 95 { 96 method = Callable.class.getMethods()[0]; 97 payload = context; 98 } 99 if (method == null) 100 { 101 method = getMethod(component, context); 102 if (method == null) 103 { 104 payload = context.getTransformedMessage(); 105 method = getMethod(component, payload); 106 if (method != null) 107 { 108 RequestContext.rewriteEvent(new MuleMessage(payload, context.getMessage())); 109 } 110 } 111 else 112 { 113 payload = context; 114 } 115 } 116 } 117 if (method != null) 118 { 119 validateMethod(component, method, method.getName()); 120 121 currentMethod = method; 122 if (payload == null) 123 { 124 payload = context.getTransformedMessage(); 125 RequestContext.rewriteEvent(new MuleMessage(payload, context.getMessage())); 126 } 127 return invokeCurrent(component, payload); 128 } 129 130 List methods = ClassUtils.getSatisfiableMethods(component.getClass(), 132 ClassUtils.getClassTypes(context), true, false, ignoreMethods); 133 if (methods.size() > 1) 134 { 135 TooManySatisfiableMethodsException tmsmex = new TooManySatisfiableMethodsException( 136 component.getClass()); 137 throw new InvocationTargetException (tmsmex, "There must be only one method accepting " 138 + context.getClass().getName() + " in component " 139 + component.getClass().getName()); 140 } 141 else if (methods.size() == 1) 142 { 143 if (logger.isDebugEnabled()) 144 { 145 logger.debug("Dynamic Entrypoint using method: " + component.getClass().getName() + "." 146 + ((Method )methods.get(0)).getName() + "(" + context.getClass().getName() + ")"); 147 } 148 addMethod(component, (Method )methods.get(0), context.getClass()); 149 return invokeCurrent(component, context); 150 } 151 else 152 { 153 methods = ClassUtils.getSatisfiableMethods(component.getClass(), 154 ClassUtils.getClassTypes(payload), true, true, ignoreMethods); 155 if (methods.size() > 1) 156 { 157 throw new TooManySatisfiableMethodsException(component.getClass()); 158 } 159 if (methods.size() == 1) 160 { 161 if (logger.isDebugEnabled()) 162 { 163 logger.debug("Dynamic Entrypoint using method: " + component.getClass().getName() + "." 164 + ((Method )methods.get(0)).getName() + "(" + payload.getClass().getName() 165 + ")"); 166 } 167 addMethod(component, (Method )methods.get(0), payload.getClass()); 168 return invokeCurrent(component, payload); 169 } 170 else 171 { 172 throw new NoSatisfiableMethodsException(component.getClass(), 173 ClassUtils.getClassTypes(payload)); 174 } 175 } 176 } 177 178 187 protected void validateMethod(Object component, Method method, String methodName) throws Exception 188 { 189 boolean fallback = component instanceof Callable; 190 if (method == null && !fallback) 191 { 192 throw new NoSuchMethodException (new Message(Messages.METHOD_X_WITH_PARAMS_X_NOT_FOUND_ON_X, 193 methodName, "unknown", component.getClass().getName()).toString()); 194 } 195 try 197 { 198 component.getClass().getMethod(method.getName(), method.getParameterTypes()); 199 } 200 catch (Exception e) 201 { 202 if (!fallback) throw e; 203 } 204 } 205 206 protected Method getMethod(Object component, Object arg) 207 { 208 return (Method )entryPoints.get(component.getClass().getName() + ":" + arg.getClass().getName()); 209 } 210 211 protected void addMethod(Object component, Method method, Class arg) 212 { 213 entryPoints.put(component.getClass().getName() + ":" + arg.getName(), method); 214 currentMethod = method; 215 } 216 217 226 private Object invokeCurrent(Object component, Object arg) 227 throws InvocationTargetException , IllegalAccessException 228 { 229 String methodCall = null; 230 if (logger.isDebugEnabled()) 231 { 232 methodCall = component.getClass().getName() + "." + currentMethod.getName() + "(" 233 + arg.getClass().getName() + ")"; 234 logger.debug("Invoking " + methodCall); 235 } 236 237 Object [] args; 238 if (arg.getClass().isArray()) 239 { 240 if (Object [].class.isAssignableFrom(arg.getClass())) 241 { 242 args = (Object [])arg; 243 } 244 else 245 { 246 args = new Object []{arg}; 247 } 248 } 249 else if (arg instanceof NullPayload) 250 { 251 args = null; 252 } 253 else 254 { 255 args = new Object []{arg}; 256 } 257 Object result = currentMethod.invoke(component, args); 258 if (logger.isDebugEnabled()) 259 { 260 logger.debug("Result of call " + methodCall + " is " + (result == null ? "null" : "not null")); 261 } 262 return result; 263 } 264 265 public boolean isVoid() 266 { 267 if (currentMethod == null) 268 { 269 return false; 270 } 271 return currentMethod.getReturnType().getName().equals("void"); 272 } 273 274 public String getMethodName() 275 { 276 if (currentMethod == null) 277 { 278 return null; 279 } 280 return currentMethod.getName(); 281 } 282 } 283 | Popular Tags |