| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.axis2.engine; |
| |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.soap.SOAPHeader; |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.Constants; |
| import org.apache.axis2.addressing.AddressingHelper; |
| import org.apache.axis2.addressing.EndpointReference; |
| import org.apache.axis2.context.ConfigurationContext; |
| import org.apache.axis2.context.MessageContext; |
| import org.apache.axis2.context.OperationContext; |
| import org.apache.axis2.context.ServiceContext; |
| import org.apache.axis2.context.ServiceGroupContext; |
| import org.apache.axis2.context.SessionContext; |
| import org.apache.axis2.description.AxisOperation; |
| import org.apache.axis2.description.AxisService; |
| import org.apache.axis2.description.AxisServiceGroup; |
| import org.apache.axis2.description.Parameter; |
| import org.apache.axis2.description.WSDL2Constants; |
| import org.apache.axis2.i18n.Messages; |
| import org.apache.axis2.transport.RequestResponseTransport; |
| import org.apache.axis2.transport.TransportListener; |
| import org.apache.axis2.transport.http.HTTPConstants; |
| import org.apache.axis2.util.JavaUtils; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import javax.xml.namespace.QName; |
| import javax.servlet.http.HttpServletResponse; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| public class DispatchPhase extends Phase { |
| private static final Log log = LogFactory.getLog(DispatchPhase.class); |
| |
| public DispatchPhase() { |
| } |
| |
| public DispatchPhase(String phaseName) { |
| super(phaseName); |
| } |
| |
| |
| private Boolean getDisableAck(MessageContext msgContext) throws AxisFault { |
| |
| // We should send an early ack to the transport whever possible, but some modules need |
| // to use the backchannel, so we need to check if they have disabled this code. |
| Boolean disableAck = (Boolean) msgContext.getProperty(Constants.Configuration.DISABLE_RESPONSE_ACK); |
| if(disableAck == null) { |
| disableAck = (Boolean) (msgContext.getAxisService() != null ? msgContext.getAxisService().getParameterValue(Constants.Configuration.DISABLE_RESPONSE_ACK) : null); |
| } |
| |
| return disableAck; |
| } |
| |
| public void checkPostConditions(MessageContext msgContext) throws AxisFault { |
| EndpointReference toEPR = msgContext.getTo(); |
| |
| if (msgContext.getAxisService() == null) { |
| AxisFault fault = new AxisFault(Messages.getMessage("servicenotfoundforepr", |
| ((toEPR != null) ? toEPR.getAddress() : ""))); |
| fault.setFaultCode(org.apache.axis2.namespace.Constants.FAULT_CLIENT); |
| Integer not_found = HttpServletResponse.SC_NOT_FOUND; |
| msgContext.setProperty(Constants.HTTP_RESPONSE_STATE, not_found.toString()); |
| throw fault; |
| } |
| |
| AxisService service = msgContext.getAxisService(); |
| AxisOperation operation = msgContext.getAxisOperation(); |
| |
| // If operation is an excluded operation, throw an exception. |
| // This code is needed to enable exclude operations for static WSDL files. |
| // Without this code, if one specifies excludeOperations in services.xml |
| // file and a static WSDL is used that contains the operation, |
| // the operation would succeed. |
| if (operation != null |
| && service.isExcludedOperation(operation.getName().getLocalPart())) { |
| AxisFault fault = new AxisFault(Messages.getMessage("operationnotfoundforepr2", |
| ((toEPR != null) ? toEPR.getAddress() |
| : ""), msgContext.getWSAAction())); |
| fault.setFaultCode(org.apache.axis2.namespace.Constants.FAULT_CLIENT); |
| throw fault; |
| } |
| |
| // If we're configured to do so, check the service for a single op... |
| if (operation == null && |
| JavaUtils.isTrue(service.getParameterValue(AxisService.SUPPORT_SINGLE_OP))) { |
| Iterator<AxisOperation> ops = service.getOperations(); |
| // If there's exactly one, that's the one we want. If there's more, forget it. |
| if (ops.hasNext()) { |
| operation = (AxisOperation)ops.next(); |
| if (ops.hasNext()) { |
| operation = null; |
| } |
| } |
| msgContext.setAxisOperation(operation); |
| } |
| |
| // If we still don't have an operation, fault. |
| if (operation == null) { |
| AxisFault fault = new AxisFault(Messages.getMessage("operationnotfoundforepr2", |
| ((toEPR != null) ? toEPR.getAddress() |
| : ""), msgContext.getWSAAction())); |
| fault.setFaultCode(org.apache.axis2.namespace.Constants.FAULT_CLIENT); |
| throw fault; |
| } |
| |
| validateTransport(msgContext); |
| |
| validateBindings(msgContext); |
| |
| loadContexts(service, msgContext); |
| |
| if (msgContext.getOperationContext() == null) { |
| throw new AxisFault(Messages.getMessage("cannotBeNullOperationContext")); |
| } |
| |
| if (msgContext.getServiceContext() == null) { |
| throw new AxisFault(Messages.getMessage("cannotBeNullServiceContext")); |
| } |
| |
| // TODO - review this |
| if ((msgContext.getAxisOperation() == null) && (msgContext.getOperationContext() != null)) { |
| msgContext.setAxisOperation(msgContext.getOperationContext().getAxisOperation()); |
| } |
| |
| if ((msgContext.getAxisService() == null) && (msgContext.getServiceContext() != null)) { |
| msgContext.setAxisService(msgContext.getServiceContext().getAxisService()); |
| } |
| |
| // We should send an early ack to the transport whever possible, but some modules need |
| // to use the backchannel, so we need to check if they have disabled this code. |
| String mepString = msgContext.getAxisOperation().getMessageExchangePattern(); |
| |
| if (isOneway(mepString)) { |
| Object requestResponseTransport = msgContext.getProperty(RequestResponseTransport.TRANSPORT_CONTROL); |
| if (requestResponseTransport != null) { |
| |
| Boolean disableAck = getDisableAck(msgContext); |
| if (disableAck == null || disableAck.booleanValue() == false) { |
| ((RequestResponseTransport) requestResponseTransport).acknowledgeMessage(msgContext); |
| } |
| } |
| } else if (AddressingHelper.isReplyRedirected(msgContext) && AddressingHelper.isFaultRedirected(msgContext)) { |
| |
| |
| if (mepString.equals(WSDL2Constants.MEP_URI_IN_OUT) |
| || mepString.equals(WSDL2Constants.MEP_URI_IN_OUT) |
| || mepString.equals(WSDL2Constants.MEP_URI_IN_OUT)) { |
| // OR, if 2 way operation but the response is intended to not use the response channel of a 2-way transport |
| // then we don't need to keep the transport waiting. |
| |
| Object requestResponseTransport = msgContext.getProperty(RequestResponseTransport.TRANSPORT_CONTROL); |
| if (requestResponseTransport != null) { |
| |
| // We should send an early ack to the transport whever possible, but some modules need |
| // to use the backchannel, so we need to check if they have disabled this code. |
| Boolean disableAck = getDisableAck(msgContext); |
| |
| if (disableAck == null || disableAck.booleanValue() == false) { |
| ((RequestResponseTransport) requestResponseTransport).acknowledgeMessage(msgContext); |
| } |
| |
| } |
| } |
| } |
| |
| |
| ArrayList operationChain = msgContext.getAxisOperation().getRemainingPhasesInFlow(); |
| msgContext.setExecutionChain((ArrayList) operationChain.clone()); |
| } |
| |
| private void loadContexts(AxisService service, MessageContext msgContext) throws AxisFault { |
| String scope = service == null ? null : service.getScope(); |
| ServiceContext serviceContext = msgContext.getServiceContext(); |
| |
| if ((msgContext.getOperationContext() != null) |
| && (serviceContext != null)) { |
| msgContext.setServiceGroupContextId( |
| ((ServiceGroupContext)serviceContext.getParent()).getId()); |
| return; |
| } |
| if (Constants.SCOPE_TRANSPORT_SESSION.equals(scope)) { |
| fillContextsFromSessionContext(msgContext); |
| } else if (Constants.SCOPE_SOAP_SESSION.equals(scope)) { |
| extractServiceGroupContextId(msgContext); |
| } |
| |
| AxisOperation axisOperation = msgContext.getAxisOperation(); |
| // if (axisOperation == null) { |
| // return; |
| // } |
| OperationContext operationContext = |
| axisOperation.findForExistingOperationContext(msgContext); |
| |
| if (operationContext != null) { |
| // register operation context and message context |
| // axisOperation.registerOperationContext(msgContext, operationContext); |
| axisOperation.registerMessageContext(msgContext, operationContext); |
| |
| serviceContext = (ServiceContext) operationContext.getParent(); |
| ServiceGroupContext serviceGroupContext = |
| (ServiceGroupContext) serviceContext.getParent(); |
| |
| msgContext.setServiceContext(serviceContext); |
| msgContext.setServiceGroupContext(serviceGroupContext); |
| msgContext.setServiceGroupContextId(serviceGroupContext.getId()); |
| } else { // 2. if null, create new opCtxt |
| if (serviceContext == null) { |
| // fill the service group context and service context info |
| msgContext.getConfigurationContext(). |
| fillServiceContextAndServiceGroupContext(msgContext); |
| serviceContext = msgContext.getServiceContext(); |
| } |
| operationContext = serviceContext.createOperationContext(axisOperation); |
| axisOperation.registerMessageContext(msgContext, operationContext); |
| } |
| |
| serviceContext.setMyEPR(msgContext.getTo()); |
| } |
| |
| /** |
| * To check whether the incoming request has come in valid transport , simply the transports |
| * that service author wants to expose |
| * |
| * @param msgctx the current MessageContext |
| * @throws AxisFault in case of error |
| */ |
| private void validateTransport(MessageContext msgctx) throws AxisFault { |
| AxisService service = msgctx.getAxisService(); |
| if (service.isEnableAllTransports()) { |
| return; |
| } else { |
| List trs = service.getExposedTransports(); |
| String incomingTrs = msgctx.getIncomingTransportName(); |
| |
| //local transport is a special case, it need not be exposed. |
| if (Constants.TRANSPORT_LOCAL.equals(incomingTrs)) { |
| return; |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Incoming transport: " + incomingTrs + "; allowed transports: " + trs); |
| } |
| |
| for (int i = 0; i < trs.size(); i++) { |
| String tr = (String) trs.get(i); |
| if (incomingTrs != null && incomingTrs.equals(tr)) { |
| return; |
| } |
| } |
| } |
| EndpointReference toEPR = msgctx.getTo(); |
| throw new AxisFault(Messages.getMessage("servicenotfoundforepr", |
| ((toEPR != null) ? toEPR.getAddress() : ""))); |
| } |
| |
| /** |
| * To check whether the incoming request has come in valid binding , we check whether service |
| * author has disabled any binding using parameters |
| * <code>org.apache.axis2.Constants.Configuration.DISABLE_SOAP12</code> |
| * <code>org.apache.axis2.Constants.Configuration.DISABLE_SOAP11</code> |
| * <code>org.apache.axis2.Constants.Configuration.DISABLE_REST</code> |
| * @param service msgctx the current MessageContext |
| * @throws AxisFault in case of error |
| */ |
| private void validateBindings(MessageContext msgctx) throws AxisFault { |
| |
| AxisService service = msgctx.getAxisService(); |
| |
| if (msgctx.isDoingREST()) { |
| |
| boolean disableREST = false; |
| Parameter disableRESTParameter = service |
| .getParameter(org.apache.axis2.Constants.Configuration.DISABLE_REST); |
| if (disableRESTParameter != null |
| && JavaUtils.isTrueExplicitly(disableRESTParameter.getValue())) { |
| disableREST = true; |
| } |
| |
| if (disableREST) { |
| throw new AxisFault(Messages.getMessage("bindingDisabled","Http")); |
| } |
| } else if (msgctx.isSOAP11()) { |
| |
| boolean disableSOAP11 = false; |
| Parameter disableSOAP11Parameter = service |
| .getParameter(org.apache.axis2.Constants.Configuration.DISABLE_SOAP11); |
| if (disableSOAP11Parameter != null |
| && JavaUtils.isTrueExplicitly(disableSOAP11Parameter.getValue())) { |
| disableSOAP11 = true; |
| } |
| |
| if (disableSOAP11) { |
| throw new AxisFault(Messages.getMessage("bindingDisabled","SOAP11")); |
| } |
| } else { |
| |
| boolean disableSOAP12 = false; |
| Parameter disableSOAP12Parameter = service |
| .getParameter(org.apache.axis2.Constants.Configuration.DISABLE_SOAP12); |
| if (disableSOAP12Parameter != null |
| && JavaUtils |
| .isTrueExplicitly(disableSOAP12Parameter.getValue())) { |
| disableSOAP12 = true; |
| } |
| |
| if(disableSOAP12) { |
| throw new AxisFault(Messages.getMessage("bindingDisabled","SOAP12")); |
| } |
| } |
| } |
| |
| private void fillContextsFromSessionContext(MessageContext msgContext) throws AxisFault { |
| AxisService service = msgContext.getAxisService(); |
| if (service == null) { |
| throw new AxisFault(Messages.getMessage("unabletofindservice")); |
| } |
| SessionContext sessionContext = msgContext.getSessionContext(); |
| if (sessionContext == null) { |
| TransportListener listener = msgContext.getTransportIn().getReceiver(); |
| sessionContext = listener.getSessionContext(msgContext); |
| if (sessionContext == null) { |
| createAndFillContexts(service, msgContext, sessionContext); |
| return; |
| } |
| } |
| String serviceGroupName = msgContext.getAxisServiceGroup().getServiceGroupName(); |
| ServiceGroupContext serviceGroupContext = |
| sessionContext.getServiceGroupContext(serviceGroupName); |
| if (serviceGroupContext != null) { |
| //setting service group context |
| msgContext.setServiceGroupContext(serviceGroupContext); |
| // setting Service context |
| msgContext.setServiceContext(serviceGroupContext.getServiceContext(service)); |
| } else { |
| createAndFillContexts(service, msgContext, sessionContext); |
| } |
| ServiceContext serviceContext = sessionContext.getServiceContext(service); |
| //found the serviceContext from session context , so adding that into msgContext |
| if (serviceContext != null) { |
| msgContext.setServiceContext(serviceContext); |
| serviceContext.setProperty(HTTPConstants.COOKIE_STRING, sessionContext.getCookieID()); |
| } |
| } |
| |
| private void createAndFillContexts(AxisService service, |
| MessageContext msgContext, |
| SessionContext sessionContext) throws AxisFault { |
| ServiceGroupContext serviceGroupContext; |
| AxisServiceGroup axisServiceGroup = service.getAxisServiceGroup(); |
| ConfigurationContext configCtx = msgContext.getConfigurationContext(); |
| serviceGroupContext = configCtx.createServiceGroupContext(axisServiceGroup); |
| |
| msgContext.setServiceGroupContext(serviceGroupContext); |
| ServiceContext serviceContext = serviceGroupContext.getServiceContext(service); |
| msgContext.setServiceContext(serviceContext); |
| if (sessionContext != null) { |
| sessionContext.addServiceContext(serviceContext); |
| sessionContext.addServiceGroupContext(serviceGroupContext); |
| } |
| } |
| |
| private static final QName SERVICE_GROUP_QNAME = new QName(Constants.AXIS2_NAMESPACE_URI, |
| Constants.SERVICE_GROUP_ID, |
| Constants.AXIS2_NAMESPACE_PREFIX); |
| |
| private void extractServiceGroupContextId(MessageContext msgContext) throws AxisFault { |
| SOAPHeader soapHeader = msgContext.getEnvelope().getHeader(); |
| if (soapHeader != null) { |
| OMElement serviceGroupId = soapHeader.getFirstChildWithName(SERVICE_GROUP_QNAME); |
| if (serviceGroupId != null) { |
| msgContext.setServiceGroupContextId(serviceGroupId.getText()); |
| } |
| } |
| } |
| |
| /** |
| * This method will determine if the MEP indicated by 'mepString' specifies |
| * a oneway MEP. |
| */ |
| @SuppressWarnings("deprecation") |
| boolean isOneway(String mepString) { |
| return (mepString.equals(WSDL2Constants.MEP_URI_IN_ONLY) |
| || mepString.equals(WSDL2Constants.MEP_URI_IN_ONLY) |
| || mepString.equals(WSDL2Constants.MEP_URI_IN_ONLY)); |
| } |
| |
| } |