1 /* 2 * Copyright (c) 1997, 2013, 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 /** 27 * 28 * @author SAAJ RI Development Team 29 */ 30 package com.sun.xml.internal.messaging.saaj.soap.ver1_2; 31 32 import java.util.*; 33 import java.util.logging.Logger; 34 import java.util.logging.Level; 35 36 import javax.xml.namespace.QName; 37 import javax.xml.soap.*; 38 39 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; 40 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocument; 41 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl; 42 import com.sun.xml.internal.messaging.saaj.soap.impl.*; 43 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl; 44 import com.sun.xml.internal.messaging.saaj.util.LogDomainConstants; 45 46 47 public class Fault1_2Impl extends FaultImpl { 48 49 protected static final Logger log = 50 Logger.getLogger( 51 LogDomainConstants.SOAP_VER1_2_DOMAIN, 52 "com.sun.xml.internal.messaging.saaj.soap.ver1_2.LocalStrings"); 53 54 private static final QName textName = 55 new QName(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE, "Text"); 56 private final QName valueName = 57 new QName(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE, "Value", getPrefix()); 58 private final QName subcodeName = 59 new QName(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE, "Subcode", getPrefix()); 60 61 private SOAPElement innermostSubCodeElement = null; 62 63 public Fault1_2Impl(SOAPDocumentImpl ownerDoc, String name, String prefix) { 64 super(ownerDoc, NameImpl.createFault1_2Name(name, prefix)); 65 } 66 67 public Fault1_2Impl(SOAPDocumentImpl ownerDocument, String prefix) { 68 super(ownerDocument, NameImpl.createFault1_2Name(null, prefix)); 69 } 70 71 protected NameImpl getDetailName() { 72 return NameImpl.createSOAP12Name("Detail", getPrefix()); 73 } 74 75 protected NameImpl getFaultCodeName() { 76 return NameImpl.createSOAP12Name("Code", getPrefix()); 77 } 78 79 protected NameImpl getFaultStringName() { 80 return getFaultReasonName(); 81 } 82 83 protected NameImpl getFaultActorName() { 84 return getFaultRoleName(); 85 } 86 87 private NameImpl getFaultRoleName() { 88 return NameImpl.createSOAP12Name("Role", getPrefix()); 89 } 90 91 private NameImpl getFaultReasonName() { 92 return NameImpl.createSOAP12Name("Reason", getPrefix()); 93 } 94 95 private NameImpl getFaultReasonTextName() { 96 return NameImpl.createSOAP12Name("Text", getPrefix()); 97 } 98 99 private NameImpl getFaultNodeName() { 100 return NameImpl.createSOAP12Name("Node", getPrefix()); 101 } 102 103 private static NameImpl getXmlLangName() { 104 return NameImpl.createXmlName("lang"); 105 } 106 107 protected DetailImpl createDetail() { 108 return new Detail1_2Impl( 109 ((SOAPDocument) getOwnerDocument()).getDocument()); 110 } 111 112 protected FaultElementImpl createSOAPFaultElement(String localName) { 113 return new FaultElement1_2Impl( 114 ((SOAPDocument) getOwnerDocument()).getDocument(), 115 localName); 116 } 117 118 protected void checkIfStandardFaultCode(String faultCode, String uri) 119 throws SOAPException { 120 QName qname = new QName(uri, faultCode); 121 if (SOAPConstants.SOAP_DATAENCODINGUNKNOWN_FAULT.equals(qname) || 122 SOAPConstants.SOAP_MUSTUNDERSTAND_FAULT.equals(qname) || 123 SOAPConstants.SOAP_RECEIVER_FAULT.equals(qname) || 124 SOAPConstants.SOAP_SENDER_FAULT.equals(qname) || 125 SOAPConstants.SOAP_VERSIONMISMATCH_FAULT.equals(qname)) 126 return; 127 log.log( 128 Level.SEVERE, 129 "SAAJ0435.ver1_2.code.not.standard", 130 qname); 131 throw new SOAPExceptionImpl(qname + " is not a standard Code value"); 132 } 133 134 protected void finallySetFaultCode(String faultcode) throws SOAPException { 135 SOAPElement value = this.faultCodeElement.addChildElement(valueName); 136 value.addTextNode(faultcode); 137 } 138 139 private void findReasonElement() { 140 findFaultStringElement(); 141 } 142 143 public Iterator getFaultReasonTexts() throws SOAPException { 144 // Fault Reason has similar semantics as faultstring 145 if (this.faultStringElement == null) 146 findReasonElement(); 147 Iterator eachTextElement = 148 this.faultStringElement.getChildElements(textName); 149 List texts = new ArrayList(); 150 while (eachTextElement.hasNext()) { 151 SOAPElement textElement = (SOAPElement) eachTextElement.next(); 152 Locale thisLocale = getLocale(textElement); 153 if (thisLocale == null) { 154 log.severe("SAAJ0431.ver1_2.xml.lang.missing"); 155 throw new SOAPExceptionImpl("\"xml:lang\" attribute is not present on the Text element"); 156 } 157 texts.add(textElement.getValue()); 158 } 159 if (texts.isEmpty()) { 160 log.severe("SAAJ0434.ver1_2.text.element.not.present"); 161 throw new SOAPExceptionImpl("env:Text must be present inside env:Reason"); 162 } 163 return texts.iterator(); 164 } 165 166 public void addFaultReasonText(String text, java.util.Locale locale) 167 throws SOAPException { 168 169 if (locale == null) { 170 log.severe("SAAJ0430.ver1_2.locale.required"); 171 throw new SOAPException("locale is required and must not be null"); 172 } 173 174 // Fault Reason has similar semantics as faultstring 175 if (this.faultStringElement == null) 176 findReasonElement(); 177 SOAPElement reasonText; 178 179 if (this.faultStringElement == null) { 180 this.faultStringElement = addSOAPFaultElement("Reason"); 181 reasonText = 182 this.faultStringElement.addChildElement( 183 getFaultReasonTextName()); 184 } else { 185 removeDefaultFaultString(); 186 reasonText = getFaultReasonTextElement(locale); 187 if (reasonText != null) { 188 reasonText.removeContents(); 189 } else { 190 reasonText = 191 this.faultStringElement.addChildElement( 192 getFaultReasonTextName()); 193 } 194 } 195 196 String xmlLang = localeToXmlLang(locale); 197 reasonText.addAttribute(getXmlLangName(), xmlLang); 198 reasonText.addTextNode(text); 199 } 200 201 private void removeDefaultFaultString() throws SOAPException { 202 SOAPElement reasonText = getFaultReasonTextElement(Locale.getDefault()); 203 if (reasonText != null) { 204 String defaultFaultString = 205 "Fault string, and possibly fault code, not set"; 206 if (defaultFaultString.equals(reasonText.getValue())) { 207 reasonText.detachNode(); 208 } 209 } 210 } 211 212 public String getFaultReasonText(Locale locale) throws SOAPException { 213 214 if (locale == null) 215 return null; 216 217 // Fault Reason has similar semantics as faultstring 218 if (this.faultStringElement == null) 219 findReasonElement(); 220 221 if (this.faultStringElement != null) { 222 SOAPElement textElement = getFaultReasonTextElement(locale); 223 if (textElement != null) { 224 textElement.normalize(); 225 return textElement.getFirstChild().getNodeValue(); 226 } 227 } 228 229 return null; 230 } 231 232 public Iterator getFaultReasonLocales() throws SOAPException { 233 // Fault Reason has similar semantics as faultstring 234 if (this.faultStringElement == null) 235 findReasonElement(); 236 Iterator eachTextElement = 237 this.faultStringElement.getChildElements(textName); 238 List localeSet = new ArrayList(); 239 while (eachTextElement.hasNext()) { 240 SOAPElement textElement = (SOAPElement) eachTextElement.next(); 241 Locale thisLocale = getLocale(textElement); 242 if (thisLocale == null) { 243 log.severe("SAAJ0431.ver1_2.xml.lang.missing"); 244 throw new SOAPExceptionImpl("\"xml:lang\" attribute is not present on the Text element"); 245 } 246 localeSet.add(thisLocale); 247 } 248 if (localeSet.isEmpty()) { 249 log.severe("SAAJ0434.ver1_2.text.element.not.present"); 250 throw new SOAPExceptionImpl("env:Text elements with mandatory xml:lang attributes must be present inside env:Reason"); 251 } 252 return localeSet.iterator(); 253 } 254 255 public Locale getFaultStringLocale() { 256 Locale locale = null; 257 try { 258 locale = (Locale) getFaultReasonLocales().next(); 259 } catch (SOAPException e) {} 260 return locale; 261 } 262 263 /* 264 * This method assumes that locale and faultStringElement are non-null 265 */ 266 private SOAPElement getFaultReasonTextElement(Locale locale) 267 throws SOAPException { 268 269 // Fault Reason has similar semantics as faultstring 270 Iterator eachTextElement = 271 this.faultStringElement.getChildElements(textName); 272 while (eachTextElement.hasNext()) { 273 SOAPElement textElement = (SOAPElement) eachTextElement.next(); 274 Locale thisLocale = getLocale(textElement); 275 if (thisLocale == null) { 276 log.severe("SAAJ0431.ver1_2.xml.lang.missing"); 277 throw new SOAPExceptionImpl("\"xml:lang\" attribute is not present on the Text element"); 278 } 279 if (thisLocale.equals(locale)) { 280 return textElement; 281 } 282 } 283 return null; 284 } 285 286 public String getFaultNode() { 287 SOAPElement faultNode = findChild(getFaultNodeName()); 288 if (faultNode == null) { 289 return null; 290 } 291 return faultNode.getValue(); 292 } 293 294 public void setFaultNode(String uri) throws SOAPException { 295 SOAPElement faultNode = findChild(getFaultNodeName()); 296 if (faultNode != null) { 297 faultNode.detachNode(); 298 } 299 faultNode = createSOAPFaultElement(getFaultNodeName()); 300 faultNode = faultNode.addTextNode(uri); 301 if (getFaultRole() != null) { 302 insertBefore(faultNode, this.faultActorElement); 303 return; 304 } 305 if (hasDetail()) { 306 insertBefore(faultNode, this.detail); 307 return; 308 } 309 addNode(faultNode); 310 } 311 312 public String getFaultRole() { 313 return getFaultActor(); 314 } 315 316 public void setFaultRole(String uri) throws SOAPException { 317 if (this.faultActorElement == null) 318 findFaultActorElement(); 319 if (this.faultActorElement != null) 320 this.faultActorElement.detachNode(); 321 this.faultActorElement = 322 createSOAPFaultElement(getFaultActorName()); 323 this.faultActorElement.addTextNode(uri); 324 if (hasDetail()) { 325 insertBefore(this.faultActorElement, this.detail); 326 return; 327 } 328 addNode(this.faultActorElement); 329 } 330 331 public String getFaultCode() { 332 if (this.faultCodeElement == null) 333 findFaultCodeElement(); 334 Iterator codeValues = 335 this.faultCodeElement.getChildElements(valueName); 336 return ((SOAPElement) codeValues.next()).getValue(); 337 } 338 339 public QName getFaultCodeAsQName() { 340 String faultcode = getFaultCode(); 341 if (faultcode == null) { 342 return null; 343 } 344 if (this.faultCodeElement == null) 345 findFaultCodeElement(); 346 Iterator valueElements = 347 this.faultCodeElement.getChildElements(valueName); 348 return convertCodeToQName( 349 faultcode, 350 (SOAPElement) valueElements.next()); 351 } 352 353 public Name getFaultCodeAsName() { 354 String faultcode = getFaultCode(); 355 if (faultcode == null) { 356 return null; 357 } 358 if (this.faultCodeElement == null) 359 findFaultCodeElement(); 360 Iterator valueElements = 361 this.faultCodeElement.getChildElements(valueName); 362 return NameImpl.convertToName( 363 convertCodeToQName( 364 faultcode, 365 (SOAPElement) valueElements.next())); 366 } 367 368 public String getFaultString() { 369 String reason = null; 370 try { 371 //reason = getFaultReasonText(Locale.getDefault()); 372 //if (reason == null) 373 reason = (String) getFaultReasonTexts().next(); 374 } catch (SOAPException e) {} 375 return reason; 376 } 377 378 public void setFaultString(String faultString) throws SOAPException { 379 addFaultReasonText(faultString, Locale.getDefault()); 380 } 381 382 public void setFaultString( 383 String faultString, 384 Locale locale) 385 throws SOAPException { 386 addFaultReasonText(faultString, locale); 387 } 388 389 public void appendFaultSubcode(QName subcode) throws SOAPException { 390 if (subcode == null) { 391 return; 392 } 393 if (subcode.getNamespaceURI() == null || 394 "".equals(subcode.getNamespaceURI())) { 395 396 log.severe("SAAJ0432.ver1_2.subcode.not.ns.qualified"); 397 throw new SOAPExceptionImpl("A Subcode must be namespace-qualified"); 398 } 399 if (innermostSubCodeElement == null) { 400 if (faultCodeElement == null) 401 findFaultCodeElement(); 402 innermostSubCodeElement = faultCodeElement; 403 } 404 String prefix = null; 405 if (subcode.getPrefix() == null || "".equals(subcode.getPrefix())) { 406 prefix = 407 ((ElementImpl) innermostSubCodeElement).getNamespacePrefix( 408 subcode.getNamespaceURI()); 409 } else 410 prefix = subcode.getPrefix(); 411 if (prefix == null || "".equals(prefix)) { 412 prefix = "ns1"; 413 } 414 innermostSubCodeElement = 415 innermostSubCodeElement.addChildElement(subcodeName); 416 SOAPElement subcodeValueElement = 417 innermostSubCodeElement.addChildElement(valueName); 418 ((ElementImpl) subcodeValueElement).ensureNamespaceIsDeclared( 419 prefix, 420 subcode.getNamespaceURI()); 421 subcodeValueElement.addTextNode(prefix + ":" + subcode.getLocalPart()); 422 } 423 424 public void removeAllFaultSubcodes() { 425 if (this.faultCodeElement == null) 426 findFaultCodeElement(); 427 Iterator subcodeElements = 428 this.faultCodeElement.getChildElements(subcodeName); 429 if (subcodeElements.hasNext()) { 430 SOAPElement subcode = (SOAPElement) subcodeElements.next(); 431 subcode.detachNode(); 432 } 433 } 434 435 public Iterator getFaultSubcodes() { 436 if (this.faultCodeElement == null) 437 findFaultCodeElement(); 438 final List subcodeList = new ArrayList(); 439 SOAPElement currentCodeElement = this.faultCodeElement; 440 Iterator subcodeElements = 441 currentCodeElement.getChildElements(subcodeName); 442 while (subcodeElements.hasNext()) { 443 currentCodeElement = (ElementImpl) subcodeElements.next(); 444 Iterator valueElements = 445 currentCodeElement.getChildElements(valueName); 446 SOAPElement valueElement = (SOAPElement) valueElements.next(); 447 String code = valueElement.getValue(); 448 subcodeList.add(convertCodeToQName(code, valueElement)); 449 subcodeElements = currentCodeElement.getChildElements(subcodeName); 450 } 451 //return subcodeList.iterator(); 452 return new Iterator() { 453 Iterator subCodeIter = subcodeList.iterator(); 454 455 public boolean hasNext() { 456 return subCodeIter.hasNext(); 457 } 458 459 public Object next() { 460 return subCodeIter.next(); 461 } 462 463 public void remove() { 464 throw new UnsupportedOperationException( 465 "Method remove() not supported on SubCodes Iterator"); 466 } 467 }; 468 } 469 470 private static Locale getLocale(SOAPElement reasonText) { 471 return xmlLangToLocale(reasonText.getAttributeValue(getXmlLangName())); 472 } 473 474 /* 475 * Override setEncodingStyle of ElementImpl to restrict adding encodingStyle 476 * attribute to SOAP Fault (SOAP 1.2 spec, part 1, section 5.1.1) 477 */ 478 public void setEncodingStyle(String encodingStyle) throws SOAPException { 479 log.severe("SAAJ0407.ver1_2.no.encodingStyle.in.fault"); 480 throw new SOAPExceptionImpl("encodingStyle attribute cannot appear on Fault"); 481 } 482 483 public SOAPElement addAttribute(Name name, String value) 484 throws SOAPException { 485 if (name.getLocalName().equals("encodingStyle") 486 && name.getURI().equals(NameImpl.SOAP12_NAMESPACE)) { 487 setEncodingStyle(value); 488 } 489 return super.addAttribute(name, value); 490 } 491 492 public SOAPElement addAttribute(QName name, String value) 493 throws SOAPException { 494 if (name.getLocalPart().equals("encodingStyle") 495 && name.getNamespaceURI().equals(NameImpl.SOAP12_NAMESPACE)) { 496 setEncodingStyle(value); 497 } 498 return super.addAttribute(name, value); 499 } 500 501 public SOAPElement addTextNode(String text) throws SOAPException { 502 log.log( 503 Level.SEVERE, 504 "SAAJ0416.ver1_2.adding.text.not.legal", 505 getElementQName()); 506 throw new SOAPExceptionImpl("Adding text to SOAP 1.2 Fault is not legal"); 507 } 508 509 public SOAPElement addChildElement(SOAPElement element) 510 throws SOAPException { 511 String localName = element.getLocalName(); 512 if ("Detail".equalsIgnoreCase(localName)) { 513 if (hasDetail()) { 514 log.severe("SAAJ0436.ver1_2.detail.exists.error"); 515 throw new SOAPExceptionImpl("Cannot add Detail, Detail already exists"); 516 } 517 String uri = element.getElementQName().getNamespaceURI(); 518 if (!uri.equals(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE)) { 519 log.severe("SAAJ0437.ver1_2.version.mismatch.error"); 520 throw new SOAPExceptionImpl("Cannot add Detail, Incorrect SOAP version specified for Detail element"); 521 } 522 } 523 if (element instanceof Detail1_2Impl) { 524 ElementImpl importedElement = (ElementImpl) importElement(element); 525 addNode(importedElement); 526 return convertToSoapElement(importedElement); 527 } else 528 return super.addChildElement(element); 529 } 530 531 protected boolean isStandardFaultElement(String localName) { 532 if (localName.equalsIgnoreCase("code") || 533 localName.equalsIgnoreCase("reason") || 534 localName.equalsIgnoreCase("node") || 535 localName.equalsIgnoreCase("role") || 536 localName.equalsIgnoreCase("detail")) { 537 return true; 538 } 539 return false; 540 } 541 542 protected QName getDefaultFaultCode() { 543 return SOAPConstants.SOAP_SENDER_FAULT; 544 } 545 546 protected FaultElementImpl createSOAPFaultElement(QName qname) { 547 return new FaultElement1_2Impl( 548 ((SOAPDocument) getOwnerDocument()).getDocument(), 549 qname); 550 } 551 552 protected FaultElementImpl createSOAPFaultElement(Name qname) { 553 return new FaultElement1_2Impl( 554 ((SOAPDocument) getOwnerDocument()).getDocument(), 555 (NameImpl)qname); 556 } 557 558 public void setFaultActor(String faultActor) throws SOAPException { 559 this.setFaultRole(faultActor); 560 } 561 562 }