handlerchainprocessor.java

来自「开源的axis2框架的源码。用于开发WEBSERVER」· Java 代码 · 共 589 行 · 第 1/2 页

JAVA
589
字号
                                                    int end, Direction direction) {
        int i = start;

        if (direction == Direction.OUT) {
            for (; i <= end; i++) {
                switchContext(direction, i);
                Handler handler = (Handler) handlers.get(i);
                
                if (log.isDebugEnabled()) {
                    log.debug("Invoking handleMessage on: " + handler.getClass().getName());
                }
                handler.handleMessage(currentMC);
            }
        } else { // IN case
            for (; i >= end; i--) {
                switchContext(direction, i);
                Handler handler = (Handler) handlers.get(i);
               
                if (log.isDebugEnabled()) {
                    log.debug("Invoking handleMessage on: " + handler.getClass().getName());
                }
                handler.handleMessage(currentMC);
            }
        }
    }


    /**
     * Calls handleMessage on the Handler. If an exception is thrown and a response is expected, the
     * MessageContext is updated with the handler information
     *
     * @returns SUCCESSFUL if successfully, UNSUCCESSFUL if false, EXCEPTION if exception thrown
     */
    private int handleMessage(Handler handler, Direction direction,
                              boolean expectResponse) throws RuntimeException {
        try {
            if (log.isDebugEnabled()) {
                log.debug("Invoking handleMessage on: " + handler.getClass().getName()); 
            }
            boolean success = handler.handleMessage(currentMC);
            if (success) {
                if (log.isDebugEnabled()) {
                    log.debug("handleMessage() returned true");
                }
                return SUCCESSFUL;
            }
            else {
                if (log.isDebugEnabled()) {
                    log.debug("handleMessage() returned false");
                }
                if (expectResponse)
                    currentMC.put(javax.xml.ws.handler.MessageContext.MESSAGE_OUTBOUND_PROPERTY,
                                    (direction != Direction.OUT));
                return FAILED;
            }
        } 
        catch (RuntimeException re) { 
            // RuntimeException and ProtocolException
            if(log.isDebugEnabled()) {
               log.debug("An exception was thrown during the handleMessage() invocation");
               log.debug("Exception: " + re.getClass().getName() + ":" +re.getMessage());
            }
            
            savedException = re;
            if (expectResponse)
                // mark it as reverse direction
                currentMC.put(javax.xml.ws.handler.MessageContext.MESSAGE_OUTBOUND_PROPERTY,
                                (direction != Direction.OUT));
            if (ProtocolException.class.isAssignableFrom(re.getClass())) {
                convertToFaultMessage(mepCtx, re, proto);
                // just re-initialize the current handler message context since
                // that will pick up the now-changed message
                return PROTOCOL_EXCEPTION;
            }
            return OTHER_EXCEPTION;
        }

    }


    /*
      * start and end should be INclusive of the handlers that have already been
      * invoked on Handler.handleMessage or Handler.handleFault
      */
    private void callCloseHandlers(int start, int end,
                                   Direction direction) {
        int i = start;

        if (direction == Direction.OUT) {
            for (; i <= end; i++) {
                try {
                    switchContext(direction, i);
                    Handler handler = (Handler) handlers.get(i);
                    if (log.isDebugEnabled()) {
                        log.debug("Invoking close on: " + handler.getClass().getName());
                    }
                    handler.close(currentMC);
                    
                    // TODO when we close, are we done with the handler instance, and thus
                    // may call the PreDestroy annotated method?  I don't think so, especially
                    // if we've cached the handler list somewhere.
                } catch (Exception e) {
                    if (log.isDebugEnabled()) {
                        log.debug("An Exception occurred while calling handler.close()");
                        log.debug("Exception: " + e.getClass().getName() + ":" + e.getMessage());
                    }
                }
            }
        } else { // IN case
            for (; i >= end; i--) {
                try {
                    switchContext(direction, i);
                    Handler handler = (Handler) handlers.get(i);
                    if (log.isDebugEnabled()) {
                        log.debug("Invoking close on: " + handler.getClass().getName());
                    }
                    handler.close(currentMC);
                    
                    // TODO when we close, are we done with the handler instance, and thus
                    // may call the PreDestroy annotated method?  I don't think so, especially
                    // if we've cached the handler list somewhere.
                } catch (Exception e) {
                    if (log.isDebugEnabled()) {
                        log.debug("An Exception occurred while calling handler.close()");
                        log.debug("Exception: " + e.getClass().getName() + ":" + e.getMessage());
                    }
                }
            }
        }
    }

    /*
     * processFault is available for a server to use when the endpoint
      * throws an exception or a client when it gets a fault response message
      *
      * In both cases, all of the handlers have run successfully in the
      * opposite direction as this call to callHandleFault, and thus
      * should be closed.
      */
    public void processFault(MEPContext mepCtx, Direction direction) {

        // direction.IN = client
        // direction.OUT = server
        if (handlers.size() == 0)
            return;

        this.mepCtx = mepCtx;
		sortChain();
        initContext(direction);
		currentMC.put(javax.xml.ws.handler.MessageContext.MESSAGE_OUTBOUND_PROPERTY, (direction == Direction.OUT));

        try {
            if (direction == Direction.OUT) {
                callGenericHandleFault(0, handlers.size() - 1, direction);
            } else { // IN case
                callGenericHandleFault(handlers.size() - 1, 0, direction);
            }
        } catch (RuntimeException re) {
            // TODO: log it
            throw re;
        } finally {
            // we can close all the Handlers in reverse order
            if (direction == Direction.OUT) {
                initContext(Direction.IN);
                callCloseHandlers(0, handlers.size() - 1, Direction.OUT);
            } else { // IN case
                initContext(Direction.IN);
                callCloseHandlers(handlers.size() - 1, 0, Direction.IN);
            }
        }
    }


    /*
      * The callGenericHandleFault caller is responsible for closing any invoked
      * Handlers.  We don't know how far the Handler.handleMessage calls got
      * before a failure may have occurred.
      *
      * Regardless of the Handler.handleFault result, the flow is the same (9.3.2.2)
      */
    private void callGenericHandleFault(int start, int end,
                                        Direction direction) throws RuntimeException {

        int i = start;
        
        // we may be starting in the middle of the list, and therefore may need to switch contexts
        switchContext(direction, i);

        if (direction == Direction.OUT) {
            for (; i <= end; i++) {
                Handler handler = (Handler) handlers.get(i);
                if (log.isDebugEnabled()) {
                    log.debug("Invoking handleFault on: " + handler.getClass().getName());
                }
                boolean success = handler.handleFault(currentMC);

                if (!success)
                    break;
                switchContext(direction, i + 1);
            }
        } else { // IN case
            for (; i >= end; i--) {
                Handler handler = (Handler) handlers.get(i);
                if (log.isDebugEnabled()) {
                    log.debug("Invoking handleFault on: " + handler.getClass().getName());
                }
                boolean success = handler.handleFault(currentMC);

                if (!success)
                    break;
                switchContext(direction, i - 1);
            }
        }
    }


    public static void convertToFaultMessage(MEPContext mepCtx, Exception e, Protocol protocol) {

        // need to check if message is already a fault message or not,
        // probably by way of a flag (isFault) in the MessageContext or Message
        if (log.isDebugEnabled()) {
            log.debug("Creating a fault Message object for the exception: " + e.getClass().getName());
        }
           
        try {
            /* TODO TODO TODO
             * There has GOT to be a better way to do this.
             */
            if (protocol == Protocol.soap11 || protocol == Protocol.soap12) {
                String protocolNS = (protocol == Protocol.soap11) ?
                        SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE :
                        SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE;

                // The following set of instructions is used to avoid 
                // some unimplemented methods in the Axis2 SAAJ implementation
                XMLFault xmlFault = MethodMarshallerUtils.createXMLFaultFromSystemException(e);
                javax.xml.soap.MessageFactory mf = SAAJFactory.createMessageFactory(protocolNS);
                SOAPMessage message = mf.createMessage();
                SOAPBody body = message.getSOAPBody();
                SOAPFault soapFault = XMLFaultUtils.createSAAJFault(xmlFault, body);

                // TODO something is wrong here.  The message should be a response message, not
                // a request message.  I don't see how to change that.  (see the debugger...)
                // TODO probably also need to turn on message.WRITE_XML_DECLARATION
                MessageFactory msgFactory = (MessageFactory) FactoryRegistry.getFactory(MessageFactory.class);
                Message msg = msgFactory.createFrom(message);
                mepCtx.setMessage(msg);

            } else {
                throw ExceptionFactory.makeWebServiceException("We only support SOAP11 and SOAP12 for JAXWS handlers");
            }

        } catch (Exception ex) {
            throw ExceptionFactory.makeWebServiceException(ex);
        }

    }


    private void initContext(Direction direction) {
        soapMC = MessageContextFactory.createSoapMessageContext(mepCtx.getMessageContext());
        logicalMC = MessageContextFactory.createLogicalMessageContext(mepCtx.getMessageContext());
        if (direction == Direction.OUT) {
            // logical context, then SOAP
            if ((logicalLength == 0) && (handlers.size() > 0)) // we only have soap handlers
                currentMC = soapMC; //MessageContextFactory.createSoapMessageContext(mepCtx.getMessageContext());
            else
                currentMC = logicalMC; //MessageContextFactory.createLogicalMessageContext(mepCtx.getMessageContext());
        } else {
            // SOAP context, then logical
            if ((logicalLength == handlers.size()) && (handlers.size() > 0)) // we only have logical handlers
                currentMC = logicalMC; //MessageContextFactory.createLogicalMessageContext(mepCtx.getMessageContext());
            else
                currentMC = soapMC; //MessageContextFactory.createSoapMessageContext(mepCtx.getMessageContext());
        }
    }

    private void switchContext(Direction direction, int index) {

        if ((logicalLength == handlers.size()) || (logicalLength == 0))
            return; // all handlers must be the same type, so no context switch

        if (((direction == Direction.OUT) && (index == logicalLength))
                || ((direction == Direction.IN) && (index == (logicalLength - 1)))) {
            //if (currentMC.getClass().isAssignableFrom(LogicalMessageContext.class))
            if (currentMC == logicalMC)  // object check, not .equals()
                currentMC = soapMC; //MessageContextFactory.createSoapMessageContext(mepCtx.getMessageContext());
            else
                currentMC = logicalMC; //MessageContextFactory.createLogicalMessageContext(mepCtx.getMessageContext());
        }
    }

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?