in axis-rt-core/src/main/java/org/apache/axis/client/Call.java [2403:2603]
public Object invoke( RPCElement body ) throws AxisFault {
if (log.isDebugEnabled()) {
log.debug("Enter: Call::invoke(RPCElement)");
}
/**
* Since JAX-RPC requires us to specify a return type if we've set
* parameter types, check for this case right now and toss a fault
* if things don't look right.
*/
if (!invokeOneWay && operation != null &&
operation.getNumParams() > 0 && getReturnType() == null) {
// TCK:
// Issue an error if the return type was not set, but continue processing.
//throw new AxisFault(Messages.getMessage("mustSpecifyReturnType"));
log.error(Messages.getMessage("mustSpecifyReturnType"));
}
SOAPEnvelope reqEnv =
new SOAPEnvelope(msgContext.getSOAPConstants(),
msgContext.getSchemaVersion());
SOAPEnvelope resEnv = null ;
Message reqMsg = new Message( reqEnv );
Message resMsg = null ;
Vector resArgs = null ;
Object result = null ;
// Clear the output params
outParams = new HashMap();
outParamsList = new ArrayList();
// Set both the envelope and the RPCElement encoding styles
try {
body.setEncodingStyle(getEncodingStyle());
setRequestMessage(reqMsg);
reqEnv.addBodyElement(body);
reqEnv.setMessageType(Message.REQUEST);
invoke();
} catch (Exception e) {
entLog.debug(Messages.getMessage("toAxisFault00"), e);
throw AxisFault.makeFault(e);
}
resMsg = msgContext.getResponseMessage();
if (resMsg == null) {
if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
throw new AxisFault(Messages.getMessage("nullResponse00"));
} else {
return null;
}
}
resEnv = resMsg.getSOAPEnvelope();
SOAPBodyElement bodyEl = resEnv.getFirstBody();
if (bodyEl == null) {
return null;
}
if (bodyEl instanceof RPCElement) {
try {
resArgs = ((RPCElement) bodyEl).getParams();
} catch (Exception e) {
log.error(Messages.getMessage("exception00"), e);
throw AxisFault.makeFault(e);
}
if (resArgs != null && resArgs.size() > 0) {
// If there is no return, then we start at index 0 to create the outParams Map.
// If there IS a return, then we start with 1.
int outParamStart = 0;
// If we have resArgs and the returnType is specified, then the first
// resArgs is the return. If we have resArgs and neither returnType
// nor paramXMLTypes are specified, then we assume that the caller is
// following the non-JAX-RPC AXIS shortcut of not having to specify
// the return, in which case we again assume the first resArgs is
// the return.
// NOTE 1: the non-JAX-RPC AXIS shortcut allows a potential error
// to escape notice. If the caller IS NOT following the non-JAX-RPC
// shortcut but instead intentionally leaves returnType and params
// null (ie., a method that takes no parameters and returns nothing)
// then, if we DO receive something it should be an error, but this
// code passes it through. The ideal solution here is to require
// this caller to set the returnType to void, but there's no void
// type in XML.
// NOTE 2: we should probably verify that the resArgs element
// types match the expected returnType and paramXMLTypes, but I'm not
// sure how to do that since the resArgs value is a Java Object
// and the returnType and paramXMLTypes are QNames.
// GD 03/15/02 : We're now checking for invalid metadata
// config at the top of this method, so don't need to do it
// here. Check for void return, though.
boolean findReturnParam = false;
QName returnParamQName = null;
if (operation != null) {
returnParamQName = operation.getReturnQName();
}
if (!XMLType.AXIS_VOID.equals(getReturnType())) {
if (returnParamQName == null) {
// Assume the first param is the return
RPCParam param = (RPCParam)resArgs.get(0);
result = param.getObjectValue();
outParamStart = 1;
} else {
// If the QName of the return value was given to us, look
// through the result arguments to find the right name
findReturnParam = true;
}
}
// The following loop looks at the resargs and
// converts the value to the appropriate return/out parameter
// value. If the return value is found, is value is
// placed in result. The remaining resargs are
// placed in the outParams list (note that if a resArg
// is found that does not match a operation parameter qname,
// it is still placed in the outParms list).
for (int i = outParamStart; i < resArgs.size(); i++) {
RPCParam param = (RPCParam) resArgs.get(i);
Class javaType = getJavaTypeForQName(param.getQName());
Object value = param.getObjectValue();
// Convert type if needed
if (javaType != null && value != null &&
!javaType.isAssignableFrom(value.getClass())) {
value = JavaUtils.convert(value, javaType);
}
// Check if this parameter is our return
// otherwise just add it to our outputs
if (findReturnParam &&
returnParamQName.equals(param.getQName())) {
// found it!
result = value;
findReturnParam = false;
} else {
outParams.put(param.getQName(), value);
outParamsList.add(value);
}
}
// added by scheu:
// If the return param is still not found, that means
// the returned value did not have the expected qname.
// The soap specification indicates that this should be
// accepted (and we also fail interop tests if we are strict here).
// Look through the outParms and find one that
// does not match one of the operation parameters.
if (findReturnParam) {
Iterator it = outParams.keySet().iterator();
while (findReturnParam && it.hasNext()) {
QName qname = (QName) it.next();
ParameterDesc paramDesc =
operation.getOutputParamByQName(qname);
if (paramDesc == null) {
// Doesn't match a paramter, so use this for the return
findReturnParam = false;
result = outParams.remove(qname);
}
}
}
// If we were looking for a particular QName for the return and
// still didn't find it, throw an exception
if (findReturnParam) {
String returnParamName = returnParamQName.toString();
throw new AxisFault(Messages.getMessage("noReturnParam",
returnParamName));
}
}
} else {
// This is a SOAPBodyElement, try to treat it like a return value
try {
result = bodyEl.getValueAsType(getReturnType());
} catch (Exception e) {
// just return the SOAPElement
result = bodyEl;
}
}
if (log.isDebugEnabled()) {
log.debug("Exit: Call::invoke(RPCElement)");
}
// Convert type if needed
if (operation != null && operation.getReturnClass() != null) {
result = JavaUtils.convert(result, operation.getReturnClass());
}
return( result );
}