1 /* 2 * Copyright (c) 1997, 2017, 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 package com.sun.xml.internal.messaging.saaj.soap.impl; 27 28 import java.util.Locale; 29 import java.util.logging.Level; 30 31 import javax.xml.namespace.QName; 32 import javax.xml.soap.*; 33 34 import com.sun.xml.internal.messaging.saaj.util.SAAJUtil; 35 import org.w3c.dom.Element; 36 37 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; 38 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl; 39 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl; 40 41 public abstract class FaultImpl extends ElementImpl implements SOAPFault { 42 43 /* This can also represent a fault reason element */ 44 protected SOAPFaultElement faultStringElement; 45 46 /* This can also represent a fault role element */ 47 protected SOAPFaultElement faultActorElement; 48 49 protected SOAPFaultElement faultCodeElement; 50 51 protected Detail detail; 52 53 protected FaultImpl(SOAPDocumentImpl ownerDoc, NameImpl name) { 54 super(ownerDoc, name); 55 } 56 57 public FaultImpl(SOAPDocumentImpl ownerDoc, Element domElement) { 58 super(ownerDoc, domElement); 59 } 60 61 protected abstract NameImpl getDetailName(); 62 protected abstract NameImpl getFaultCodeName(); 63 protected abstract NameImpl getFaultStringName(); 64 protected abstract NameImpl getFaultActorName(); 65 protected abstract DetailImpl createDetail(); 66 protected abstract FaultElementImpl createSOAPFaultElement(String localName); 67 protected abstract FaultElementImpl createSOAPFaultElement(QName qname); 68 protected abstract FaultElementImpl createSOAPFaultElement(Name qname); 69 protected abstract void checkIfStandardFaultCode(String faultCode, String uri) throws SOAPException; 70 protected abstract void finallySetFaultCode(String faultcode) throws SOAPException; 71 protected abstract boolean isStandardFaultElement(String localName); 72 protected abstract QName getDefaultFaultCode(); 73 74 75 protected void findFaultCodeElement() { 76 this.faultCodeElement = 77 (SOAPFaultElement) findAndConvertChildElement(getFaultCodeName()); 78 } 79 80 protected void findFaultActorElement() { 81 this.faultActorElement = 82 (SOAPFaultElement) findAndConvertChildElement(getFaultActorName()); 83 } 84 85 protected void findFaultStringElement() { 86 this.faultStringElement = 87 (SOAPFaultElement) findAndConvertChildElement(getFaultStringName()); 88 } 89 90 @Override 91 public void setFaultCode(String faultCode) throws SOAPException { 92 setFaultCode( 93 NameImpl.getLocalNameFromTagName(faultCode), 94 NameImpl.getPrefixFromTagName(faultCode), 95 null); 96 } 97 98 public void setFaultCode(String faultCode, String prefix, String uri) 99 throws SOAPException { 100 101 if (prefix == null || "".equals(prefix)) { 102 if (uri != null && !"".equals(uri)) { 103 prefix = getNamespacePrefix(uri); 104 if (prefix == null || "".equals(prefix)) { 105 prefix = "ns0"; 106 } 107 } 108 } 109 if (this.faultCodeElement == null) 110 findFaultCodeElement(); 111 112 if (this.faultCodeElement == null) 113 this.faultCodeElement = addFaultCodeElement(); 114 else 115 this.faultCodeElement.removeContents(); 116 117 if (uri == null || "".equals(uri)) { 118 uri = this.faultCodeElement.getNamespaceURI(prefix); 119 } 120 if (uri == null || "".equals(uri)) { 121 if (prefix != null && !"".equals(prefix)) { 122 //cannot allow an empty URI for a non-Empty prefix 123 log.log(Level.SEVERE, "SAAJ0140.impl.no.ns.URI", new Object[]{prefix + ":" + faultCode}); 124 throw new SOAPExceptionImpl("Empty/Null NamespaceURI specified for faultCode \"" + prefix + ":" + faultCode + "\""); 125 } else { 126 uri = ""; 127 } 128 } 129 checkIfStandardFaultCode(faultCode, uri); 130 ((FaultElementImpl) this.faultCodeElement).ensureNamespaceIsDeclared(prefix, uri); 131 132 if (prefix == null || "".equals(prefix)) { 133 finallySetFaultCode(faultCode); 134 } else { 135 finallySetFaultCode(prefix + ":" + faultCode); 136 } 137 } 138 139 @Override 140 public void setFaultCode(Name faultCodeQName) throws SOAPException { 141 setFaultCode( 142 faultCodeQName.getLocalName(), 143 faultCodeQName.getPrefix(), 144 faultCodeQName.getURI()); 145 } 146 147 @Override 148 public void setFaultCode(QName faultCodeQName) throws SOAPException { 149 setFaultCode( 150 faultCodeQName.getLocalPart(), 151 faultCodeQName.getPrefix(), 152 faultCodeQName.getNamespaceURI()); 153 } 154 155 protected static QName convertCodeToQName( 156 String code, 157 SOAPElement codeContainingElement) { 158 159 int prefixIndex = code.indexOf(':'); 160 if (prefixIndex == -1) { 161 return new QName(code); 162 } 163 164 String prefix = code.substring(0, prefixIndex); 165 String nsName =((ElementImpl) codeContainingElement).lookupNamespaceURI(prefix); 166 //((ElementImpl) codeContainingElement).getNamespaceURI(prefix); 167 return new QName(nsName, getLocalPart(code), prefix); 168 } 169 170 protected void initializeDetail() { 171 NameImpl detailName = getDetailName(); 172 detail = (Detail) findAndConvertChildElement(detailName); 173 } 174 175 @Override 176 public Detail getDetail() { 177 if (detail == null) 178 initializeDetail(); 179 if ((detail != null) && (detail.getParentNode() == null)) { 180 // a detach node was called on it 181 detail = null; 182 } 183 return detail; 184 } 185 186 @Override 187 public Detail addDetail() throws SOAPException { 188 if (detail == null) 189 initializeDetail(); 190 if (detail == null) { 191 detail = createDetail(); 192 addNode(detail); 193 return detail; 194 } else { 195 // Log 196 throw new SOAPExceptionImpl("Error: Detail already exists"); 197 } 198 } 199 200 @Override 201 public boolean hasDetail() { 202 return (getDetail() != null); 203 } 204 205 @Override 206 public abstract void setFaultActor(String faultActor) throws SOAPException; 207 208 @Override 209 public String getFaultActor() { 210 if (this.faultActorElement == null) 211 findFaultActorElement(); 212 if (this.faultActorElement != null) { 213 return this.faultActorElement.getValue(); 214 } 215 return null; 216 } 217 218 @Override 219 public SOAPElement setElementQName(QName newName) throws SOAPException { 220 221 log.log( 222 Level.SEVERE, 223 "SAAJ0146.impl.invalid.name.change.requested", 224 new Object[] {elementQName.getLocalPart(), newName.getLocalPart()}); 225 throw new SOAPException( 226 "Cannot change name for " + elementQName.getLocalPart() + " to " + newName.getLocalPart()); 227 } 228 229 @Override 230 protected SOAPElement convertToSoapElement(Element element) { 231 final org.w3c.dom.Node soapNode = getSoapDocument().findIfPresent(element); 232 if (soapNode instanceof SOAPFaultElement) { 233 return (SOAPElement) soapNode; 234 } else if (soapNode instanceof SOAPElement) { 235 SOAPElement soapElement = (SOAPElement) soapNode; 236 if (getDetailName().equals(soapElement.getElementName())) { 237 return replaceElementWithSOAPElement(element, createDetail()); 238 } else { 239 String localName = 240 soapElement.getElementName().getLocalName(); 241 if (isStandardFaultElement(localName)) 242 return replaceElementWithSOAPElement( 243 element, 244 createSOAPFaultElement(soapElement.getElementQName())); 245 return soapElement; 246 } 247 } else { 248 Name elementName = NameImpl.copyElementName(element); 249 ElementImpl newElement; 250 if (getDetailName().equals(elementName)) { 251 newElement = createDetail(); 252 } else { 253 String localName = elementName.getLocalName(); 254 if (isStandardFaultElement(localName)) 255 newElement = 256 createSOAPFaultElement(elementName); 257 else 258 newElement = (ElementImpl) createElement(elementName); 259 } 260 return replaceElementWithSOAPElement(element, newElement); 261 } 262 } 263 264 protected SOAPFaultElement addFaultCodeElement() throws SOAPException { 265 if (this.faultCodeElement == null) 266 findFaultCodeElement(); 267 if (this.faultCodeElement == null) { 268 this.faultCodeElement = 269 addSOAPFaultElement(getFaultCodeName().getLocalName()); 270 return this.faultCodeElement; 271 } else { 272 throw new SOAPExceptionImpl("Error: Faultcode already exists"); 273 } 274 } 275 276 private SOAPFaultElement addFaultStringElement() throws SOAPException { 277 if (this.faultStringElement == null) 278 findFaultStringElement(); 279 if (this.faultStringElement == null) { 280 this.faultStringElement = 281 addSOAPFaultElement(getFaultStringName().getLocalName()); 282 return this.faultStringElement; 283 } else { 284 // Log 285 throw new SOAPExceptionImpl("Error: Faultstring already exists"); 286 } 287 } 288 289 private SOAPFaultElement addFaultActorElement() throws SOAPException { 290 if (this.faultActorElement == null) 291 findFaultActorElement(); 292 if (this.faultActorElement == null) { 293 this.faultActorElement = 294 addSOAPFaultElement(getFaultActorName().getLocalName()); 295 return this.faultActorElement; 296 } else { 297 // Log 298 throw new SOAPExceptionImpl("Error: Faultactor already exists"); 299 } 300 } 301 302 @Override 303 protected SOAPElement addElement(Name name) throws SOAPException { 304 if (getDetailName().equals(name)) { 305 return addDetail(); 306 } else if(getFaultCodeName().equals(name)) { 307 return addFaultCodeElement(); 308 } else if(getFaultStringName().equals(name)) { 309 return addFaultStringElement(); 310 } else if(getFaultActorName().equals(name)) { 311 return addFaultActorElement(); 312 } 313 return super.addElement(name); 314 } 315 316 @Override 317 protected SOAPElement addElement(QName name) throws SOAPException { 318 return addElement(NameImpl.convertToName(name)); 319 } 320 321 protected FaultElementImpl addSOAPFaultElement(String localName) 322 throws SOAPException { 323 324 FaultElementImpl faultElem = createSOAPFaultElement(localName); 325 addNode(faultElem); 326 return faultElem; 327 } 328 329 /** 330 * Convert an xml:lang attribute value into a Locale object 331 * @param xmlLang xml:lang attribute value 332 * @return Locale 333 */ 334 protected static Locale xmlLangToLocale(String xmlLang) { 335 if (xmlLang == null) { 336 return null; 337 } 338 339 // Spec uses hyphen as separator 340 int index = xmlLang.indexOf("-"); 341 342 // Accept underscore as separator as well 343 if (index == -1) { 344 index = xmlLang.indexOf("_"); 345 } 346 347 if (index == -1) { 348 // No separator so assume only a language component 349 return new Locale(xmlLang, ""); 350 } 351 352 String language = xmlLang.substring(0, index); 353 String country = xmlLang.substring(index + 1); 354 return new Locale(language, country); 355 } 356 357 protected static String localeToXmlLang(Locale locale) { 358 String xmlLang = locale.getLanguage(); 359 String country = locale.getCountry(); 360 if (!"".equals(country)) { 361 xmlLang += "-" + country; 362 } 363 return xmlLang; 364 } 365 }