FileDocCategorySizeDatePackage
AxisFault.javaAPI DocApache Axis 1.427940Sat Apr 22 18:57:28 BST 2006org.apache.axis

AxisFault

public class AxisFault extends RemoteException
An exception which maps cleanly to a SOAP fault. This is a base class for exceptions which are mapped to faults. SOAP faults contain
  1. A fault string
  2. A fault code
  3. A fault actor
  4. Fault details; an xml tree of fault specific stuff
author
Doug Davis (dug@us.ibm.com)
author
James Snell (jasnell@us.ibm.com)
author
Steve Loughran

Fields Summary
protected static Log
log
The Log used by this class for all logging.
protected QName
faultCode
protected Vector
faultSubCode
SOAP1.2 addition: subcodes of faults; a Vector of QNames
protected String
faultString
protected String
faultActor
protected Vector
faultDetails
protected String
faultNode
protected ArrayList
faultHeaders
SOAP headers which should be serialized with the Fault.
Constructors Summary
public AxisFault(String code, String faultString, String actor, Element[] details)
Make a fault in the Constants.NS_URI_AXIS namespace.

param
code fault code which will be passed into the Axis namespace
param
faultString fault string
param
actor fault actor
param
details details; if null the current stack trace and classname is inserted into the details.

        this(new QName(Constants.NS_URI_AXIS, code),
                faultString, actor, details);
    
public AxisFault(QName code, String faultString, String actor, Element[] details)
Make a fault in any namespace.

param
code fault code which will be passed into the Axis namespace
param
faultString fault string
param
actor fault actor
param
details details; if null the current stack trace and classname is inserted into the details.

        super (faultString);
        setFaultCode( code );
        setFaultString( faultString );
        setFaultActor( actor );
        setFaultDetail( details );
        if (details == null) {
            initFromException(this);
        }
    
public AxisFault(QName code, QName[] subcodes, String faultString, String actor, String node, Element[] details)
Make a fault in any namespace.

param
code fault code which will be passed into the Axis namespace
param
subcodes fault subcodes which will be pased into the Axis namespace
param
faultString fault string
param
actor fault actor, same as fault role in SOAP 1.2
param
node which node caused the fault on the SOAP path
param
details details; if null the current stack trace and classname is inserted into the details.
since
axis1.1

        super (faultString);
        setFaultCode( code );
        if (subcodes != null) {
            for (int i = 0; i < subcodes.length; i++) {
                addFaultSubCode( subcodes[i] );
            }
        }
        setFaultString( faultString );
        setFaultActor( actor );
        setFaultNode( node );
        setFaultDetail( details );
        if (details == null) {
            initFromException(this);
        }
    
protected AxisFault(Exception target)
Wrap an AxisFault around an existing Exception. This is private to force everyone to use makeFault() above, which sanity-checks us.

param
target the target Exception

        super ("", target);
        // ? SOAP 1.2 or 1.1 ?
        setFaultCodeAsString( Constants.FAULT_SERVER_USER );
        initFromException(target);

        // if the target is a JAX-RPC SOAPFaultException init
        // AxisFault with the values from the SOAPFaultException
        if ( target instanceof SOAPFaultException ) {
            //strip out the hostname as we want any new one
            removeHostname();
            initFromSOAPFaultException((SOAPFaultException) target);
            //but if they left it out, add it
            addHostnameIfNeeded();
        }

    
public AxisFault(String message)
create a simple axis fault from the message. Classname and stack trace go into the fault details.

param
message

        super (message);
        setFaultCodeAsString(Constants.FAULT_SERVER_GENERAL);
        setFaultString(message);
        initFromException(this);
    
public AxisFault()
No-arg constructor for building one from an XML stream.

        super();
        setFaultCodeAsString(Constants.FAULT_SERVER_GENERAL);
        initFromException(this);
    
public AxisFault(String message, Throwable t)
create a fault from any throwable; When faulting a throwable (as opposed to an exception), stack trace information does not go into the fault.

param
message any extra text to with the fault
param
t whatever is to be turned into a fault

        super (message, t);
        setFaultCodeAsString(Constants.FAULT_SERVER_GENERAL);
        setFaultString(getMessage());
        addHostnameIfNeeded();
    
