Package org.objectweb.celtix.bindings

Source Code of org.objectweb.celtix.bindings.ServerRequest

package org.objectweb.celtix.bindings;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;

import org.objectweb.celtix.common.i18n.Message;
import org.objectweb.celtix.common.logging.LogUtils;
import org.objectweb.celtix.context.InputStreamMessageContext;
import org.objectweb.celtix.context.ObjectMessageContext;
import org.objectweb.celtix.context.OutputStreamMessageContext;
import org.objectweb.celtix.context.WebServiceContextImpl;
import org.objectweb.celtix.handlers.HandlerInvoker;
import org.objectweb.celtix.transports.ServerTransport;

public class ServerRequest {
   
    public enum ServerRequestState {
        STREAM_HANDLERS_INVOKED (1),
        STREAM_READ (2),
        PROTOCOL_HANDLERS_INVOKED (3),
        UNMARSHALLED (4),
        LOGICAL_HANDLERS_INVOKED (5),
        DISPATCHED (6);
       
        private final int val;
      
        ServerRequestState(int v) {
            this.val = v;
        }
       
        public int value() {
            return val;
        }
    }
   
    private static final Logger LOG = LogUtils.getL7dLogger(ServerRequest.class);

    private final AbstractBindingBase binding;
    private HandlerInvoker handlerInvoker;

    private InputStreamMessageContext istreamCtx;
    private MessageContext bindingCtx;
    private ObjectMessageContext objectCtx;
    private ServerRequestState state;
    private boolean isOneway;
    private boolean isOnewayDetermined;

    public ServerRequest(AbstractBindingBase b, InputStreamMessageContext i) {
        binding = b;
        istreamCtx = i;
        istreamCtx.put(ObjectMessageContext.MESSAGE_INPUT, Boolean.FALSE);
    }

    /**
     * Used to create a ServerRequest to represent a resent outgoing
     * message. Hence the state is set up to allow us to proceed directly
     * to the processOutbound() phase.
     * 
     * @param b the underlying binding
     * @param objectContext the object message context
     */
    public ServerRequest(AbstractBindingBase b, ObjectMessageContext objectContext) {
        binding = b;
        objectCtx = objectContext;
        handlerInvoker = binding.createHandlerInvoker();
        state = ServerRequestState.DISPATCHED;
    }

    public AbstractBindingBase getBinding() {
        return binding;
    }

    public HandlerInvoker getHandlerInvoker() {
        return handlerInvoker;
    }

    public void setHandlerInvoker(HandlerInvoker h) {
        handlerInvoker = h;
    }

    public MessageContext getBindingCtx() {
        return bindingCtx;
    }

    public ObjectMessageContext getObjectCtx() {
        return objectCtx;
    }
  
    public ServerRequestState getState() {
        return state;
    }

    public void processInbound() {

        if (null == handlerInvoker) {
            handlerInvoker = binding.createHandlerInvoker();
        }
        handlerInvoker.setInbound();

        handlerInvoker.invokeStreamHandlers(istreamCtx);
        state = ServerRequestState.STREAM_HANDLERS_INVOKED;

        if (bindingCtx == null) {
            bindingCtx = binding.getBindingImpl().createBindingMessageContext(istreamCtx);
        } else {
            bindingCtx.putAll(istreamCtx);
        }
        bindingCtx.put(ObjectMessageContext.MESSAGE_INPUT, Boolean.FALSE);

        try {
            binding.getBindingImpl().read(istreamCtx, bindingCtx);
            state = ServerRequestState.STREAM_READ;
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, "REQUEST_UNREADABLE_MSG", ex);
            throw new WebServiceException(ex);
        }

        boolean continueProcessing = handlerInvoker.invokeProtocolHandlers(isRequestor(), bindingCtx);
        state = ServerRequestState.PROTOCOL_HANDLERS_INVOKED;
        if (!continueProcessing) {
            return;
        }

        // store method and operation name in binding context if not already there -
        // using server binding endpoint callback

        storeOperationName();

        if (null == objectCtx) {
            objectCtx = binding.createObjectContext()
            initObjectContext(objectCtx);
            objectCtx.putAll(bindingCtx);  
        }

        binding.getBindingImpl().unmarshal(bindingCtx, objectCtx, getDataBindingCallback());
        state = ServerRequestState.UNMARSHALLED;
        objectCtx.put(OutputStreamMessageContext.ONEWAY_MESSAGE_TF, isOneway());

        handlerInvoker.invokeLogicalHandlers(isRequestor(), objectCtx);

