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.logging.Level; 29 30 import javax.xml.namespace.QName; 31 32 import org.w3c.dom.Element; 33 34 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; 35 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocument; 36 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl; 37 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl; 38 import java.util.ArrayList; 39 import java.util.Iterator; 40 import java.util.List; 41 import javax.xml.soap.Name; 42 import javax.xml.soap.SOAPElement; 43 import javax.xml.soap.SOAPEnvelope; 44 import javax.xml.soap.SOAPException; 45 import javax.xml.soap.SOAPHeader; 46 import javax.xml.soap.SOAPHeaderElement; 47 48 public abstract class HeaderImpl extends ElementImpl implements SOAPHeader { 49 protected static final boolean MUST_UNDERSTAND_ONLY = false; 50 51 protected HeaderImpl(SOAPDocumentImpl ownerDoc, NameImpl name) { 52 super(ownerDoc, name); 53 } 54 55 public HeaderImpl(SOAPDocumentImpl ownerDoc, Element domElement) { 56 super(ownerDoc, domElement); 57 } 58 59 protected abstract SOAPHeaderElement createHeaderElement(Name name) 60 throws SOAPException; 61 protected abstract SOAPHeaderElement createHeaderElement(QName name) 62 throws SOAPException; 63 protected abstract NameImpl getNotUnderstoodName(); 64 protected abstract NameImpl getUpgradeName(); 65 protected abstract NameImpl getSupportedEnvelopeName(); 66 67 @Override 68 public SOAPHeaderElement addHeaderElement(Name name) throws SOAPException { 69 SOAPElement newHeaderElement = 70 ElementFactory.createNamedElement( 71 ((SOAPDocument) getOwnerDocument()).getDocument(), 72 name.getLocalName(), 73 name.getPrefix(), 74 name.getURI()); 75 if (newHeaderElement == null 76 || !(newHeaderElement instanceof SOAPHeaderElement)) { 77 newHeaderElement = createHeaderElement(name); 78 } 79 80 // header elements must be namespace qualified 81 // check that URI is not empty, ensuring that the element is NS qualified. 82 String uri = newHeaderElement.getElementQName().getNamespaceURI(); 83 if ((uri == null) || ("").equals(uri)) { 84 log.severe("SAAJ0131.impl.header.elems.ns.qualified"); 85 throw new SOAPExceptionImpl("HeaderElements must be namespace qualified"); 86 } 87 addNode(newHeaderElement); 88 return (SOAPHeaderElement) newHeaderElement; 89 } 90 91 @Override 92 public SOAPHeaderElement addHeaderElement(QName name) throws SOAPException { 93 SOAPElement newHeaderElement = 94 ElementFactory.createNamedElement( 95 ((SOAPDocument) getOwnerDocument()).getDocument(), 96 name.getLocalPart(), 97 name.getPrefix(), 98 name.getNamespaceURI()); 99 if (newHeaderElement == null 100 || !(newHeaderElement instanceof SOAPHeaderElement)) { 101 newHeaderElement = createHeaderElement(name); 102 } 103 104 // header elements must be namespace qualified 105 // check that URI is not empty, ensuring that the element is NS qualified. 106 String uri = newHeaderElement.getElementQName().getNamespaceURI(); 107 if ((uri == null) || ("").equals(uri)) { 108 log.severe("SAAJ0131.impl.header.elems.ns.qualified"); 109 throw new SOAPExceptionImpl("HeaderElements must be namespace qualified"); 110 } 111 addNode(newHeaderElement); 112 return (SOAPHeaderElement) newHeaderElement; 113 } 114 115 @Override 116 protected SOAPElement addElement(Name name) throws SOAPException { 117 return addHeaderElement(name); 118 } 119 120 @Override 121 protected SOAPElement addElement(QName name) throws SOAPException { 122 return addHeaderElement(name); 123 } 124 125 @Override 126 public Iterator<SOAPHeaderElement> examineHeaderElements(String actor) { 127 return getHeaderElementsForActor(actor, false, false); 128 } 129 130 @Override 131 public Iterator<SOAPHeaderElement> extractHeaderElements(String actor) { 132 return getHeaderElementsForActor(actor, true, false); 133 } 134 135 protected Iterator<SOAPHeaderElement> getHeaderElementsForActor( 136 String actor, 137 boolean detach, 138 boolean mustUnderstand) { 139 if (actor == null || actor.equals("")) { 140 log.severe("SAAJ0132.impl.invalid.value.for.actor.or.role"); 141 throw new IllegalArgumentException("Invalid value for actor or role"); 142 } 143 return getHeaderElements(actor, detach, mustUnderstand); 144 } 145 146 protected Iterator<SOAPHeaderElement> getHeaderElements( 147 String actor, 148 boolean detach, 149 boolean mustUnderstand) { 150 List<SOAPHeaderElement> elementList = new ArrayList<>(); 151 152 Iterator<javax.xml.soap.Node> eachChild = getChildElements(); 153 154 org.w3c.dom.Node currentChild = iterate(eachChild); 155 while (currentChild != null) { 156 if (!(currentChild instanceof SOAPHeaderElement)) { 157 currentChild = iterate(eachChild); 158 } else { 159 HeaderElementImpl currentElement = 160 (HeaderElementImpl) currentChild; 161 currentChild = iterate(eachChild); 162 163 boolean isMustUnderstandMatching = 164 (!mustUnderstand || currentElement.getMustUnderstand()); 165 boolean doAdd = false; 166 if (actor == null && isMustUnderstandMatching) { 167 doAdd = true; 168 } else { 169 String currentActor = currentElement.getActorOrRole(); 170 if (currentActor == null) { 171 currentActor = ""; 172 } 173 174 if (currentActor.equalsIgnoreCase(actor) 175 && isMustUnderstandMatching) { 176 doAdd = true; 177 } 178 } 179 180 if (doAdd) { 181 elementList.add(currentElement); 182 if (detach) { 183 currentElement.detachNode(); 184 } 185 } 186 } 187 } 188 189 return elementList.listIterator(); 190 } 191 192 private <T> T iterate(Iterator<T> each) { 193 return each.hasNext() ? each.next() : null; 194 } 195 196 @Override 197 public void setParentElement(SOAPElement element) throws SOAPException { 198 if (!(element instanceof SOAPEnvelope)) { 199 log.severe("SAAJ0133.impl.header.parent.mustbe.envelope"); 200 throw new SOAPException("Parent of SOAPHeader has to be a SOAPEnvelope"); 201 } 202 super.setParentElement(element); 203 } 204 205 // overriding ElementImpl's method to ensure that HeaderElements are 206 // namespace qualified. Holds for both SOAP versions. 207 // TODO - This check needs to be made for other addChildElement() methods 208 // as well. 209 @Override 210 public SOAPElement addChildElement(String localName) throws SOAPException { 211 212 SOAPElement element = super.addChildElement(localName); 213 // check that URI is not empty, ensuring that the element is NS qualified. 214 String uri = element.getElementName().getURI(); 215 if ((uri == null) || ("").equals(uri)) { 216 log.severe("SAAJ0134.impl.header.elems.ns.qualified"); 217 throw new SOAPExceptionImpl("HeaderElements must be namespace qualified"); 218 } 219 return element; 220 } 221 222 @Override 223 public Iterator<SOAPHeaderElement> examineAllHeaderElements() { 224 return getHeaderElements(null, false, MUST_UNDERSTAND_ONLY); 225 } 226 227 @Override 228 public Iterator<SOAPHeaderElement> examineMustUnderstandHeaderElements(String actor) { 229 return getHeaderElements(actor, false, true); 230 231 } 232 233 @Override 234 public Iterator<SOAPHeaderElement> extractAllHeaderElements() { 235 return getHeaderElements(null, true, false); 236 } 237 238 @Override 239 public SOAPHeaderElement addUpgradeHeaderElement(Iterator supportedSoapUris) 240 throws SOAPException { 241 if (supportedSoapUris == null) { 242 log.severe("SAAJ0411.ver1_2.no.null.supportedURIs"); 243 throw new SOAPException("Argument cannot be null; iterator of supportedURIs cannot be null"); 244 } 245 if (!supportedSoapUris.hasNext()) { 246 log.severe("SAAJ0412.ver1_2.no.empty.list.of.supportedURIs"); 247 throw new SOAPException("List of supported URIs cannot be empty"); 248 } 249 Name upgradeName = getUpgradeName(); 250 SOAPHeaderElement upgradeHeaderElement = 251 (SOAPHeaderElement) addChildElement(upgradeName); 252 Name supportedEnvelopeName = getSupportedEnvelopeName(); 253 int i = 0; 254 while (supportedSoapUris.hasNext()) { 255 SOAPElement subElement = 256 upgradeHeaderElement.addChildElement(supportedEnvelopeName); 257 String ns = "ns" + Integer.toString(i); 258 subElement.addAttribute( 259 NameImpl.createFromUnqualifiedName("qname"), 260 ns + ":Envelope"); 261 subElement.addNamespaceDeclaration( 262 ns, (String) supportedSoapUris.next()); 263 i ++; 264 } 265 return upgradeHeaderElement; 266 } 267 268 @Override 269 public SOAPHeaderElement addUpgradeHeaderElement(String supportedSoapUri) 270 throws SOAPException { 271 return addUpgradeHeaderElement(new String[] {supportedSoapUri}); 272 } 273 274 @Override 275 public SOAPHeaderElement addUpgradeHeaderElement(String[] supportedSoapUris) 276 throws SOAPException { 277 278 if (supportedSoapUris == null) { 279 log.severe("SAAJ0411.ver1_2.no.null.supportedURIs"); 280 throw new SOAPException("Argument cannot be null; array of supportedURIs cannot be null"); 281 } 282 if (supportedSoapUris.length == 0) { 283 log.severe("SAAJ0412.ver1_2.no.empty.list.of.supportedURIs"); 284 throw new SOAPException("List of supported URIs cannot be empty"); 285 } 286 Name upgradeName = getUpgradeName(); 287 SOAPHeaderElement upgradeHeaderElement = 288 (SOAPHeaderElement) addChildElement(upgradeName); 289 Name supportedEnvelopeName = getSupportedEnvelopeName(); 290 for (int i = 0; i < supportedSoapUris.length; i ++) { 291 SOAPElement subElement = 292 upgradeHeaderElement.addChildElement(supportedEnvelopeName); 293 String ns = "ns" + Integer.toString(i); 294 subElement.addAttribute( 295 NameImpl.createFromUnqualifiedName("qname"), 296 ns + ":Envelope"); 297 subElement.addNamespaceDeclaration(ns, supportedSoapUris[i]); 298 } 299 return upgradeHeaderElement; 300 } 301 302 @Override 303 protected SOAPElement convertToSoapElement(Element element) { 304 final org.w3c.dom.Node soapNode = getSoapDocument().findIfPresent(element); 305 if (soapNode instanceof SOAPHeaderElement) { 306 return (SOAPElement) soapNode; 307 } else { 308 SOAPHeaderElement headerElement; 309 try { 310 headerElement = 311 createHeaderElement(NameImpl.copyElementName(element)); 312 } catch (SOAPException e) { 313 throw new ClassCastException("Could not convert Element to SOAPHeaderElement: " + e.getMessage()); 314 } 315 return replaceElementWithSOAPElement( 316 element, 317 (ElementImpl) headerElement); 318 } 319 } 320 321 @Override 322 public SOAPElement setElementQName(QName newName) throws SOAPException { 323 log.log(Level.SEVERE, 324 "SAAJ0146.impl.invalid.name.change.requested", 325 new Object[] {elementQName.getLocalPart(), 326 newName.getLocalPart()}); 327 throw new SOAPException("Cannot change name for " 328 + elementQName.getLocalPart() + " to " 329 + newName.getLocalPart()); 330 } 331 332 }