/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.axis.message; import org.apache.axis.AxisFault; import org.apache.axis.Constants; import org.apache.axis.description.FaultDesc; import org.apache.axis.description.OperationDesc; import org.apache.axis.encoding.DeserializationContext; import org.apache.axis.encoding.SerializationContext; import org.apache.axis.soap.SOAPConstants; import org.apache.axis.utils.Messages; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.Attributes; import org.xml.sax.helpers.AttributesImpl; import javax.xml.namespace.QName; import javax.xml.soap.DetailEntry; import javax.xml.soap.Name; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import java.util.List; import java.util.Locale; import java.util.Iterator; /** A Fault body element. * * @author Sam Ruby (rubys@us.ibm.com) * @author Glen Daniels (gdaniels@apache.org) * @author Tom Jordahl (tomj@macromedia.com) */ public class SOAPFault extends SOAPBodyElement implements javax.xml.soap.SOAPFault { protected AxisFault fault; protected String prefix; private java.util.Locale locale; protected Detail detail = null; public SOAPFault(String namespace, String localName, String prefix, Attributes attrs, DeserializationContext context) throws AxisFault { super(namespace, localName, prefix, attrs, context); } public SOAPFault(AxisFault fault) { this.fault = fault; } public void outputImpl(SerializationContext context) throws Exception { SOAPConstants soapConstants = context.getMessageContext() == null ? SOAPConstants.SOAP11_CONSTANTS : context.getMessageContext().getSOAPConstants(); namespaceURI = soapConstants.getEnvelopeURI(); name = Constants.ELEM_FAULT; context.registerPrefixForURI(prefix, soapConstants.getEnvelopeURI()); context.startElement(new QName(this.getNamespaceURI(), this.getName()), attributes); // XXX - Can fault be anything but an AxisFault here? if (fault instanceof AxisFault) { AxisFault axisFault = fault; if (axisFault.getFaultCode() != null) { // Do this BEFORE starting the element, so the prefix gets // registered if needed. if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) { String faultCode = context.qName2String(axisFault.getFaultCode()); context.startElement(Constants.QNAME_FAULTCODE_SOAP12, null); context.startElement(Constants.QNAME_FAULTVALUE_SOAP12, null); context.writeSafeString(faultCode); context.endElement(); QName[] subcodes = axisFault.getFaultSubCodes(); if (subcodes != null) { for (int i = 0; i < subcodes.length; i++) { faultCode = context.qName2String(subcodes[i]); context.startElement(Constants.QNAME_FAULTSUBCODE_SOAP12, null); context.startElement(Constants.QNAME_FAULTVALUE_SOAP12, null); context.writeSafeString(faultCode); context.endElement(); } for (int i = 0; i < subcodes.length; i++) context.endElement(); } context.endElement(); } else { String faultCode = context.qName2String(axisFault.getFaultCode()); context.startElement(Constants.QNAME_FAULTCODE, null); context.writeSafeString(faultCode); context.endElement(); } } if (axisFault.getFaultString() != null) { if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) { context.startElement(Constants.QNAME_FAULTREASON_SOAP12, null); AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute("http://www.w3.org/XML/1998/namespace", "lang", "xml:lang", "CDATA", "en"); context.startElement(Constants.QNAME_TEXT_SOAP12, attrs); } else context.startElement(Constants.QNAME_FAULTSTRING, null); context.writeSafeString(axisFault.getFaultString()); context.endElement(); if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) { context.endElement(); } } if (axisFault.getFaultActor() != null) { if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) context.startElement(Constants.QNAME_FAULTROLE_SOAP12, null); else context.startElement(Constants.QNAME_FAULTACTOR, null); context.writeSafeString(axisFault.getFaultActor()); context.endElement(); } if (axisFault.getFaultNode() != null) { if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) { context.startElement(Constants.QNAME_FAULTNODE_SOAP12, null); context.writeSafeString(axisFault.getFaultNode()); context.endElement(); } } // get the QName for this faults detail element QName qname = getFaultQName(fault.getClass(), context); if (qname == null && fault.detail != null) { qname = getFaultQName(fault.detail.getClass(), context); } if (qname == null) { // not the greatest, but... qname = new QName("", "faultData"); } Element[] faultDetails = axisFault.getFaultDetails(); if (faultDetails != null) { if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) context.startElement(Constants.QNAME_FAULTDETAIL_SOAP12, null); else context.startElement(Constants.QNAME_FAULTDETAILS, null); // Allow the fault to write its data, if any axisFault.writeDetails(qname, context); // Then output any other elements for (int i = 0; i < faultDetails.length; i++) { context.writeDOMElement(faultDetails[i]); } if (detail!= null) { for (Iterator it = detail.getChildren().iterator(); it.hasNext();) { ((NodeImpl)it.next()).output(context); } } context.endElement(); } } context.endElement(); } private QName getFaultQName(Class cls, SerializationContext context) { QName qname = null; if (! cls.equals(AxisFault.class)) { FaultDesc faultDesc = null; if (context.getMessageContext() != null) { OperationDesc op = context.getMessageContext().getOperation(); if (op != null) { faultDesc = op.getFaultByClass(cls); } } if (faultDesc != null) { qname = faultDesc.getQName(); } } return qname; } public AxisFault getFault() { return fault; } public void setFault(AxisFault fault) { this.fault = fault; } /** * Sets this SOAPFaultException object with the given * fault code. * *

Fault codes, which given information about the fault, * are defined in the SOAP 1.1 specification.

* @param faultCode a String giving * the fault code to be set; must be one of the fault codes * defined in the SOAP 1.1 specification * @throws SOAPException if there was an error in * adding the faultCode to the underlying XML * tree. */ public void setFaultCode(String faultCode) throws SOAPException { fault.setFaultCodeAsString(faultCode); } /** * Gets the fault code for this SOAPFaultException * object. * @return a String with the fault code */ public String getFaultCode() { return fault.getFaultCode().getLocalPart(); } /** * Sets this SOAPFaultException object with the given * fault actor. * *

The fault actor is the recipient in the message path who * caused the fault to happen.

* @param faultActor a String * identifying the actor that caused this * SOAPFaultException object * @throws SOAPException if there was an error in * adding the faultActor to the underlying XML * tree. */ public void setFaultActor(String faultActor) throws SOAPException { fault.setFaultActor(faultActor); } /** * Gets the fault actor for this SOAPFaultException * object. * @return a String giving the actor in the message * path that caused this SOAPFaultException object * @see #setFaultActor(java.lang.String) setFaultActor(java.lang.String) */ public String getFaultActor() { return fault.getFaultActor(); } /** * Sets the fault string for this SOAPFaultException * object to the given string. * * @param faultString a String * giving an explanation of the fault * @throws SOAPException if there was an error in * adding the faultString to the underlying XML * tree. * @see #getFaultString() getFaultString() */ public void setFaultString(String faultString) throws SOAPException { fault.setFaultString(faultString); } /** * Gets the fault string for this SOAPFaultException * object. * @return a String giving an explanation of the * fault */ public String getFaultString() { return fault.getFaultString(); } /** * Returns the detail element for this SOAPFaultException * object. * *

A Detail object carries * application-specific error information related to * SOAPBodyElement objects.

* @return a Detail object with * application-specific error information */ public javax.xml.soap.Detail getDetail() { List children = this.getChildren(); if(children==null || children.size()<=0) return null; // find detail element for (int i=0; i < children.size(); i++) { Object obj = children.get(i); if (obj instanceof javax.xml.soap.Detail) { return (javax.xml.soap.Detail) obj; } } return null; } /** * Creates a Detail object and sets it as the * Detail object for this SOAPFaultException * object. * *

It is illegal to add a detail when the fault already * contains a detail. Therefore, this method should be called * only after the existing detail has been removed.

* @return the new Detail object * @throws SOAPException if this * SOAPFaultException object already contains a valid * Detail object */ public javax.xml.soap.Detail addDetail() throws SOAPException { if(getDetail() != null){ throw new SOAPException(Messages.getMessage("valuePresent")); } Detail detail = convertToDetail(fault); addChildElement(detail); return detail; } public void setFaultCode(Name faultCodeQName) throws SOAPException { String uri = faultCodeQName.getURI(); String local = faultCodeQName.getLocalName(); String prefix = faultCodeQName.getPrefix(); this.prefix = prefix; QName qname = new QName(uri,local); fault.setFaultCode(qname); } public Name getFaultCodeAsName() { QName qname = fault.getFaultCode(); String uri = qname.getNamespaceURI(); String local = qname.getLocalPart(); return new PrefixedQName(uri, local, prefix); } public void setFaultString(String faultString, Locale locale) throws SOAPException { fault.setFaultString(faultString); this.locale = locale; } public Locale getFaultStringLocale() { return locale; } /** * Convert the details in an AxisFault to a Detail object * * @param fault source of the fault details * @return a detail element contructed from the AxisFault details * @throws SOAPException */ private Detail convertToDetail(AxisFault fault) throws SOAPException { detail = new Detail(); Element[] darray = fault.getFaultDetails(); fault.setFaultDetail(new Element[]{}); for (int i = 0; i < darray.length; i++) { Element detailtEntryElem = darray[i]; DetailEntry detailEntry = detail.addDetailEntry( new PrefixedQName(detailtEntryElem.getNamespaceURI(), detailtEntryElem.getLocalName(), detailtEntryElem.getPrefix())); copyChildren(detailEntry, detailtEntryElem); } return detail; } /** * Copy the children of a DOM element to a SOAPElement. * * @param soapElement target of the copy * @param domElement source for the copy * @throws SOAPException */ private static void copyChildren(SOAPElement soapElement, Element domElement) throws SOAPException { org.w3c.dom.NodeList nl = domElement.getChildNodes(); for (int j = 0; j < nl.getLength(); j++) { org.w3c.dom.Node childNode = nl.item(j); if (childNode.getNodeType() == Node.TEXT_NODE) { soapElement.addTextNode(childNode.getNodeValue()); break; // only one text node assmed } if (childNode.getNodeType() == Node.ELEMENT_NODE) { String uri = childNode.getNamespaceURI(); SOAPElement childSoapElement = null; if (uri == null) { childSoapElement = soapElement.addChildElement(childNode.getLocalName ()); } else { childSoapElement = soapElement.addChildElement( childNode.getLocalName(), childNode.getPrefix(), uri); } copyChildren(childSoapElement, (Element) childNode); } } } }