        state = ServerRequestState.LOGICAL_HANDLERS_INVOKED;
    }

    public void doInvocation() {
        LOG.fine("doInvocation");
        QName operationName = (QName)objectCtx.get(MessageContext.WSDL_OPERATION);
        if (null == operationName) {
            Message msg = new Message("CONTEXT_MISSING_OPERATION_NAME_EXC", LOG);
            LOG.log(Level.SEVERE, msg.toString());
            objectCtx.setException(new WebServiceException(msg.toString()));
            return;
        }
        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("operation name: " + operationName);
        }

       
       
        ServerDataBindingCallback method = (ServerDataBindingCallback)
            BindingContextUtils.retrieveDataBindingCallback(objectCtx);
        if (null == method) {
            Message msg = new Message("IMPLEMENTOR_MISSING_METHOD_EXC", LOG, operationName);
            LOG.log(Level.SEVERE, msg.toString());
            objectCtx.setException(new WebServiceException(msg.toString()));
            return;
        }
        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("method: " + method);
        }

        try {
            new WebServiceContextImpl(objectCtx);
           
            method.invoke(objectCtx);
        } catch (WebServiceException wex) {
            Throwable cause = wex.getCause();
            if (cause != null) {
                objectCtx.setException(cause);
            } else {
                objectCtx.setException(wex);
            }
        } catch (InvocationTargetException ex) {
            LogUtils.log(LOG, Level.FINE, "IMPLEMENTOR_INVOCATION_EXCEPTION_MSG",
                         ex, method.getOperationName());
            Throwable cause = ex.getCause();
            if (cause != null) {
                objectCtx.setException(cause);
            } else {
                objectCtx.setException(ex);
            }
        }
       
        state = ServerRequestState.DISPATCHED;
    }

    public void processOutbound(ServerTransport st, Exception inboundException) {
        processOutbound(st, inboundException, false);
    }

    public void processOutbound(ServerTransport st,
                                Exception inboundException,
                                boolean logicalChainTraversed) {
        if (LOG.isLoggable(Level.FINE)) {
            LOG.info("Reverse processing inbound message, exception: " + inboundException);
        }

        handlerInvoker.setOutbound();

        ObjectMessageContext replyObjectCtx = objectCtx;
        if (null == replyObjectCtx) {
            replyObjectCtx = binding.createObjectContext();
        }
        replyObjectCtx.put(ObjectMessageContext.MESSAGE_INPUT, Boolean.TRUE);       
       
        if (null != inboundException) {
            replyObjectCtx.setException(inboundException);
        }

        // If protocol handlers were invoked inbound, then also invoke them
        // outbound - except when message is oneway.
        // TODO: relax this restriction to allow outbound processing of system
        // handlers.
       
        if (!logicalChainTraversed
            && state.value() >= ServerRequestState.LOGICAL_HANDLERS_INVOKED.value()
            && !isOneway()) {
           
            // Protocol and runtime exceptions have already been caught by
            // handler invoker and stored in the object context.
           
            handlerInvoker.invokeLogicalHandlers(isRequestor(), replyObjectCtx);
        }
       
        // If on the inbound path we managed to construct a binding message
        // context use it - otherwise create a new one.

        MessageContext replyBindingCtx = bindingCtx;
        if (null == replyBindingCtx) {
            bindingCtx = binding.getBindingImpl().createBindingMessageContext(replyObjectCtx);
            replyBindingCtx = bindingCtx;
        } else if (null != replyObjectCtx) {
            replyBindingCtx.putAll(replyObjectCtx);
        }
               

        // The following will only succeed if we have a data binding callback.
       
        if (handlerInvoker.faultRaised(replyObjectCtx)) {
            LOG.fine("Marshalling fault.");
            marshalFault(replyObjectCtx, replyBindingCtx);
        } else if (null != replyObjectCtx.get(ObjectMessageContext.MESSAGE_PAYLOAD)
            || state.value() >= ServerRequestState.DISPATCHED.value()
            || null != replyObjectCtx.get(ObjectMessageContext.METHOD_RETURN)) {
            LOG.fine("Marshalling.");
            marshal(replyObjectCtx, replyBindingCtx);
        }

        // If protocol handlers were invoked inbound, then also invoke them
        // outbound - except when message is oneway.
        // TODO: relax this restriction to allow outbound processing of system
        // handlers.
        // Note we may not be able to find out if the message is oneway (in case where
        // inbound processing failed while invoking stream handlers).

        if (state.value() >= ServerRequestState.PROTOCOL_HANDLERS_INVOKED.value() && !isOneway()) {

            // Protocol and runtime exceptions have already been caught by
            // handler invoker and stored in binding context
            // As marshalling took place prior to invoking the
            // protocol handlers we need to go back and marshal this fault.
           
            handlerInvoker.invokeProtocolHandlers(isRequestor(), replyBindingCtx);
           
            if (handlerInvoker.faultRaised(replyBindingCtx)
                && !binding.getBindingImpl().hasFault(replyBindingCtx)) {
                LOG.fine("Marshalling fault raised by protocol handlers.");
                replyObjectCtx.setException((Exception)replyBindingCtx.get(
                    ObjectMessageContext.METHOD_FAULT));
                marshalFault(replyObjectCtx, replyBindingCtx);
            }
        }

        // create an output stream message context

        binding.getBindingImpl().updateMessageContext(replyBindingCtx);

        try {

            OutputStreamMessageContext ostreamCtx = st.createOutputStreamContext(replyBindingCtx);
            ostreamCtx.setOneWay(isOneway());

            if (isOneway()) {
                st.finalPrepareOutputStreamContext(ostreamCtx);
            } else {
               
                if (binding.getBindingImpl().hasFault(replyBindingCtx)) {
                    ostreamCtx.setFault(true);
                }

                handlerInvoker.invokeStreamHandlers(ostreamCtx);
                st.finalPrepareOutputStreamContext(ostreamCtx);
                binding.getBindingImpl().write(replyBindingCtx, ostreamCtx);
                OutputStream os = ostreamCtx.getOutputStream();
                os.flush();
            }

            LOG.fine("postDispatch from binding on thread : " + Thread.currentThread());
            st.postDispatch(replyBindingCtx, ostreamCtx);
            if (ostreamCtx.getOutputStream() != null) {
                ostreamCtx.getOutputStream().close();
            }
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, "RESPONSE_UNWRITABLE_MSG", ex);
            throw new WebServiceException(ex);
        } finally {
            complete();
        }
    }

    public void complete() {
        handlerInvoker.mepComplete(istreamCtx);
    }

    public boolean isRequestor() {
        return false;
    }

    public boolean isOneway() {
        if (!isOnewayDetermined) {
            isOneway = BindingContextUtils.isOnewayMethod(bindingCtx);
        }
        return isOneway;
    }
   
    public void setOneway(boolean oneway) {
        isOneway = oneway;
        isOnewayDetermined = true;
    }
   
    public boolean doDispatch() {
        return state.value() >= ServerRequestState.LOGICAL_HANDLERS_INVOKED.value()
            && handlerInvoker.isInbound()
            && objectCtx != null
            && BindingContextUtils.retrieveDispatch(objectCtx);
    }

    protected void storeOperationName() {
        AbstractServerBinding sb = (AbstractServerBinding)binding;
        if (bindingCtx.containsKey(MessageContext.WSDL_OPERATION)) {
            if (LOG.isLoggable(Level.FINE)) {
                LOG.fine("Determined operation using pre-existing operation name: "
                         + bindingCtx.get(MessageContext.WSDL_OPERATION));
            }
            return;
        }

        QName operationName = sb.getOperationName(bindingCtx);

        if (null != operationName) {
            bindingCtx.put(MessageContext.WSDL_OPERATION, operationName);
        } else {
            throw new WebServiceException("No operation matching message was found");
        }

        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("Determined operation name using server binding endpoint callback: "
                     + operationName);
        }
    }

    public ServerDataBindingCallback getDataBindingCallback() {
        ServerDataBindingCallback callback =
            (ServerDataBindingCallback)BindingContextUtils.retrieveDataBindingCallback(bindingCtx);
        if (null == callback) {
            assert null != objectCtx;
            ServerBindingEndpointCallback sbeCallback = BindingContextUtils
                .retrieveServerBindingEndpointCallback(bindingCtx);
            DataBindingCallback.Mode mode = sbeCallback.getServiceMode();
            callback = sbeCallback
                .getDataBindingCallback((QName)bindingCtx.get(MessageContext.WSDL_OPERATION),
                                        objectCtx, mode);
            if (LOG.isLoggable(Level.FINE)) {
                LOG.fine("Using data binding callback constructed by server endpoint callback: " + callback);
            }
            BindingContextUtils.storeDataBindingCallback(bindingCtx, callback);
        } else if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("Using data binding callback stored in context.");
        }
        return callback;
    }


    private void initObjectContext(ObjectMessageContext octx) {
        getDataBindingCallback().initObjectContext(octx);
    }
   
   
    private void marshalFault(ObjectMessageContext octx, MessageContext bctx) {
        DataBindingCallback callback =
            BindingContextUtils.retrieveDataBindingCallback(bindingCtx);
        if (null == callback) {
            ServerBindingEndpointCallback sbeCallback = BindingContextUtils
                .retrieveServerBindingEndpointCallback(bindingCtx);
            callback = sbeCallback.getFaultDataBindingCallback(octx);
        }
        if (null == callback) {
            // TODO
            LOG.log(Level.SEVERE, "NO_DATA_BINDING_CALLBACK");
        }
        try {
            binding.getBindingImpl().marshalFault(octx, bctx, callback);
        } catch (Exception ex) {
            LOG.log(Level.SEVERE, "COULD_NOT_MARSHAL_FAULT_MSG", ex);
        }
    }
   
    private void marshal(ObjectMessageContext octx, MessageContext bctx) {
        DataBindingCallback callback = getDataBindingCallback();
        if (null == callback) {
            // TODO
            LOG.log(Level.SEVERE, "NO_DATA_BINDING_CALLBACK");        
        } else {
            try {
                binding.getBindingImpl().marshal(octx, bctx, callback);
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "COULD_NOT_MARSHAL_MSG", ex);
            }
        }
    }

}
TOP

Related Classes of org.objectweb.celtix.bindings.ServerRequest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.