com.sun.xml.messaging.saaj.soap.impl.EnvelopeImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of saaj-impl Show documentation
Show all versions of saaj-impl Show documentation
Open source Reference Implementation of JSR-67: SOAP with Attachments API for Java (SAAJ MR: 1.4)
The newest version!
/*
* Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package com.sun.xml.messaging.saaj.soap.impl;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import com.sun.xml.messaging.saaj.util.LogDomainConstants;
import jakarta.xml.soap.*;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import com.sun.xml.messaging.saaj.SOAPExceptionImpl;
import com.sun.xml.messaging.saaj.soap.LazyEnvelope;
import com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl;
import com.sun.xml.messaging.saaj.soap.StaxBridge;
import com.sun.xml.messaging.saaj.soap.StaxLazySourceBridge;
import com.sun.xml.messaging.saaj.soap.name.NameImpl;
import com.sun.xml.messaging.saaj.util.FastInfosetReflection;
import com.sun.xml.messaging.saaj.util.stax.LazyEnvelopeStaxReader;
import com.sun.xml.messaging.saaj.util.transform.EfficientStreamingTransformer;
import org.jvnet.staxex.util.DOMStreamReader;
import org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter;
import org.w3c.dom.Element;
/**
* Our implementation of the SOAP envelope.
*
* @author Anil Vijendran ([email protected])
*/
public abstract class EnvelopeImpl extends ElementImpl implements LazyEnvelope {
private static final Logger log = Logger.getLogger(LogDomainConstants.SOAP_IMPL_DOMAIN, "com.sun.xml.messaging.saaj.soap.impl.LocalStrings");
protected HeaderImpl header;
protected BodyImpl body;
String omitXmlDecl = "yes";
String charset = "utf-8";
String xmlDecl = null;
protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, Name name) {
super(ownerDoc, name);
}
protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, QName name) {
super(ownerDoc, name);
}
protected EnvelopeImpl(
SOAPDocumentImpl ownerDoc,
NameImpl name,
boolean createHeader,
boolean createBody)
throws SOAPException {
this(ownerDoc, name);
ensureNamespaceIsDeclared(
getElementQName().getPrefix(), getElementQName().getNamespaceURI());
// XXX
if (createHeader)
addHeader();
if (createBody)
addBody();
}
protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, Element domElement) {
super(ownerDoc, domElement);
}
protected abstract NameImpl getHeaderName(String prefix);
protected abstract NameImpl getBodyName(String prefix);
@Override
public SOAPHeader addHeader() throws SOAPException {
return addHeader(null);
}
public SOAPHeader addHeader(String prefix) throws SOAPException {
if (prefix == null || prefix.equals("")) {
prefix = getPrefix();
}
NameImpl headerName = getHeaderName(prefix);
NameImpl bodyName = getBodyName(prefix);
HeaderImpl header = null;
SOAPElement firstChild = (SOAPElement) getFirstChildElement();
if (firstChild != null) {
if (firstChild.getElementName().equals(headerName)) {
log.severe("SAAJ0120.impl.header.already.exists");
throw new SOAPExceptionImpl("Can't add a header when one is already present.");
} else if (!firstChild.getElementName().equals(bodyName)) {
log.severe("SAAJ0121.impl.invalid.first.child.of.envelope");
throw new SOAPExceptionImpl("First child of Envelope must be either a Header or Body");
}
}
header = (HeaderImpl) createElement(headerName);
insertBefore(header.getDomElement(), firstChild);
header.ensureNamespaceIsDeclared(headerName.getPrefix(), headerName.getURI());
return header;
}
protected void lookForHeader() throws SOAPException {
NameImpl headerName = getHeaderName(null);
HeaderImpl hdr = (HeaderImpl) findChild(headerName);
header = hdr;
}
@Override
public SOAPHeader getHeader() throws SOAPException {
lookForHeader();
return header;
}
protected void lookForBody() throws SOAPException {
NameImpl bodyName = getBodyName(null);
BodyImpl bodyChildElement = (BodyImpl) findChild(bodyName);
body = bodyChildElement;
}
@Override
public SOAPBody addBody() throws SOAPException {
return addBody(null);
}
public SOAPBody addBody(String prefix) throws SOAPException {
lookForBody();
if (prefix == null || prefix.equals("")) {
prefix = getPrefix();
}
if (body == null) {
NameImpl bodyName = getBodyName(prefix);
body = (BodyImpl) createElement(bodyName);
insertBefore(body.getDomElement(), null);
body.ensureNamespaceIsDeclared(bodyName.getPrefix(), bodyName.getURI());
} else {
log.severe("SAAJ0122.impl.body.already.exists");
throw new SOAPExceptionImpl("Can't add a body when one is already present.");
}
return body;
}
@Override
protected SOAPElement addElement(Name name) throws SOAPException {
if (getBodyName(null).equals(name)) {
return addBody(name.getPrefix());
}
if (getHeaderName(null).equals(name)) {
return addHeader(name.getPrefix());
}
return super.addElement(name);
}
@Override
protected SOAPElement addElement(QName name) throws SOAPException {
if (getBodyName(null).equals(NameImpl.convertToName(name))) {
return addBody(name.getPrefix());
}
if (getHeaderName(null).equals(NameImpl.convertToName(name))) {
return addHeader(name.getPrefix());
}
return super.addElement(name);
}
@Override
public SOAPBody getBody() throws SOAPException {
lookForBody();
return body;
}
@Override
public Source getContent() {
return new DOMSource(getOwnerDocument());
}
@Override
public Name createName(String localName, String prefix, String uri)
throws SOAPException {
// validating parameters before passing them on
// to make sure that the namespace specification rules are followed
// reserved xmlns prefix cannot be used.
if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
log.severe("SAAJ0123.impl.no.reserved.xmlns");
throw new SOAPExceptionImpl("Cannot declare reserved xmlns prefix");
}
// Qualified name cannot be xmlns.
if ((prefix == null) && (XMLConstants.XMLNS_ATTRIBUTE.equals(localName))) {
log.severe("SAAJ0124.impl.qualified.name.cannot.be.xmlns");
throw new SOAPExceptionImpl("Qualified name cannot be xmlns");
}
return NameImpl.create(localName, prefix, uri);
}
public Name createName(String localName, String uri)
throws SOAPException {
return NameImpl.createFromQualifiedName(localName, uri);
}
@Override
public Name createName(String localName) throws SOAPException {
return NameImpl.createFromUnqualifiedName(localName);
}
public void setOmitXmlDecl(String value) {
this.omitXmlDecl = value;
}
public void setXmlDecl(String value) {
this.xmlDecl = value;
}
public void setCharsetEncoding(String value) {
charset = value;
}
@Override
public void output(OutputStream out) throws IOException {
try {
// materializeBody();
Transformer transformer =
EfficientStreamingTransformer.newTransformer();
transformer.setOutputProperty(
OutputKeys.OMIT_XML_DECLARATION, "yes");
/*omitXmlDecl);*/
// no equivalent for "setExpandEmptyElements"
transformer.setOutputProperty(
OutputKeys.ENCODING,
charset);
if (omitXmlDecl.equals("no") && xmlDecl == null) {
xmlDecl = "";
}
StreamResult result = new StreamResult(out);
if (xmlDecl != null) {
OutputStreamWriter writer = new OutputStreamWriter(out, charset);
writer.write(xmlDecl);
writer.flush();
result = new StreamResult(writer);
}
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE, "SAAJ0190.impl.set.xml.declaration",
new String[] { omitXmlDecl.replaceAll("[\r\n]","") });
log.log(Level.FINE, "SAAJ0191.impl.set.encoding",
new String[] { charset.replaceAll("[\r\n]","") });
}
//StreamResult result = new StreamResult(out);
transformer.transform(getContent(), result);
} catch (Exception ex) {
throw new IOException(ex.getMessage());
}
}
/**
* Serialize to FI if boolean parameter set.
*/
@Override
public void output(OutputStream out, boolean isFastInfoset)
throws IOException
{
if (!isFastInfoset) {
output(out);
}
else {
try {
// Run transform and generate FI output from content
Transformer transformer = EfficientStreamingTransformer.newTransformer();
transformer.transform(getContent(),
FastInfosetReflection.FastInfosetResult_new(out));
}
catch (Exception ex) {
throw new IOException(ex.getMessage());
}
}
}
// public void prettyPrint(OutputStream out) throws IOException {
// if (getDocument() == null)
// initDocument();
//
// OutputFormat format = OutputFormat.createPrettyPrint();
//
// format.setIndentSize(2);
// format.setNewlines(true);
// format.setTrimText(true);
// format.setPadText(true);
// format.setExpandEmptyElements(false);
//
// XMLWriter writer = new XMLWriter(out, format);
// writer.write(getDocument());
// }
//
// public void prettyPrint(Writer out) throws IOException {
// if (getDocument() == null)
// initDocument();
//
// OutputFormat format = OutputFormat.createPrettyPrint();
//
// format.setIndentSize(2);
// format.setNewlines(true);
// format.setTrimText(true);
// format.setPadText(true);
// format.setExpandEmptyElements(false);
//
// XMLWriter writer = new XMLWriter(out, format);
// writer.write(getDocument());
// }
@Override
public SOAPElement setElementQName(QName newName) throws SOAPException {
log.log(Level.SEVERE,
"SAAJ0146.impl.invalid.name.change.requested",
new Object[] {elementQName.getLocalPart().replaceAll("[\r\n]",""),
newName.getLocalPart().replaceAll("[\r\n]","")});
throw new SOAPException("Cannot change name for "
+ elementQName.getLocalPart() + " to "
+ newName.getLocalPart());
}
@Override
public void setStaxBridge(StaxBridge bridge) throws SOAPException {
//set it on the body
((BodyImpl) getBody()).setStaxBridge(bridge);
}
@Override
public StaxBridge getStaxBridge() throws SOAPException {
return ((BodyImpl) getBody()).getStaxBridge();
}
@Override
public XMLStreamReader getPayloadReader() throws SOAPException {
return ((BodyImpl) getBody()).getPayloadReader();
}
@Override
public void writeTo(final XMLStreamWriter writer) throws XMLStreamException, SOAPException {
StaxBridge readBridge = this.getStaxBridge();
if (readBridge instanceof StaxLazySourceBridge) {
// StaxSoapWriteBridge writingBridge = new StaxSoapWriteBridge(this);
// writingBridge.write(writer);
final String soapEnvNS = this.getNamespaceURI();
final DOMStreamReader reader = new DOMStreamReader(this);
XMLStreamReaderToXMLStreamWriter writingBridge = new XMLStreamReaderToXMLStreamWriter();
writingBridge.bridge( new XMLStreamReaderToXMLStreamWriter.Breakpoint(reader, writer) {
@Override
public boolean proceedAfterStartElement() {
if ("Body".equals(reader.getLocalName()) && soapEnvNS.equals(reader.getNamespaceURI()) ){
return false;
} else
return true;
}
});//bridgeToBodyStartTag
((StaxLazySourceBridge)readBridge).writePayloadTo(writer);
writer.writeEndElement();//body
writer.writeEndElement();//env
writer.writeEndDocument();
writer.flush();
} else {
LazyEnvelopeStaxReader lazyEnvReader = new LazyEnvelopeStaxReader(this);
XMLStreamReaderToXMLStreamWriter writingBridge = new XMLStreamReaderToXMLStreamWriter();
writingBridge.bridge(lazyEnvReader, writer);
// writingBridge.bridge(new XMLStreamReaderToXMLStreamWriter.Breakpoint(lazyEnvReader, writer));
}
//Assume the staxBridge is exhausted now since we would have read the body reader
((BodyImpl) getBody()).setPayloadStreamRead();
}
@Override
public QName getPayloadQName() throws SOAPException {
return ((BodyImpl) getBody()).getPayloadQName();
}
@Override
public String getPayloadAttributeValue(String localName) throws SOAPException {
return ((BodyImpl) getBody()).getPayloadAttributeValue(localName);
}
@Override
public String getPayloadAttributeValue(QName qName) throws SOAPException {
return ((BodyImpl) getBody()).getPayloadAttributeValue(qName);
}
@Override
public boolean isLazy() {
try {
return ((BodyImpl) getBody()).isLazy();
} catch (SOAPException e) {
return false;
}
}
}