messagecontextbuilder.java

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

JAVA
625
字号
            (outboundToEPR != null && !outboundToEPR.hasAnonymousAddress())) {
            faultContext.setMessageID(UUIDGenerator.getUUID());
            faultContext.setReplyTo(new EndpointReference(AddressingConstants.Final.WSA_NONE_URI));
        }

        // do Target Resolution
        TargetResolver targetResolver = faultContext.getConfigurationContext()
                .getAxisConfiguration().getTargetResolverChain();
        if (targetResolver != null) {
            targetResolver.resolveTarget(faultContext);
        }

        // Ensure transport settings match the scheme for the To EPR
        setupCorrectTransportOut(faultContext);

        SOAPEnvelope envelope = createFaultEnvelope(processingContext, e);
        faultContext.setEnvelope(envelope);

        //get the SOAP headers, user is trying to send in the fault
        // TODO: Rationalize this mechanism a bit - maybe headers should live in the fault?
        List soapHeadersList =
                (List) processingContext.getProperty(SOAPConstants.HEADER_LOCAL_NAME);
        if (soapHeadersList != null) {
            SOAPHeader soapHeaderElement = envelope.getHeader();
            for (int i = 0; i < soapHeadersList.size(); i++) {
                OMElement soapHeaderBlock = (OMElement) soapHeadersList.get(i);
                soapHeaderElement.addChild(soapHeaderBlock);
            }
        }

        // TODO: Transport-specific stuff in here?  Why?  Is there a better way?
        // now add HTTP Headers
        faultContext.setProperty(HTTPConstants.HTTP_HEADERS,
                                 processingContext.getProperty(HTTPConstants.HTTP_HEADERS));

        return faultContext;
    }

    /**
     * Ensure that if the scheme of the To EPR for the response is different than the
     * transport used for the request that the correct TransportOut is available
     */
    private static void setupCorrectTransportOut(MessageContext context) throws AxisFault {
        // Determine that we have the correct transport available.
        TransportOutDescription transportOut = context.getTransportOut();

        try {
            EndpointReference responseEPR = context.getTo();
            if (context.isServerSide() && responseEPR != null) {
                if (!responseEPR.hasAnonymousAddress() && !responseEPR.hasNoneAddress()) {
                    URI uri = new URI(responseEPR.getAddress());
                    String scheme = uri.getScheme();
                    if (!transportOut.getName().equals(scheme)) {
                        ConfigurationContext configurationContext =
                                context.getConfigurationContext();
                        transportOut = configurationContext.getAxisConfiguration()
                                .getTransportOut(scheme);
                        if (transportOut == null) {
                            throw new AxisFault("Can not find the transport sender : " + scheme);
                        }
                        context.setTransportOut(transportOut);
                    }
                    if (context.getOperationContext() != null) {
                        context.getOperationContext().setProperty(
                                Constants.DIFFERENT_EPR, Constants.VALUE_TRUE);
                    }
                }
            }
        } catch (URISyntaxException urise) {
            throw AxisFault.makeFault(urise);
        }
    }

    /**
     * Information to create the SOAPFault can be extracted from different places.
     * 1. Those information may have been put in to the message context by some handler. When someone
     * is putting like that, he must make sure the SOAPElements he is putting must be from the
     * correct SOAP Version.
     * 2. SOAPProcessingException is flexible enough to carry information about the fault. For example
     * it has an attribute to store the fault code. The fault reason can be extracted from the
     * message of the exception. I opted to put the stacktrace under the detail element.
     * eg : <Detail>
     * <Exception> stack trace goes here </Exception>
     * <Detail>
     * <p/>
     * If those information can not be extracted from any of the above places, I default the soap
     * fault values to following.
     * <Fault>
     * <Code>
     * <Value>env:Receiver</Value>
     * </Code>
     * <Reason>
     * <Text>unknown</Text>
     * </Reason>
     * <Role/>
     * <Node/>
     * <Detail/>
     * </Fault>
     * <p/>
     * -- EC
     *
     * @param context
     * @param e
     */
    private static SOAPEnvelope createFaultEnvelope(MessageContext context, Throwable e) {
        SOAPEnvelope envelope;

        if (context.isSOAP11()) {
            envelope = OMAbstractFactory.getSOAP11Factory().getDefaultFaultEnvelope();
        } else {
            // Following will make SOAP 1.2 as the default, too.
            envelope = OMAbstractFactory.getSOAP12Factory().getDefaultFaultEnvelope();
        }
        SOAPFault fault = envelope.getBody().getFault();

        SOAPProcessingException soapException = null;
        AxisFault axisFault = null;

        if (e == null) return envelope;

        if (e instanceof AxisFault) {
            axisFault = (AxisFault) e;
        } else if (e.getCause() instanceof AxisFault) {
            axisFault = (AxisFault) e.getCause();
        }

        if (axisFault != null) {
            Iterator iter = axisFault.headerIterator();
            while (iter.hasNext()) {
                SOAPHeaderBlock header = (SOAPHeaderBlock) iter.next();
                envelope.getHeader().addChild(header);
            }
        }

        if (e instanceof SOAPProcessingException) {
            soapException = (SOAPProcessingException) e;
        } else if (axisFault != null) {
            if (axisFault.getCause() instanceof SOAPProcessingException) {
                soapException = (SOAPProcessingException) axisFault.getCause();
            }
        }

        // user can set the fault information to the message context or to the AxisFault itself.
        // whatever user sets to the message context, supercedes eerything.
        
        Object faultCode = context.getProperty(SOAP12Constants.SOAP_FAULT_CODE_LOCAL_NAME);
        String soapFaultCode = "";

        if (faultCode != null) {
            fault.setCode((SOAPFaultCode) faultCode);
        } else if (soapException != null) {
            soapFaultCode = soapException.getFaultCode();
        } else if (axisFault != null) {
            if (axisFault.getFaultCodeElement() != null) {
                fault.setCode(axisFault.getFaultCodeElement());
            } else {
                QName faultCodeQName = axisFault.getFaultCode();
                if (faultCodeQName != null) {
                    if (faultCodeQName.getLocalPart().indexOf(":") == -1) {
                        String prefix = faultCodeQName.getPrefix();
                        String uri = faultCodeQName.getNamespaceURI();
                        prefix = prefix == null || "".equals(prefix) ?
                                fault.getNamespace().getPrefix() : prefix;
                        uri = uri == null || "" .equals(uri) ?
                                fault.getNamespace().getNamespaceURI() : uri;
                        soapFaultCode = prefix + ":" + faultCodeQName.getLocalPart();
                        fault.declareNamespace(uri, prefix);
                    } else {
                        soapFaultCode = faultCodeQName.getLocalPart();
                    }
                }
            }
        }

        // defaulting to fault code Receiver, if no message is available
        if (faultCode == null && context.getEnvelope() != null) {
            soapFaultCode = ("".equals(soapFaultCode) || (soapFaultCode == null))
                    ? SOAP12Constants.SOAP_DEFAULT_NAMESPACE_PREFIX + ":" +
                        context.getEnvelope().getVersion().getReceiverFaultCode().getLocalPart()
                    : soapFaultCode;
        }
        
        if (faultCode == null) {
            if (context.isSOAP11()) {
                fault.getCode().setText(soapFaultCode);
            } else {
                fault.getCode().getValue().setText(soapFaultCode);
            }
        }

        SOAPFaultReason faultReason = (SOAPFaultReason)context.getProperty(
                                            SOAP12Constants.SOAP_FAULT_REASON_LOCAL_NAME);

        if (faultReason == null && axisFault != null) {
            faultReason = axisFault.getFaultReasonElement();
        }
        if (faultReason != null) {
            fault.setReason(faultReason);
        } else {
            String message = "";
            if (soapException != null) {
                message = soapException.getMessage();
            } else if (axisFault != null) {
                // Couldn't find FaultReasonElement, try reason string
                message = axisFault.getReason();
            }

            if (message == null || "".equals(message)) {
                message = getFaultReasonFromException(e, context);
            }

            if (message == null || "".equals(message)) message = "unknown";

            if (context.isSOAP11()) {
                fault.getReason().setText(message);
            } else {
                fault.getReason().getFirstSOAPText().setLang("en-US");
                fault.getReason().getFirstSOAPText().setText(message);
            }
        }

        Object faultRole = context.getProperty(SOAP12Constants.SOAP_FAULT_ROLE_LOCAL_NAME);
        if (faultRole != null) {
            fault.getRole().setText((String) faultRole);
        } else if (axisFault != null) {
            if (axisFault.getFaultRoleElement() != null) {
                fault.setRole(axisFault.getFaultRoleElement());
            }
        }

        Object faultNode = context.getProperty(SOAP12Constants.SOAP_FAULT_NODE_LOCAL_NAME);
        if (faultNode != null) {
            fault.getNode().setText((String) faultNode);
        } else if (axisFault != null) {
            if (axisFault.getFaultNodeElement() != null) {
                fault.setNode(axisFault.getFaultNodeElement());
            }
        }

        // Allow handlers to override the sendStacktraceDetailsWithFaults setting from the Configuration to allow
        // WS-* protocol faults to not include the exception.
        boolean sendStacktraceDetailsWithFaults = false;
        OperationContext oc = context.getOperationContext();
        Object flagFromContext = null;
        if (oc != null) {
            flagFromContext = context.getOperationContext()
                    .getProperty(Constants.Configuration.SEND_STACKTRACE_DETAILS_WITH_FAULTS);
        }
        if (flagFromContext != null) {
            sendStacktraceDetailsWithFaults = JavaUtils.isTrue(flagFromContext);
        } else {
            Parameter param = context.getParameter(
                    Constants.Configuration.SEND_STACKTRACE_DETAILS_WITH_FAULTS);
            if (param != null) {
                sendStacktraceDetailsWithFaults = JavaUtils.isTrue(param.getValue());
            }
        }

        Object faultDetail = context.getProperty(SOAP12Constants.SOAP_FAULT_DETAIL_LOCAL_NAME);
        if (faultDetail != null) {
            fault.setDetail((SOAPFaultDetail) faultDetail);
        } else if (axisFault != null) {
            if (axisFault.getFaultDetailElement() != null) {
                fault.setDetail(axisFault.getFaultDetailElement());
            } else {
                OMElement detail = axisFault.getDetail();
                if (detail != null) {
                    fault.getDetail().addDetailEntry(detail);
                } else if (sendStacktraceDetailsWithFaults) {
                    fault.setException(axisFault);
                }
            }
        } else if (fault.getException() == null && sendStacktraceDetailsWithFaults) {
            if (e instanceof Exception) {
                fault.setException((Exception) e);
            } else {
                fault.setException(new Exception(e));
            }
        }

        return envelope;
    }

    /**
     * By the time the exception comes here it can be wrapped by so many levels. This will crip down
     * to the root cause and get the initial error depending on the property
     *
     * @param e
     */
    private static String getFaultReasonFromException(Throwable e, MessageContext context) {
        Throwable throwable = e;
        Parameter param = context.getParameter(
                Constants.Configuration.DRILL_DOWN_TO_ROOT_CAUSE_FOR_FAULT_REASON);
        boolean drillDownToRootCauseForFaultReason =
                param != null && ((String) param.getValue()).equalsIgnoreCase("true");
        if (drillDownToRootCauseForFaultReason) {
            while (throwable.getCause() != null) {
                throwable = throwable.getCause();
            }
        }
        return throwable.getMessage();
    }

    private static String getSenderFaultCode(OMNamespace soapNamespace) {
        return SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapNamespace.getNamespaceURI())
                ? SOAP12Constants.SOAP_DEFAULT_NAMESPACE_PREFIX + ":"
                + SOAP12Constants.FAULT_CODE_SENDER
                : SOAP12Constants.SOAP_DEFAULT_NAMESPACE_PREFIX + ":"
                + SOAP11Constants.FAULT_CODE_SENDER;
    }
}

⌨️ 快捷键说明

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