aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.message.jaxb; aoqi@0: aoqi@0: import com.sun.xml.internal.ws.api.SOAPVersion; aoqi@0: import com.sun.xml.internal.ws.api.message.Message; aoqi@0: import com.sun.xml.internal.ws.api.message.MessageHeaders; aoqi@0: import com.sun.xml.internal.ws.encoding.SOAPBindingCodec; aoqi@0: import com.sun.xml.internal.ws.message.AbstractMessageImpl; aoqi@0: import com.sun.xml.internal.ws.message.PayloadElementSniffer; aoqi@0: import com.sun.xml.internal.ws.spi.db.BindingContext; aoqi@0: import com.sun.xml.internal.ws.spi.db.XMLBridge; aoqi@0: import com.sun.xml.internal.ws.streaming.MtomStreamWriter; aoqi@0: import com.sun.xml.internal.ws.streaming.XMLStreamWriterUtil; aoqi@0: import org.xml.sax.ContentHandler; aoqi@0: import org.xml.sax.ErrorHandler; aoqi@0: import org.xml.sax.SAXException; aoqi@0: aoqi@0: import javax.xml.bind.JAXBContext; aoqi@0: import javax.xml.bind.JAXBException; aoqi@0: import javax.xml.bind.Marshaller; aoqi@0: import javax.xml.bind.attachment.AttachmentMarshaller; aoqi@0: import javax.xml.namespace.QName; aoqi@0: import javax.xml.stream.XMLStreamException; aoqi@0: import javax.xml.stream.XMLStreamReader; aoqi@0: import javax.xml.stream.XMLStreamWriter; aoqi@0: import javax.xml.transform.Source; aoqi@0: import javax.xml.ws.WebServiceException; aoqi@0: import java.io.OutputStream; aoqi@0: aoqi@0: /** aoqi@0: * {@link Message} backed by a JAXB bean; this implementation is used when client uses aoqi@0: * Dispatch mechanism in JAXB/MESSAGE mode; difference from {@link JAXBMessage} is aoqi@0: * that {@code jaxbObject} holds whole SOAP message including SOAP envelope; aoqi@0: * it's the client who is responsible for preparing message content. aoqi@0: * aoqi@0: * @author Miroslav Kos (miroslav.kos at oracle.com) aoqi@0: */ aoqi@0: public class JAXBDispatchMessage extends AbstractMessageImpl { aoqi@0: aoqi@0: private final Object jaxbObject; aoqi@0: aoqi@0: private final XMLBridge bridge; aoqi@0: aoqi@0: /** aoqi@0: * For the use case of a user-supplied JAXB context that is not aoqi@0: * a known JAXB type, as when creating a Disaptch object with a aoqi@0: * JAXB object parameter, we will marshal and unmarshal directly with aoqi@0: * the context object, as there is no Bond available. In this case, aoqi@0: * swaRef is not supported. aoqi@0: */ aoqi@0: private final JAXBContext rawContext; aoqi@0: aoqi@0: /** aoqi@0: * Lazily sniffed payload element name aoqi@0: */ aoqi@0: private QName payloadQName; aoqi@0: aoqi@0: /** aoqi@0: * Copy constructor. aoqi@0: */ aoqi@0: private JAXBDispatchMessage(JAXBDispatchMessage that) { aoqi@0: super(that); aoqi@0: jaxbObject = that.jaxbObject; aoqi@0: rawContext = that.rawContext; aoqi@0: bridge = that.bridge; aoqi@0: } aoqi@0: aoqi@0: public JAXBDispatchMessage(JAXBContext rawContext, Object jaxbObject, SOAPVersion soapVersion) { aoqi@0: super(soapVersion); aoqi@0: this.bridge = null; aoqi@0: this.rawContext = rawContext; aoqi@0: this.jaxbObject = jaxbObject; aoqi@0: } aoqi@0: aoqi@0: public JAXBDispatchMessage(BindingContext context, Object jaxbObject, SOAPVersion soapVersion) { aoqi@0: super(soapVersion); aoqi@0: this.bridge = context.createFragmentBridge(); aoqi@0: this.rawContext = null; aoqi@0: this.jaxbObject = jaxbObject; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: protected void writePayloadTo(ContentHandler contentHandler, ErrorHandler errorHandler, boolean fragment) throws SAXException { aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean hasHeaders() { aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public MessageHeaders getHeaders() { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String getPayloadLocalPart() { aoqi@0: if (payloadQName == null) { aoqi@0: readPayloadElement(); aoqi@0: } aoqi@0: return payloadQName.getLocalPart(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String getPayloadNamespaceURI() { aoqi@0: if (payloadQName == null) { aoqi@0: readPayloadElement(); aoqi@0: } aoqi@0: return payloadQName.getNamespaceURI(); aoqi@0: } aoqi@0: aoqi@0: private void readPayloadElement() { aoqi@0: PayloadElementSniffer sniffer = new PayloadElementSniffer(); aoqi@0: try { aoqi@0: if (rawContext != null) { aoqi@0: Marshaller m = rawContext.createMarshaller(); aoqi@0: m.setProperty("jaxb.fragment", Boolean.FALSE); aoqi@0: m.marshal(jaxbObject, sniffer); aoqi@0: } else { aoqi@0: bridge.marshal(jaxbObject, sniffer, null); aoqi@0: } aoqi@0: aoqi@0: } catch (JAXBException e) { aoqi@0: // if it's due to us aborting the processing after the first element, aoqi@0: // we can safely ignore this exception. aoqi@0: // aoqi@0: // if it's due to error in the object, the same error will be reported aoqi@0: // when the readHeader() method is used, so we don't have to report aoqi@0: // an error right now. aoqi@0: payloadQName = sniffer.getPayloadQName(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean hasPayload() { aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Source readPayloadAsSource() { aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public XMLStreamReader readPayload() throws XMLStreamException { aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException { aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Message copy() { aoqi@0: return new JAXBDispatchMessage(this); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: @SuppressWarnings("unchecked") aoqi@0: public void writeTo(XMLStreamWriter sw) throws XMLStreamException { aoqi@0: try { aoqi@0: // MtomCodec sets its own AttachmentMarshaller aoqi@0: AttachmentMarshaller am = (sw instanceof MtomStreamWriter) aoqi@0: ? ((MtomStreamWriter) sw).getAttachmentMarshaller() aoqi@0: : new AttachmentMarshallerImpl(attachmentSet); aoqi@0: aoqi@0: // Get the encoding of the writer aoqi@0: String encoding = XMLStreamWriterUtil.getEncoding(sw); aoqi@0: aoqi@0: // Get output stream and use JAXB UTF-8 writer aoqi@0: OutputStream os = bridge.supportOutputStream() ? XMLStreamWriterUtil.getOutputStream(sw) : null; aoqi@0: if (rawContext != null) { aoqi@0: Marshaller m = rawContext.createMarshaller(); aoqi@0: m.setProperty("jaxb.fragment", Boolean.FALSE); aoqi@0: m.setAttachmentMarshaller(am); aoqi@0: if (os != null) { aoqi@0: m.marshal(jaxbObject, os); aoqi@0: } else { aoqi@0: m.marshal(jaxbObject, sw); aoqi@0: } aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: if (os != null && encoding != null && encoding.equalsIgnoreCase(SOAPBindingCodec.UTF8_ENCODING)) { aoqi@0: bridge.marshal(jaxbObject, os, sw.getNamespaceContext(), am); aoqi@0: } else { aoqi@0: bridge.marshal(jaxbObject, sw, am); aoqi@0: } aoqi@0: } aoqi@0: //cleanup() is not needed since JAXB doesn't keep ref to AttachmentMarshaller aoqi@0: } catch (JAXBException e) { aoqi@0: // bug 6449684, spec 4.3.4 aoqi@0: throw new WebServiceException(e); aoqi@0: } aoqi@0: } aoqi@0: }