/* Loop over each entry in the SOAPBody - each one is a different */
/* RPC call. */
/******************************************************************/
for ( int bNum = 0 ; bNum < bodies.size() ; bNum++ ) {
RPCElement body;
// If this is a regular old SOAPBodyElement, and it's a root,
// we're probably a non-wrapped doc/lit service. In this case,
// we deserialize the element, and create an RPCElement "wrapper"
// around it which points to the correct method.
// FIXME : There should be a cleaner way to do this...
if (!(bodies.get(bNum) instanceof RPCElement)) {
SOAPBodyElement bodyEl = (SOAPBodyElement)bodies.get(bNum);
// igors: better check if bodyEl.getID() != null
// to make sure this loop does not step on SOAP-ENC objects
// that follow the parameters! FIXME?
if (bodyEl.isRoot() && operation != null) {
ParameterDesc param = operation.getParameter(bNum);
// at least do not step on non-existent parameters!
if(param != null) {
Object val = bodyEl.getValueAsType(param.getTypeQName());
body = new RPCElement("",
operation.getName(),
new Object [] { val });
}
else continue;
} else {
continue;
}
} else {
body = (RPCElement) bodies.get( bNum );
}
String methodName = body.getMethodName();
Vector args = body.getParams();
int numArgs = args.size();
// This may have changed, so get it again...
// FIXME (there should be a cleaner way to do this)
operation = msgContext.getOperation();
if (operation == null) {
QName qname = new QName(body.getNamespaceURI(),
body.getName());
operation = serviceDesc.getOperationByElementQName(qname);
}
if (operation == null) {
throw new AxisFault(JavaUtils.getMessage("noSuchOperation",
methodName));
}
// Create the array we'll use to hold the actual parameter
// values. We know how big to make it from the metadata.
Object[] argValues = new Object [operation.getNumParams()];
// A place to keep track of the out params (INOUTs and OUTs)
ArrayList outs = new ArrayList();
// Put the values contained in the RPCParams into an array
// suitable for passing to java.lang.reflect.Method.invoke()
// Make sure we respect parameter ordering if we know about it
// from metadata, and handle whatever conversions are necessary
// (values -> Holders, etc)
if ( args != null && args.size() > 0 ) {
for ( int i = 0 ; i < numArgs ; i++ ) {
RPCParam rpcParam = (RPCParam)args.get(i);
Object value = rpcParam.getValue();
ParameterDesc paramDesc = rpcParam.getParamDesc();
if (paramDesc != null && paramDesc.getJavaType() != null) {
value = JavaUtils.convert(value,
paramDesc.getJavaType());
rpcParam.setValue(value);
if (paramDesc.getMode() == ParameterDesc.INOUT)
outs.add(rpcParam);
}
if (paramDesc == null || paramDesc.getOrder() == -1) {
argValues[i] = value;
} else {
argValues[paramDesc.getOrder()] = value;
}
if (log.isDebugEnabled()) {
log.debug(" " + JavaUtils.getMessage("value00",
"" + argValues[i]) );
}
}
}
// Check if we can find a Method by this name
// FIXME : Shouldn't this type of thing have already occurred?
checkMethodName(msgContext, allowedMethods, operation.getName());
// Now create any out holders we need to pass in
if (numArgs < argValues.length) {
ArrayList outParams = operation.getOutParams();
for (int i = 0; i < outParams.size(); i++) {
ParameterDesc param = (ParameterDesc)outParams.get(i);
Class holderClass = param.getJavaType();
if (Holder.class.isAssignableFrom(holderClass)) {
argValues[numArgs + i] = holderClass.newInstance();
// Store an RPCParam in the outs collection so we
// have an easy and consistent way to write these
// back to the client below
outs.add(new RPCParam(param.getQName(),
argValues[numArgs + i]));
} else {
// !!! Throw a fault here?
}
}
}
// OK! Now we can invoke the method
Object objRes = operation.getMethod().invoke(obj, argValues);
/* Now put the result in the result SOAPEnvelope */
/*************************************************/
RPCElement resBody = new RPCElement(methodName + "Response");
resBody.setPrefix( body.getPrefix() );
resBody.setNamespaceURI( body.getNamespaceURI() );
resBody.setEncodingStyle(msgContext.getEncodingStyle());
// Return first
if ( operation.getMethod().getReturnType() != Void.TYPE ) {
QName returnQName = operation.getReturnQName();
if (returnQName == null) {
returnQName = new QName("", methodName + "Return");
}
RPCParam param = new RPCParam(returnQName, objRes);
resBody.addParam(param);
}
// Then any other out params
if (!outs.isEmpty()) {
for (Iterator i = outs.iterator(); i.hasNext();) {
// We know this has a holder, so just unwrap the value
RPCParam param = (RPCParam) i.next();
Holder holder = (Holder)param.getValue();
param.setValue(JavaUtils.getHolderValue(holder));
resBody.addParam(param);
}
}
resEnv.addBodyElement(resBody);
}