1 /* 2 * Copyright (c) 1997, 2010, 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.Iterator; 29 import java.util.Locale; 30 import java.util.logging.Level; 31 32 import javax.xml.namespace.QName; 33 import javax.xml.soap.*; 34 import javax.xml.parsers.DocumentBuilder; 35 import javax.xml.parsers.DocumentBuilderFactory; 36 37 import org.w3c.dom.*; 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.name.NameImpl; 43 44 /** 45 * The implementation of SOAP-ENV:BODY or the SOAPBody abstraction. 46 * 47 * @author Anil Vijendran (anil@sun.com) 48 */ 49 public abstract class BodyImpl extends ElementImpl implements SOAPBody { 50 private SOAPFault fault; 51 52 protected BodyImpl(SOAPDocumentImpl ownerDoc, NameImpl bodyName) { 53 super(ownerDoc, bodyName); 54 } 55 56 protected abstract NameImpl getFaultName(String name); 57 protected abstract boolean isFault(SOAPElement child); 58 protected abstract SOAPBodyElement createBodyElement(Name name); 59 protected abstract SOAPBodyElement createBodyElement(QName name); 60 protected abstract SOAPFault createFaultElement(); 61 protected abstract QName getDefaultFaultCode(); 62 63 public SOAPFault addFault() throws SOAPException { 64 if (hasFault()) { 65 log.severe("SAAJ0110.impl.fault.already.exists"); 66 throw new SOAPExceptionImpl("Error: Fault already exists"); 67 } 68 69 fault = createFaultElement(); 70 71 addNode(fault); 72 73 fault.setFaultCode(getDefaultFaultCode()); 74 fault.setFaultString("Fault string, and possibly fault code, not set"); 75 76 return fault; 77 } 78 79 public SOAPFault addFault( 80 Name faultCode, 81 String faultString, 82 Locale locale) 83 throws SOAPException { 84 85 SOAPFault fault = addFault(); 86 fault.setFaultCode(faultCode); 87 fault.setFaultString(faultString, locale); 88 return fault; 89 } 90 91 public SOAPFault addFault( 92 QName faultCode, 93 String faultString, 94 Locale locale) 95 throws SOAPException { 96 97 SOAPFault fault = addFault(); 98 fault.setFaultCode(faultCode); 99 fault.setFaultString(faultString, locale); 100 return fault; 101 } 102 103 public SOAPFault addFault(Name faultCode, String faultString) 104 throws SOAPException { 105 106 SOAPFault fault = addFault(); 107 fault.setFaultCode(faultCode); 108 fault.setFaultString(faultString); 109 return fault; 110 } 111 112 public SOAPFault addFault(QName faultCode, String faultString) 113 throws SOAPException { 114 115 SOAPFault fault = addFault(); 116 fault.setFaultCode(faultCode); 117 fault.setFaultString(faultString); 118 return fault; 119 } 120 121 void initializeFault() { 122 FaultImpl flt = (FaultImpl) findFault(); 123 fault = flt; 124 } 125 126 protected SOAPElement findFault() { 127 Iterator eachChild = getChildElementNodes(); 128 while (eachChild.hasNext()) { 129 SOAPElement child = (SOAPElement) eachChild.next(); 130 if (isFault(child)) { 131 return child; 132 } 133 } 134 135 return null; 136 } 137 138 public boolean hasFault() { 139 initializeFault(); 140 return fault != null; 141 } 142 143 public SOAPFault getFault() { 144 if (hasFault()) 145 return fault; 146 return null; 147 } 148 149 public SOAPBodyElement addBodyElement(Name name) throws SOAPException { 150 SOAPBodyElement newBodyElement = 151 (SOAPBodyElement) ElementFactory.createNamedElement( 152 ((SOAPDocument) getOwnerDocument()).getDocument(), 153 name.getLocalName(), 154 name.getPrefix(), 155 name.getURI()); 156 if (newBodyElement == null) { 157 newBodyElement = createBodyElement(name); 158 } 159 addNode(newBodyElement); 160 return newBodyElement; 161 } 162 163 public SOAPBodyElement addBodyElement(QName qname) throws SOAPException { 164 SOAPBodyElement newBodyElement = 165 (SOAPBodyElement) ElementFactory.createNamedElement( 166 ((SOAPDocument) getOwnerDocument()).getDocument(), 167 qname.getLocalPart(), 168 qname.getPrefix(), 169 qname.getNamespaceURI()); 170 if (newBodyElement == null) { 171 newBodyElement = createBodyElement(qname); 172 } 173 addNode(newBodyElement); 174 return newBodyElement; 175 } 176 177 public void setParentElement(SOAPElement element) throws SOAPException { 178 179 if (!(element instanceof SOAPEnvelope)) { 180 log.severe("SAAJ0111.impl.body.parent.must.be.envelope"); 181 throw new SOAPException("Parent of SOAPBody has to be a SOAPEnvelope"); 182 } 183 super.setParentElement(element); 184 } 185 186 protected SOAPElement addElement(Name name) throws SOAPException { 187 return addBodyElement(name); 188 } 189 190 protected SOAPElement addElement(QName name) throws SOAPException { 191 return addBodyElement(name); 192 } 193 194 // public Node insertBefore(Node newElement, Node ref) throws DOMException { 195 // if (!(newElement instanceof SOAPBodyElement) && (newElement instanceof SOAPElement)) { 196 // newElement = new ElementWrapper((ElementImpl) newElement); 197 // } 198 // return super.insertBefore(newElement, ref); 199 // } 200 // 201 // public Node replaceChild(Node newElement, Node ref) throws DOMException { 202 // if (!(newElement instanceof SOAPBodyElement) && (newElement instanceof SOAPElement)) { 203 // newElement = new ElementWrapper((ElementImpl) newElement); 204 // } 205 // return super.replaceChild(newElement, ref); 206 // } 207 208 public SOAPBodyElement addDocument(Document document) 209 throws SOAPException { 210 /* 211 212 Element rootNode = 213 document.getDocumentElement(); 214 // Causes all deferred nodes to be inflated 215 rootNode.normalize(); 216 adoptElement(rootNode); 217 SOAPBodyElement bodyElement = (SOAPBodyElement) convertToSoapElement(rootNode); 218 addNode(bodyElement); 219 return bodyElement; 220 */ 221 ///* 222 SOAPBodyElement newBodyElement = null; 223 DocumentFragment docFrag = document.createDocumentFragment(); 224 Element rootElement = document.getDocumentElement(); 225 if(rootElement != null) { 226 docFrag.appendChild(rootElement); 227 228 Document ownerDoc = getOwnerDocument(); 229 // This copies the whole tree which could be very big so it's slow. 230 // However, it does have the advantage of actually working. 231 org.w3c.dom.Node replacingNode = ownerDoc.importNode(docFrag, true); 232 // Adding replacingNode at the last of the children list of body 233 addNode(replacingNode); 234 Iterator i = 235 getChildElements(NameImpl.copyElementName(rootElement)); 236 // Return the child element with the required name which is at the 237 // end of the list 238 while(i.hasNext()) 239 newBodyElement = (SOAPBodyElement) i.next(); 240 } 241 return newBodyElement; 242 //*/ 243 } 244 245 protected SOAPElement convertToSoapElement(Element element) { 246 if ((element instanceof SOAPBodyElement) && 247 //this check is required because ElementImpl currently 248 // implements SOAPBodyElement 249 !(element.getClass().equals(ElementImpl.class))) { 250 return (SOAPElement) element; 251 } else { 252 return replaceElementWithSOAPElement( 253 element, 254 (ElementImpl) createBodyElement(NameImpl 255 .copyElementName(element))); 256 } 257 } 258 259 public SOAPElement setElementQName(QName newName) throws SOAPException { 260 log.log(Level.SEVERE, 261 "SAAJ0146.impl.invalid.name.change.requested", 262 new Object[] {elementQName.getLocalPart(), 263 newName.getLocalPart()}); 264 throw new SOAPException("Cannot change name for " 265 + elementQName.getLocalPart() + " to " 266 + newName.getLocalPart()); 267 } 268 269 public Document extractContentAsDocument() throws SOAPException { 270 271 Iterator eachChild = getChildElements(); 272 javax.xml.soap.Node firstBodyElement = null; 273 274 while (eachChild.hasNext() && 275 !(firstBodyElement instanceof SOAPElement)) 276 firstBodyElement = (javax.xml.soap.Node) eachChild.next(); 277 278 boolean exactlyOneChildElement = true; 279 if (firstBodyElement == null) 280 exactlyOneChildElement = false; 281 else { 282 for (org.w3c.dom.Node node = firstBodyElement.getNextSibling(); 283 node != null; 284 node = node.getNextSibling()) { 285 286 if (node instanceof Element) { 287 exactlyOneChildElement = false; 288 break; 289 } 290 } 291 } 292 293 if(!exactlyOneChildElement) { 294 log.log(Level.SEVERE, 295 "SAAJ0250.impl.body.should.have.exactly.one.child"); 296 throw new SOAPException("Cannot extract Document from body"); 297 } 298 299 Document document = null; 300 try { 301 DocumentBuilderFactory factory = 302 new com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl(); 303 factory.setNamespaceAware(true); 304 DocumentBuilder builder = factory.newDocumentBuilder(); 305 document = builder.newDocument(); 306 307 Element rootElement = (Element) document.importNode( 308 firstBodyElement, 309 true); 310 311 document.appendChild(rootElement); 312 313 } catch(Exception e) { 314 log.log(Level.SEVERE, 315 "SAAJ0251.impl.cannot.extract.document.from.body"); 316 throw new SOAPExceptionImpl( 317 "Unable to extract Document from body", e); 318 } 319 320 firstBodyElement.detachNode(); 321 322 return document; 323 } 324 325 }