View Javadoc

1   package org.codehaus.xfire.fault;
2   
3   import java.io.PrintStream;
4   import java.io.PrintWriter;
5   import java.util.HashMap;
6   import java.util.Map;
7   
8   import org.codehaus.xfire.XFireException;
9   import org.codehaus.yom.Element;
10  
11  /***
12   * In XFire, applications throw their own declared exceptions which are then turned into faults.  The
13   * <code>XFireFault</code> class wraps these exceptions extracting out the details for the fault message.
14   * <p/>
15   * If the developer wishes to generate their own custom fault messages, they can either override XFireFault to provide
16   * the FaultHandlers with the necessary information or write a new FaultHandler. </p>
17   * <p/>
18   * TODO Add i18n support
19   *
20   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
21   * @since Feb 14, 2004
22   */
23  public class XFireFault
24          extends XFireException
25  {
26      /***
27  	 * Serialization ID. 
28  	 */
29  	private static final long serialVersionUID = 1L;
30  	
31  	/***
32       * Fault codes.
33       */
34      public final static String VERSION_MISMATCH = "VersionMismatch";
35      public final static String MUST_UNDERSTAND = "MustUnderstand";
36      public final static String DATA_ENCODING_UNKNOWN = "DataEncodingUnknown";
37  
38      /***
39       * "The message was incorrectly formed or did not contain the appropriate information in order to succeed." -- SOAP
40       * 1.2 Spec
41       */
42      public final static String SENDER = "Sender";
43  
44      /***
45       * A SOAP 1.2 only fault code.
46       * <p/>
47       * "The message could not be processed for reasons attributable to the processing of the message rather than to the
48       * contents of the message itself." -- SOAP 1.2 Spec
49       * <p/>
50       * If this message is used in a SOAP 1.1 Fault it will most likely (depending on the FaultHandler) be mapped to
51       * "Sender" instead.
52       */
53      public final static String RECEIVER = "Receiver";
54  
55      private String faultCode;
56      private String subCode;
57      private String message;
58      private String role;
59      private Element detail;
60      private Map namespaces;
61      private Throwable cause;
62  
63      /***
64       * Creates a <code>XFireFault</code> from the given throwable. If the throwable is a <code>XFireFault</code>, it is
65       * not wrapped.
66       *
67       * @param throwable the throwable
68       * @return the fault
69       */
70      public static XFireFault createFault(Throwable throwable)
71      {
72          XFireFault fault = null;
73  
74          if (throwable instanceof XFireFault)
75          {
76              fault = (XFireFault) throwable;
77          }
78          else
79          {
80              fault = new XFireFault(throwable);
81          }
82  
83          return fault;
84      }
85  
86      protected XFireFault()
87      {
88      }
89  
90      /***
91       * Create a fault for the specified exception. The faultCode is set to RECEIVER.
92       *
93       * @param throwable
94       */
95      public XFireFault(Throwable throwable)
96      {
97          this(throwable.getMessage(), throwable, RECEIVER);
98      }
99  
100     /***
101      * Create a fault with the specified faultCode. The exception message is used for the fault message.
102      *
103      * @param throwable The exception that caused this fault.
104      * @param code      The fault code. See XFireFault's static fields.
105      */
106     public XFireFault(Throwable throwable, String code)
107     {
108         this(throwable.getMessage(), throwable, code);
109     }
110 
111     /***
112      * Create an exception wih the specified fault message and faultCode.
113      *
114      * @param message The fault message.
115      * @param code    The fault code. See XFireFault's static fields.
116      */
117     public XFireFault(String message, String code)
118     {
119         this(message, null, code);
120     }
121 
122     /***
123      * Create a fault.
124      *
125      * @param cause The exception which caused this fault.
126      * @param code  The fault code. See XFireFault's static fields.
127      */
128     public XFireFault(String message,
129                       Throwable cause,
130                       String code)
131     {
132         this.message = message != null ? message : "Fault";
133         this.faultCode = code;
134         this.cause = cause;
135         this.namespaces = new HashMap();
136     }
137 
138     /***
139      * Adds a namespace with prefix to this fault.
140      *
141      * @param prefix the prefix
142      * @param ns     the namespace.
143      */
144     public void addNamespace(String prefix, String ns)
145     {
146         namespaces.put(prefix, ns);
147     }
148 
149     /***
150      * Prints this throwable and its backtrace to the specified print stream.
151      *
152      * @param s <code>PrintStream</code> to use for output
153      */
154     public void printStackTrace(PrintStream s)
155     {
156         if (this.cause == null || this.cause == this)
157         {
158             super.printStackTrace(s);
159         }
160         else
161         {
162             s.println(this);
163             this.cause.printStackTrace(s);
164         }
165     }
166 
167     /***
168      * Prints this throwable and its backtrace to the specified print writer.
169      *
170      * @param w <code>PrintWriter</code> to use for output
171      */
172     public void printStackTrace(PrintWriter w)
173     {
174         if (this.cause == null || this.cause == this)
175         {
176             super.printStackTrace(w);
177         }
178         else
179         {
180             w.println(this);
181             this.cause.printStackTrace(w);
182         }
183     }
184 
185     /***
186      * Returns the cause of this throwable or <code>null</code> if the  cause is nonexistent or unknown.
187      *
188      * @return the nested cause.
189      */
190     public Throwable getCause()
191     {
192         return (this.cause == this ? null : this.cause);
193     }
194 
195     /***
196      * Returns the detail node. If no detail node has been set, an empty <code>&lt;detail&gt;</code> is created.
197      *
198      * @return the detail node.
199      */
200     public Element getDetail()
201     {
202         if (detail == null)
203         {
204             detail = new Element("detail");
205         }
206         return detail;
207     }
208 
209     /***
210      * Sets a details <code>Node</code> on this fault.
211      *
212      * @param details the detail node.
213      */
214     public void setDetail(Element details)
215     {
216         detail = details;
217     }
218 
219     /***
220      * Returns the fault code of this fault.
221      *
222      * @return the fault code.
223      */
224     public String getFaultCode()
225     {
226         return faultCode;
227     }
228 
229     /***
230      * Sets the fault code of this fault.
231      *
232      * @param faultCode the fault code.
233      */
234     public void setFaultCode(String faultCode)
235     {
236         this.faultCode = faultCode;
237     }
238 
239     /***
240      * Returns the detail message string of this fault.
241      *
242      * @return the detail message string of this <code>XfireFault</code> (which may be <code>null</code>)
243      */
244     public String getMessage()
245     {
246         return message;
247     }
248 
249     /***
250      * @param message The message to set.
251      */
252     public void setMessage(String message)
253     {
254         this.message = message;
255     }
256 
257     /***
258      * User defined namespaces which will be written out on the resultant SOAP Fault (for use easy with SubCodes and
259      * Detail) elements.
260      *
261      * @return
262      */
263     public Map getNamespaces()
264     {
265         return namespaces;
266     }
267 
268     public String getReason()
269     {
270         return getMessage();
271     }
272 
273     /***
274      * Returns the fault actor.
275      *
276      * @return the fault actor.
277      */
278     public String getRole()
279     {
280         return role;
281     }
282 
283     /***
284      * Sets the fault actor.
285      *
286      * @param actor the actor.
287      */
288     public void setRole(String actor)
289     {
290         this.role = actor;
291     }
292 
293     /***
294      * Returns the SubCode for the Fault Code.
295      *
296      * @return The SubCode element as detailed by the SOAP 1.2 spec.
297      */
298     public String getSubCode()
299     {
300         return subCode;
301     }
302 
303     /***
304      * Sets the SubCode for the Fault Code.
305      *
306      * @param subCode The SubCode element as detailed by the SOAP 1.2 spec.
307      */
308     public void setSubCode(String subCode)
309     {
310         this.subCode = subCode;
311     }
312 
313     /***
314      * Indicates whether this fault has a detail message.
315      *
316      * @return <code>true</code> if this fault has a detail message; <code>false</code> otherwise.
317      */
318     public boolean hasDetails()
319     {
320         return detail == null ? false : true;
321     }
322 }
323