001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: SOAPFaultDetail.java,v 1.2 2008/06/25 05:47:23 qcheng Exp $ 026 * 027 */ 028 029 030package com.sun.identity.liberty.ws.soapbinding; 031 032import java.lang.Object; 033 034import java.io.InputStream; 035import java.io.ByteArrayOutputStream; 036import java.io.StringReader; 037 038import java.util.ArrayList; 039import java.util.Iterator; 040import java.util.List; 041 042import java.security.cert.X509Certificate; 043 044import org.w3c.dom.Document; 045import org.w3c.dom.Element; 046import org.w3c.dom.Node; 047import org.w3c.dom.NodeList; 048 049import javax.xml.soap.SOAPMessage; 050import javax.xml.bind.JAXBContext; 051import javax.xml.bind.JAXBException; 052import javax.xml.bind.Marshaller; 053import javax.xml.bind.Unmarshaller; 054import javax.xml.namespace.QName; 055import javax.xml.transform.stream.StreamSource; 056 057import com.sun.identity.saml.common.SAMLConstants; 058import com.sun.identity.saml.common.SAMLException; 059import com.sun.identity.saml.common.SAMLUtils; 060 061import com.sun.identity.shared.xml.XMLUtils; 062 063/** 064 * The <code>SOAPFaultDetail</code> class represents the 'Detail' child element 065 * of SOAP Fault element. Its children can be of any type. This class provides 066 * specific methods to get and set the following children: Status element, 067 * <code>CorrelationHeader</code>, <code>ProviderHeader</code>, 068 * <code>ConsentHeader</code>, <code>UsageDirectiveHeader</code> and 069 * <code>ProcessingContextHeader</code>. It also provides generic methods to 070 * get and set other children. 071 * 072 * @supported.all.api 073 */ 074public class SOAPFaultDetail { 075 public static final QName BOGUS_ACTOR = 076 new QName(SOAPBindingConstants.NS_SOAP_BINDING, "BogusActor"); 077 public static final QName BOGUS_MUST_UNSTND = 078 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 079 "BogusMustUnstnd"); 080 public static final QName STALE_MSG = 081 new QName(SOAPBindingConstants.NS_SOAP_BINDING, "StaleMsg"); 082 public static final QName DUPLICATE_MSG = 083 new QName(SOAPBindingConstants.NS_SOAP_BINDING, "DuplicateMsg"); 084 public static final QName INVALID_REF_TO_MSG_ID = 085 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 086 "invalidRefToMsgID"); 087 public static final QName PROVIDER_ID_NOT_VALID = 088 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 089 "ProviderIDNotValid"); 090 public static final QName AFFILIATION_ID_NOT_VALID = 091 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 092 "AffiliationIDNotValid"); 093 public static final QName ID_STAR_MSG_NOT_UNSTD = 094 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 095 "IDStarMsgNotUnstd"); 096 public static final QName PROC_CTX_URI_NOT_UNSTD = 097 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 098 "ProcCtxURINotUnstd"); 099 public static final QName PROC_CTX_UNWILLING = 100 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 101 "ProcCtxUnwilling"); 102 public static final QName CAN_NOT_HONOUR_USAGE_DIRECTIVE = 103 new QName(SOAPBindingConstants.NS_SOAP_BINDING, 104 "CannotHonourUsageDirective"); 105 public static final QName ENDPOINT_MOVED = 106 new QName(SOAPBindingConstants.NS_SOAP_BINDING_11, 107 "EndpointMoved"); 108 public static final QName INAPPROPRIATE_CREDENTIALS = 109 new QName(SOAPBindingConstants.NS_SOAP_BINDING_11, 110 "InappropriateCredentials"); 111 112 private QName statusCode = null; 113 private String statusRef = null; 114 private String statusComment = null; 115 private CorrelationHeader correlationHeader = null; 116 private ConsentHeader consentHeader = null; 117 private List usageDirectiveHeaders = null; 118 private ProviderHeader providerHeader = null; 119 private ProcessingContextHeader processingContextHeader = null; 120 private ServiceInstanceUpdateHeader serviceInstanceUpdateHeader = null; 121 private List otherChildren = null; 122 123 /** 124 * This constructor takes a status code, a status ref and a status comment. 125 * If the status code is not null, a Status child element will be created. 126 * 127 * @param statusCode the value of <code>code</code> attribute of the Status 128 * element. 129 * @param statusRef the value of <code>ref</code> attribute of the Status 130 * element. 131 * @param statusComment the value of <code>comment</code> attribute of the 132 * Status element. 133 */ 134 public SOAPFaultDetail(QName statusCode,String statusRef, 135 String statusComment) { 136 this.statusCode = statusCode; 137 this.statusRef = statusRef; 138 this.statusComment = statusComment; 139 } 140 141 /** 142 * This constructor takes a list of children except Status element, 143 * <code>CorrelationHeader</code>, <code>ProviderHeader</code> 144 * <code>ConsentHeader</code>, <code>UsageDirectiveHeader</code>, 145 * <code>ProcessingContextHeader</code> and 146 * <code>ServiceInstanceUpdateHeader</code>. 147 * Each entry will be a <code>org.w3c.dom.Element</code>. 148 * 149 * @param otherChildren a list of children element 150 */ 151 public SOAPFaultDetail(List otherChildren) { 152 this.otherChildren = otherChildren; 153 } 154 155 /** 156 * Parses a <code>org.w3c.dom.Document</code> to construct this object. 157 * 158 * @param detailElement a <code>org.w3c.dom.Document</code>. 159 * @throws SOAPBindingException if an error occurs while parsing 160 * the document 161 */ 162 SOAPFaultDetail(Element detailElement) throws SOAPBindingException { 163 NodeList nl = detailElement.getChildNodes(); 164 int length = nl.getLength(); 165 166 if (length == 0) { 167 return; 168 } 169 170 otherChildren = new ArrayList(); 171 for (int i = 0; i < length; i++) { 172 Node child = nl.item(i); 173 if (child.getNodeType() == Node.ELEMENT_NODE) { 174 Element element = (Element)child; 175 String localName = element.getLocalName(); 176 String ns = element.getNamespaceURI(); 177 178 if (SOAPBindingConstants.NS_SOAP_BINDING.equals(ns)) { 179 if (SOAPBindingConstants.TAG_STATUS.equals(localName)) { 180 String value = XMLUtils.getNodeAttributeValue( 181 element, 182 SOAPBindingConstants.ATTR_CODE); 183 if (value == null || value.length() ==0) { 184 String msg = Utils.bundle 185 .getString("missingFaultStatusCode"); 186 Utils.debug.error("SOAPFaultException: " + msg); 187 throw new SOAPBindingException(msg); 188 } 189 statusCode = Utils.convertStringToQName(value,element); 190 statusRef = XMLUtils.getNodeAttributeValue( 191 element, 192 SOAPBindingConstants.ATTR_REF); 193 statusComment = XMLUtils.getNodeAttributeValue( 194 element, 195 SOAPBindingConstants.ATTR_COMMENT); 196 } else if (SOAPBindingConstants.TAG_CORRELATION 197 .equals(localName)) { 198 correlationHeader = new CorrelationHeader(element); 199 } else if (SOAPBindingConstants.TAG_CONSENT 200 .equals(localName)) { 201 consentHeader = new ConsentHeader(element); 202 } else if(SOAPBindingConstants.TAG_USAGE_DIRECTIVE 203 .equals(localName)){ 204 if (usageDirectiveHeaders == null) { 205 usageDirectiveHeaders = new ArrayList(); 206 } 207 usageDirectiveHeaders.add( 208 new UsageDirectiveHeader(element)); 209 } else if (SOAPBindingConstants.TAG_PROVIDER 210 .equals(localName)) { 211 providerHeader = new ProviderHeader(element); 212 } else if (SOAPBindingConstants.TAG_PROCESSING_CONTEXT 213 .equals(localName)){ 214 processingContextHeader = 215 new ProcessingContextHeader(element); 216 } else { 217 otherChildren.add(element); 218 } 219 } else if (SOAPBindingConstants.NS_SOAP_BINDING_11.equals(ns)&& 220 SOAPBindingConstants.TAG_SERVICE_INSTANCE_UPDATE 221 .equals(localName)){ 222 serviceInstanceUpdateHeader = 223 new ServiceInstanceUpdateHeader(element); 224 } else { 225 otherChildren.add(element); 226 } 227 } 228 } 229 if (otherChildren.isEmpty()) { 230 otherChildren = null; 231 } 232 } 233 234 /** 235 * Returns the <code>CorrelationHeader</code>. 236 * 237 * @return the <code>CorrelationHeader</code>. 238 */ 239 public CorrelationHeader getCorrelationHeader() { 240 return correlationHeader; 241 } 242 243 /** 244 * Returns the <code>ConsentHeader</code>. 245 * 246 * @return the <code>ConsentHeader</code>. 247 */ 248 public ConsentHeader getConsentHeader() { 249 return consentHeader; 250 } 251 252 /** 253 * Returns a list of <code>UsageDirectiveHeader</code>. 254 * 255 * @return a list of <code>UsageDirectiveHeader</code>. 256 */ 257 public List getUsageDirectiveHeaders() { 258 return usageDirectiveHeaders; 259 } 260 261 /** 262 * Returns the <code>ProviderHeader</code>. 263 * 264 * @return the <code>ProviderHeader</code>. 265 */ 266 public ProviderHeader getProviderHeader() { 267 return providerHeader; 268 } 269 270 /** 271 * Returns <code>ProcessingContextHeader</code>. 272 * 273 * @return <code>ProcessingContextHeader</code>. 274 */ 275 public ProcessingContextHeader getProcessingContextHeader() { 276 return processingContextHeader; 277 } 278 279 /** 280 * Returns <code>ServiceInstanceUpdateHeader</code>. 281 * 282 * @return <code>ServiceInstanceUpdateHeader</code>. 283 */ 284 public ServiceInstanceUpdateHeader getServiceInstanceUpdateHeader() { 285 return serviceInstanceUpdateHeader; 286 } 287 288 /** 289 * Returns a list of children except Status element, 290 * <code>CorrelationHeader</code>, <code>ProviderHeader</code> 291 * <code>ConsentHeader</code>, <code>UsageDirectiveHeader</code>, 292 * <code>ProcessingContextHeader</code> and 293 * <code>ServiceInstanceUpdateHeader</code>. 294 * Each entry will be a <code>org.w3c.dom.Element</code>. 295 * 296 * @return a list of children element 297 */ 298 public List getOtherChildren() { 299 return otherChildren; 300 } 301 302 /** 303 * Returns value of <code>code</code> attribute of Status element. 304 * 305 * @return value of <code>code</code> attribute of Status element. 306 */ 307 public QName getStatusCode() { 308 return statusCode; 309 } 310 311 /** 312 * Returns value of <code>ref</code> attribute of Status element. 313 * 314 * @return value of <code>ref</code> attribute of Status element. 315 */ 316 public String getStatusRef() { 317 return statusRef; 318 } 319 320 /** 321 * Returns value of <code>comment</code> attribute of Status element. 322 * 323 * @return value of <code>comment</code> attribute of Status element. 324 */ 325 public String getStatusComment() { 326 return statusComment; 327 } 328 329 /** 330 * Sets the value of <code>CorrelationHeader</code>. 331 * 332 * @param correlationHeader the <code>CorrelationHeader</code>. 333 */ 334 public void setCorrelationHeader(CorrelationHeader correlationHeader) { 335 if (correlationHeader != null) { 336 this.correlationHeader = correlationHeader; 337 } 338 } 339 340 /** 341 * Sets <code>ConsentHeader</code>. 342 * 343 * @param consentHeader <code>ConsentHeader</code>. 344 */ 345 public void setConsentHeader(ConsentHeader consentHeader) { 346 this.consentHeader = consentHeader; 347 } 348 349 /** 350 * Sets a list of <code>UsageDirectiveHeader</code>. 351 * 352 * @param usageDirectiveHeaders a list of <code>UsageDirectiveHeader</code>. 353 */ 354 public void setUsageDirectiveHeaders(List usageDirectiveHeaders) { 355 this.usageDirectiveHeaders = usageDirectiveHeaders; 356 } 357 358 /** 359 * Sets <code>ProviderHeader</code> if it is not null. 360 * 361 * @param providerHeader <code>ProviderHeader</code> 362 */ 363 public void setProviderHeader(ProviderHeader providerHeader) { 364 if (providerHeader != null) { 365 this.providerHeader = providerHeader; 366 } 367 } 368 369 /** 370 * Sets <code>ProcessingContextHeader</code>. 371 * 372 * @param processingContextHeader <code>ProcessingContextHeader</code> 373 */ 374 public void setProcessingContextHeader( 375 ProcessingContextHeader processingContextHeader) { 376 this.processingContextHeader = processingContextHeader; 377 } 378 379 /** 380 * Sets <code>ServiceInstanceUpdateHeader</code>. 381 * 382 * @param serviceInstanceUpdateHeader 383 * <code>ServiceInstanceUpdateHeader</code> 384 */ 385 public void setServiceInstanceUpdateHeader( 386 ServiceInstanceUpdateHeader serviceInstanceUpdateHeader) { 387 this.serviceInstanceUpdateHeader = serviceInstanceUpdateHeader; 388 } 389 390 /** 391 * Sets a list of children except Status element, 392 * <code>CorrelationHeader</code>, <code>ProviderHeader</code> 393 * <code>ConsentHeader</code>, <code>UsageDirectiveHeader</code>, 394 * <code>ProcessingContextHeader</code> and 395 * <code>ServiceInstanceUpdateHeader</code>. 396 * Each entry will be a <code>org.w3c.dom.Element</code>. 397 * 398 * @param otherChildren a list of children element 399 */ 400 public void setOtherChildren(List otherChildren) { 401 this.otherChildren = otherChildren; 402 } 403 404 /** 405 * Sets a child except Status element, <code>CorrelationHeader</code>, 406 * <code>ProviderHeader</code>, <code>ConsentHeader</code>, 407 * <code>UsageDirectiveHeader</code> and 408 * <code>ProcessingContextHeader</code> and 409 * <code>ServiceInstanceUpdateHeader</code>. 410 * 411 * @param child the child element. 412 */ 413 public void setOtherChild(Element child) { 414 otherChildren = new ArrayList(1); 415 otherChildren.add(child); 416 } 417 418 /** 419 * Sets value of <code>code</code> attribute of Status element. 420 * 421 * @param statusCode value of <code>code</code> attribute of Status element. 422 */ 423 public void setStatusCode(QName statusCode) { 424 this.statusCode = statusCode; 425 } 426 427 /** 428 * Sets value of <code>ref</code> attribute of Status element. 429 * 430 * @param statusRef value of <code>ref</code> attribute of Status element. 431 */ 432 public void setStatusRef(String statusRef) { 433 this.statusRef = statusRef; 434 } 435 436 /** 437 * Sets value of <code>comment</code> attribute of Status element. 438 * 439 * @param statusComment value of <code>comment</code> attribute in Status 440 * element. 441 */ 442 public void setStatusComment(String statusComment) { 443 this.statusComment = statusComment; 444 } 445 446 /** 447 * Converts this header to <code>org.w3c.dom.Element</code> and add to 448 * parent Fault Element. 449 * 450 * @param faultE the Fault Element object. 451 */ 452 void addToParent(Element faultE) { 453 Document doc = faultE.getOwnerDocument(); 454 Element detailE = doc.createElement(SOAPBindingConstants.TAG_DETAIL); 455 faultE.appendChild(detailE); 456 457 if (statusCode != null) { 458 Element statusE = doc.createElementNS( 459 SOAPBindingConstants.NS_SOAP_BINDING, 460 SOAPBindingConstants.PTAG_STATUS); 461 String localPart = statusCode.getLocalPart(); 462 String ns = statusCode.getNamespaceURI(); 463 if (ns != null && ns.length() > 0) { 464 String prefix; 465 if (ns.equals(SOAPBindingConstants.NS_SOAP)) { 466 prefix = SOAPBindingConstants.PREFIX_SOAP; 467 } else if (ns.equals(SOAPBindingConstants.NS_SOAP_BINDING)) { 468 prefix = SOAPBindingConstants.PREFIX_SOAP_BINDING; 469 } else if (ns.equals(SOAPBindingConstants.NS_SOAP_BINDING_11)){ 470 prefix = SOAPBindingConstants.PREFIX_SOAP_BINDING_11; 471 } else { 472 prefix = 473 SOAPBindingConstants.DEFAULT_PREFIX_FAULT_CODE_VALUE; 474 statusE.setAttributeNS(SOAPBindingConstants.NS_XML, 475 "xmlns:" + prefix, ns); 476 } 477 statusE.setAttributeNS(null, SOAPBindingConstants.ATTR_CODE, 478 prefix +":" +localPart); 479 } else { 480 statusE.setAttributeNS(null, SOAPBindingConstants.ATTR_CODE, 481 localPart); 482 } 483 484 if (statusRef != null) { 485 statusE.setAttributeNS(null, SOAPBindingConstants.ATTR_REF, 486 statusRef); 487 } 488 if (statusComment != null) { 489 statusE.setAttributeNS(null, SOAPBindingConstants.ATTR_COMMENT, 490 statusComment); 491 } 492 detailE.appendChild(statusE); 493 } 494 if (correlationHeader != null) { 495 correlationHeader.addToParent(detailE); 496 } 497 if (consentHeader != null) { 498 consentHeader.addToParent(detailE); 499 } 500 if (usageDirectiveHeaders != null && 501 !usageDirectiveHeaders.isEmpty()) { 502 Iterator iter = usageDirectiveHeaders.iterator(); 503 while(iter.hasNext()) { 504 ((UsageDirectiveHeader)iter.next()).addToParent(detailE); 505 } 506 } 507 if (providerHeader != null) { 508 providerHeader.addToParent(detailE); 509 } 510 if (processingContextHeader != null) { 511 processingContextHeader.addToParent(detailE); 512 } 513 if (serviceInstanceUpdateHeader != null) { 514 serviceInstanceUpdateHeader.addToParent(detailE); 515 } 516 517 if (otherChildren != null && !otherChildren.isEmpty()) { 518 Iterator iter = otherChildren.iterator(); 519 while(iter.hasNext()) { 520 Element childE = (Element)iter.next(); 521 detailE.appendChild(doc.importNode(childE, true)); 522 } 523 } 524 } 525}