Methods Summary
public voidaddFaultDetail(org.w3c.dom.Element detail)
Append an element to the fault detail list.

param
detail the new element to add
since
Axis1.1

        initFaultDetails();
        faultDetails.add(detail);
    
public voidaddFaultDetail(javax.xml.namespace.QName qname, java.lang.String body)
Create an element of the given qname and add it to the details.

param
qname qname of the element
param
body string to use as body

        Element detail = XMLUtils.StringToElement(qname.getNamespaceURI(),
                qname.getLocalPart(),
                body);

        addFaultDetail(detail);
    
public voidaddFaultDetailString(java.lang.String detail)
add a string tag to the fault details.

param
detail XML fragment

        initFaultDetails();
        try {
            Document doc = XMLUtils.newDocument();
            Element element = doc.createElement("string");
            Text text = doc.createTextNode(detail);
            element.appendChild(text);
            faultDetails.add(element);
        } catch (ParserConfigurationException e) {
            // This should not occur
            throw new InternalException(e);
        }
    
public voidaddFaultSubCode(javax.xml.namespace.QName code)
Add a fault sub-code. This is new in SOAP 1.2, ignored in SOAP 1.1.

param
code the QName of the fault sub-code to add
since
axis1.1

        initFaultSubCodes();
        faultSubCode.add(code);
    
public voidaddFaultSubCodeAsString(java.lang.String code)
Add a fault sub-code with the local name code and namespace Constants.NS_URI_AXIS. This is new in SOAP 1.2, ignored in SOAP 1.1

param
code the local name of the code to add
since
axis1.1

        initFaultSubCodes();
        faultSubCode.add(new QName(Constants.NS_URI_AXIS, code));
    
public voidaddHeader(org.apache.axis.message.SOAPHeaderElement header)
Add a SOAP header which should be serialized along with the fault.

param
header a SOAPHeaderElement containing some fault-relevant stuff

        if (faultHeaders == null) {
            faultHeaders = new ArrayList();
        }
        faultHeaders.add(header);
    
public voidaddHostname(java.lang.String hostname)
add the hostname string. If one already exists, remove it.

param
hostname string name of a host
since
Axis1.2

        //add the hostname
        removeHostname();
        addFaultDetail(Constants.QNAME_FAULTDETAIL_HOSTNAME,
                hostname);
    
public voidaddHostnameIfNeeded()
add the hostname of the current system. This is very useful for locating faults on a cluster.

since
Axis1.2

        //look for an existing declaration
        if(lookupFaultDetail(Constants.QNAME_FAULTDETAIL_HOSTNAME)!=null) {
            //and do nothing if it exists
            return;
        }
        addHostname(NetworkUtils.getLocalHostname());
    
public voidclearFaultDetails()
Clear the fault details list.

        faultDetails=null;
    
public voidclearFaultSubCodes()
Clear all fault sub-codes. This is new in SOAP 1.2, ignored in SOAP 1.1.

since
axis1.1

        faultSubCode = null;
    
public voidclearHeaders()
Clear all fault headers.

        faultHeaders = null;
    
public voiddump()
Dump the fault info to the log at debug level.

        log.debug(dumpToString());
    
public java.lang.StringdumpToString()
turn the fault and details into a string, with XML escaping. subclassers: for security (cross-site-scripting) reasons, escape everything that could contain caller-supplied data.

return
stringified fault details

        StringBuffer buf = new StringBuffer("AxisFault");
        buf.append(JavaUtils.LS);
        buf.append(" faultCode: ");
        buf.append(XMLUtils.xmlEncodeString(faultCode.toString()));
        buf.append(JavaUtils.LS);
        buf.append(" faultSubcode: ");
        if (faultSubCode != null) {
            for (int i = 0; i < faultSubCode.size(); i++) {
                buf.append(JavaUtils.LS);
                buf.append(faultSubCode.elementAt(i).toString());
            }
        }
        buf.append(JavaUtils.LS);
        buf.append(" faultString: ");
        try {
        	buf.append(XMLUtils.xmlEncodeString(faultString));
        } catch (RuntimeException re) {
        	buf.append(re.getMessage());
        }
        buf.append(JavaUtils.LS);
        buf.append(" faultActor: ");
        buf.append(XMLUtils.xmlEncodeString(faultActor));
        buf.append(JavaUtils.LS);
        buf.append(" faultNode: ");
        buf.append(XMLUtils.xmlEncodeString(faultNode));
        buf.append(JavaUtils.LS);
        buf.append(" faultDetail: ");
        if (faultDetails != null) {
            for (int i=0; i < faultDetails.size(); i++) {
                Element e = (Element) faultDetails.get(i);
                buf.append(JavaUtils.LS);
                buf.append("\t{");
                buf.append(null == e.getNamespaceURI() ? "" : e.getNamespaceURI());
                buf.append("}");
                buf.append(null == e.getLocalName() ? "" : e.getLocalName());
                buf.append(":");
                buf.append(XMLUtils.getInnerXMLString(e));
            }
        }
        buf.append(JavaUtils.LS);
        return buf.toString();
    
