View Javadoc
1   /*
2    * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.xml.internal.ws.fault;
27  
28  
29  import com.sun.xml.internal.ws.api.SOAPVersion;
30  import com.sun.xml.internal.ws.util.DOMUtil;
31  import org.w3c.dom.Element;
32  import org.w3c.dom.Node;
33  
34  import javax.xml.bind.annotation.XmlAccessType;
35  import javax.xml.bind.annotation.XmlAccessorType;
36  import javax.xml.bind.annotation.XmlElement;
37  import javax.xml.bind.annotation.XmlRootElement;
38  import javax.xml.bind.annotation.XmlTransient;
39  import javax.xml.bind.annotation.XmlType;
40  import javax.xml.namespace.QName;
41  import javax.xml.soap.SOAPException;
42  import javax.xml.soap.SOAPFault;
43  import javax.xml.ws.WebServiceException;
44  import javax.xml.ws.soap.SOAPFaultException;
45  import java.util.Iterator;
46  
47  /**
48   * SOAP 1.2 Fault class that can be marshalled/unmarshalled by JAXB
49   * <p/>
50   * <pre>
51   * Example:
52   * &lt;env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
53   *            xmlns:m="http://www.example.org/timeouts"
54   *            xmlns:xml="http://www.w3.org/XML/1998/namespace">
55   * &lt;env:Body>
56   *     &lt;env:Fault>
57   *         &lt;env:Code>
58   *             &lt;env:Value>env:Sender* &lt;/env:Value>
59   *             &lt;env:Subcode>
60   *                 &lt;env:Value>m:MessageTimeout* &lt;/env:Value>
61   *             &lt;/env:Subcode>
62   *         &lt;/env:Code>
63   *         &lt;env:Reason>
64   *             &lt;env:Text xml:lang="en">Sender Timeout* &lt;/env:Text>
65   *         &lt;/env:Reason>
66   *         &lt;env:Detail>
67   *             &lt;m:MaxTime>P5M* &lt;/m:MaxTime>
68   *         &lt;/env:Detail>
69   *     &lt;/env:Fault>
70   * &lt;/env:Body>
71   * &lt;/env:Envelope>
72   * </pre>
73   *
74   * @author Vivek Pandey
75   */
76  @XmlRootElement(name = "Fault", namespace = "http://www.w3.org/2003/05/soap-envelope")
77  @XmlAccessorType(XmlAccessType.FIELD)
78  @XmlType(name = "", propOrder = {
79      "code",
80      "reason",
81      "node",
82      "role",
83      "detail"
84  })
85  class SOAP12Fault extends SOAPFaultBuilder {
86      @XmlTransient
87      private static final String ns = "http://www.w3.org/2003/05/soap-envelope";
88  
89      @XmlElement(namespace=ns, name="Code")
90      private CodeType code;
91  
92      @XmlElement(namespace=ns, name="Reason")
93      private ReasonType reason;
94  
95      @XmlElement(namespace=ns, name="Node")
96      private String node;
97  
98      @XmlElement(namespace=ns, name="Role")
99      private String role;
100 
101     @XmlElement(namespace=ns, name="Detail")
102     private DetailType detail;
103 
104     SOAP12Fault() {
105     }
106 
107     SOAP12Fault(CodeType code, ReasonType reason, String node, String role, DetailType detail) {
108         this.code = code;
109         this.reason = reason;
110         this.node = node;
111         this.role = role;
112         this.detail = detail;
113     }
114 
115     SOAP12Fault(CodeType code, ReasonType reason, String node, String role, Element detailObject) {
116         this.code = code;
117         this.reason = reason;
118         this.node = node;
119         this.role = role;
120         if (detailObject != null) {
121             if(detailObject.getNamespaceURI().equals(ns) && detailObject.getLocalName().equals("Detail")){
122                 detail = new DetailType();
123                 for(Element detailEntry : DOMUtil.getChildElements(detailObject)){
124                     detail.getDetails().add(detailEntry);
125                 }
126             }else{
127                 detail = new DetailType(detailObject);
128             }
129         }
130     }
131 
132     SOAP12Fault(SOAPFault fault) {
133         code = new CodeType(fault.getFaultCodeAsQName());
134         try {
135             fillFaultSubCodes(fault);
136         } catch (SOAPException e) {
137             throw new WebServiceException(e);
138         }
139 
140         reason = new ReasonType(fault.getFaultString());
141         role = fault.getFaultRole();
142         node = fault.getFaultNode();
143         if (fault.getDetail() != null) {
144             detail = new DetailType();
145             Iterator iter = fault.getDetail().getDetailEntries();
146             while(iter.hasNext()){
147                 Element fd = (Element)iter.next();
148                 detail.getDetails().add(fd);
149             }
150         }
151     }
152 
153     SOAP12Fault(QName code, String reason, Element detailObject) {
154         this(new CodeType(code), new ReasonType(reason), null, null, detailObject);
155     }
156 
157     CodeType getCode() {
158         return code;
159     }
160 
161     ReasonType getReason() {
162         return reason;
163     }
164 
165     String getNode() {
166         return node;
167     }
168 
169     String getRole() {
170         return role;
171     }
172 
173     @Override
174     DetailType getDetail() {
175         return detail;
176     }
177 
178     @Override
179     void setDetail(DetailType detail) {
180         this.detail = detail;
181     }
182 
183     @Override
184     String getFaultString() {
185         return reason.texts().get(0).getText();
186     }
187 
188      protected Throwable getProtocolException() {
189         try {
190             SOAPFault fault = SOAPVersion.SOAP_12.getSOAPFactory().createFault();;
191             if(reason != null){
192                 for(TextType tt : reason.texts()){
193                     fault.setFaultString(tt.getText());
194                 }
195             }
196 
197             if(code != null){
198                 fault.setFaultCode(code.getValue());
199                 fillFaultSubCodes(fault, code.getSubcode());
200             }
201 
202             if(detail != null && detail.getDetail(0) != null){
203                 javax.xml.soap.Detail detail = fault.addDetail();
204                 for(Node obj: this.detail.getDetails()){
205                     Node n = fault.getOwnerDocument().importNode(obj, true);
206                     detail.appendChild(n);
207                 }
208             }
209 
210             if(node != null) {
211                 fault.setFaultNode(node);
212             }
213 
214             return new ServerSOAPFaultException(fault);
215         } catch (SOAPException e) {
216             throw new WebServiceException(e);
217         }
218     }
219 
220     /**
221      * Recursively populate the Subcodes
222      */
223     private void fillFaultSubCodes(SOAPFault fault, SubcodeType subcode) throws SOAPException {
224         if(subcode != null){
225             fault.appendFaultSubcode(subcode.getValue());
226             fillFaultSubCodes(fault, subcode.getSubcode());
227         }
228     }
229 
230     /**
231      * Adds Fault subcodes from {@link SOAPFault} to {@link #code}
232      */
233     private void fillFaultSubCodes(SOAPFault fault) throws SOAPException {
234         Iterator subcodes = fault.getFaultSubcodes();
235         SubcodeType firstSct = null;
236         while(subcodes.hasNext()){
237             QName subcode = (QName)subcodes.next();
238             if(firstSct == null){
239                 firstSct = new SubcodeType(subcode);
240                 code.setSubcode(firstSct);
241                 continue;
242             }
243             SubcodeType nextSct = new SubcodeType(subcode);
244             firstSct.setSubcode(nextSct);
245             firstSct = nextSct;
246         }
247     }
248 
249 }