package org.jboss.axis.providers.java;
import org.jboss.axis.AxisFault;
import org.jboss.axis.Constants;
import org.jboss.axis.Message;
import org.jboss.axis.MessageContext;
import org.jboss.axis.MessagePart;
import org.jboss.axis.description.OperationDesc;
import org.jboss.axis.description.ParameterDesc;
import org.jboss.axis.description.ServiceDesc;
import org.jboss.axis.enums.Style;
import org.jboss.axis.enums.Use;
import org.jboss.axis.handlers.soap.SOAPService;
import org.jboss.axis.message.RPCElement;
import org.jboss.axis.message.RPCHeaderParam;
import org.jboss.axis.message.RPCParam;
import org.jboss.axis.message.RPCParamElementImpl;
import org.jboss.axis.message.SOAPBodyElementAxisImpl;
import org.jboss.axis.message.SOAPElementAxisImpl;
import org.jboss.axis.message.SOAPEnvelopeAxisImpl;
import org.jboss.axis.soap.SOAPConstants;
import org.jboss.axis.utils.JavaUtils;
import org.jboss.axis.utils.Messages;
import org.jboss.logging.Logger;
import org.w3c.dom.Element;
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.holders.Holder;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPHeaderElement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
public class RPCInvocation
{
private static Logger log = Logger.getLogger(RPCInvocation.class.getName());
private RPCProvider rpcProvider;
private MessageContext messageContext;
private SOAPEnvelopeAxisImpl requestEnvelope;
private SOAPEnvelopeAxisImpl responseEnvelope;
private Object targetObject;
private OperationDesc operation;
private Object[] argValues;
private Object returnValue;
private RPCElement body;
private List outParams;
private boolean responsePrepared;
public RPCInvocation(RPCProvider rpcProvider, MessageContext messageContext, SOAPEnvelopeAxisImpl reqEnv, SOAPEnvelopeAxisImpl resEnv, Object targetObject)
{
this.rpcProvider = rpcProvider;
this.messageContext = messageContext;
this.requestEnvelope = reqEnv;
this.responseEnvelope = resEnv;
this.targetObject = targetObject;
}
public RPCInvocation(RPCInvocation invocation)
{
this.rpcProvider = invocation.rpcProvider;
this.messageContext = invocation.messageContext;
this.requestEnvelope = invocation.requestEnvelope;
this.responseEnvelope = invocation.responseEnvelope;
this.targetObject = invocation.targetObject;
this.responsePrepared = invocation.responsePrepared;
}
public RPCProvider getProvider()
{
return rpcProvider;
}
public void prepareFromRequestEnvelope()
{
log.debug("Enter: prepareFromRequestEnvelope\n" + requestEnvelope);
SOAPService service = messageContext.getService();
ServiceDesc serviceDesc = service.getServiceDescription();
operation = messageContext.getOperation();
try
{
Vector bodies = requestEnvelope.getBodyElements();
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage("bodyElems00", "" + bodies.size()));
log.debug(Messages.getMessage("bodyIs00", "" + bodies.get(0)));
}
for (int bNum = 0; body == null && bNum < bodies.size(); bNum++)
{
if (!(bodies.get(bNum) instanceof RPCElement))
{
SOAPBodyElementAxisImpl bodyEl = (SOAPBodyElementAxisImpl)bodies.get(bNum);
if (bodyEl.isRoot() && operation != null && bodyEl.getID() == null)
{
ParameterDesc param = operation.getParameter(bNum);
if (param != null)
{
Object val = bodyEl.getValueAsType(param.getTypeQName());
body = new RPCElement("",
operation.getName(),
new Object[]{val});
}
}
}
else
{
body = (RPCElement)bodies.get(bNum);
}
}
if (body == null)
{
if (!(serviceDesc.getStyle().equals(Style.DOCUMENT)))
{
throw new JAXRPCException(Messages.getMessage("noBody00"));
}
ArrayList ops = serviceDesc.getOperations();
for (Iterator iterator = ops.iterator(); iterator.hasNext();)
{
OperationDesc desc = (OperationDesc)iterator.next();
if (desc.getNumInParams() == 0)
{
messageContext.setOperation(desc);
body = new RPCElement(desc.getName());
break;
}
}
if (body == null)
{
throw new JAXRPCException(Messages.getMessage("noBody00"));
}
}
String methodName = body.getMethodName();
Vector args = body.getParams();
int numArgs = args.size();
operation = messageContext.getOperation();
if (operation == null)
{
QName qname = new QName(body.getNamespaceURI(),
body.getName());
operation = getOperation(serviceDesc, qname);
}
if (operation == null)
{
Vector headers = requestEnvelope.getHeaders();
for (int i = 0; i < headers.size(); i++)
{
SOAPHeaderElement header = (SOAPHeaderElement)headers.elementAt(i);
if (header.getMustUnderstand() == true)
{
AxisFault fault = new AxisFault(Messages.getMessage("noSuchOperation", methodName));
fault.setFaultCode(Constants.FAULT_MUSTUNDERSTAND);
throw new JAXRPCException(fault);
}
}
throw new JAXRPCException(Messages.getMessage("noSuchOperation", methodName));
}
argValues = new Object[operation.getNumParams()];
outParams = new ArrayList();
boolean isGenericDocumentEndpoint = false;
Style style = serviceDesc.getStyle();
Use use = serviceDesc.getUse();
if (style.equals(Style.DOCUMENT) && use.equals(Use.LITERAL) && operation.getInParams().size() == 1)
{
ParameterDesc firstInParam = (ParameterDesc)operation.getInParams().get(0);
if (Element.class.isAssignableFrom(firstInParam.getJavaType()))
{
isGenericDocumentEndpoint = true;
argValues[0] = body;
}
}
if (isGenericDocumentEndpoint == false)
{
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)
{
Class sigType = paramDesc.getJavaType();
if (value instanceof AttachmentPart)
{
if (sigType.equals(DataHandler.class))
value = ((AttachmentPart)value).getDataHandler();
else
value = ((AttachmentPart)value).getContent();
}
value = JavaUtils.convert(value, sigType);
rpcParam.setValue(value);
if (paramDesc.getMode() == ParameterDesc.INOUT)
{
outParams.add(rpcParam);
}
}
if (paramDesc == null || paramDesc.getOrder() == -1)
{
argValues[i] = value;
}
else
{
argValues[paramDesc.getOrder()] = value;
}
if (log.isDebugEnabled())
{
log.debug(" " + Messages.getMessage("value00", "" + argValues[i]));
}
}
}
String allowedMethods = (String)service.getOption("allowedMethods");
rpcProvider.checkMethodName(messageContext, allowedMethods, operation.getName());
int count = numArgs;
for (int i = 0; i < argValues.length; i++)
{
ParameterDesc param = operation.getParameter(i);
if (param.getMode() == ParameterDesc.IN)
continue;
Class holderClass = param.getJavaType();
if (holderClass != null &&
Holder.class.isAssignableFrom(holderClass))
{
int index = count;
if (param.getMode() == ParameterDesc.OUT)
{
count++;
}
else if (param.getMode() == ParameterDesc.INOUT)
{
if (param.getOrder() != -1)
{
index = param.getOrder();
}
else
{
count++;
}
if (argValues[index] != null)
{
continue;
}
}
argValues[index] = holderClass.newInstance();
RPCParam p = new RPCParam(param.getQName(),
argValues[index]);
p.setParamDesc(param);
outParams.add(p);
}
else
{
String message = Messages.getMessage("badOutParameter00", "" + param.getQName(), operation.getName());
log.error(message);
throw new JAXRPCException(message);
}
}
log.debug("Exit: prepareFromRequestEnvelope");
}
catch (JAXRPCException e)
{
log.error(e.toString(), e);
throw e;
}
catch (Exception e)
{
log.error(e.toString(), e);
throw new JAXRPCException(e);
}
}
public OperationDesc getOperation(ServiceDesc serviceDesc, QName qname)
{
return serviceDesc.getOperationByElementQName(qname);
}
public void prepareResponseEnvelope(Object resObject)
{
returnValue = resObject;
log.debug("Enter: prepareResponseEnvelope: [resObject=" + resObject + "]");
if (responsePrepared)
{
log.debug("Ignoring request to prepare response envelope");
log.debug("Exit: prepareResponseEnvelope\n" + responseEnvelope);
return;
}
SOAPService service = messageContext.getService();
ServiceDesc serviceDesc = service.getServiceDescription();
ArrayList immutableElements = new ArrayList();
try
{
String encodingStyle = messageContext.getEncodingStyle();
String bodyEncStyle = responseEnvelope.getBody().getEncodingStyle();
if (bodyEncStyle.equals(encodingStyle) == false)
{
if (bodyEncStyle.equals(""))
responseEnvelope.getBody().setEncodingStyle(encodingStyle);
else
log.warn("Mixed encoding styles are not supported: " + bodyEncStyle + "!=" + encodingStyle);
}
RPCElement resBody = null;
boolean isGenericDocumentReturn = false;
Style style = serviceDesc.getStyle();
Use use = serviceDesc.getUse();
if (style.equals(Style.DOCUMENT) && use.equals(Use.LITERAL) && resObject != null && Element.class.isAssignableFrom(resObject.getClass()))
{
Element resElement = (Element)resObject;
resBody = new RPCElement(resElement.getLocalName());
resBody.setPrefix(resElement.getPrefix());
resBody.setNamespaceURI(resElement.getNamespaceURI());
immutableElements.add(resBody);
isGenericDocumentReturn = true;
}
if (isGenericDocumentReturn == false)
{
String methodName = operation.getMethod().getName();
resBody = new RPCElement(methodName + "Response");
resBody.setPrefix(body.getPrefix());
resBody.setNamespaceURI(body.getNamespaceURI());
immutableElements.add(resBody);
}
if (operation.getMethod().getReturnType() != Void.TYPE)
{
QName returnQName = operation.getReturnQName();
if (returnQName == null)
{
String methodName = operation.getMethod().getName();
returnQName = new QName(body.getNamespaceURI(), methodName + "Response");
}
ParameterDesc retParamDesc = operation.getReturnParamDesc();
QName retTypeQName = retParamDesc.getTypeQName();
if (resObject != null && retTypeQName != null)
{
Class retType = messageContext.getTypeMapping().getClassForQName(retTypeQName);
if (retType != null && JavaUtils.isConvertable(resObject, retType))
resObject = JavaUtils.convert(resObject, retType);
}
RPCParam param = new RPCParam(returnQName, resObject);
param.setParamDesc(retParamDesc);
param.setRPCCall(resBody);
if (operation.getUse().equals(Use.LITERAL))
param.setXSITypeGeneration(Boolean.TRUE);
RPCParamElementImpl paramElement = new RPCParamElementImpl(param);
resBody.addChildElement(paramElement);
immutableElements.add(paramElement);
if (!operation.isReturnHeader())
{
if (messageContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS &&
(serviceDesc.getStyle().equals(Style.RPC)))
{
RPCParam resultParam = new RPCParam(Constants.QNAME_RPC_RESULT, returnQName);
resultParam.setXSITypeGeneration(Boolean.FALSE);
resBody.addParam(resultParam);
}
resBody.addParam(param);
}
else
{
responseEnvelope.addHeader(new RPCHeaderParam(param));
}
}
if (!outParams.isEmpty())
{
for (Iterator i = outParams.iterator(); i.hasNext();)
{
RPCParam param = (RPCParam)i.next();
Object value = param.getValue();
if (value instanceof Holder)
{
Holder holder = (Holder)value;
value = JavaUtils.getHolderValue(holder);
}
ParameterDesc paramDesc = param.getParamDesc();
param.setValue(value);
if (paramDesc != null && paramDesc.isOutHeader())
{
responseEnvelope.addHeader(new RPCHeaderParam(param));
}
else
{
resBody.addParam(param);
}
}
}
responseEnvelope.addBodyElement(resBody);
responsePrepared = true;
Iterator it = immutableElements.iterator();
while (it.hasNext())
{
SOAPElementAxisImpl soapElement = (SOAPElementAxisImpl)it.next();
soapElement.setImmutable(true);
}
messageContext.setPastPivot(true);
Message respMessage = (Message)messageContext.getMessage();
((MessagePart)respMessage.getSOAPPart()).setSOAPEnvelope(responseEnvelope);
log.debug("Exit: prepareResponseEnvelope\n" + responseEnvelope);
}
catch (JAXRPCException e)
{
throw e;
}
catch (Exception e)
{
throw new JAXRPCException(e);
}
}
public Object[] getArgValues()
{
return argValues;
}
public RPCElement getBody()
{
return body;
}
public MessageContext getMessageContext()
{
return messageContext;
}
public OperationDesc getOperation()
{
return operation;
}
public List getOutParams()
{
return outParams;
}
public SOAPEnvelopeAxisImpl getRequestEnvelope()
{
return requestEnvelope;
}
public SOAPEnvelopeAxisImpl getResponseEnvelope()
{
return responseEnvelope;
}
public Object getTargetObject()
{
return targetObject;
}
public String toString()
{
StringBuffer ret = new StringBuffer("\nRPCInvocation:\n");
ret.append("TargetObject=" + targetObject + "\n");
ret.append("Operation=" + operation);
ret.append("ArgValues=" + (argValues != null ? Arrays.asList(argValues) : null) + "\n");
ret.append("ReturnValue=" + returnValue + "\n");
return ret.toString();
}
}