public java.lang.StringgetFaultActor()
get the fault actor

return
actor or null

        return( faultActor );
    
public javax.xml.namespace.QNamegetFaultCode()
Get the fault code QName.

return
fault code QName or null if there is none yet.

        return( faultCode );
    
public org.w3c.dom.Element[]getFaultDetails()
Get all the fault details.

return
an array of fault details, or null for none

        if (faultDetails == null) {
            return null;
        }
        Element result[] = new Element[faultDetails.size()];
        for (int i=0; i<result.length; i++) {
            result[i] = (Element) faultDetails.elementAt(i);
        }
        return result;
    
public java.lang.StringgetFaultNode()
Get the fault node. This is new in SOAP 1.2

since
axis1.1
return

        return( faultNode );
    
public java.lang.StringgetFaultReason()
This is SOAP 1.2 equivalent of {@link #getFaultString()}.

since
axis1.1
return
the fault String

        return getFaultString();
    
public java.lang.StringgetFaultRole()
This is SOAP 1.2 equivalent of {@link #getFaultActor()}.

since
axis1.1
return
the name of the fault actor

        return getFaultActor();
    
public java.lang.StringgetFaultString()
Get the fault string; this will never be null but may be the empty string.

return
a fault string

        return( faultString );
    
public javax.xml.namespace.QName[]getFaultSubCodes()
get the fault subcode list; only used in SOAP 1.2

since
axis1.1
return
null for no subcodes, or a QName array

        if (faultSubCode == null) {
            return null;
        }
        QName[] q = new QName[faultSubCode.size()];
        return (QName[])faultSubCode.toArray(q);
    
public java.util.ArrayListgetHeaders()
Get the SOAP headers associated with this fault.

return
an ArrayList containing any headers associated with this fault

        return faultHeaders;
    
private java.lang.StringgetPlainStackTrace()
Gets the stack trace as a string.

        StringWriter sw = new StringWriter(512);
        PrintWriter pw = new PrintWriter(sw); 
        super.printStackTrace(pw);
        pw.close();
        return sw.toString();
    
private voidinitFaultDetails()
Init the fault details data structure; does nothing if this exists already.

        if (faultDetails == null) {
            faultDetails = new Vector();
        }
    
protected voidinitFaultSubCodes()
Do whatever is needed to create the fault subcodes data structure, if it is needed.

        if (faultSubCode == null) {
            faultSubCode = new Vector();
        }
    
private voidinitFromException(java.lang.Exception target)
fill in soap fault details from the exception, unless this object already has a stack trace in its details. Which, given the way this private method is invoked, is a pretty hard situation to ever achieve. This method adds classname of the exception and the stack trace.

param
target what went wrong

        //look for old stack trace
        Element oldStackTrace = lookupFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE);
        if (oldStackTrace != null) {
            // todo: Should we replace it or just let it be?
            return;
        }

        // Set the exception message (if any) as the fault string
        setFaultString( target.toString() );


        // Put the exception class into the AXIS SPECIFIC HACK
        //  "exceptionName" element in the details.  This allows
        // us to get back a correct Java Exception class on the other side
        // (assuming they have it available).
        // NOTE: This hack is obsolete!  We now serialize exception data
        // and the other side uses *that* QName to figure out what exception
        // to use, because the class name may be completly different on the
        // client.
        if ((target instanceof AxisFault) &&
            (target.getClass() != AxisFault.class)) {
          addFaultDetail(Constants.QNAME_FAULTDETAIL_EXCEPTIONNAME,
                    target.getClass().getName());
        }

        //add stack trace
        if (target == this) {
            // only add stack trace. JavaUtils.stackToString() call would
            // include dumpToString() info which is already sent as different
            // elements of this fault.
            addFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE,
                           getPlainStackTrace());
        } else {
            addFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE,
                           JavaUtils.stackToString(target));
        }

        //add the hostname
        addHostnameIfNeeded();
    
