blob: d73ba5b0ceaa246a3889723d928ca4be2b327cff [file] [log] [blame]
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.messaging.saaj.soap.impl;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.logging.Level;
import javax.xml.namespace.QName;
import javax.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.internal.messaging.saaj.SOAPExceptionImpl;
import com.sun.xml.internal.messaging.saaj.soap.LazyEnvelope;
import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl;
import com.sun.xml.internal.messaging.saaj.soap.StaxBridge;
import com.sun.xml.internal.messaging.saaj.soap.StaxLazySourceBridge;
import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
import com.sun.xml.internal.messaging.saaj.util.FastInfosetReflection;
import com.sun.xml.internal.messaging.saaj.util.stax.LazyEnvelopeStaxReader;
import com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer;
import com.sun.xml.internal.org.jvnet.staxex.util.DOMStreamReader;
import com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter;
/**
* Our implementation of the SOAP envelope.
*
* @author Anil Vijendran (anil@sun.com)
*/
public abstract class EnvelopeImpl extends ElementImpl implements LazyEnvelope {
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 abstract NameImpl getHeaderName(String prefix);
protected abstract NameImpl getBodyName(String prefix);
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, 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;
}
public SOAPHeader getHeader() throws SOAPException {
lookForHeader();
return header;
}
protected void lookForBody() throws SOAPException {
NameImpl bodyName = getBodyName(null);
BodyImpl bodyChildElement = (BodyImpl) findChild(bodyName);
body = bodyChildElement;
}
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, 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;
}
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);
}
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);
}
public SOAPBody getBody() throws SOAPException {
lookForBody();
return body;
}
public Source getContent() {
return new DOMSource(getOwnerDocument());
}
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 ("xmlns".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) && ("xmlns".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 prefix)
throws SOAPException {
String namespace = getNamespaceURI(prefix);
if (namespace == null) {
log.log(
Level.SEVERE,
"SAAJ0126.impl.cannot.locate.ns",
new String[] { prefix });
throw new SOAPExceptionImpl(
"Unable to locate namespace for prefix " + prefix);
}
return NameImpl.create(localName, prefix, namespace);
}
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;
}
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 = "<?xml version=\"" + getOwnerDocument().getXmlVersion() + "\" encoding=\"" +
charset + "\" ?>";
}
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 });
log.log(Level.FINE, "SAAJ0191.impl.set.encoding",
new String[] { charset });
}
//StreamResult result = new StreamResult(out);
transformer.transform(getContent(), result);
} catch (Exception ex) {
throw new IOException(ex.getMessage());
}
}
/**
* Serialize to FI if boolean parameter set.
*/
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());
// }
public SOAPElement setElementQName(QName newName) throws SOAPException {
log.log(Level.SEVERE,
"SAAJ0146.impl.invalid.name.change.requested",
new Object[] {elementQName.getLocalPart(),
newName.getLocalPart()});
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 != null && 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) {
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;
}
}
}