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