private voidinitFromSOAPFaultException(javax.xml.rpc.soap.SOAPFaultException fault)
Initiates the AxisFault with the values from a SOAPFaultException

param
fault SOAPFaultException

        
        // faultcode
        if ( fault.getFaultCode() != null ) {
            setFaultCode(fault.getFaultCode());
        }
        
        // faultstring
        if ( fault.getFaultString() != null ) {
            setFaultString(fault.getFaultString());
        }
        
        // actor
        if ( fault.getFaultActor() != null ) {
            setFaultActor(fault.getFaultActor());
        }

        if ( null == fault.getDetail() ) {
            return;
        }
        
        // We get an Iterator but we need a List
        Vector details = new Vector();       
        Iterator detailIter = fault.getDetail().getChildElements();
        while (detailIter.hasNext()) {
            details.add( detailIter.next());            
        }        
        
        // Convert the List in an Array an return the array 
        setFaultDetail( XMLUtils.asElementArray(details));                
    
public org.w3c.dom.ElementlookupFaultDetail(javax.xml.namespace.QName qname)
Find a fault detail element by its qname.

param
qname name of the node to look for
return
the matching element or null
since
axis1.1

        if (faultDetails != null) {
            //extract details from the qname. the empty namespace is represented
            //by the empty string
            String searchNamespace = qname.getNamespaceURI();
            String searchLocalpart = qname.getLocalPart();
            //now spin through the elements, seeking a match
            Iterator it=faultDetails.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String localpart= e.getLocalName();
                if(localpart==null) {
                    localpart=e.getNodeName();
                }
                String namespace= e.getNamespaceURI();
                if(namespace==null) {
                    namespace="";
                }
                //we match on matching namespace and local part; empty namespace
                //in an element may be null, which matches QName's ""
                if(searchNamespace.equals(namespace)
                    && searchLocalpart.equals(localpart)) {
                    return e;
                }
            }
        }
        return null;
    
public static org.apache.axis.AxisFaultmakeFault(java.lang.Exception e)
Make an AxisFault based on a passed Exception. If the Exception is already an AxisFault, simply use that. Otherwise, wrap it in an AxisFault. If the Exception is an InvocationTargetException (which already wraps another Exception), get the wrapped Exception out from there and use that instead of the passed one.

param
e the Exception to build a fault for
return
an AxisFault representing e


                                                                             
        
    
        if (e instanceof InvocationTargetException) {
            Throwable t = ((InvocationTargetException)e).getTargetException();
            if (t instanceof Exception) {
                e = (Exception)t;
            }
        }

        if (e instanceof AxisFault) {
            return (AxisFault)e;
        }

        return new AxisFault(e);
    
public voidoutput(org.apache.axis.encoding.SerializationContext context)
Add this fault and any needed headers to the output context.

param
context
throws
Exception


        SOAPConstants soapConstants = Constants.DEFAULT_SOAP_VERSION;
        if (context.getMessageContext() != null) {
            soapConstants = context.getMessageContext().getSOAPConstants();
        }

        SOAPEnvelope envelope = new SOAPEnvelope(soapConstants);

        SOAPFault fault = new SOAPFault(this);
        envelope.addBodyElement(fault);

        // add any headers we need
        if (faultHeaders != null) {
            for (Iterator i = faultHeaders.iterator(); i.hasNext();) {
                SOAPHeaderElement header = (SOAPHeaderElement) i.next();
                envelope.addHeader(header);
            }
        }

        envelope.output(context);
    
public voidprintStackTrace(java.io.PrintStream ps)
The override of the base class method prints out the fault info before the stack trace.

param
ps where to print

        ps.println(dumpToString());
        super.printStackTrace(ps);
    
