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 }