All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.rpc.client.StreamingSender Maven / Gradle / Ivy

/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.xml.rpc.client;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.rmi.MarshalException;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.Iterator;

import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerChain;
import javax.xml.rpc.soap.SOAPFaultException;
import javax.xml.soap.Detail;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import com.sun.xml.messaging.saaj.util.ByteInputStream;
import com.sun.xml.rpc.encoding.JAXRPCSerializer;
import com.sun.xml.rpc.encoding.ReferenceableSerializer;
import com.sun.xml.rpc.encoding.SOAPDeserializationContext;
import com.sun.xml.rpc.encoding.SOAPDeserializationState;
import com.sun.xml.rpc.encoding.SOAPFaultInfoSerializer;
import com.sun.xml.rpc.encoding.SOAPSerializationContext;
import com.sun.xml.rpc.encoding.soap.SOAPConstants;
import com.sun.xml.rpc.soap.message.SOAPBlockInfo;
import com.sun.xml.rpc.soap.message.SOAPFaultInfo;
import com.sun.xml.rpc.soap.message.SOAPHeaderBlockInfo;
import com.sun.xml.rpc.soap.message.SOAPMessageContext;
import com.sun.xml.rpc.soap.streaming.SOAPNamespaceConstants;
import com.sun.xml.rpc.soap.streaming.SOAPProtocolViolationException;
import com.sun.xml.rpc.streaming.Attributes;
import com.sun.xml.rpc.streaming.PrefixFactoryImpl;
import com.sun.xml.rpc.streaming.XMLReader;
import com.sun.xml.rpc.streaming.XMLReaderFactory;
import com.sun.xml.rpc.streaming.XMLWriter;
import com.sun.xml.rpc.streaming.XMLWriterFactory;
import com.sun.xml.rpc.streaming.XmlTreeReader;
import com.sun.xml.rpc.streaming.XmlTreeWriter;

import org.jvnet.fastinfoset.FastInfosetSource;
import com.sun.xml.rpc.streaming.FastInfosetWriter;
import com.sun.xml.rpc.streaming.FastInfosetReaderFactoryImpl;