public voidprintStackTrace(java.io.PrintWriter pw)
The override of the base class method prints out the fault info before the stack trace.

param
pw where to print

        pw.println(dumpToString());
        super.printStackTrace(pw);
    
public booleanremoveFaultDetail(javax.xml.namespace.QName qname)
Find and remove a specified fault detail element.

param
qname qualified name of detail
return
true if it was found and removed, false otherwise
since
axis1.1

        Element elt=lookupFaultDetail(qname);
        if(elt==null) {
            return false;
        } else {
            return faultDetails.remove(elt);
        }
    
public voidremoveHostname()
strip out the hostname on a message. This is useful for security reasons.

        removeFaultDetail(Constants.QNAME_FAULTDETAIL_HOSTNAME);
    
public voidsetFaultActor(java.lang.String actor)
Set the fault actor.

param
actor fault actor

        faultActor = actor ;
    
public voidsetFaultCode(javax.xml.namespace.QName code)
Set the fault code.

param
code a new fault code

        faultCode = code ;
    
public voidsetFaultCode(java.lang.String code)
Set the fault code (as a String).

param
code a new fault code
deprecated
expect to see this go away after 1.1, use setFaultCodeAsString instead!

        setFaultCodeAsString(code);
    
public voidsetFaultCodeAsString(java.lang.String code)
set a fault code string that is turned into a qname in the SOAP 1.1 or 1.2 namespace, depending on the current context

param
code fault code

        SOAPConstants soapConstants = MessageContext.getCurrentContext() == null ?
                                        SOAPConstants.SOAP11_CONSTANTS :
                                        MessageContext.getCurrentContext().getSOAPConstants();

        faultCode = new QName(soapConstants.getEnvelopeURI(), code);
    
public voidsetFaultDetail(org.w3c.dom.Element[] details)
Set the fault detail element to the arrary of details.

param
details list of detail elements, can be null

        if ( details == null ) {
            faultDetails=null;
            return ;
        }
        faultDetails = new Vector( details.length );
        for ( int loop = 0 ; loop < details.length ; loop++ ) {
            faultDetails.add( details[loop] );
        }
    
public voidsetFaultDetailString(java.lang.String details)
set the fault details to a string element.

param
details XML fragment

        clearFaultDetails();
        addFaultDetailString(details);
    
public voidsetFaultNode(java.lang.String node)
Set the fault node. This is new in SOAP 1.2.

param
node a String representing the fault node
since
axis1.1

        faultNode = node;
    
public voidsetFaultReason(java.lang.String str)
This is SOAP 1.2 equivalent of {@link #setFaultString(java.lang.String)}.

param
str the fault reason as a String
since
axis1.1

        setFaultString(str);
    
public voidsetFaultRole(java.lang.String role)
This is SOAP 1.2 equivalent of {@link #setFaultActor(java.lang.String)}.

since
axis1.1

        setFaultActor(role);
    
public voidsetFaultString(java.lang.String str)
Set a fault string.

param
str new fault string; null is turned into ""

        if (str != null) {
            faultString = str ;
        } else {
            faultString = "";
        }
    
public java.lang.StringtoString()
Stringify this fault as the current fault string.

return
the fault string, possibly the empty string, but never null

        return faultString;
    
public voidwriteDetails(javax.xml.namespace.QName qname, org.apache.axis.encoding.SerializationContext context)
Writes any exception data to the faultDetails. This can be overridden (and is) by emitted exception clases. The base implementation will attempt to serialize exception data the fault was created from an Exception and a type mapping is found for it.

param
qname the QName to write this under
param
context the SerializationContext to write this fault to
throws
java.io.IOException if we can't write ourselves for any reason

        Object detailObject = this.detail;
        if (detailObject == null) {
            return;
        }

        boolean haveSerializer = false;
        try {
            if (context.getTypeMapping().getSerializer(detailObject.getClass()) != null) {
                haveSerializer = true;
            }
        } catch (Exception e) {
            // swallow this exception, it means that we don't know how to serialize
            // the details.
        }
        if (haveSerializer) {
            boolean oldMR = context.getDoMultiRefs();
            context.setDoMultiRefs(false);
            context.serialize(qname, null, detailObject);
            context.setDoMultiRefs(oldMR);
        }