001: /*
002: * $Id: MethodHeaderPropertyEntryPointResolver.java 10489 2008-01-23 17:53:38Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010: package org.mule.model.resolvers;
011:
012: import org.mule.api.MuleEventContext;
013: import org.mule.api.config.MuleProperties;
014: import org.mule.api.lifecycle.Callable;
015: import org.mule.api.model.InvocationResult;
016: import org.mule.config.i18n.CoreMessages;
017: import org.mule.util.ClassUtils;
018:
019: import java.lang.reflect.Method;
020:
021: import org.apache.commons.lang.BooleanUtils;
022:
023: /**
024: * This resolver will look for a 'method' property on the incoming event to determine which method to invoke
025: * Users can customise the name of the property used to look up the method name on the event
026: */
027: public class MethodHeaderPropertyEntryPointResolver extends
028: AbstractEntryPointResolver {
029:
030: private String methodProperty = MuleProperties.MULE_METHOD_PROPERTY;
031:
032: public String getMethodProperty() {
033: return methodProperty;
034: }
035:
036: public void setMethodProperty(String methodProperty) {
037: this .methodProperty = methodProperty;
038: }
039:
040: public InvocationResult invoke(Object component,
041: MuleEventContext context) throws Exception {
042: //TODO: RM* This is a hack that can be fixed by introducing property scoping on the message
043: // Transports such as SOAP need to ignore the method property
044: boolean ignoreMethod = BooleanUtils.toBoolean((Boolean) context
045: .getMessage().removeProperty(
046: MuleProperties.MULE_IGNORE_METHOD_PROPERTY));
047:
048: if (ignoreMethod) {
049: //TODO: Removed once we have property scoping
050: InvocationResult result = new InvocationResult(
051: InvocationResult.STATE_INVOKE_NOT_SUPPORTED);
052: result.setErrorMessage("Property: "
053: + MuleProperties.MULE_IGNORE_METHOD_PROPERTY
054: + " was set so skipping this resolver: " + this );
055: return result;
056: }
057:
058: //TODO: with scoped properties we wouldn't need to remove the property here
059: Object methodProp = context.getMessage().removeProperty(
060: getMethodProperty());
061: if (methodProp == null) {
062: InvocationResult result = new InvocationResult(
063: InvocationResult.STATE_INVOKED_FAILED);
064: // no method for the explicit method header
065: result.setErrorMessage(CoreMessages
066: .propertyIsNotSetOnEvent(getMethodProperty())
067: .toString());
068: return result;
069: }
070:
071: Method method;
072: String methodName;
073: if (methodProp instanceof Method) {
074: method = (Method) methodProp;
075: methodName = method.getName();
076: } else {
077: methodName = methodProp.toString();
078: method = getMethodByName(methodName, context);
079: }
080:
081: if (method != null && method.getParameterTypes().length == 0) {
082: return invokeMethod(component, method,
083: ClassUtils.NO_ARGS_TYPE);
084: }
085:
086: Object[] payload = getPayloadFromMessage(context);
087:
088: if (method == null) {
089: Class[] classTypes = ClassUtils.getClassTypes(payload);
090: try {
091: method = component.getClass().getMethod(methodName,
092: classTypes);
093: } catch (NoSuchMethodException e) {
094: InvocationResult result = new InvocationResult(
095: InvocationResult.STATE_INVOKED_FAILED);
096: result.setErrorNoMatchingMethods(component, classTypes,
097: this );
098: return result;
099:
100: }
101: }
102:
103: validateMethod(component, method);
104: addMethodByName(method, context);
105:
106: return invokeMethod(component, method, payload);
107:
108: }
109:
110: /**
111: * This method can be used to validate that the method exists and is allowed to
112: * be executed.
113: */
114: protected void validateMethod(Object component, Method method)
115: throws NoSuchMethodException {
116: boolean fallback = component instanceof Callable;
117:
118: if (method != null) {
119: // This will throw NoSuchMethodException if it doesn't exist
120: try {
121: component.getClass().getMethod(method.getName(),
122: method.getParameterTypes());
123: } catch (NoSuchMethodException e) {
124: if (!fallback) {
125: throw e;
126: }
127: }
128: } else {
129: if (!fallback) {
130: throw new NoSuchMethodException(CoreMessages
131: .methodWithParamsNotFoundOnObject("null",
132: "unknown", component.getClass())
133: .toString());
134: }
135: }
136: }
137:
138: public String toString() {
139: final StringBuffer sb = new StringBuffer();
140: sb.append("MethodHeaderPropertyEntryPointResolver");
141: sb.append("{methodHeader=").append(methodProperty);
142: sb.append("transformFirst=").append(isTransformFirst());
143: sb.append(", acceptVoidMethods=").append(isAcceptVoidMethods());
144: sb.append('}');
145: return sb.toString();
146: }
147:
148: }
|