/*
* Copyright (C) 2000 - 2008 TagServlet Ltd
*
* This file is part of Open BlueDragon (OpenBD) CFML Server Engine.
*
* OpenBD is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Free Software Foundation,version 3.
*
* OpenBD is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenBD. If not, see http://www.gnu.org/licenses/
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with any of the JARS listed in the README.txt (or a modified version of
* (that library), containing parts covered by the terms of that JAR, the
* licensors of this Program grant you additional permission to convey the
* resulting work.
* README.txt @ http://www.openbluedragon.org/license/README.txt
*
* http://www.openbluedragon.org/
*/
/*
* Created on Jan 3, 2005
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package com.naryx.tagfusion.cfm.xml.ws.dynws;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.rpc.holders.Holder;
import org.apache.axis.AxisFault;
import org.apache.axis.AxisProperties;
import org.apache.axis.client.Stub;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.utils.ClassUtils;
import org.w3c.dom.Document;
import com.naryx.tagfusion.cfm.engine.catchDataFactory;
import com.naryx.tagfusion.cfm.engine.cfCatchData;
import com.naryx.tagfusion.cfm.engine.cfData;
import com.naryx.tagfusion.cfm.engine.cfEngine;
import com.naryx.tagfusion.cfm.engine.cfStringData;
import com.naryx.tagfusion.cfm.engine.cfStructData;
import com.naryx.tagfusion.cfm.engine.cfWSParameter;
import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
import com.naryx.tagfusion.cfm.xml.ws.CallParameters;
/**
* Invokes the web service operation specified by the <cfinvoke> or cfWSObject
* object.
*/
public class DynamicWebServiceInvoker {
private DynamicWebServiceStubGeneratorInterface dws = null;
private List requestHeaders = null;
private SOAPHeaderElement[] responseHeaders = null;
private Document requestDoc = null;
private Document responseDoc = null;
private Stub currProxy = null;
private ParameterConverter converter = null;
/**
* Default constructor. Takes the path to the cache directory.
*
* @param javaCache
* path to the cache directory
* @param converter
* ParameterConverter for converting between web service types and BD
* types
*/
public DynamicWebServiceInvoker(String javaCache, ParameterConverter converter) {
this.dws = (DynamicWebServiceStubGeneratorInterface)cfEngine.thisPlatform.loadClass("com.naryx.tagfusion.cfm.xml.ws.javaplatform.DynamicWebServiceStubGenerator");
this.dws.setCacheDir(javaCache);
this.converter = converter;
this.requestHeaders = new LinkedList();
}
/**
* Uses the DynamicWebServiceStubGenerator to create an Axis Stub to execute.
*
* @param wsdlURL
* URL for the WSDL
* @param portName
* specified port binding name (or null)
* @param callParms
* proxy/connection specific settings
* @return Axis Stub that can execute the web service operation
* @throws cfmRunTimeException
*/
public Stub getStub(String wsdlURL, String portName, CallParameters callParms) throws cfmRunTimeException {
if (this.currProxy == null) {
// Generate and configure the proxy/stub
this.currProxy = this.dws.generateStub(wsdlURL, portName, callParms);
configureStub(this.currProxy, callParms);
}
return this.currProxy;
}
/**
* Configures the specified Stub with the specified CallParameters.
*
* @param stub
* Stub to configure
* @param callParms
* CalParameters containing the values to configure the Stub
* @throws cfmRunTimeException
*/
protected void configureStub(Stub stub, CallParameters callParms) throws cfmRunTimeException {
// Register the stub's classloader
getParameterConverter().registerLocalClassLoader(stub.getClass().getClassLoader());
// Set the timeout
stub.setTimeout(callParms.getTimeout());
// Set the credentials
if (callParms.getUsername() != null)
stub.setUsername(callParms.getUsername());
if (callParms.getPassword() != null)
stub.setPassword(callParms.getPassword());
}
/**
* Returns the ParameterConverter to help convert web service types to BD
* types.
*
* @return ParameterConverter
*/
public ParameterConverter getParameterConverter() {
return this.converter;
}
/**
* Adds the specified SOAP request header to the operation invocation.
*
* @param header
* SOAPHeaderElement to add
* @throws cfmRunTimeException
*/
public void addRequestHeader(SOAPHeaderElement header) throws cfmRunTimeException {
// If this same header exists, throw an exception
// (same meaning, identical namespace/name pair)
for (int i = 0; i < this.requestHeaders.size(); i++) {
SOAPHeaderElement h = (SOAPHeaderElement) this.requestHeaders.get(i);
if ((h.getNamespaceURI() == null && header.getNamespaceURI() == null && h.getName() == null && header.getName() == null) || (h.getNamespaceURI() != null && h.getNamespaceURI().equalsIgnoreCase(header.getNamespaceURI()) && h.getName() != null && h.getName().equalsIgnoreCase(header.getName())))
throw new cfmRunTimeException(catchDataFactory.generalException("errorCode.runtimeError", "SOAP header value: " + header.getNamespaceURI() + ":" + header.getName() + " already set."));
}
this.requestHeaders.add(header);
}
/**
* Returns the response SOAP headers.
*
* @return response SOAP headers
*/
public SOAPHeaderElement[] getResponseHeaders() {
return this.responseHeaders;
}
/**
* Returns the xml comprising the web service request.
*
* @return xml comprising the web service request
*/
public Object getRequestXml() {
return this.requestDoc;
}
/**
* Returns the xml comprising the web service response.
*
* @return xml comprising the web service response
*/
public Object getResponseXml() {
return this.responseDoc;
}
/**
* Invokes the web service operation specified and returns the response object
* (if any).
*
* @param wsdlURL
* URL for the web service WSDL
* @param portName
* name of the port binding (if any)
* @param callParms
* proxy/connection specific settings
* @param operationName
* name of the operation to execute
* @param parms
* user specified web service parameters
* @param outParms
* List of out parameters for the web service operation
* @return response object (if any)
* @throws cfmRunTimeException
*/
public Object invoke(String wsdlURL, String portName, CallParameters callParms, String operationName, cfWSParameter[] parms, List outParms) throws cfmRunTimeException {
String oldProxyHost = null;
String oldProxyPort = null;
String oldNonProxyHosts = null;
String nonProxyHosts = null;
String oldProxyUser = null;
String oldProxyPassword = null;
try {
// Get the stub
Stub stub = getStub(wsdlURL, portName, callParms);
// Find an operation with the correct name and the correct number
// of arguments (correct signature)
OperationSearchResult searchResult = findOperation(stub, operationName, this.dws.getStubInfo(), parms);
// Verify the operation was found
if (searchResult.method == null) {
// Try for a method instead
searchResult = findMethod(stub, operationName, this.dws.getStubInfo(), parms);
}
// Verify the method was found
if (searchResult.method == null) {
// Didn't find the operation method
throw noOperationMethodFound(operationName, searchResult, parms);
}
// Convert the parameters
Object[] params = convertParameters(searchResult, outParms);
if (searchResult.isWebServiceOperation) {
// Add the SOAPHeaderElements (if any)
for (int i = 0; i < this.requestHeaders.size(); i++)
stub.setHeader((SOAPHeaderElement) this.requestHeaders.get(i));
// Register the ClassLoader for all the classes
DynamicCacheClassLoader cl = (DynamicCacheClassLoader) stub.getClass().getClassLoader();
Class[] klasses = cl.findAllClasses();
for (int i = 0; i < klasses.length; i++) {
ClassUtils.setClassLoader(klasses[i].getName(), cl);
ClassUtils.setClassLoader("[L" + klasses[i].getName() + ";", cl);
}
if (callParms.getProxyServer() != null) {
// Set the proxy server settings
oldProxyHost = AxisProperties.getProperty("http.proxyHost");
System.setProperty("http.proxyHost", callParms.getProxyServer());
oldProxyPort = AxisProperties.getProperty("http.proxyPort");
System.setProperty("http.proxyPort", String.valueOf(callParms.getProxyPort()));
oldNonProxyHosts = AxisProperties.getProperty("http.nonProxyHosts");
if (oldNonProxyHosts == null)
oldNonProxyHosts = "";
nonProxyHosts = (oldNonProxyHosts.trim().equals("") ? "" : oldNonProxyHosts + "|");
nonProxyHosts += "localhost|127.0.0.1";
System.setProperty("http.nonProxyHosts", nonProxyHosts);
if (callParms.getProxyUser() != null || callParms.getProxyPassword() != null) {
// Set the proxy credentials
oldProxyUser = AxisProperties.getProperty("http.proxyUser");
System.setProperty("http.proxyUser", callParms.getProxyUser());
oldProxyPassword = AxisProperties.getProperty("http.proxyPassword");
System.setProperty("http.proxyPassword", callParms.getProxyPassword());
}
}
}
Object result = null;
try {
// Execute the method
result = searchResult.method.invoke(stub, params);
if (searchResult.isWebServiceOperation) {
// Get the request, response, and headers (if any)
this.responseHeaders = stub.getResponseHeaders();
this.requestDoc = stub._getCall().getMessageContext().getRequestMessage().getSOAPEnvelope().getAsDocument();
this.responseDoc = stub._getCall().getMessageContext().getResponseMessage().getSOAPEnvelope().getAsDocument();
// Update any in/out parameters.
Iterator itr = outParms.iterator();
while (itr.hasNext()) {
Object[] tuple = (Object[]) itr.next();
int i = ((Integer) tuple[0]).intValue();
tuple[0] = tuple[1];
tuple[1] = params[i];
}
}
} catch (Exception ex) {
StringBuilder buffy = new StringBuilder();
String faultString = null;
Throwable th = ex;
while (th != null) {
if (th instanceof AxisFault)
faultString = ((AxisFault) th).dumpToString();
buffy.append(th.getMessage() + " ");
th.printStackTrace();
th = th.getCause();
}
cfCatchData catchData = catchDataFactory.generalException("errorCode.runtimeError", "Invalid web service operation. Cannot call operation " + operationName + ". Error: " + buffy.toString());
if (faultString != null)
catchData.setExtendedInfo(faultString);
throw new cfmRunTimeException(catchData);
}
return result;
} finally {
if (oldProxyHost != null)
System.setProperty("http.proxyHost", oldProxyHost);
if (oldProxyPort != null)
System.setProperty("http.proxyPort", oldProxyPort);
if (oldNonProxyHosts != null)
System.setProperty("http.nonProxyHosts", oldNonProxyHosts);
if (oldProxyUser != null)
System.setProperty("http.proxyUser", oldProxyUser);
if (oldProxyPassword != null)
System.setProperty("http.proxyPassword", oldProxyPassword);
}
}
/**
* Returns a cfmRuntimeExcxeption suitable to throw that contains information
* regarding the operation not found.
*
* @param operationName
* name of the operatio we're looking for
* @param result
* OperationSearchResult from the operation search
* @param parms
* array of cfWSParameter parameters
* @return new cfmRuntimeException suitable to throw
*/
private cfmRunTimeException noOperationMethodFound(String operationName, OperationSearchResult result, cfWSParameter[] parms) {
// Describe the parameter types we're looking for
StringBuilder paramTypes = new StringBuilder("{ ");
boolean first = true;
for (int i = 0; i < parms.length; i++) {
if (!first)
paramTypes.append(", ");
if (parms[i] == null) {
paramTypes.append("null");
first = false;
} else if (!parms[i].isOmit() && parms[i].getVal() != null) {
paramTypes.append(parms[i].getVal().getDataTypeName());
if (parms[i].getName() != null)
paramTypes.append(" (" + parms[i].getName() + ")");
first = false;
} else if (!parms[i].isOmit()) {
paramTypes.append(parms[i].getVal().getClass().getName());
if (parms[i].getName() != null)
paramTypes.append(" (" + parms[i].getName() + ")");
first = false;
}
}
paramTypes.append(" }");
// Describe the closest match we found (if any)
StringBuilder closest = new StringBuilder();
if (result.closestOp != null) {
boolean userPassParams = false;
closest.append(". The closest match found was: ");
closest.append(result.closestOp.getName());
closest.append("(");
first = true;
for (int i = 0; i < result.closestOp.getParameters().length; i++) {
if (!first)
closest.append(", ");
else
first = false;
closest.append(result.closestOp.getParameters()[i].getName());
if (result.closestOp.getParameters()[i].getName().equalsIgnoreCase("USERNAME") || result.closestOp.getParameters()[i].getName().equalsIgnoreCase("PASSWORD"))
userPassParams = true;
}
closest.append(").");
if (userPassParams)
closest.append(" Be sure to specify the username and/or password arguments using " + " <CFINVOKEARGUMENT> or as an entry in a struct for <CFINVOKE>'s ARGUMENTCOLLECTION attribute.");
if (result.closestOpMsg != null)
closest.append(" Also please note. " + result.closestOpMsg);
}
// Throw the exception
return new cfmRunTimeException(catchDataFactory.generalException("errorCode.runtimeError", "Invalid web service operation. Cannot locate operation " + operationName + " that accepts parameters: " + paramTypes.toString() + closest.toString()));
}
/**
* Looks for the correct operation on the Stub that matches the specified
* operationName and parms. The search will attempt to match up argument names
* if they are specified. Additionally, for 1 arg operations, a convenience
* search is performed that will match individual parms to a single arg
* operation if the parms are named and they correspond to the names for the
* properties of the single argument type.
*
* Operations with the most arguments will be attempt to be matched first
* using all specified parameters (including those marked omitted).
*
* @param stub
* Axis Stub to execute
* @param operationName
* name of the operation
* @param stubInfo
* web service WSDL operation/parameter information
* @param parms
* user specified parameters
* @return results of searching for the web service operation
*/
private OperationSearchResult findOperation(Stub stub, String operationName, StubInfo stubInfo, cfWSParameter[] parms) {
OperationSearchResult result = new OperationSearchResult();
result.isWebServiceOperation = true;
// Create a name indexed Map for easy parm access
HashMap parmMap = new HashMap();
int nonOmittedParmCount = 0;
for (int i = 0; i < parms.length; i++) {
if (!parms[i].isOmit())
nonOmittedParmCount++;
if (parms[i].getName() != null)
parmMap.put(parms[i].getName().trim().toLowerCase(), parms[i]);
}
// Get all the operations with the correct name and order them by
// number of parameters, descending.
LinkedList operations = new LinkedList();
for (int i = 0; i < stubInfo.getOperations().length; i++) {
if (stubInfo.getOperations()[i].getName().equalsIgnoreCase(operationName))
operations.add(stubInfo.getOperations()[i]);
}
Collections.sort(operations, new Comparator() {
public int compare(Object o1, Object o2) {
return (((StubInfo.Operation) o2).getParameters().length - ((StubInfo.Operation) o1).getParameters().length);
}
});
// Examine all the operations
Iterator itr = operations.iterator();
while (itr.hasNext()) {
// Try to match up the parameters
StubInfo.Operation operation = (StubInfo.Operation) itr.next();
StubInfo.Parameter[] parameters = operation.getParameters();
examineOperation(result, operation, parameters, parms, (HashMap) parmMap.clone(), nonOmittedParmCount);
if (result.foundOp != null)
break;
}
if (result.foundOp == null) {
// Examine all the 1 arg operations using the single argument's
// type definition as the argument parameters.
itr = operations.iterator();
while (itr.hasNext()) {
// Try to match up the sub parameters
StubInfo.Operation operation = (StubInfo.Operation) itr.next();
if (operation.getParameters().length == 1) {
StubInfo.Parameter[] parameters = operation.getSubParameters();
if (parameters != null && parameters.length > 0) {
examineOperation(result, operation, parameters, parms, (HashMap) parmMap.clone(), nonOmittedParmCount);
if (result.foundOp != null) {
result.singleArgUnwrap = true;
break;
}
}
}
}
}
if (result.foundOp != null) {
// Get the method equivalent
Method[] methods = stub.getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (Modifier.isPublic(methods[i].getModifiers()) && methods[i].getName().equalsIgnoreCase(result.foundOp.getName())) {
int argCount = methods[i].getParameterTypes().length;
if ((result.singleArgUnwrap && argCount == 1) || (!result.singleArgUnwrap && argCount == result.foundOp.getParameters().length)) {
result.method = methods[i];
break;
}
}
}
}
return result;
}
/**
* Looks for the correct local method (i.e. not a web service operation proxy
* method) on the Stub that matches the specified operationName and parms.
*
* Operations with the most arguments will be matched first using all
* specified parameters.
*
* @param stub
* Axis Stub to execute
* @param operationName
* name of the operation
* @param stubInfo
* web service WSDL operation/parameter information
* @param parms
* user specified parameters
* @return results of searching for the web service operation
*/
private OperationSearchResult findMethod(Stub stub, String operationName, StubInfo stubInfo, cfWSParameter[] parms) {
OperationSearchResult result = new OperationSearchResult();
result.isWebServiceOperation = false;
// Get all the methods with the correct name and order them by
// number of parameters, descending.
Method[] methods = stub.getClass().getMethods();
LinkedList operations = new LinkedList();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equalsIgnoreCase(operationName))
operations.add(methods[i]);
}
Collections.sort(operations, new Comparator() {
public int compare(Object o1, Object o2) {
return (((Method) o2).getParameterTypes().length - ((Method) o1).getParameterTypes().length);
}
});
// Examine all the methods
Iterator itr = operations.iterator();
while (itr.hasNext()) {
// Try to match up the parameters
Method operation = (Method) itr.next();
examineMethod(result, operation, parms);
if (result.method != null)
break;
}
return result;
}
/**
* Examines the specified web service operation to see if it is the one that
* needs to be executed. Populates the OperationSearchResult with the
* operation information if this is indeed the correct operation.
*
* @param result
* results of searching for the web service operation
* @param operation
* WSDL operation info
* @param parameters
* WSDL parameters for the operation
* @param parms
* user supplied parameters
* @param parmMap
* Map of user supplied parameters
* @param nonOmittedParmCount
* number of user supplied parameters that are not marked omit=true
*/
private void examineOperation(OperationSearchResult result, StubInfo.Operation operation, StubInfo.Parameter[] parameters, cfWSParameter[] parms, Map parmMap, int nonOmittedParmCount) {
// Try to match up the parameters
result.closestOp = operation;
result.closestOpMsg = null;
if (parameters.length == 0) {
// No matching needed, operation is a no-arg operation so we
// shouldn't have any parameters we need to send. Since we've
// examined all the operations with arguments first, we know
// we're not choosing this over an operation that has args
// but that just all happen to be "omitted".
if (nonOmittedParmCount == 0) {
result.foundOp = result.closestOp;
result.usableParms = new cfWSParameter[0];
return;
}
} else if (parms.length > 0) {
if (parms[0].getName() == null) {
// No names for these parameters, so match up by total count.
// All parms will be non-omitted as there's no way to specify
// an omit=true if the names are null (i.e. via the
// function(arg1, arg2, ... ) style).
if (parameters.length == parms.length) {
result.foundOp = result.closestOp;
result.usableParms = parms;
return;
}
} else {
// Parameters are named, so try to match them up with the names
// known to the WSDL (i.e. the StubInfo.Parameter names).
LinkedList usableParms = new LinkedList();
boolean correctMatch = true;
for (int j = 0; j < parameters.length; j++) {
// Get the parameter name
String parmName = parameters[j].getName().trim().toLowerCase();
cfWSParameter parm = findParameter(j, parmName, parms);
if (parm == null) {
// Not the right operation
correctMatch = false;
break;
} else {
if (parm.isOmit() && !parameters[j].getNillable() && !parameters[j].getOmittable()) {
// Cannot omit this parameter
result.closestOpMsg = "Parameter: " + parmName + " cannot be omitted according to the web service WSDL.";
correctMatch = false;
break;
} else {
// Remove it from our specified parms collection, add it to
// our usable parms collection, and continue
usableParms.add(parmMap.remove(parm.getName().toLowerCase()));
}
}
}
if (correctMatch) {
// See if we found an operation that uses all the parameters
Iterator tmpItr = parmMap.values().iterator();
while (tmpItr.hasNext()) {
cfWSParameter parm = (cfWSParameter) tmpItr.next();
if (!parm.isOmit()) {
// Didn't use all the parameters specified
correctMatch = false;
break;
}
}
}
if (correctMatch) {
// We've used all the non-omitted parameters and possibly some of the
// omitted ones (if the WSDL allows it), and we're not missing any
// parameters.
result.foundOp = result.closestOp;
result.usableParms = (cfWSParameter[]) usableParms.toArray(new cfWSParameter[usableParms.size()]);
}
}
}
}
/**
* Examines the specified Method to see if it is the one that needs to be
* executed. Populates the OperationSearchResult with the method information
* if this is indeed the correct method.
*
* @param result
* results of searching for the local method
* @param operation
* Method matching the operation name
* @param parms
* user supplied parameters
*/
private void examineMethod(OperationSearchResult result, Method operation, cfWSParameter[] parms) {
Class[] parameterTypes = operation.getParameterTypes();
// Try to match up the parameters
if (parameterTypes.length == 0) {
// No matching needed, method is a no-arg method so we
// shouldn't have any parameters we need to send. Since we've
// examined all the method with arguments first, we know
// we're not choosing this over a method that has args.
if (parms.length == 0) {
result.method = operation;
result.usableParms = new cfWSParameter[0];
return;
}
} else if (parms.length > 0) {
// No names/types for these parameters, so match up by total count
// (i.e. via the function(arg1, arg2, ... ) style).
if (parameterTypes.length == parms.length) {
result.method = operation;
result.usableParms = parms;
return;
}
}
}
/**
* Converts the user specified parameters into the expected web service
* operation argument types and returns them as an Object array.
*
* @param result
* results of the web service operation search
* @param outParms
* List of out parameters for the web service operation
* @return array of converted parameters
* @throws cfmRunTimeException
*/
private Object[] convertParameters(OperationSearchResult result, List outParms) throws cfmRunTimeException {
// Check the arguments and get the values from each parameter
Class[] parmKlass = result.method.getParameterTypes();
Object[] rtn = new Object[parmKlass.length];
if (result.singleArgUnwrap) {
// We need to "wrap up" all the parameters as if they
// were supplied as struct attributes (this is a convenience
// enhancement for developers that don't read WSDL very well).
// Note, this means there should only be a single argument
// to the result.method.
cfStructData struct = new cfStructData();
for (int i = 0; i < result.usableParms.length; i++) {
if (!result.usableParms[i].isOmit())
struct.setData(result.usableParms[i].getName(), result.usableParms[i].getVal());
}
rtn[0] = convertParameter(0, result.foundOp.getParameters()[0].getName(), struct, parmKlass[0], outParms);
} else {
// For each method argument, find the parameter value in
// result.usableParms and convert it. The name for method
// argument i should be the name in the StubInfo.Operation
// at the same position.
for (int i = 0; i < parmKlass.length; i++) {
String name = null;
if (result.foundOp != null && result.foundOp.getParameters() != null)
name = result.foundOp.getParameters()[i].getName();
cfWSParameter parm = findParameter(i, name, result.usableParms);
if (parm == null) {
throw new cfmRunTimeException(catchDataFactory.generalException("errorCode.runtimeError", "Invalid web service parameters supplied. Missing value for " + (name == null ? "position " + String.valueOf(i) : name)));
}
if (!parm.isOmit())
rtn[i] = convertParameter(i, name, parm.getVal(), parmKlass[i], outParms);
}
}
return rtn;
}
/**
* Returns the cfWSParameter from the array of parms with the specified name
* (or at the specified position).
*
* @param methodArgNdx
* position of the parameter in the web service operation
* @param name
* name of the parameter in the web service operation
* @param parms
* array of cfWSParameters to search
* @return cfWSParameter from the array of parms with the specified name (or
* at the specified position)
*/
private cfWSParameter findParameter(int methodArgNdx, String name, cfWSParameter[] parms) {
if (parms[0].getName() == null || name == null) {
// No parameter names so let's just hope the array of
// parameters matches up with the method arguments
return parms[methodArgNdx];
} else {
// Find the parameter with the specified name
for (int i = 0; i < parms.length; i++) {
if (parms[i].getName().equalsIgnoreCase(name))
return parms[i];
}
}
return null;
}
/**
* Converts the specified user supplied parameter (val) into the target type
* using this instance's ParameterConverter. Populates the List of outParms in
* the process. Returns the converted parameter.
*
* @param methodArgNdx
* position of the parameter in the operation
* @param name
* name of the parameter in the operation
* @param val
* user supplied parameter
* @param targetClass
* type to which we need to convert the user supplied parameter
* @param outParms
* List of out parameters, we populate this list if the user
* parameter is of the out or in/out type.
* @return converted parameter
* @throws cfmRunTimeException
*/
private Object convertParameter(int methodArgNdx, String name, cfData val, Class targetClass, List outParms) throws cfmRunTimeException {
Object rtn = this.getParameterConverter().toWebServiceType(val, targetClass);
// See if it's an out parameter (denoted by the Holder class)
if (rtn != null && Holder.class.isAssignableFrom(rtn.getClass())) {
// We'll use the value of string out parameters as the name
// of a new variable to create with the returned (out) value.
// If the out parameter isn't a string, then use the name of
// that non-string out parameter as the name of the variable
// to assign the returned (out) value.
if (val instanceof cfStringData)
outParms.add(new Object[] { new Integer(methodArgNdx), val.toString() });
else if (name != null)
outParms.add(new Object[] { new Integer(methodArgNdx), name });
}
return rtn;
}
/**
* Value object used to hold the results of searching for the correct web
* service operation.
*/
private class OperationSearchResult {
public Method method = null;
public StubInfo.Operation foundOp = null;
public StubInfo.Operation closestOp = null;
public String closestOpMsg = null;
public boolean singleArgUnwrap = false;
public cfWSParameter[] usableParms = null;
public boolean isWebServiceOperation = false;
public OperationSearchResult() {
}
}
}