RPCHandlerpublic class RPCHandler extends SOAPHandler This is the SOAPHandler which is called for each RPC parameter as we're
deserializing the XML for a method call or return. In other words for
this XML:
Hello!
3.14159
...we'll get onStartChild() events for and . |
Fields Summary |
---|
protected static Log | log | private RPCElement | rpcElem | private RPCParam | currentParam | private boolean | isResponse | private org.apache.axis.description.OperationDesc | operation | private boolean | isHeaderElement |
Constructors Summary |
---|
public RPCHandler(RPCElement rpcElem, boolean isResponse)
this.rpcElem = rpcElem;
this.isResponse = isResponse;
|
Methods Summary |
---|
public void | endElement(java.lang.String namespace, java.lang.String localName, org.apache.axis.encoding.DeserializationContext context)
// endElement may not be called in all circumstances.
// In addition, onStartChild may be called after endElement
// (for header parameter/response processing).
// So please don't add important logic to this method.
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("setProp00",
"MessageContext", "RPCHandler.endElement()."));
}
context.getMessageContext().setProperty("RPC", rpcElem);
| public SOAPHandler | onStartChild(java.lang.String namespace, java.lang.String localName, java.lang.String prefix, org.xml.sax.Attributes attributes, org.apache.axis.encoding.DeserializationContext context)Register the start of a parameter (child element of the method call
element).
Our job here is to figure out a) which parameter this is (based on
the QName of the element or its position), and b) what type it is
(based on the xsi:type attribute or operation metadata) so we can
successfully deserialize it.
if (log.isDebugEnabled()) {
log.debug("Enter: RPCHandler.onStartChild()");
}
if (!context.isDoneParsing()) {
try {
context.pushNewElement(new MessageElement(namespace, localName,
prefix, attributes,
context));
} catch (AxisFault axisFault) {
throw new SAXException(axisFault);
}
}
MessageElement curEl = context.getCurElement();
QName type = null;
QName qname = new QName(namespace, localName);
ParameterDesc paramDesc = null;
SOAPConstants soapConstants = context.getSOAPConstants();
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS &&
Constants.QNAME_RPC_RESULT.equals(qname)) {
// TODO: fix it ... now we just skip it
return new DeserializerImpl();
}
// Create a new param if not the same element
if (currentParam == null ||
!currentParam.getQName().getNamespaceURI().equals(namespace) ||
!currentParam.getQName().getLocalPart().equals(localName)) {
currentParam = new RPCParam(namespace, localName, null);
rpcElem.addParam(currentParam);
}
// Grab xsi:type attribute if present, on either this element or
// the referent (if it's an href). MessageElement.getType() will
// automatically dig through to the referent if necessary.
type = curEl.getType();
if (type == null) {
type = context.getTypeFromAttributes(namespace,
localName,
attributes);
}
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("typeFromAttr00", "" + type));
}
Class destClass = null;
// If we have an operation descriptor, try to associate this parameter
// with the appropriate ParameterDesc
if (operation != null) {
// Try by name first
if (isResponse) {
paramDesc = operation.getOutputParamByQName(qname);
} else {
paramDesc = operation.getInputParamByQName(qname);
}
// If that didn't work, try position
// FIXME : Do we need to be in EITHER named OR positional
// mode? I.e. will it screw us up to find something
// by position if we've already looked something up
// by name? I think so...
if (paramDesc == null) {
if (isResponse) {
paramDesc = operation.getReturnParamDesc();
}
else {
paramDesc = operation.getParameter(rpcElem.getParams().size() - 1);
}
}
if (paramDesc == null) {
throw new SAXException(Messages.getMessage("noParmDesc"));
}
// Make sure that we don't find body parameters that should
// be in the header
if (!isHeaderElement &&
((isResponse && paramDesc.isOutHeader()) ||
(!isResponse && paramDesc.isInHeader()))) {
throw new SAXException(
Messages.getMessage("expectedHeaderParam",
paramDesc.getQName().toString()));
}
destClass = paramDesc.getJavaType();
if ((destClass != null) && (destClass.isArray())) {
context.setDestinationClass(destClass);
}
// Keep the association so we can use it later
// (see RPCProvider.processMessage())
currentParam.setParamDesc(paramDesc);
if (type == null) {
type = paramDesc.getTypeQName();
}
}
if (type != null && type.equals(XMLType.AXIS_VOID)) {
Deserializer nilDSer = new DeserializerImpl();
return (SOAPHandler) nilDSer;
}
// If the nil attribute is set, just
// return the base DeserializerImpl.
// Register the value target to set the value
// on the RPCParam. This is necessary for cases like
// <method>
// <foo>123</foo>
// <foo>456</foo>
// <foo xsi:nil="true" />
// </method>
// so that a list of 3 items is created.
// Failure to register the target would result in the last
// item not being added to the list
if (context.isNil(attributes)) {
Deserializer nilDSer = new DeserializerImpl();
nilDSer.registerValueTarget(new RPCParamTarget(currentParam));
return (SOAPHandler) nilDSer;
}
Deserializer dser = null;
if ((type == null) && (namespace != null) && (!namespace.equals(""))) {
dser = context.getDeserializerForType(qname);
} else {
dser = context.getDeserializer(destClass, type);
// !!!
if (dser == null && destClass != null && destClass.isArray() &&
operation.getStyle() == Style.DOCUMENT) {
dser = context.getDeserializerForClass(destClass);
}
// !!!
}
if (dser == null) {
if (type != null) {
dser = context.getDeserializerForType(type);
if(null != destClass && dser == null && Element.class.isAssignableFrom(destClass)){
//If a DOM element is expected, as last resort always allow direct mapping
// of parameter's SOAP xml to a DOM element. Support of literal parms by default.
dser = context.getDeserializerForType(Constants.SOAP_ELEMENT);
}
if (dser == null) {
dser = context.getDeserializerForClass(destClass);
}
if (dser == null) {
throw new SAXException(Messages.getMessage(
"noDeser01", localName,"" + type));
}
if (paramDesc != null && paramDesc.getJavaType() != null) {
// If we have an xsi:type, make sure it makes sense
// with the current paramDesc type
Class xsiClass =
context.getTypeMapping().getClassForQName(type);
if (null != xsiClass && !JavaUtils.isConvertable(xsiClass, destClass)) {
throw new SAXException("Bad types (" +
xsiClass + " -> " + destClass + ")"); // FIXME!
}
}
} else {
dser = context.getDeserializerForClass(destClass);
if (dser == null) {
dser = new DeserializerImpl();
}
}
}
dser.setDefaultType(type);
dser.registerValueTarget(new RPCParamTarget(currentParam));
if (log.isDebugEnabled()) {
log.debug("Exit: RPCHandler.onStartChild()");
}
return (SOAPHandler)dser;
| public void | setHeaderElement(boolean value)Indicate RPCHandler is processing header elements
isHeaderElement = true;
| public void | setOperation(org.apache.axis.description.OperationDesc myOperation)
this.operation = myOperation;
| public void | startElement(java.lang.String namespace, java.lang.String localName, java.lang.String prefix, org.xml.sax.Attributes attributes, org.apache.axis.encoding.DeserializationContext context)This method is invoked when an element start tag is encountered.
The purpose of this method in RPCHandler is to reset variables
(this allows re-use of RPCHandlers)
super.startElement(namespace, localName, prefix, attributes, context);
currentParam = null;
|
|