jaxws/src/java.xml.soap/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/EnvelopeImpl.java
changeset 28644 a70f5680dbab
parent 28643 a665e19ca007
parent 28642 a42fefc69922
child 28647 f44908f03772
equal deleted inserted replaced
28643:a665e19ca007 28644:a70f5680dbab
     1 /*
       
     2  * Copyright (c) 1997, 2014, 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.io.IOException;
       
    29 import java.io.OutputStream;
       
    30 import java.io.OutputStreamWriter;
       
    31 
       
    32 import java.util.logging.Level;
       
    33 
       
    34 import javax.xml.namespace.QName;
       
    35 import javax.xml.soap.*;
       
    36 import javax.xml.stream.XMLStreamException;
       
    37 import javax.xml.stream.XMLStreamReader;
       
    38 import javax.xml.stream.XMLStreamWriter;
       
    39 import javax.xml.transform.*;
       
    40 import javax.xml.transform.dom.DOMSource;
       
    41 import javax.xml.transform.stream.StreamResult;
       
    42 
       
    43 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
       
    44 import com.sun.xml.internal.messaging.saaj.soap.LazyEnvelope;
       
    45 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl;
       
    46 import com.sun.xml.internal.messaging.saaj.soap.StaxBridge;
       
    47 import com.sun.xml.internal.messaging.saaj.soap.StaxLazySourceBridge;
       
    48 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
       
    49 import com.sun.xml.internal.messaging.saaj.util.FastInfosetReflection;
       
    50 import com.sun.xml.internal.messaging.saaj.util.stax.LazyEnvelopeStaxReader;
       
    51 import com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer;
       
    52 
       
    53 import com.sun.xml.internal.org.jvnet.staxex.util.DOMStreamReader;
       
    54 import com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter;
       
    55 
       
    56 /**
       
    57  * Our implementation of the SOAP envelope.
       
    58  *
       
    59  * @author Anil Vijendran (anil@sun.com)
       
    60  */
       
    61 public abstract class EnvelopeImpl extends ElementImpl implements LazyEnvelope {
       
    62     protected HeaderImpl header;
       
    63     protected BodyImpl body;
       
    64     String omitXmlDecl = "yes";
       
    65     String charset = "utf-8";
       
    66     String xmlDecl = null;
       
    67 
       
    68     protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, Name name) {
       
    69         super(ownerDoc, name);
       
    70     }
       
    71 
       
    72     protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, QName name) {
       
    73         super(ownerDoc, name);
       
    74     }
       
    75 
       
    76     protected EnvelopeImpl(
       
    77         SOAPDocumentImpl ownerDoc,
       
    78         NameImpl name,
       
    79         boolean createHeader,
       
    80         boolean createBody)
       
    81         throws SOAPException {
       
    82         this(ownerDoc, name);
       
    83 
       
    84         ensureNamespaceIsDeclared(
       
    85             getElementQName().getPrefix(), getElementQName().getNamespaceURI());
       
    86 
       
    87         // XXX
       
    88         if (createHeader)
       
    89             addHeader();
       
    90 
       
    91         if (createBody)
       
    92             addBody();
       
    93     }
       
    94 
       
    95     protected abstract NameImpl getHeaderName(String prefix);
       
    96     protected abstract NameImpl getBodyName(String prefix);
       
    97 
       
    98     public SOAPHeader addHeader() throws SOAPException {
       
    99         return addHeader(null);
       
   100     }
       
   101 
       
   102     public SOAPHeader addHeader(String prefix) throws SOAPException {
       
   103 
       
   104         if (prefix == null || prefix.equals("")) {
       
   105             prefix = getPrefix();
       
   106         }
       
   107 
       
   108         NameImpl headerName = getHeaderName(prefix);
       
   109         NameImpl bodyName = getBodyName(prefix);
       
   110 
       
   111         HeaderImpl header = null;
       
   112         SOAPElement firstChild = (SOAPElement) getFirstChildElement();
       
   113 
       
   114         if (firstChild != null) {
       
   115             if (firstChild.getElementName().equals(headerName)) {
       
   116                 log.severe("SAAJ0120.impl.header.already.exists");
       
   117                 throw new SOAPExceptionImpl("Can't add a header when one is already present.");
       
   118             } else if (!firstChild.getElementName().equals(bodyName)) {
       
   119                 log.severe("SAAJ0121.impl.invalid.first.child.of.envelope");
       
   120                 throw new SOAPExceptionImpl("First child of Envelope must be either a Header or Body");
       
   121             }
       
   122         }
       
   123 
       
   124         header = (HeaderImpl) createElement(headerName);
       
   125         insertBefore(header, firstChild);
       
   126         header.ensureNamespaceIsDeclared(headerName.getPrefix(), headerName.getURI());
       
   127 
       
   128         return header;
       
   129     }
       
   130 
       
   131     protected void lookForHeader() throws SOAPException {
       
   132         NameImpl headerName = getHeaderName(null);
       
   133 
       
   134         HeaderImpl hdr = (HeaderImpl) findChild(headerName);
       
   135         header = hdr;
       
   136     }
       
   137 
       
   138     public SOAPHeader getHeader() throws SOAPException {
       
   139         lookForHeader();
       
   140         return header;
       
   141     }
       
   142 
       
   143     protected void lookForBody() throws SOAPException {
       
   144         NameImpl bodyName = getBodyName(null);
       
   145 
       
   146         BodyImpl bodyChildElement = (BodyImpl) findChild(bodyName);
       
   147         body = bodyChildElement;
       
   148     }
       
   149 
       
   150     public SOAPBody addBody() throws SOAPException {
       
   151         return addBody(null);
       
   152     }
       
   153 
       
   154     public SOAPBody addBody(String prefix) throws SOAPException {
       
   155         lookForBody();
       
   156 
       
   157         if (prefix == null || prefix.equals("")) {
       
   158             prefix = getPrefix();
       
   159         }
       
   160 
       
   161         if (body == null) {
       
   162             NameImpl bodyName = getBodyName(prefix);
       
   163             body = (BodyImpl) createElement(bodyName);
       
   164             insertBefore(body, null);
       
   165             body.ensureNamespaceIsDeclared(bodyName.getPrefix(), bodyName.getURI());
       
   166         } else {
       
   167             log.severe("SAAJ0122.impl.body.already.exists");
       
   168             throw new SOAPExceptionImpl("Can't add a body when one is already present.");
       
   169         }
       
   170 
       
   171         return body;
       
   172     }
       
   173 
       
   174     protected SOAPElement addElement(Name name) throws SOAPException {
       
   175         if (getBodyName(null).equals(name)) {
       
   176             return addBody(name.getPrefix());
       
   177         }
       
   178         if (getHeaderName(null).equals(name)) {
       
   179             return addHeader(name.getPrefix());
       
   180         }
       
   181 
       
   182         return super.addElement(name);
       
   183     }
       
   184 
       
   185     protected SOAPElement addElement(QName name) throws SOAPException {
       
   186         if (getBodyName(null).equals(NameImpl.convertToName(name))) {
       
   187             return addBody(name.getPrefix());
       
   188         }
       
   189         if (getHeaderName(null).equals(NameImpl.convertToName(name))) {
       
   190             return addHeader(name.getPrefix());
       
   191         }
       
   192 
       
   193         return super.addElement(name);
       
   194     }
       
   195 
       
   196     public SOAPBody getBody() throws SOAPException {
       
   197         lookForBody();
       
   198         return body;
       
   199     }
       
   200 
       
   201     public Source getContent() {
       
   202         return new DOMSource(getOwnerDocument());
       
   203     }
       
   204 
       
   205     public Name createName(String localName, String prefix, String uri)
       
   206         throws SOAPException {
       
   207 
       
   208         // validating parameters before passing them on
       
   209         // to make sure that the namespace specification rules are followed
       
   210 
       
   211         // reserved xmlns prefix cannot be used.
       
   212         if ("xmlns".equals(prefix)) {
       
   213             log.severe("SAAJ0123.impl.no.reserved.xmlns");
       
   214             throw new SOAPExceptionImpl("Cannot declare reserved xmlns prefix");
       
   215         }
       
   216         // Qualified name cannot be xmlns.
       
   217         if ((prefix == null) && ("xmlns".equals(localName))) {
       
   218             log.severe("SAAJ0124.impl.qualified.name.cannot.be.xmlns");
       
   219             throw new SOAPExceptionImpl("Qualified name cannot be xmlns");
       
   220         }
       
   221 
       
   222         return NameImpl.create(localName, prefix, uri);
       
   223     }
       
   224 
       
   225     public Name createName(String localName, String prefix)
       
   226         throws SOAPException {
       
   227         String namespace = getNamespaceURI(prefix);
       
   228         if (namespace == null) {
       
   229             log.log(
       
   230                 Level.SEVERE,
       
   231                 "SAAJ0126.impl.cannot.locate.ns",
       
   232                 new String[] { prefix });
       
   233             throw new SOAPExceptionImpl(
       
   234                 "Unable to locate namespace for prefix " + prefix);
       
   235         }
       
   236         return NameImpl.create(localName, prefix, namespace);
       
   237     }
       
   238 
       
   239     public Name createName(String localName) throws SOAPException {
       
   240         return NameImpl.createFromUnqualifiedName(localName);
       
   241     }
       
   242 
       
   243     public void setOmitXmlDecl(String value) {
       
   244         this.omitXmlDecl = value;
       
   245     }
       
   246 
       
   247     public void setXmlDecl(String value) {
       
   248         this.xmlDecl = value;
       
   249     }
       
   250 
       
   251     private String getOmitXmlDecl() {
       
   252         return this.omitXmlDecl;
       
   253     }
       
   254 
       
   255     public void setCharsetEncoding(String value) {
       
   256         charset = value;
       
   257     }
       
   258 
       
   259     public void output(OutputStream out) throws IOException {
       
   260         try {
       
   261 //            materializeBody();
       
   262             Transformer transformer =
       
   263                 EfficientStreamingTransformer.newTransformer();
       
   264 
       
   265             transformer.setOutputProperty(
       
   266                 OutputKeys.OMIT_XML_DECLARATION, "yes");
       
   267                 /*omitXmlDecl);*/
       
   268             // no equivalent for "setExpandEmptyElements"
       
   269             transformer.setOutputProperty(
       
   270                 OutputKeys.ENCODING,
       
   271                 charset);
       
   272 
       
   273             if (omitXmlDecl.equals("no") && xmlDecl == null) {
       
   274                 xmlDecl = "<?xml version=\"" + getOwnerDocument().getXmlVersion() + "\" encoding=\"" +
       
   275                     charset + "\" ?>";
       
   276             }
       
   277 
       
   278            StreamResult result = new StreamResult(out);
       
   279             if (xmlDecl != null) {
       
   280                 OutputStreamWriter writer = new OutputStreamWriter(out, charset);
       
   281                 writer.write(xmlDecl);
       
   282                 writer.flush();
       
   283                 result = new StreamResult(writer);
       
   284             }
       
   285 
       
   286             if (log.isLoggable(Level.FINE)) {
       
   287                 log.log(Level.FINE, "SAAJ0190.impl.set.xml.declaration",
       
   288                         new String[] { omitXmlDecl });
       
   289                 log.log(Level.FINE, "SAAJ0191.impl.set.encoding",
       
   290                         new String[] { charset });
       
   291             }
       
   292 
       
   293             //StreamResult result = new StreamResult(out);
       
   294             transformer.transform(getContent(), result);
       
   295         } catch (Exception ex) {
       
   296             throw new IOException(ex.getMessage());
       
   297         }
       
   298     }
       
   299 
       
   300     /**
       
   301      * Serialize to FI if boolean parameter set.
       
   302      */
       
   303     public void output(OutputStream out, boolean isFastInfoset)
       
   304         throws IOException
       
   305     {
       
   306         if (!isFastInfoset) {
       
   307             output(out);
       
   308         }
       
   309         else {
       
   310             try {
       
   311                 // Run transform and generate FI output from content
       
   312                 Source source = getContent();
       
   313                 Transformer transformer = EfficientStreamingTransformer.newTransformer();
       
   314                     transformer.transform(getContent(),
       
   315                         FastInfosetReflection.FastInfosetResult_new(out));
       
   316             }
       
   317             catch (Exception ex) {
       
   318                 throw new IOException(ex.getMessage());
       
   319             }
       
   320         }
       
   321     }
       
   322 
       
   323     //    public void prettyPrint(OutputStream out) throws IOException {
       
   324     //        if (getDocument() == null)
       
   325     //            initDocument();
       
   326     //
       
   327     //        OutputFormat format = OutputFormat.createPrettyPrint();
       
   328     //
       
   329     //        format.setIndentSize(2);
       
   330     //        format.setNewlines(true);
       
   331     //        format.setTrimText(true);
       
   332     //        format.setPadText(true);
       
   333     //        format.setExpandEmptyElements(false);
       
   334     //
       
   335     //        XMLWriter writer = new XMLWriter(out, format);
       
   336     //        writer.write(getDocument());
       
   337     //    }
       
   338     //
       
   339     //    public void prettyPrint(Writer out) throws IOException {
       
   340     //        if (getDocument() == null)
       
   341     //            initDocument();
       
   342     //
       
   343     //        OutputFormat format = OutputFormat.createPrettyPrint();
       
   344     //
       
   345     //        format.setIndentSize(2);
       
   346     //        format.setNewlines(true);
       
   347     //        format.setTrimText(true);
       
   348     //        format.setPadText(true);
       
   349     //        format.setExpandEmptyElements(false);
       
   350     //
       
   351     //        XMLWriter writer = new XMLWriter(out, format);
       
   352     //        writer.write(getDocument());
       
   353     //    }
       
   354 
       
   355 
       
   356      public SOAPElement setElementQName(QName newName) throws SOAPException {
       
   357         log.log(Level.SEVERE,
       
   358                 "SAAJ0146.impl.invalid.name.change.requested",
       
   359                 new Object[] {elementQName.getLocalPart(),
       
   360                               newName.getLocalPart()});
       
   361         throw new SOAPException("Cannot change name for "
       
   362                                 + elementQName.getLocalPart() + " to "
       
   363                                 + newName.getLocalPart());
       
   364      }
       
   365 
       
   366     @Override
       
   367     public void setStaxBridge(StaxBridge bridge) throws SOAPException {
       
   368         //set it on the body
       
   369         ((BodyImpl) getBody()).setStaxBridge(bridge);
       
   370     }
       
   371 
       
   372     @Override
       
   373     public StaxBridge getStaxBridge() throws SOAPException {
       
   374         return ((BodyImpl) getBody()).getStaxBridge();
       
   375     }
       
   376 
       
   377     @Override
       
   378     public XMLStreamReader getPayloadReader() throws SOAPException {
       
   379         return ((BodyImpl) getBody()).getPayloadReader();
       
   380     }
       
   381 
       
   382     @Override
       
   383     public void writeTo(final XMLStreamWriter writer) throws XMLStreamException, SOAPException {
       
   384         StaxBridge readBridge = this.getStaxBridge();
       
   385         if (readBridge != null && readBridge instanceof StaxLazySourceBridge) {
       
   386 //              StaxSoapWriteBridge writingBridge =  new StaxSoapWriteBridge(this);
       
   387 //              writingBridge.write(writer);
       
   388                 final String soapEnvNS = this.getNamespaceURI();
       
   389                 final DOMStreamReader reader = new DOMStreamReader(this);
       
   390                 XMLStreamReaderToXMLStreamWriter writingBridge =  new XMLStreamReaderToXMLStreamWriter();
       
   391                 writingBridge.bridge( new XMLStreamReaderToXMLStreamWriter.Breakpoint(reader, writer) {
       
   392                         public boolean proceedAfterStartElement()  {
       
   393                                 if ("Body".equals(reader.getLocalName()) && soapEnvNS.equals(reader.getNamespaceURI()) ){
       
   394                                         return false;
       
   395                                 } else
       
   396                                         return true;
       
   397                         }
       
   398             });//bridgeToBodyStartTag
       
   399             ((StaxLazySourceBridge)readBridge).writePayloadTo(writer);
       
   400             writer.writeEndElement();//body
       
   401             writer.writeEndElement();//env
       
   402             writer.writeEndDocument();
       
   403             writer.flush();
       
   404         } else {
       
   405                 LazyEnvelopeStaxReader lazyEnvReader = new LazyEnvelopeStaxReader(this);
       
   406                 XMLStreamReaderToXMLStreamWriter writingBridge = new XMLStreamReaderToXMLStreamWriter();
       
   407                 writingBridge.bridge(lazyEnvReader, writer);
       
   408 //            writingBridge.bridge(new XMLStreamReaderToXMLStreamWriter.Breakpoint(lazyEnvReader, writer));
       
   409         }
       
   410         //Assume the staxBridge is exhausted now since we would have read the body reader
       
   411         ((BodyImpl) getBody()).setPayloadStreamRead();
       
   412     }
       
   413 
       
   414     @Override
       
   415     public QName getPayloadQName() throws SOAPException {
       
   416         return ((BodyImpl) getBody()).getPayloadQName();
       
   417     }
       
   418 
       
   419     @Override
       
   420     public String getPayloadAttributeValue(String localName) throws SOAPException {
       
   421         return ((BodyImpl) getBody()).getPayloadAttributeValue(localName);
       
   422     }
       
   423 
       
   424     @Override
       
   425     public String getPayloadAttributeValue(QName qName) throws SOAPException {
       
   426         return ((BodyImpl) getBody()).getPayloadAttributeValue(qName);
       
   427     }
       
   428 
       
   429     @Override
       
   430     public boolean isLazy() {
       
   431         try {
       
   432             return ((BodyImpl) getBody()).isLazy();
       
   433         } catch (SOAPException e) {
       
   434             return false;
       
   435         }
       
   436     }
       
   437 
       
   438 }