/**
 * 

A base class for streaming-oriented message senders (such as stubs).

* * @author JAX-RPC Development Team */ public abstract class StreamingSender { protected StreamingSender() { } protected StreamingSenderState _start(HandlerChain handlerChain) { //create the SOAPMessageContext SOAPMessageContext messageContext = new SOAPMessageContext(); ((HandlerChainImpl) handlerChain).addUnderstoodHeaders( _getUnderstoodHeaders()); //create and return StreamingSenderState containing message context //and a handler chain return new StreamingSenderState(messageContext, handlerChain, false, true); } protected String _getActor() { return null; } protected void _send(String endpoint, StreamingSenderState state) throws Exception { //send the request over the wire _preSendingHook(state); _preRequestWritingHook(state); _writeRequest(state); _postRequestWritingHook(state); boolean invoke = _preRequestSendingHook(state); //get the transport mechanism and invoke the request //the transport may be HTTP or Local transport if (invoke == true) _getTransport().invoke(endpoint, state.getMessageContext()); _postRequestSendingHook(state); XMLReader reader = null; //gets the response and reads it using XMLReader try { SOAPFaultInfo fault = null; _preHandlingHook(state); Source source = state.getResponse().getMessage().getSOAPPart().getContent(); if (source instanceof StreamSource && ((StreamSource) source).getInputStream() != null) { InputStream istream = ((StreamSource) source).getInputStream(); reader = _getXMLReaderFactory().createXMLReader(istream, true); } else if (source instanceof FastInfosetSource) { // Avoid going through an XmlTreeReader by using FI factory InputStream istream = ((FastInfosetSource) source).getInputSource().getByteStream(); reader = FastInfosetReaderFactoryImpl.newInstance().createXMLReader(istream, true); } else { reader = new XmlTreeReader( state .getResponse() .getMessage() .getSOAPPart() .getEnvelope()); } _preEnvelopeReadingHook(state); reader.nextElementContent(); SOAPDeserializationContext deserializationContext = new SOAPDeserializationContext(); deserializationContext.setMessage(state.getResponse().getMessage()); //make sure that this is a valid SOAP Envelope if (reader.getState() == XMLReader.START && SOAPNamespaceConstants.ENVELOPE.equals(reader.getURI()) && SOAPNamespaceConstants.TAG_ENVELOPE.equals( reader.getLocalName())) { boolean envelopePushedEncodingStyle = deserializationContext.processEncodingStyle(reader); _preHeaderReadingHook(state); if (state.isFailure()) { return; } reader.nextElementContent(); //check for valid SOAP Headers if (reader.getState() == XMLReader.START && SOAPNamespaceConstants.ENVELOPE.equals(reader.getURI())) { if (SOAPNamespaceConstants .TAG_HEADER .equals(reader.getLocalName())) { boolean headerPushedEncodingStyle = deserializationContext.processEncodingStyle(reader); _processHeaders(reader, deserializationContext, state); // if (state.isFailure()) { return; } _postHeaderReadingHook(state); // if (state.isFailure()) { return; } if (headerPushedEncodingStyle) { deserializationContext.popEncodingStyle(); } reader.nextElementContent(); } //Has the SOAP Body been reached? if (reader.getState() == XMLReader.START && SOAPNamespaceConstants.ENVELOPE.equals(reader.getURI()) && SOAPNamespaceConstants.TAG_BODY.equals( reader.getLocalName())) { boolean bodyPushedEncodingStyle = deserializationContext.processEncodingStyle(reader); Object faultOrFaultState = null; // go through all body blocks //case of empty SOAP Body if (reader.nextElementContent() == XMLReader.END) { _handleEmptyBody( reader, deserializationContext, state); if (state.isFailure()) { return; } _preBodyReadingHook(state); if (state.isFailure()) { return; } } else { _preBodyReadingHook(state); if (state.isFailure()) { return; } //read the SOAP Fault if (reader.getName().equals(QNAME_SOAP_FAULT)) { faultOrFaultState = _readBodyFaultElement( reader, deserializationContext, state); } else { //or else read the first Body Element _readFirstBodyElement( reader, deserializationContext, state); } if (state.isFailure()) { return; } //deserialize the rest of the response deserializationContext.deserializeMultiRefObjects( reader); //xsd:IDREF deserializationContext .runPostDeserializationAction(); } _postBodyReadingHook(state); // now deal with the trailer blocks // deserializationContext.deserializeMultiRefObjects(reader); while (reader.nextElementContent() == XMLReader.START) { reader.skipElement(); } deserializationContext.doneDeserializing(); if (bodyPushedEncodingStyle) { deserializationContext.popEncodingStyle(); } if (faultOrFaultState != null) { if (faultOrFaultState instanceof SOAPFaultInfo) { fault = (SOAPFaultInfo) faultOrFaultState; } else if ( faultOrFaultState instanceof SOAPDeserializationState) { fault = (SOAPFaultInfo) ( (SOAPDeserializationState) faultOrFaultState) .getInstance(); } else { throw new SenderException("sender.response.unrecognizedFault"); } } } else { throw new SOAPProtocolViolationException("soap.protocol.missingBody"); } } else { throw new SOAPProtocolViolationException("soap.protocol.invalidEnvelopeContent"); } if (envelopePushedEncodingStyle) { deserializationContext.popEncodingStyle(); } } else if ( reader.getState() == XMLReader.START && SOAPNamespaceConstants.TAG_ENVELOPE.equals( reader.getLocalName())) { // got an Envelope element in the wrong namespace throw new SOAPProtocolViolationException("soap.protocol.envelopeVersionMismatch"); } else { // not an envelope throw new SOAPProtocolViolationException("soap.protocol.notAnEnvelope"); } if (state.isFailure()) { return; } _postEnvelopeReadingHook(state); // raise a fault if (fault != null) { //if header, get the headerelement _raiseFault(fault, state); } } catch (SOAPFaultException e) { throw e; } catch (RuntimeException rex) { _handleRuntimeExceptionInSend(rex); } catch (Exception e) { throw e; } finally { if (reader != null) { reader.close(); } try { _postHandlingHook(state); } finally { _postSendingHook(state); } } } protected void _handleRuntimeExceptionInSend(RuntimeException rex) throws Exception { throw new RemoteException("Runtime exception", rex); } protected void _sendOneWay(String endpoint, StreamingSenderState state) throws Exception { _preSendingHook(state); _preRequestWritingHook(state); _writeRequest(state); _postRequestWritingHook(state); boolean invoke = _preRequestSendingHook(state); if (invoke == true) _getTransport().invokeOneWay(endpoint, state.getMessageContext()); _postRequestSendingHook(state); _postSendingHook(state); } protected void _processHeaders( XMLReader reader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { // try to process all headers, stopping prematurely only if // we encounter a serious failure (typically, a mustUnderstand // attribute we cannot honor) while (reader.nextElementContent() != XMLReader.END) { _processHeaderElement(reader, deserializationContext, state); } } protected void _processHeaderElement( XMLReader reader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { Attributes attributes = reader.getAttributes(); String actorAttr = attributes.getValue( SOAPNamespaceConstants.ENVELOPE, SOAPNamespaceConstants.ATTR_ACTOR); String mustUnderstandAttr = attributes.getValue( SOAPNamespaceConstants.ENVELOPE, SOAPNamespaceConstants.ATTR_MUST_UNDERSTAND); boolean mustUnderstand = false; if (mustUnderstandAttr != null) { // TODO - remember to change this if mustUnderstand is made to allow "true", "false" as values if (mustUnderstandAttr.equals("1") || mustUnderstandAttr.equals("true")) { mustUnderstand = true; } else if ( mustUnderstandAttr.equals("0") || mustUnderstandAttr.equals("false")) { // no-op } else { throw new SenderException( "sender.response.illegalValueOfMustUnderstandAttribute", mustUnderstandAttr); } } if ((_getActor() == null && (actorAttr == null || actorAttr.equals(SOAPNamespaceConstants.ACTOR_NEXT))) || (_getActor() != null && (_getActor().equals(actorAttr)))) { // intended for us SOAPHeaderBlockInfo headerInfo = new SOAPHeaderBlockInfo( reader.getName(), actorAttr, mustUnderstand); boolean succeeded = _readHeaderElement( headerInfo, reader, deserializationContext, state); if (!succeeded && mustUnderstand) { throw new SOAPFaultException( SOAPConstants.FAULT_CODE_MUST_UNDERSTAND, MUST_UNDERSTAND_FAULT_MESSAGE_STRING, _getActor(), null); } } else { // not intended for us: check mustUnderstand // just ignore it reader.skipElement(); return; /* removed this code and added above 2 statements to fix bug# 4731903 if (mustUnderstand) { throw new SOAPFaultException(SOAPConstants.FAULT_CODE_MUST_UNDERSTAND, MUST_UNDERSTAND_FAULT_MESSAGE_STRING, _getActor(), null); // TODO - when moving to SOAP 1.2, use a "Misunderstood" header fault here } else { // just ignore it reader.skipElement(); return; }*/ } } protected boolean _readHeaderElement( SOAPHeaderBlockInfo headerInfo, XMLReader reader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { // by default, ignore the header reader.skipElement(); return false; } protected Object _readBodyFaultElement( XMLReader reader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { return faultInfoSerializer.deserialize( null, reader, deserializationContext); } protected void _readFirstBodyElement( XMLReader reader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { reader.skipElement(); } protected void _handleEmptyBody( XMLReader reader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { throw new SOAPProtocolViolationException("soap.protocol.emptyBody"); } protected void _raiseFault(SOAPFaultInfo fault, StreamingSenderState state) throws Exception { if (fault.getDetail() != null && fault.getDetail() instanceof Exception) { throw (Exception) fault.getDetail(); } Object detail = fault.getDetail(); if (detail != null && (detail instanceof Detail)) { throw new SOAPFaultException( fault.getCode(), fault.getString(), fault.getActor(), (Detail) detail); } else if (detail == null) { //its headerfault Object obj = null; if (state.getResponse().headers().hasNext()) { obj = state.getResponse().headers().next(); throw new RemoteException( fault.getString(), new com.sun.xml.rpc.util.HeaderFaultException( fault.getString(), obj)); } } if (fault.getCode().equals(SOAPConstants.FAULT_CODE_SERVER)) { throw new ServerException(fault.getString()); } else if ( fault.getCode().equals( SOAPConstants.FAULT_CODE_DATA_ENCODING_UNKNOWN)) { throw new MarshalException(fault.getString()); } else if ( fault.getCode().equals( SOAPConstants.FAULT_CODE_PROCEDURE_NOT_PRESENT) || fault.getCode().equals( SOAPConstants.FAULT_CODE_BAD_ARGUMENTS)) { throw new RemoteException(fault.getString()); } else { Object obj = null; // somehow put all the information from a fault into a remote exception //javax.xml.soap.Detail detail=null; if (state.getResponse().headers().hasNext()) { obj = state.getResponse().headers().next(); } throw new SOAPFaultException( fault.getCode(), fault.getString(), fault.getActor(), (javax.xml.soap.Detail) detail); } } protected void _writeRequest(StreamingSenderState state) throws Exception { // make sure there is something to write SOAPBlockInfo bodyInfo = state.getRequest().getBody(); boolean pushedEncodingStyle = false; if (bodyInfo == null || bodyInfo.getSerializer() == null) { throw new SenderException("sender.request.missingBodyInfo"); } //write out the XML Request using the XMLWriter XMLWriter writer = null; ByteArrayOutputStream bufferedStream = null; HandlerChain handlerChain = state.getHandlerChain(); if (handlerChain == null || handlerChain.size() == 0) { // no handlers are present. bufferedStream = new ByteArrayOutputStream(); writer = _getXMLWriterFactory().createXMLWriter( bufferedStream, _getPreferredCharacterEncoding()); } else { writer = new XmlTreeWriter( (SOAPPart) state.getRequest().getMessage().getSOAPPart()); } writer.setPrefixFactory(new PrefixFactoryImpl("ans")); SOAPSerializationContext serializationContext = new SOAPSerializationContext("ID"); serializationContext.setMessage(state.getRequest().getMessage()); //write SOAP Envelope writer.startElement( SOAPNamespaceConstants.TAG_ENVELOPE, SOAPNamespaceConstants.ENVELOPE, "env"); //write needed SOAP Namespace declarations writer.writeNamespaceDeclaration("xsd", SOAPNamespaceConstants.XSD); writer.writeNamespaceDeclaration("xsi", SOAPNamespaceConstants.XSI); writer.writeNamespaceDeclaration( "enc", SOAPNamespaceConstants.ENCODING); //look for request namspaces and write those String[] namespaceDeclarations = _getNamespaceDeclarations(); if (namespaceDeclarations != null) { for (int i = 0; i < namespaceDeclarations.length; i += 2) { writer.writeNamespaceDeclaration( namespaceDeclarations[i], namespaceDeclarations[i + 1]); } } if (_getDefaultEnvelopeEncodingStyle() != null) { pushedEncodingStyle = serializationContext.pushEncodingStyle( _getDefaultEnvelopeEncodingStyle(), writer); } else if (_getImplicitEnvelopeEncodingStyle() != null) { pushedEncodingStyle = serializationContext.setImplicitEncodingStyle( _getImplicitEnvelopeEncodingStyle()); } //write SOAP Header boolean wroteHeader = false; for (Iterator iter = state.getRequest().headers(); iter.hasNext();) { SOAPHeaderBlockInfo headerInfo = (SOAPHeaderBlockInfo) iter.next(); if (headerInfo.getValue() != null && headerInfo.getSerializer() != null) { if (!wroteHeader) { writer.startElement( SOAPNamespaceConstants.TAG_HEADER, SOAPNamespaceConstants.ENVELOPE); wroteHeader = true; } serializationContext.beginFragment(); JAXRPCSerializer serializer = headerInfo.getSerializer(); if (serializer instanceof ReferenceableSerializer) { ((ReferenceableSerializer) serializer).serializeInstance( headerInfo.getValue(), headerInfo.getName(), false, writer, serializationContext); } else { serializer.serialize( headerInfo.getValue(), headerInfo.getName(), null, writer, serializationContext); } serializationContext.endFragment(); } } if (wroteHeader) { writer.endElement(); // env:HEADER } //start writing the SOAP Body writer.startElement( SOAPNamespaceConstants.TAG_BODY, SOAPNamespaceConstants.ENVELOPE, "env"); serializationContext.beginFragment(); //serialize the request bodyInfo.getSerializer().serialize( bodyInfo.getValue(), bodyInfo.getName(), null, writer, // XML or FI writer passed to serializer serializationContext); serializationContext.serializeMultiRefObjects(writer); serializationContext.endFragment(); writer.endElement(); // env:BODY writer.endElement(); // env:ENVELOPE if (pushedEncodingStyle) { serializationContext.popEncodingStyle(); } writer.close(); if (handlerChain == null || handlerChain.size() == 0) { // no handlers are present. byte[] data = bufferedStream.toByteArray(); // Set source in SAAJ object depending on which XMLWriter was used ByteInputStream bis = new ByteInputStream(data, data.length); state.getRequest().getMessage().getSOAPPart().setContent( writer instanceof FastInfosetWriter ? (Source) new FastInfosetSource(bis) : (Source) new StreamSource(bis)); } else { // XMLTreeWriter must have updated the SOAPPart } } protected String[] _getNamespaceDeclarations() { return null; } public QName[] _getUnderstoodHeaders() { return new QName[0]; } //for soap protected String _getDefaultEnvelopeEncodingStyle() { return SOAPNamespaceConstants.ENCODING; // return null; } protected String _getImplicitEnvelopeEncodingStyle() { return null; } protected String _getPreferredCharacterEncoding() { return "UTF-8"; } //////// protected void _preSendingHook(StreamingSenderState state) throws Exception { } protected void _postSendingHook(StreamingSenderState state) throws Exception { } protected void _preHandlingHook(StreamingSenderState state) throws Exception { _callResponseHandlers(state); } protected void _postHandlingHook(StreamingSenderState state) throws Exception { } protected void _preRequestWritingHook(StreamingSenderState state) throws Exception { } protected void _postRequestWritingHook(StreamingSenderState state) throws Exception { } protected boolean _preRequestSendingHook(StreamingSenderState state) throws Exception { return _callRequestHandlers(state); } protected void _postRequestSendingHook(StreamingSenderState state) throws Exception { } protected void _preEnvelopeReadingHook(StreamingSenderState state) throws Exception { } protected void _preHeaderReadingHook(StreamingSenderState state) throws Exception { } protected void _postHeaderReadingHook(StreamingSenderState state) throws Exception { } protected void _preBodyReadingHook(StreamingSenderState state) throws Exception { } protected void _postBodyReadingHook(StreamingSenderState state) throws Exception { } protected void _postEnvelopeReadingHook(StreamingSenderState state) throws Exception { } protected boolean _callRequestHandlers(StreamingSenderState state) throws Exception { HandlerChain handlerChain = state.getHandlerChain(); if (handlerChain != null) { try { return handlerChain.handleRequest(state.getMessageContext()); } catch (RuntimeException e) { throw new RemoteException("request handler error: ", e); } } return true; } protected void _callResponseHandlers(StreamingSenderState state) throws Exception { HandlerChainImpl handlerChain = (HandlerChainImpl) state.getHandlerChain(); if (hasNonEmptyHandlerChain(handlerChain)) { boolean allUnderstood = handlerChain.checkMustUnderstand(state.getMessageContext()); if (allUnderstood == false) { throw new SOAPFaultException( SOAPConstants.FAULT_CODE_MUST_UNDERSTAND, MUST_UNDERSTAND_FAULT_MESSAGE_STRING, _getActor(), null); } try { handlerChain.handleResponse(state.getMessageContext()); } catch (RuntimeException e) { throw new RemoteException("response handler error: ", e); } } } private boolean hasNonEmptyHandlerChain(HandlerChain chain) { return (chain != null && !chain.isEmpty()); } //////// protected abstract ClientTransport _getTransport(); protected XMLReaderFactory _getXMLReaderFactory() { return XMLReaderFactory.newInstance(); } protected XMLWriterFactory _getXMLWriterFactory() { return XMLWriterFactory.newInstance(); } private static final SOAPFaultInfoSerializer faultInfoSerializer = new SOAPFaultInfoSerializer(true, false); private final static QName QNAME_SOAP_FAULT = new QName(SOAPNamespaceConstants.ENVELOPE, "Fault"); private final static String MUST_UNDERSTAND_FAULT_MESSAGE_STRING = "SOAP must understand error"; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy