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

com.sun.xml.rpc.server.StreamingHandler Maven / Gradle / Ivy

There is a newer version: 4.0.4
Show newest version
/*
 * 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.server;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.HandlerChain;
import javax.xml.rpc.soap.SOAPFaultException;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import com.sun.xml.messaging.saaj.soap.SOAPVersionMismatchException;
import com.sun.xml.messaging.saaj.util.ByteInputStream;
import com.sun.xml.rpc.client.HandlerChainImpl;
import com.sun.xml.rpc.encoding.DeserializationException;
import com.sun.xml.rpc.encoding.JAXRPCSerializer;
import com.sun.xml.rpc.encoding.MissingTrailingBlockIDException;
import com.sun.xml.rpc.encoding.ReferenceableSerializer;
import com.sun.xml.rpc.encoding.SOAPDeserializationContext;
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.server.http.MessageContextProperties;
import com.sun.xml.rpc.soap.message.Handler;
import com.sun.xml.rpc.soap.message.InternalSOAPMessage;
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.sp.ParseException;
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 com.sun.xml.rpc.util.exception.JAXRPCExceptionBase;
import com.sun.xml.rpc.util.exception.LocalizableExceptionAdapter;
import com.sun.xml.rpc.util.localization.Localizable;
import com.sun.xml.rpc.util.localization.LocalizableMessageFactory;
import com.sun.xml.rpc.util.localization.Localizer;

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

// Static dependency with our impl of SAAJ for FI
import com.sun.xml.messaging.saaj.soap.MessageImpl;
    
/**
 * A base class for streaming-oriented handlers (such as ties).
 *
 * @author JAX-RPC Development Team
 */
public abstract class StreamingHandler
    implements Handler, com.sun.xml.rpc.spi.runtime.StreamingHandler {
        
    protected StreamingHandler() {
        localizer = new Localizer();
        messageFactory =
            new LocalizableMessageFactory("com.sun.xml.rpc.resources.tie");
    }

    protected String getActor() {
        return null;
    }

    public void handle(
        com.sun.xml.rpc.spi.runtime.SOAPMessageContext spiContext) {
        SOAPMessageContext context = (SOAPMessageContext) spiContext;

        // NOTE - due to the addition of handlers and their processing model,
        // the logic in this method has become quite obscure; we should rewrite
        // it so that it deals with handlers (and later interceptors)
        // explicitely, rather than through generic extension points

        StreamingHandlerState state = new StreamingHandlerState(context);

        try {

            XMLReader reader = null;

            try {
                
                boolean invoke = preHandlingHook(state);
                if (invoke == false) {
                    return;
                }

                if (context.isFailure() || state.isFailure()) {
                    return;
                }
                
                Source source = state.getRequest().getMessage().getSOAPPart().getContent();
                if (source instanceof StreamSource
                    && ((StreamSource) source).getInputStream() != null) {
                    InputStream istream =
                        ((StreamSource) source).getInputStream();
                    reader =
                        getXMLReaderFactory(state).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
                                .getRequest()
                                .getMessage()
                                .getSOAPPart()
                                .getEnvelope());
                }

                preEnvelopeReadingHook(state);

                reader.nextElementContent();

                SOAPDeserializationContext deserializationContext =
                    new SOAPDeserializationContext();
                deserializationContext.setMessage(
                    state.getRequest().getMessage());

                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();

                    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();
                        }

                        if (reader.getState() == XMLReader.START
                            && SOAPNamespaceConstants.ENVELOPE.equals(
                                reader.getURI())
                            && SOAPNamespaceConstants.TAG_BODY.equals(
                                reader.getLocalName())) {

                            boolean bodyPushedEncodingStyle =
                                deserializationContext.processEncodingStyle(
                                    reader);

                            // go through all body blocks

                            if (reader.nextElementContent() == XMLReader.END) {
                                handleEmptyBody(
                                    reader,
                                    deserializationContext,
                                    state);

                                if (state.isFailure()) {
                                    return;
                                }

                                preBodyReadingHook(state);

                                if (state.isFailure()) {
                                    return;
                                }
                            } else {
                                peekFirstBodyElement(
                                    reader,
                                    deserializationContext,
                                    state);

                                if (state.isFailure()) {
                                    return;
                                }

                                preBodyReadingHook(state);

                                if (state.isFailure()) {
                                    return;
                                }

                                readFirstBodyElement(
                                    reader,
                                    deserializationContext,
                                    state);

                                if (state.isFailure()) {
                                    return;
                                }

                                deserializationContext
                                    .deserializeMultiRefObjects(
                                    reader);
                                //xsd:IDREF
                                deserializationContext
                                    .runPostDeserializationAction();
                            }

                            postBodyReadingHook(state);

                            // now deal with the trailer blocks
                            while (reader.nextElementContent()
                                == XMLReader.START) {
                                reader.skipElement();
                            }

                            if (bodyPushedEncodingStyle) {
                                deserializationContext.popEncodingStyle();
                            }

                            deserializationContext.doneDeserializing();

                        } else {
                            setBadRequestProp(state);
                            SOAPFaultInfo fault =
                                new SOAPFaultInfo(
                                    SOAPConstants.FAULT_CODE_CLIENT,
                                    BODY_EXPECTED_MESSAGE_STRING,
                                    getActor());
                            reportFault(fault, state);
                        }
                    } else {
                        setBadRequestProp(state);
                        SOAPFaultInfo fault =
                            new SOAPFaultInfo(
                                SOAPConstants.FAULT_CODE_CLIENT,
                                INVALID_ENVELOPE_CONTENT_MESSAGE_STRING,
                                getActor());
                        reportFault(fault, state);
                    }

                    if (envelopePushedEncodingStyle) {
                        deserializationContext.popEncodingStyle();
                    }

                } else if (
                    reader.getState() == XMLReader.START
                        && SOAPNamespaceConstants.TAG_ENVELOPE.equals(
                            reader.getLocalName())) {
                    // got an Envelope element in the wrong namespace
                    setBadRequestProp(state);
                    SOAPFaultInfo fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_VERSION_MISMATCH,
                            ENVELOPE_VERSION_MISMATCH_MESSAGE_STRING,
                            getActor());
                    reportFault(fault, state);

                } else {
                    // not an envelope
                    setBadRequestProp(state);
                    SOAPFaultInfo fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_CLIENT,
                            INVALID_ENVELOPE_MESSAGE_STRING,
                            getActor());
                    reportFault(fault, state);
                }

                if (state.isFailure()) {
                    return;
                }

                postEnvelopeReadingHook(state);

                if (state.isFailure()) {
                    return;
                }

                processingHook(state);

            } catch (Exception e) {

                logger.log(Level.SEVERE, e.getMessage(), e);
                String message = null;
                if (e instanceof Localizable) {
                    message = localizer.localize((Localizable) e);
                } else {
                    message =
                        localizer.localize(
                            messageFactory.getMessage(
                                "error.caughtExceptionWhileHandlingRequest",
                                new Object[] { e.toString()}));
                }

                SOAPFaultInfo fault = null;

                // DeserializationException here means it was an error in a well
                // formed request
                if (e instanceof SOAPProtocolViolationException
                    || e instanceof DeserializationException) {
                    logger.log(Level.SEVERE, message, e);
                    String faultMessage =
                        localizer.localize(
                            messageFactory.getMessage(
                                "error.caughtExceptionWhileHandlingRequest",
                                message));
                    fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_CLIENT,
                            faultMessage,
                            getActor());
                    reportFault(fault, state);
                } else if (
                    e
                        instanceof com
                            .sun
                            .xml
                            .messaging
                            .saaj
                            .soap
                            .SOAPVersionMismatchException) {
                    logger.log(Level.SEVERE, message, e);
                    String faultMessage =
                        localizer.localize(
                            messageFactory.getMessage(
                                "error.caughtExceptionWhileHandlingRequest",
                                message));
                    fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_VERSION_MISMATCH,
                            faultMessage,
                            getActor());
                    reportFault(fault, state);
                } else if (isMalformedXML(e)) { // the 400 case
                    setBadRequestProp(state);
                    logger.log(Level.SEVERE, message, e);
                    state.getResponse().setFailure(true);
                    state.getMessageContext().setFailure(true);
                } else {
                    logger.log(Level.SEVERE, message, e);
                    String faultMessage =
                        localizer.localize(
                            messageFactory.getMessage(
                                "message.faultMessageForException",
                                message));
                    fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_SERVER,
                            faultMessage,
                            getActor());
                    reportFault(fault, state);
                }

            } finally {

                if (reader != null) {
                    reader.close();
                }

                try {

                    preResponseWritingHook(state);

                    writeResponse(state);

                    context.setFailure(state.getResponse().isFailure());

                    context.setMessage(state.getResponse().getMessage());

                    postResponseWritingHook(state);

                } catch (Exception e) {

                    String message = null;
                    if (e instanceof Localizable) {
                        message = localizer.localize((Localizable) e);
                    } else {
                        message =
                            localizer.localize(
                                messageFactory.getMessage(
                                    "error.caughtExceptionWhileHandlingRequest",
                                    new Object[] { e.toString()}));
                    }
                    logger.log(Level.SEVERE, message, e);
                    String faultMessage =
                        localizer.localize(
                            messageFactory.getMessage(
                                "message.faultMessageForException",
                                message));
                    SOAPFaultInfo fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_SERVER,
                            faultMessage,
                            getActor());
                    reportFault(fault, state);
                    writeResponse(state);
                    context.setFailure(state.getResponse().isFailure());
                    context.setMessage(state.getResponse().getMessage());
                }

            }

        } catch (Exception e) {

            String message = null;
            if (e instanceof Localizable) {
                message = localizer.localize((Localizable) e);
            } else {
                message =
                    localizer.localize(
                        messageFactory.getMessage(
                            "error.caughtExceptionWhilePreparingResponse",
                            new Object[] { e.toString()}));
            }
            logger.log(Level.SEVERE, message, e);
            context.writeInternalServerErrorResponse();

        } finally {

            try {
                postHandlingHook(state);
            } catch (Exception e) {

                String message = null;
                if (e instanceof Localizable) {
                    logger.log(
                        Level.SEVERE,
                        localizer.localize((Localizable) e),
                        e);
                } else {
                    logger.log(
                        Level.SEVERE,
                        localizer.localize(
                            messageFactory.getMessage(
                                "error.caughtExceptionPostHandlingRequest",
                                new Object[] { e })));
                }
                logger.log(Level.SEVERE, message, e);
                context.writeInternalServerErrorResponse();

            }
        }
    }

    protected void processHeaders(
        XMLReader reader,
        SOAPDeserializationContext deserializationContext,
        StreamingHandlerState 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) {
            if (!processHeaderElement(reader, deserializationContext, state)) {
                return;
            }
        }
    }

    protected boolean processHeaderElement(
        XMLReader reader,
        SOAPDeserializationContext deserializationContext,
        StreamingHandlerState 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) {
            if (mustUnderstandAttr.equals("1")
                || mustUnderstandAttr.equals("true")) {
                mustUnderstand = true;
            } else if (
                mustUnderstandAttr.equals("0")
                    || mustUnderstandAttr.equals("false")) {
                // no-op
            } else {
                setBadRequestProp(state);
                SOAPFaultInfo fault =
                    new SOAPFaultInfo(
                        SOAPConstants.FAULT_CODE_CLIENT,
                        ILLEGAL_VALUE_OF_MUST_UNDERSTAND_ATTRIBUTE_FAULT_MESSAGE_STRING,
                        getActor());
                reportFault(fault, state);
                return false;
            }
        }

        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) {
                SOAPFaultInfo fault =
                    new SOAPFaultInfo(
                        SOAPConstants.FAULT_CODE_MUST_UNDERSTAND,
                        MUST_UNDERSTAND_FAULT_MESSAGE_STRING,
                        getActor());
                reportFault(fault, state);
                state.getRequest().setHeaderNotUnderstood(true);
                return false;
            }
        } else {
            // not intended for us: check mustUnderstand
            // just ignore it
            reader.skipElement();
        }

        return true;
    }

    protected boolean readHeaderElement(
        SOAPHeaderBlockInfo headerInfo,
        XMLReader reader,
        SOAPDeserializationContext deserializationContext,
        StreamingHandlerState state)
        throws Exception {
        // by default, ignore the header
        reader.skipElement();
        return false;
    }

    protected void handleEmptyBody(
        XMLReader reader,
        SOAPDeserializationContext deserializationContext,
        StreamingHandlerState state)
        throws Exception {
        setBadRequestProp(state); //does this count as malformed xml
        SOAPFaultInfo fault =
            new SOAPFaultInfo(
                SOAPConstants.FAULT_CODE_CLIENT,
                NO_BODY_INFO_MESSAGE_STRING,
                getActor());
        reportFault(fault, state);
    }

    protected void peekFirstBodyElement(
        XMLReader reader,
        SOAPDeserializationContext deserializationContext,
        StreamingHandlerState state)
        throws Exception {
        // no-op
    }

    protected void readFirstBodyElement(
        XMLReader reader,
        SOAPDeserializationContext deserializationContext,
        StreamingHandlerState state)
        throws Exception {
        reader.skipElement();
    }

    public int getOpcodeForRequestMessage(SOAPMessage request) {
        if (usesSOAPActionForDispatching()) {
            String[] soapactionheaders =
                request.getMimeHeaders().getHeader("SOAPAction");
            if (soapactionheaders.length > 0) {
                String soapaction = soapactionheaders[0];
                return getOpcodeForSOAPAction(soapaction);
            }
        } else {
            try {
                SOAPBody body = request.getSOAPPart().getEnvelope().getBody();
                if (body != null) {
                    Iterator iter = body.getChildElements();
                    if (iter.hasNext()) {
                        SOAPElement firstBodyElement =
                            (SOAPElement) iter.next();
                        Name firstBodyElementName =
                            firstBodyElement.getElementName();
                        return getOpcodeForFirstBodyElementName(
                            new QName(
                                firstBodyElementName.getURI(),
                                firstBodyElementName.getLocalName()));
                    } else {
                        // body is empty
                        return getOpcodeForFirstBodyElementName(null);
                    }
                }
            } catch (SOAPException e) {
            }
        }

        // catch-all case
        return InternalSOAPMessage.NO_OPERATION;
    }

    public boolean usesSOAPActionForDispatching() {
        return false;
    }

    public int getOpcodeForFirstBodyElementName(QName name) {
        return InternalSOAPMessage.NO_OPERATION;
    }

    public int getOpcodeForSOAPAction(String s) {
        return InternalSOAPMessage.NO_OPERATION;
    }

    public Method getMethodForOpcode(int opcode)
        throws ClassNotFoundException, NoSuchMethodException {
        return null;
    }

    protected String[] getNamespaceDeclarations() {
        return null;
    }

    public QName[] getUnderstoodHeaders() {
        return new QName[0];
    }

    protected String getDefaultEnvelopeEncodingStyle() {
        return SOAPNamespaceConstants.ENCODING;
    }

    protected String getImplicitEnvelopeEncodingStyle() {
        return null;
    }

    protected String getPreferredCharacterEncoding() {
        return "UTF-8";
    }

    protected void writeResponse(StreamingHandlerState state)
        throws Exception {

        // make sure there is something to write
        SOAPBlockInfo bodyInfo = state.getResponse().getBody();
        boolean pushedEncodingStyle = false;

        if (bodyInfo == null || bodyInfo.getSerializer() == null) {
            if (state.getHandlerFlag()
                == StreamingHandlerState.CALL_NO_HANDLERS) {
                SOAPFaultInfo fault =
                    new SOAPFaultInfo(
                        SOAPConstants.FAULT_CODE_SERVER,
                        NO_BODY_INFO_MESSAGE_STRING,
                        getActor());
                reportFault(fault, state);
            }
            return;
        }

        ByteArrayOutputStream bufferedStream = null;
        XMLWriter writer = null;
        HandlerChain handlerChain = getHandlerChain();
        if (handlerChain == null || handlerChain.size() == 0) {
            // no handlers are present.
            bufferedStream = new ByteArrayOutputStream();
            writer =
                getXMLWriterFactory(state).createXMLWriter(
                    bufferedStream,
                    getPreferredCharacterEncoding());
        } else {
            // Ensure FI content negotiation is carried out
            MessageImpl response = (MessageImpl) state.getResponse().getMessage();
            MessageImpl request = (MessageImpl) state.getRequest ().getMessage(); 
            if (request.acceptFastInfoset()) {  //check if the Client accept FI
                response.setIsFastInfoset(true); 
            }
            // use our own XmlTreeWriter
            writer = new XmlTreeWriter((SOAPPart) response.getSOAPPart());
        }
        writer.setPrefixFactory(new PrefixFactoryImpl("ans"));

        SOAPSerializationContext serializationContext =
            new SOAPSerializationContext("ID");
        serializationContext.setMessage(state.getResponse().getMessage());

        writer.startElement(
            SOAPNamespaceConstants.TAG_ENVELOPE,
            SOAPNamespaceConstants.ENVELOPE,
            "env");

        writer.writeNamespaceDeclaration("xsd", SOAPNamespaceConstants.XSD);
        writer.writeNamespaceDeclaration("xsi", SOAPNamespaceConstants.XSI);
        writer.writeNamespaceDeclaration(
            "enc",
            SOAPNamespaceConstants.ENCODING);

        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());
        }

        boolean wroteHeader = false;
        for (Iterator iter = state.getResponse().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
        }

        writer.startElement(
            SOAPNamespaceConstants.TAG_BODY,
            SOAPNamespaceConstants.ENVELOPE,
            "env");

        serializationContext.beginFragment();
        bodyInfo.getSerializer().serialize(
            bodyInfo.getValue(),
            bodyInfo.getName(),
            null,
            writer,
            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.getResponse().getMessage().getSOAPPart().setContent(
                writer instanceof FastInfosetWriter ? 
                    (Source) new FastInfosetSource(bis) :
                    (Source) new StreamSource(bis));
        } else {
            // XmlTreeWriter must have modified the SOAPPart
        }
    }

    protected boolean preHandlingHook(StreamingHandlerState state)
        throws Exception {
        return callRequestHandlers(state);
    }

    protected void postHandlingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void preEnvelopeReadingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void preHeaderReadingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void postHeaderReadingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void preBodyReadingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void postBodyReadingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void postEnvelopeReadingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void processingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void preResponseWritingHook(StreamingHandlerState state)
        throws Exception {
    }

    protected void postResponseWritingHook(StreamingHandlerState state)
        throws Exception {
        String oneWay =
            (String) state.getMessageContext().getProperty(
                MessageContextProperties.ONE_WAY_OPERATION);
        if (oneWay == null || !oneWay.equalsIgnoreCase("true")) {
            // not a one-way message, so handle response or fault
            if (state.getHandlerFlag()
                == StreamingHandlerState.CALL_RESPONSE_HANDLERS) {
                callResponseHandlers(state);
            } else if (
                state.getHandlerFlag()
                    == StreamingHandlerState.CALL_FAULT_HANDLERS) {
                callFaultHandlers(state);
            }
        }
    }

    protected void callFaultHandlers(StreamingHandlerState state)
        throws Exception {
        HandlerChain handlerChain = getHandlerChain();

        if (handlerChain != null)
            handlerChain.handleFault(state.getMessageContext());
    }

    /**
     * This method has a number of different exit points. For all of them,
     * except when true is returned, FI content negotiation must
     * be carried out.
     */
    protected boolean callRequestHandlers(StreamingHandlerState state)
        throws Exception 
    {
        HandlerChainImpl handlerChain = getHandlerChain();
        if (hasNonEmptyHandlerChain(handlerChain)) {
            try {
                boolean allUnderstood =
                    handlerChain.checkMustUnderstand(state.getMessageContext());
                if (allUnderstood == false) {
                    SOAPFaultInfo fault =
                        new SOAPFaultInfo(
                            SOAPConstants.FAULT_CODE_MUST_UNDERSTAND,
                            MUST_UNDERSTAND_FAULT_MESSAGE_STRING,
                            getActor());                    
                    // FI Content negotiation is completed in this call
                    reportFault(fault, state);                    
                    state.getRequest().setHeaderNotUnderstood(true);
                    state.setHandlerFlag(
                        StreamingHandlerState.CALL_NO_HANDLERS);
                    return false;
                }

                state.setHandlerFlag(
                    StreamingHandlerState.CALL_RESPONSE_HANDLERS);
                boolean r =
                    handlerChain.handleRequest(state.getMessageContext());
                if (r == false) {
                    // Ensure FI content negotiation is carried out
                    MessageImpl request = (MessageImpl) state.getMessageContext().getMessage();
                    if (request.acceptFastInfoset()) {
                        request.setIsFastInfoset(true);
                    }
                    state.setResponse(new InternalSOAPMessage(request));
                }
                return r;
            } catch (SOAPFaultException sfe) {
                // Ensure FI content negotiation is carried out 
                MessageImpl request = (MessageImpl) state.getMessageContext().getMessage();
                if (request.acceptFastInfoset()) {
                    request.setIsFastInfoset(true);
                }
                state.setResponse(new InternalSOAPMessage(request));
                state.setHandlerFlag(StreamingHandlerState.CALL_FAULT_HANDLERS);
                return false;
            } catch (SOAPVersionMismatchException svme) {
                SOAPFaultInfo fault =
                    new SOAPFaultInfo(
                        SOAPConstants.FAULT_CODE_VERSION_MISMATCH,
                        ENVELOPE_VERSION_MISMATCH_MESSAGE_STRING,
                        getActor());
                // FI Content negotiation is completed in this call
                reportFault(fault, state);
                state.setHandlerFlag(StreamingHandlerState.CALL_NO_HANDLERS);
                return false;
            } catch (JAXRPCException jre) {
                state.setHandlerFlag(StreamingHandlerState.CALL_NO_HANDLERS);
                throw jre;
            } catch (RuntimeException rex) {
                state.setHandlerFlag(StreamingHandlerState.CALL_NO_HANDLERS);
                throw rex;
            }
        }
        return true;
    }

    private boolean hasNonEmptyHandlerChain(HandlerChain chain) {
        return (chain != null && !chain.isEmpty());
    }

    protected void callResponseHandlers(StreamingHandlerState state)
        throws Exception {
        HandlerChain handlerChain = getHandlerChain();

        if (handlerChain != null)
            handlerChain.handleResponse(state.getMessageContext());
    }

    protected HandlerChainImpl getHandlerChain() {
        return null;
    }

    /**
     * Return an FI reader if request is FI
     */
    protected XMLReaderFactory getXMLReaderFactory(StreamingHandlerState state) {
        return state.isFastInfoset() ? FastInfosetReaderFactoryImpl.newInstance()
                                     : XMLReaderFactory.newInstance();
    }

    /**
     * Return an FI writer if request is FI or FI is accept by client
     */
    protected XMLWriterFactory getXMLWriterFactory(StreamingHandlerState state) {
        return state.isFastInfoset() || state.acceptFastInfoset() ? 
            FastInfosetWriterFactoryImpl.newInstance() : XMLWriterFactory.newInstance();
    }

    /**
     * Note that a call to StreamingHandlerState.resetResponse()
     * creates a new SAAJ SOAPMessage for the response with the FI flag based
     * on the SOAPMessageContext state. This is needed for content negotiation.
     */
    protected void reportFault(
        SOAPFaultInfo fault,
        StreamingHandlerState state) {
        if (state.getRequest().isHeaderNotUnderstood()) {
            // avoid overwriting an already reported mustUnderstand fault
            return;
        }

        state.resetResponse();      // FI content negotiation
        SOAPBlockInfo faultBlock =
            new SOAPBlockInfo(SOAPConstants.QNAME_SOAP_FAULT);
        faultBlock.setValue(fault);
        faultBlock.setSerializer(soapFaultInfoSerializer);
        state.getResponse().setBody(faultBlock);
        state.getResponse().setFailure(true);
        state.getMessageContext().setFailure(true);
    }

    boolean isMalformedXML(Exception e) {
        //currently just use parseException as malformed xml here
        if (e instanceof JAXRPCExceptionBase) {
            if (e instanceof DeserializationException
                || e instanceof MissingTrailingBlockIDException) {
                return true;
            }
            Throwable cause = ((JAXRPCExceptionBase) e).getLinkedException();
            if (cause != null
                && cause instanceof LocalizableExceptionAdapter) {
                Throwable ex =
                    ((LocalizableExceptionAdapter) cause).getNestedException();
                if (ex != null) {
                    if (ex instanceof ParseException)
                        return true;
                    if (ex instanceof DeserializationException)
                        return true;
                }
            }
        } else if (e instanceof ParseException) {
            return true;
        }

        return false;
    }

    void setBadRequestProp(StreamingHandlerState state) {
        state.getMessageContext().setProperty(
            MessageContextProperties.CLIENT_BAD_REQUEST,
            "true");
    }

    private final static SOAPFaultInfoSerializer soapFaultInfoSerializer =
        new SOAPFaultInfoSerializer(false, false);

    private Localizer localizer;
    private LocalizableMessageFactory messageFactory;

    private final static String MUST_UNDERSTAND_FAULT_MESSAGE_STRING =
        "SOAP must understand error";
    private final static String NO_BODY_INFO_MESSAGE_STRING =
        "Missing body information";
    private final static String BODY_EXPECTED_MESSAGE_STRING =
        "SOAP body expected";
    private final static String INVALID_ENVELOPE_CONTENT_MESSAGE_STRING =
        "Invalid content in SOAP envelope";
    private final static String INVALID_ENVELOPE_MESSAGE_STRING =
        "Invalid SOAP envelope";
    private final static String ENVELOPE_VERSION_MISMATCH_MESSAGE_STRING =
        "Invalid SOAP envelope version";
    private final static String ILLEGAL_VALUE_OF_MUST_UNDERSTAND_ATTRIBUTE_FAULT_MESSAGE_STRING =
        "Illegal value of SOAP mustUnderstand attribute";

    private static final Logger logger =
        Logger.getLogger("com.sun.xml.rpc.server");
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy