View Javadoc

1   package org.codehaus.xfire.fault;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   
6   import javax.xml.parsers.DocumentBuilder;
7   import javax.xml.parsers.DocumentBuilderFactory;
8   import javax.xml.parsers.ParserConfigurationException;
9   
10  import org.w3c.dom.Document;
11  import org.w3c.dom.Node;
12  
13  /***
14   * <p>
15   * In XFire, applications throw their own declared exceptions which are
16   * then turned into faults.  The XFireFault class wraps these exceptions
17   * extracting out the details for the fault message.
18   * </p>
19   * <p>
20   * If the developer wishes to generate their own custom fault messages,
21   * they can either override XFireFault to provide the FaultHandlers with
22   * the necessary information or write a new FaultHandler.
23   * </p>
24   * <p>
25   * TODO Add i18n support
26   * </p>
27   * 
28   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
29   * @since Feb 14, 2004
30   */
31  public class XFireFault
32      extends Exception
33  {
34      /*** Fault codes. */
35      public final static String VERSION_MISMATCH = "VersionMismatch";
36      public final static String MUST_UNDERSTAND = "MustUnderstand";
37      public final static String DATA_ENCODING_UNKNOWN = "DataEncodingUnknown";
38      
39      /***
40       * "The message was incorrectly formed or did not contain the appropriate 
41       * information in order to succeed." -- SOAP 1.2 Spec
42       */
43      public final static String SENDER = "Sender";
44      
45      /*** 
46       * <p>
47       * A SOAP 1.2 only fault code.
48       * </p>
49       * <p>
50       * "The message could not be processed for reasons attributable to the
51       * processing of the message rather than to the contents of the message itself."
52       *  -- SOAP 1.2 Spec
53       * </p>
54       * <p>
55       * If this message is used in a SOAP 1.1 Fault it will most likely
56       * (depending on the FaultHandler) be mapped to "Sender" instead.
57       * </p>
58       */
59      public final static String RECEIVER = "Receiver";
60  
61  	private String faultCode;
62      
63  	private String subCode;
64  	
65  	private String message;
66  	
67  	private String role;
68  	
69  	private Node detail;
70  
71      private DocumentBuilder docBuilder;
72      
73      private Map namespaces;
74      
75      /***
76       * Create a fault.
77       * 
78  	 * @param throwable The exception which caused this fault.
79       * @param code The fault code. See XFireFault's static fields.
80       */
81  	public XFireFault( String message, 
82  	                   Throwable throwable,
83  	                   String code )
84  	{
85  		super( throwable );
86  		
87  		if ( message != null )
88  		    this.message = message;
89  		else
90  		    this.message = "Fault";
91  		
92  		this.faultCode = code;
93          this.namespaces = new HashMap();
94  	}
95  
96      /***
97       * Create a fault for the specified exception. The faultCode is
98       * set to RECEIVER.
99       * @param throwable
100      */
101 	public XFireFault( Throwable throwable )
102 	{
103 	    this( throwable, RECEIVER );
104 	}
105 	
106 	/***
107      * Create a fault with the specified faultCode. The exception
108      * message is used for the fault message.
109      * 
110      * @param throwable The exception that caused this fault.
111      * @param code The fault code. See XFireFault's static fields.
112      */
113     public XFireFault(Throwable throwable, String code)
114     {
115         this( throwable.getMessage(), throwable, code );
116     }
117 
118     /***
119      * Create an exception wih the specified fault message
120      * and faultCode.
121      * 
122      * @param message The fault message.
123 	 * @param code The fault code. See XFireFault's static fields.
124      */
125 	public XFireFault(String message, String code)
126 	{
127 		super();
128 		this.message = message;
129         this.faultCode = code;
130         this.namespaces = new HashMap();
131 	}
132 
133 	protected XFireFault()
134     {
135     }
136 
137     public static XFireFault createFault( Throwable throwable )
138 	{
139 	    XFireFault fault = null;
140         
141         if ( throwable instanceof XFireFault )
142         {
143             fault = (XFireFault) throwable;
144         }
145         else
146         {
147             fault = new XFireFault( throwable );
148         }
149         
150         return fault;
151 	}
152 	
153     /***
154      * @return
155      */
156     public String getCode()
157     {
158         return faultCode;
159     }
160     
161     public String getReason()
162     {
163         return getMessage();
164     }
165     
166     /***
167      * Returns the SubCode for the Fault Code.
168      * 
169      * @return The SubCode element as detailed by the SOAP 1.2 spec.
170      */
171     public String getSubCode()
172     {
173         return subCode;
174     }
175     
176     public Node getDetail()
177     {
178         if ( detail == null )
179         {
180             try
181             {
182                 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
183                 DocumentBuilder b = factory.newDocumentBuilder();
184                 
185                 Document doc = b.newDocument();
186                 detail = doc.createElement("detail");
187             }
188             catch (ParserConfigurationException e)
189             {
190                 throw new RuntimeException("Couldn't find a DOM parser.", e);
191             }
192         }
193         return detail;
194     }
195     
196     public void setDetail(Node details)
197     {
198         detail = details;
199     }
200     
201     public void setSubCode(String subCode)
202     {
203         this.subCode = subCode;
204     }
205 
206     public String getFaultCode()
207     {
208         return faultCode;
209     }
210 
211     public void setFaultCode(String faultCode)
212     {
213         this.faultCode = faultCode;
214     }
215     
216     /***
217      * User defined namespaces which will be written out
218      * on the resultant SOAP Fault (for use easy with SubCodes and Detail)
219      * elements.
220      * 
221      * @return
222      */
223     public Map getNamespaces()
224     {
225         return namespaces;
226     }
227     
228     public void addNamespace( String prefix, String ns )
229     {
230         namespaces.put(prefix, ns);
231     }
232 
233     /***
234      * @return
235      */
236     public boolean hasDetails()
237     {
238         if ( detail == null )
239             return false;
240         
241         return true;
242     }
243         
244     /***
245      * @return Returns the message.
246      */
247     public String getMessage()
248     {
249         return message;
250     }
251     
252     /***
253      * @param message The message to set.
254      */
255     public void setMessage(String message)
256     {
257         this.message = message;
258     }
259 
260     /***
261      * @return Returns the fault actor.
262      */
263     public String getRole()
264     {
265         return role;
266     }
267     
268     /***
269      * Sets the fault actor.
270      * @param actor
271      */
272     public void setRole(String actor)
273     {
274         this.role = actor;
275     }
276 }