| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.axis2; |
| |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.soap.SOAPFault; |
| import org.apache.axiom.soap.SOAPFaultCode; |
| import org.apache.axiom.soap.SOAPFaultDetail; |
| import org.apache.axiom.soap.SOAPFaultNode; |
| import org.apache.axiom.soap.SOAPFaultReason; |
| import org.apache.axiom.soap.SOAPFaultRole; |
| import org.apache.axiom.soap.SOAPFaultSubCode; |
| import org.apache.axiom.soap.SOAPHeaderBlock; |
| import org.apache.axis2.context.MessageContext; |
| |
| import javax.xml.namespace.QName; |
| import java.io.Serializable; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.UndeclaredThrowableException; |
| import java.rmi.RemoteException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Locale; |
| |
| /** |
| * An exception which maps cleanly to a SOAP fault. |
| * This is a base class for exceptions which are mapped to faults. |
| * |
| * @see <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#soapfault"> |
| * SOAP1.2 specification</a> |
| * @see <a href="http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383507">SOAP1.1 Faults</a> |
| * <p/> |
| * SOAP faults contain |
| * <ol> |
| * <li>A fault string |
| * <li>A fault code |
| * <li>A fault actor |
| * <li>Fault details; an xml tree of fault specific elements |
| * </ol> |
| * <p/> |
| * As SOAP1.2 faults are a superset of SOAP1.1 faults, this type holds soap1.2 fault information. When |
| * a SOAP1.1 fault is created, spurious information can be discarded. |
| * Mapping |
| * <pre> |
| * SOAP1.2 SOAP1.1 |
| * node faultactor |
| * reason(0).text faultstring |
| * faultcode.value faultcode |
| * faultcode.subcode (discarded) |
| * detail detail |
| * role (discarded) |
| * </pre> |
| */ |
| |
| |
| public class AxisFault extends RemoteException { |
| private static final long serialVersionUID = -374933082062124907L; |
| |
| /** |
| * assume headers are not used very often |
| */ |
| private List<SOAPHeaderBlock> headers = new ArrayList<SOAPHeaderBlock>(0); |
| |
| private String message; |
| |
| private List<FaultReason> faultReasonList = new ArrayList<FaultReason>(1); |
| private QName faultCode; |
| private List<QName> faultSubCodes; |
| private String faultNode; |
| private String faultRole; |
| private List<OMElement> details; |
| |
| private SOAPFaultCode soapFaultCode; |
| private SOAPFaultReason soapFaultReason; |
| private SOAPFaultNode soapFaultNode; |
| private SOAPFaultRole soapFaultRole; |
| private SOAPFaultDetail soapFaultDetail; |
| |
| /** |
| * If not null, this MessageContext represents the fault as it |
| * should be returned. This is used by higher-level layers |
| * that want to generate the message themselves so that |
| * processing may take place before they return control (e.g. JAX-WS.) |
| */ |
| private MessageContext faultMessageContext; |
| |
| /** |
| * SOAP1.2: URI of faulting node. Null for unknown. |
| * <p/> |
| * The value of the Node element information item is the URI that |
| * identifies the SOAP node that generated the fault. |
| * SOAP nodes that do not act as the ultimate SOAP receiver MUST include this element |
| * information item. |
| * An ultimate SOAP receiver MAY include this element information item to |
| * indicate explicitly that it generated the fault. |
| */ |
| private String nodeURI; |
| |
| private String faultAction; |
| |
| |
| /** |
| * Constructor. |
| * |
| * @param message the human-readable text describing the fault |
| */ |
| public AxisFault(String message) { |
| this.message = message; |
| addReason(message); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param faultCode - fault code of the message as a QName |
| * @param faultReason - the reason for the fault. The language will be defaulted to 'en' |
| * @param cause embedded fault which caused this one |
| */ |
| public AxisFault(QName faultCode, String faultReason, Throwable cause) { |
| this(faultReason, cause); |
| setFaultCode(faultCode); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param faultCode - fault code of the message as a QName |
| * @param faultSubCodes - list sub fault codes as a list if QNames |
| * @param faultReason - the reason for the fault. The language will be defaulted to 'en' |
| * @param cause embedded fault which caused this one |
| */ |
| public AxisFault(QName faultCode, List<QName> faultSubCodes, String faultReason, Throwable cause) { |
| this(faultReason, cause); |
| setFaultCode(faultCode); |
| setFaultSubCodes(faultSubCodes); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param faultCode a QName for the fault code |
| * @param faultReason the reason for the fault. The language will be defaulted to 'en' |
| * @param faultNode a URL identifying the SOAP node generating this fault, or null |
| * @param faultRole a URL identifying the SOAP role active when generating this fault, or null |
| * @param faultDetail arbitrary XML containing application-specific fault data |
| */ |
| public AxisFault(QName faultCode, String faultReason, String faultNode, String faultRole, |
| OMElement faultDetail) { |
| this(faultReason, faultCode); |
| this.faultNode = faultNode; |
| this.faultRole = faultRole; |
| setDetail(faultDetail); |
| } |
| |
| /** |
| * This is just a convenience method for the user. If you set these, do not use other methods |
| * in this class to get and set things. |
| * Any of the parameters can be null |
| * |
| * @param soapFaultCode the fault code |
| * @param soapFaultReason the fault reason |
| * @param soapFaultNode the SOAPFaultNode representing the source node for this fault |
| * @param soapFaultRole the SOAPFaultRole representing the source role for this fault |
| * @param soapFaultDetail the SOAPFaultDetail containing any application-specific info |
| */ |
| public AxisFault(SOAPFaultCode soapFaultCode, SOAPFaultReason soapFaultReason, |
| SOAPFaultNode soapFaultNode, SOAPFaultRole soapFaultRole, |
| SOAPFaultDetail soapFaultDetail) { |
| initializeValues(soapFaultCode, soapFaultReason, soapFaultNode, soapFaultRole, |
| soapFaultDetail); |
| } |
| |
| public AxisFault(SOAPFault fault) { |
| initializeValues(fault); |
| } |
| |
| public AxisFault(SOAPFault fault, MessageContext faultCtx) { |
| initializeValues(fault); |
| faultMessageContext = faultCtx; |
| } |
| |
| private void initializeValues(SOAPFault fault) { |
| if (fault != null) { |
| initializeValues(fault.getCode(), fault.getReason(), fault.getNode(), |
| fault.getRole(), fault.getDetail()); |
| } |
| } |
| |
| private void initializeValues(SOAPFaultCode soapFaultCode, |
| SOAPFaultReason soapFaultReason, |
| SOAPFaultNode soapFaultNode, |
| SOAPFaultRole soapFaultRole, |
| SOAPFaultDetail soapFaultDetail) { |
| this.soapFaultCode = soapFaultCode; |
| this.soapFaultReason = soapFaultReason; |
| this.soapFaultNode = soapFaultNode; |
| this.soapFaultRole = soapFaultRole; |
| this.soapFaultDetail = soapFaultDetail; |
| |
| if (soapFaultDetail != null) { |
| // OMElement exceptionElement = soapFaultDetail.getFirstChildWithName( |
| // new QName(SOAPConstants.SOAP_FAULT_DETAIL_EXCEPTION_ENTRY)); |
| // if (exceptionElement != null && exceptionElement.getText() != null) { |
| // cause = new Exception(exceptionElement.getText()); |
| // } |
| |
| details = new ArrayList<OMElement>(); |
| for (Iterator<?> it = soapFaultDetail.getChildElements(); it.hasNext(); ) { |
| details.add((OMElement)it.next()); |
| } |
| } |
| |
| if (soapFaultReason != null) { |
| message = soapFaultReason.getFaultReasonText(Locale.ENGLISH); |
| } |
| |
| if (soapFaultCode != null) { |
| // This works the same regardless of SOAP version |
| faultCode = soapFaultCode.getValueAsQName(); |
| |
| SOAPFaultSubCode subCode = soapFaultCode.getSubCode(); |
| if (subCode != null) { |
| faultSubCodes = new ArrayList<QName>(); |
| while (subCode != null) { |
| faultSubCodes.add(subCode.getValueAsQName()); |
| subCode = subCode.getSubCode(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Construct a fault from a Throwable. This is a protected constructor - in general |
| * to make an AxisFault from an Exception, you should be calling AxisFault.makeFault(e), |
| * which prevents AxisFaults within AxisFaults. |
| * |
| * @param cause the Throwable that caused the problem |
| */ |
| protected AxisFault(Throwable cause) { |
| this((cause != null) |
| ? cause.getMessage() |
| : null, cause); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param messageText - this will appear as the Text in the Reason information item of SOAP Fault |
| * @param faultCode - this will appear as the Value in the Code information item of SOAP Fault |
| */ |
| public AxisFault(String messageText, String faultCode) { |
| this(messageText); |
| setFaultCode(faultCode); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param messageText this will appear as the Text in the Reason information item of SOAP Fault |
| * @param faultCode this will appear as the Value in the Code information item of SOAP Fault |
| */ |
| public AxisFault(String messageText, QName faultCode) { |
| this(messageText); |
| setFaultCode(faultCode); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param message this will appear as the Text in the Reason information item of SOAP Fault |
| * @param cause the embedded Throwable that caused this fault |
| */ |
| public AxisFault(String message, Throwable cause) { |
| super(message, cause); |
| |
| if (message != null) { |
| addReason(message); |
| this.message = message; |
| } |
| } |
| |
| /** |
| * @param messageText - this will appear as the Text in the Reason information item of SOAP Fault |
| * @param faultCode - this will appear as the Value in the Code information item of SOAP Fault |
| * @param cause - this will appear under the Detail information item of SOAP Fault |
| */ |
| public AxisFault(String messageText, QName faultCode, Throwable cause) { |
| this(messageText, cause); |
| setFaultCode(faultCode); |
| } |
| |
| |
| /** |
| * @param message |
| * @param faultMessageContext |
| * @param cause |
| */ |
| public AxisFault(String message, MessageContext faultMessageContext, Throwable cause) { |
| super(message, cause); |
| |
| this.faultMessageContext = faultMessageContext; |
| } |
| |
| |
| /** |
| * @param messageText - this will appear as the Text in the Reason information item of SOAP Fault |
| * @param faultCode - this will appear as the Value in the Code information item of SOAP Fault |
| * @param cause - this will appear under the Detail information item of SOAP Fault |
| */ |
| public AxisFault(String messageText, String faultCode, Throwable cause) { |
| this(messageText, cause); |
| setFaultCode(faultCode); |
| } |
| |
| /** |
| * Create an AxisFault by providing a textual message and a MessageContext |
| * that contains the actual fault representation. |
| * |
| * @param message A string that's really only useful for logging. |
| * @param faultMessageContext A MessageContext which must contain SOAP fault info |
| */ |
| public AxisFault(String message, MessageContext faultMessageContext) { |
| this(message); |
| this.faultMessageContext = faultMessageContext; |
| } |
| |
| /** |
| * Add a header to the list of fault headers |
| * |
| * @param header to add. |
| */ |
| public void addHeader(SOAPHeaderBlock header) { |
| headers.add(header); |
| } |
| |
| /** |
| * Add a reason for the fault in the empty "" language |
| * |
| * @param text text message |
| */ |
| public void addReason(String text) { |
| faultReasonList.add(new FaultReason(text, "")); |
| } |
| |
| /** |
| * Add a reason for the fault |
| * |
| * @param text text message |
| * @param language language |
| */ |
| public void addReason(String text, String language) { |
| faultReasonList.add(new FaultReason(text, language)); |
| } |
| |
| /** |
| * Returns the first fault reason, if available. If not found, returns null. |
| * |
| * @return faultReason |
| */ |
| public String getReason() { |
| if (faultReasonList.size() >= 1) { |
| return faultReasonList.get(0).getText(); |
| } else if (soapFaultReason != null) { |
| return soapFaultReason.getFaultReasonText(Locale.ENGLISH); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Iterate over all of the headers |
| * |
| * @return iterator |
| */ |
| public ListIterator<SOAPHeaderBlock> headerIterator() { |
| return headers.listIterator(); |
| } |
| |
| /** |
| * Get at the headers. Useful for java1.5 iteration. |
| * |
| * @return the headers for this fault |
| */ |
| public List<SOAPHeaderBlock> headers() { |
| return headers; |
| } |
| |
| /** |
| * 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 <code>Exception</code> to build a fault for |
| * @return an <code>AxisFault</code> representing <code>e</code> |
| */ |
| public static AxisFault makeFault(Throwable e) { |
| if (e instanceof InvocationTargetException) { |
| return makeFault(((InvocationTargetException) e).getTargetException()); |
| } else if (e instanceof UndeclaredThrowableException) { |
| Throwable t = ((UndeclaredThrowableException) e).getCause(); |
| if (t instanceof Exception) { |
| e = t; |
| } |
| } |
| if (e instanceof AxisFault) { |
| return (AxisFault) e; |
| } |
| |
| return new AxisFault(e); |
| } |
| |
| /** |
| * Get the current fault detail. If the fault has several detail elements, only the first one is |
| * returned. |
| * |
| * @return the (first) detail element, or <code>null</code> if there is no detail element |
| */ |
| public OMElement getDetail() { |
| return details == null || details.isEmpty() ? null : details.get(0); |
| } |
| |
| /** |
| * Get the SOAP fault detail elements. |
| * |
| * @return the list of SOAP fault detail elements, or <code>null</code> if no detail elements |
| * have been set for this fault |
| */ |
| public List<OMElement> getDetails() { |
| return details; |
| } |
| |
| public QName getFaultCode() { |
| return faultCode; |
| } |
| |
| public List<QName> getFaultSubCodes() { |
| return faultSubCodes; |
| } |
| |
| /** |
| * @return SOAPFaultCode if, user has set a {@link SOAPFaultCode} element when constructing the |
| * {@link #AxisFault(org.apache.axiom.soap.SOAPFaultCode, org.apache.axiom.soap.SOAPFaultReason, org.apache.axiom.soap.SOAPFaultNode, org.apache.axiom.soap.SOAPFaultRole, org.apache.axiom.soap.SOAPFaultDetail) AxisFault} |
| */ |
| public SOAPFaultCode getFaultCodeElement() { |
| return soapFaultCode; |
| } |
| |
| /** |
| * @return SOAPFaultCode if, user has set a {@link SOAPFaultReason} element when constructing the |
| * {@link #AxisFault(org.apache.axiom.soap.SOAPFaultCode, org.apache.axiom.soap.SOAPFaultReason, org.apache.axiom.soap.SOAPFaultNode, org.apache.axiom.soap.SOAPFaultRole, org.apache.axiom.soap.SOAPFaultDetail) AxisFault} |
| */ |
| public SOAPFaultReason getFaultReasonElement() { |
| return soapFaultReason; |
| } |
| |
| /** |
| * @return SOAPFaultCode if, user has set a {@link SOAPFaultNode} element when constructing the |
| * {@link #AxisFault(org.apache.axiom.soap.SOAPFaultCode, org.apache.axiom.soap.SOAPFaultReason, org.apache.axiom.soap.SOAPFaultNode, org.apache.axiom.soap.SOAPFaultRole, org.apache.axiom.soap.SOAPFaultDetail) AxisFault} |
| */ |
| public SOAPFaultNode getFaultNodeElement() { |
| return soapFaultNode; |
| } |
| |
| /** |
| * @return SOAPFaultCode if, user has set a {@link SOAPFaultRole} element when constructing the |
| * {@link #AxisFault(org.apache.axiom.soap.SOAPFaultCode, org.apache.axiom.soap.SOAPFaultReason, org.apache.axiom.soap.SOAPFaultNode, org.apache.axiom.soap.SOAPFaultRole, org.apache.axiom.soap.SOAPFaultDetail) AxisFault} |
| */ |
| public SOAPFaultRole getFaultRoleElement() { |
| return soapFaultRole; |
| } |
| |
| /** |
| * @return SOAPFaultCode if, user has set a {@link SOAPFaultDetail} element when constructing the |
| * {@link #AxisFault(org.apache.axiom.soap.SOAPFaultCode, org.apache.axiom.soap.SOAPFaultReason, org.apache.axiom.soap.SOAPFaultNode, org.apache.axiom.soap.SOAPFaultRole, org.apache.axiom.soap.SOAPFaultDetail) AxisFault} |
| */ |
| public SOAPFaultDetail getFaultDetailElement() { |
| return soapFaultDetail; |
| } |
| |
| /** |
| * Get the faulting node uri. |
| * SOAP1.2 |
| * |
| * @return URI as a string or null |
| */ |
| public String getNodeURI() { |
| return nodeURI; |
| } |
| |
| /** |
| * Set the entire detail element of the fault |
| * |
| * @param detail an OMElement which MUST be |
| */ |
| public void setDetail(OMElement detail) { |
| details = new ArrayList<OMElement>(); |
| details.add(detail); |
| } |
| |
| /** |
| * Set the SOAP fault details. |
| * |
| * @param details |
| * a list of elements for the SOAP fault details |
| */ |
| public void setDetails(List<OMElement> details) { |
| this.details = details; |
| } |
| |
| public void setFaultCode(QName soapFaultCode) { |
| this.faultCode = soapFaultCode; |
| } |
| |
| public void setFaultSubCodes(List<QName> faultSubCodes) { |
| this.faultSubCodes = faultSubCodes; |
| } |
| |
| public void setFaultCode(String soapFaultCode) { |
| // TODO: is it really safe to assume that the passed string is always the localpart? |
| // What if someone passes soapenv:Sender? |
| faultCode = new QName(soapFaultCode); |
| } |
| |
| /** |
| * Set the faulting node uri. (SOAP1.2) |
| * |
| * @param nodeURI a String containing a URI indicating which SOAP Node faulted |
| */ |
| public void setNodeURI(String nodeURI) { |
| this.nodeURI = nodeURI; |
| } |
| |
| public String getFaultNode() { |
| return faultNode; |
| } |
| |
| public String getFaultRole() { |
| return faultRole; |
| } |
| |
| /** |
| * Returns the MessageContext representation of the fault if the fault |
| * was created by providing that. |
| * |
| * @return The MessageContext representing the fault message or null if the |
| * fault was not created with MessageContext representation. |
| */ |
| public MessageContext getFaultMessageContext() { |
| return faultMessageContext; |
| } |
| |
| class FaultReason implements Serializable{ |
| |
| private static final long serialVersionUID = -8125991422614607169L; |
| |
| /** |
| * Language of the reason. |
| * xml:lang="en" "en-GB" or just "" |
| */ |
| private String language = ""; |
| |
| /** |
| * env:reasontext |
| */ |
| private String text; |
| |
| public FaultReason() { |
| } |
| |
| public FaultReason(String text, String language) { |
| this.text = text; |
| this.language = language; |
| } |
| |
| /** |
| * Returns a string representation of the object. |
| * |
| * @return the text value |
| */ |
| public String toString() { |
| return text; |
| } |
| |
| public String getLanguage() { |
| return language; |
| } |
| |
| public String getText() { |
| return text; |
| } |
| |
| public void setLanguage(String language) { |
| this.language = language; |
| } |
| |
| public void setText(String text) { |
| this.text = text; |
| } |
| } |
| |
| /** |
| * @return the action value set for the fault message |
| */ |
| public String getFaultAction() { |
| return faultAction; |
| } |
| |
| /** |
| * Set the (OPTIONAL) action value for the fault message |
| * |
| * @param faultAction a String containing an action URI for the fault |
| */ |
| public void setFaultAction(String faultAction) { |
| this.faultAction = faultAction; |
| } |
| |
| /** |
| * Returns the detail message, including the message from the cause, if any, of this exception. |
| * |
| * @return the detail message |
| */ |
| public String getMessage() { |
| return message; |
| } |
| |
| /** |
| * this field is used to identify the axis2 fault type |
| */ |
| private int faultType; |
| |
| public int getFaultType() { |
| return faultType; |
| } |
| |
| public void setFaultType(int faultType) { |
| this.faultType = faultType; |
| } |
| } |