Package org.apache.axis2.engine

Source Code of org.apache.axis2.engine.AxisEngine

/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed 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.axis2.AxisFault;
import org.apache.axis2.SOAPFaultException;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.OperationDescription;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.om.OMAbstractFactory;
import org.apache.axis2.soap.SOAP11Constants;
import org.apache.axis2.soap.SOAP12Constants;
import org.apache.axis2.soap.SOAPEnvelope;
import org.apache.axis2.soap.SOAPFault;
import org.apache.axis2.soap.SOAPFaultCode;
import org.apache.axis2.soap.SOAPFaultDetail;
import org.apache.axis2.soap.SOAPFaultReason;
import org.apache.axis2.soap.impl.llom.SOAPProcessingException;
import org.apache.axis2.transport.TransportSender;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

/**
* There is one engine for the Server and the Client. the send() and receive()
* Methods are the basic operations the Sync, Async messageing are build on top.
*/
public class AxisEngine {
    /**
     * Field log
     */
    private Log log = LogFactory.getLog(getClass());
    private ConfigurationContext engineContext;

    /**
     * Constructor AxisEngine
     */
    public AxisEngine(ConfigurationContext engineContext) {
        log.info("Axis Engine Started");
        this.engineContext = engineContext;
    }

    /**
     * This methods represents the outflow of the Axis, this could be either at the server side or the client side.
     * Here the <code>ExecutionChain</code> is created using the Phases. The Handlers at the each Phases is ordered in
     * deployment time by the deployment module
     *
     * @param context
     * @throws AxisFault
     * @see MessageContext
     * @see ExecutionChain
     * @see Phase
     * @see Handler
     */
    public void send(MessageContext msgContext) throws AxisFault {
        verifyContextBuilt(msgContext);

        //find and invoke the Phases       
        OperationContext operationContext = msgContext.getOperationContext();
        ArrayList phases =
            operationContext.getAxisOperation().getPhasesOutFlow();
        if (msgContext.isPaused()) {
            // the message has paused, so rerun them from the position they stoped. The Handler
            //who paused the Message will be the first one to run
            //resume fixed, global precalulated phases
            resumeInvocationPhases(phases, msgContext);
        } else {
            invokePhases(phases, msgContext);
        }

        if (!msgContext.isPaused()) {
            //write the Message to the Wire
            TransportOutDescription transportOut = msgContext.getTransportOut();
            TransportSender sender = transportOut.getSender();
            sender.invoke(msgContext);
        }
    }

    /**
     * This methods represents the inflow of the Axis, this could be either at the server side or the client side.
     * Here the <code>ExecutionChain</code> is created using the Phases. The Handlers at the each Phases is ordered in
     * deployment time by the deployment module
     *
     * @param context
     * @throws AxisFault
     * @see MessageContext
     * @see ExecutionChain
     * @see Phase
     * @see Handler
     */
    public void receive(MessageContext msgContext) throws AxisFault {

        ConfigurationContext sysCtx = msgContext.getSystemContext();
        OperationDescription operationDescription = null;
        ArrayList preCalculatedPhases =
            sysCtx
                .getAxisConfiguration()
                .getInPhasesUptoAndIncludingPostDispatch();
        ArrayList operationSpecificPhases = null;

        if (msgContext.isPaused()) {
            // the message has paused, so rerun them from the position they stoped. The Handler
            //who paused the Message will be the first one to run
            //resume fixed, global precalulated phases
            resumeInvocationPhases(preCalculatedPhases, msgContext);
            verifyContextBuilt(msgContext);
            //resume operation specific phases
            OperationContext operationContext =
                msgContext.getOperationContext();
            operationDescription = operationContext.getAxisOperation();
            operationSpecificPhases =
                operationDescription.getRemainingPhasesInFlow();
            resumeInvocationPhases(operationSpecificPhases, msgContext);
        } else {
            invokePhases(preCalculatedPhases, msgContext);
            verifyContextBuilt(msgContext);
            OperationContext operationContext =
                msgContext.getOperationContext();
            operationDescription = operationContext.getAxisOperation();
            operationSpecificPhases =
                operationDescription.getRemainingPhasesInFlow();
            invokePhases(operationSpecificPhases, msgContext);
        }

        if (msgContext.isServerSide() && !msgContext.isPaused()) {
            // invoke the Message Receivers
            MessageReceiver receiver =
                operationDescription.getMessageReceiver();
            receiver.receive(msgContext);
        }
    }

    /**
     * This Method Send the SOAP Fault to a Other SOAP Node
     *
     * @param msgContext
     * @throws AxisFault
     */
    public void sendFault(MessageContext msgContext) throws AxisFault {
        OperationContext opContext = msgContext.getOperationContext();
        //find and execute the Fault Out Flow Handlers
        if (opContext != null) {
            OperationDescription axisOperation = opContext.getAxisOperation();
            ArrayList phases = axisOperation.getPhasesOutFaultFlow();
            if (msgContext.isPaused()) {
                resumeInvocationPhases(phases, msgContext);
            } else {
                invokePhases(phases, msgContext);
            }
        }
        //it is possible that Operation Context is Null as the error occered before the
        //Dispatcher. We do not run Handlers in that case

        if (!msgContext.isPaused()) {
            //Actually send the SOAP Fault
            TransportSender sender = msgContext.getTransportOut().getSender();
            sender.invoke(msgContext);
        }
    }

    /**
     * This is invoked when a SOAP Fault is received from a Other SOAP Node
     *
     * @param msgContext
     * @throws AxisFault
     */
    public void receiveFault(MessageContext msgContext) throws AxisFault {

        OperationContext opContext = msgContext.getOperationContext();
        if (opContext == null) {
            //If we do not have a OperationContext that means this may be a incoming
            //Dual Channel response. So try to dispatch the Service
            ConfigurationContext sysCtx = msgContext.getSystemContext();
            ArrayList phases =
                sysCtx
                    .getAxisConfiguration()
                    .getInPhasesUptoAndIncludingPostDispatch();

            if (msgContext.isPaused()) {
                resumeInvocationPhases(phases, msgContext);
            } else {
                invokePhases(phases, msgContext);
            }
            verifyContextBuilt(msgContext);
        }
        opContext = msgContext.getOperationContext();
        //find and execute the Fault In Flow Handlers
        if (opContext != null) {
            OperationDescription axisOperation = opContext.getAxisOperation();
            ArrayList phases = axisOperation.getPhasesInFaultFlow();
            if (msgContext.isPaused()) {
                resumeInvocationPhases(phases, msgContext);
            } else {
                invokePhases(phases, msgContext);
            }
        }
    }

    /**
     * If error occurs at inflow or the out flow this method will call to handle the error. But if the
     * execution reach this method twice, means the sending the error handling failed an in that case the
     * this method just log the error and exit</p>
     *
     * @param context
     * @param e
     * @throws AxisFault
     */
    public MessageContext createFaultMessageContext(
        MessageContext processingContext,
        Throwable e)
        throws AxisFault {
        if (processingContext.isProcessingFault()) {
            //We get the error file processing the fault. nothing we can do
            throw new AxisFault(
                Messages.getMessage("errorwhileProcessingFault"));
        }

        MessageContext faultContext =
            new MessageContext(
                engineContext,
                processingContext.getSessionContext(),
                processingContext.getTransportIn(),
                processingContext.getTransportOut());

        faultContext.setProcessingFault(true);
        if (processingContext.getFaultTo() != null) {
            faultContext.setFaultTo(processingContext.getFaultTo());
        } else {
            Object writer =
                processingContext.getProperty(MessageContext.TRANSPORT_OUT);
            if (writer != null) {
                faultContext.setProperty(MessageContext.TRANSPORT_OUT, writer);
            } else {
                throw new AxisFault(Messages.getMessage("nowhereToSendError"));
            }
        }

        faultContext.setOperationContext(processingContext.getOperationContext());
        faultContext.setProcessingFault(true);
        faultContext.setServerSide(true);
        SOAPEnvelope envelope = null;

         faultContext.setProperty(HTTPConstants.HTTPOutTransportInfo,
                processingContext.getProperty(HTTPConstants.HTTPOutTransportInfo));

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

        // TODO do we need to set old Headers back?

        //            body.addFault(new AxisFault(e.getMessage(), e));
        //        body.getFault().setException(new AxisFault(e));
        extractFaultInformationFromMessageContext(
            processingContext,
            envelope.getBody().getFault(),
            e);

        faultContext.setEnvelope(envelope);
        faultContext.setProperty(HTTPConstants.HTTPOutTransportInfo, processingContext.getProperty(HTTPConstants.HTTPOutTransportInfo));
        return faultContext;
    }

    /**
     * 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 fault
     * @param e
     */
    private void extractFaultInformationFromMessageContext(
        MessageContext context,
        SOAPFault fault,
        Throwable e) {
        SOAPFaultException soapException = null;
        String soapNamespaceURI = "";

        // get the current SOAP version
        if (!context.isSOAP11()) {
            // defaulting to SOAP 1.2
            soapNamespaceURI = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
        } else {
            soapNamespaceURI = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
        }

        if (e instanceof SOAPProcessingException) {
            soapException = (SOAPProcessingException) e;
        } else if (e instanceof AxisFault) {
            if (e.getCause() instanceof SOAPProcessingException) {
                soapException = (SOAPProcessingException) e.getCause();
            } else  {
                soapException = (SOAPFaultException) e;
            }
        } else {
            // we have recd an instance of just the Exception class
        }

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

            // defaulting to fault code Sender, if no message is available
            soapFaultCode =
                ("".equals(soapFaultCode) || soapFaultCode == null)
                    ? getSenderFaultCode(soapNamespaceURI)
                    : soapFaultCode;
            fault.getCode().getValue().setText(soapFaultCode);
        }

        Object faultReason =
            context.getProperty(SOAP12Constants.SOAP_FAULT_REASON_LOCAL_NAME);
        String message = "";
        if (faultReason != null) {
            fault.setReason((SOAPFaultReason) faultReason);
        } else if (soapException != null) {
            message = soapException.getMessage();

            // defaulting to reason, unknown, if no reason is available
            message =
                ("".equals(message) || message == null) ? "unknown" : message;
            fault.getReason().getSOAPText().setText(message);
        }

        Object faultRole =
            context.getProperty(SOAP12Constants.SOAP_FAULT_ROLE_LOCAL_NAME);
        if (faultRole != null) {
            fault.getRole().setText((String) faultRole);
        } else {
            // TODO : get the role of this server and assign it here
            fault.getRole().setText("http://myAxisServer/role/default");
        }

        Object faultNode =
            context.getProperty(SOAP12Constants.SOAP_FAULT_NODE_LOCAL_NAME);
        if (faultNode != null) {
            fault.getNode().setText((String) faultNode);
        } else {
            // TODO : get the node of this server and assign it here
            fault.getNode().setText("http://myAxisServer/role/default");

        }

        Object faultDetail =
            context.getProperty(SOAP12Constants.SOAP_FAULT_DETAIL_LOCAL_NAME);
        if (faultDetail != null) {
            fault.setDetail((SOAPFaultDetail) faultDetail);
        } else if (fault.getException() == null) {
            if(e instanceof Exception){
                fault.setException((Exception)e);
            }else{
                fault.setException(new Exception(e));
            }

        }
    }

    private void verifyContextBuilt(MessageContext msgctx) throws AxisFault {
        if (msgctx.getSystemContext() == null) {
            throw new AxisFault(
                Messages.getMessage("cannotBeNullConfigurationContext"));
        }
        if (msgctx.getOperationContext() == null) {
            throw new AxisFault(
                Messages.getMessage("cannotBeNullOperationContext"));
        }
        if (msgctx.getServiceContext() == null) {
            throw new AxisFault(
                Messages.getMessage("cannotBeNullServiceContext"));
        }
    }

    private void invokePhases(ArrayList phases, MessageContext msgctx)
        throws AxisFault {
        int count = phases.size();
        for (int i = 0;(i < count && !msgctx.isPaused()); i++) {
            Phase phase = (Phase) phases.get(i);
            phase.invoke(msgctx);
        }
    }

    public void resumeInvocationPhases(ArrayList phases, MessageContext msgctx)
        throws AxisFault {
        msgctx.setPausedFalse();
        int count = phases.size();
        boolean foundMatch = false;

        for (int i = 0; i < count && !msgctx.isPaused(); i++) {
            Phase phase = (Phase) phases.get(i);
            if (phase.getPhaseName().equals(msgctx.getPausedPhaseName())) {
                foundMatch = true;
                phase.invokeStartFromHandler(
                    msgctx.getPausedHandlerName(),
                    msgctx);
            } else {
                if (foundMatch) {
                    phase.invoke(msgctx);
                }

            }
        }
    }

    /* --------------------------------------------------------------------------------------------*/
    /* -----------------   Methods related to storage ----------------------------------------------*/
    /**
     * Stores an object in the underlying storage
     *
     * @param context The relevant engine context
     * @param obj     the object to be stored
     * @return the storage key
     */
    public Object store(ConfigurationContext context, Object obj) {
        return context.getStorage().put(obj);
    }

    /**
     * retrieves an object from the underlying storage
     *
     * @param context
     * @param key
     * @return
     */
    public Object retrieve(ConfigurationContext context, Object key) {
        return context.getStorage().get(key);
    }

    /**
     * removes an object from the underlying storage
     *
     * @param context
     * @param key
     * @return the object removed
     */
    public Object remove(ConfigurationContext context, Object key) {
        return context.getStorage().remove(key);
    }

    /**
     * Clears the underlying storage
     *
     * @param context
     * @return
     */
    public boolean clearStorage(ConfigurationContext context) {
        return context.getStorage().clean();
    }



    private String getSenderFaultCode(String soapNamespace) {
        return SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(
            soapNamespace)
            ? SOAP12Constants.FAULT_CODE_SENDER
            : SOAP11Constants.FAULT_CODE_SENDER;
    }

    private String getReceiverFaultCode(String soapNamespace) {
        return SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(
            soapNamespace)
            ? SOAP12Constants.FAULT_CODE_RECEIVER
            : SOAP11Constants.FAULT_CODE_RECEIVER;
    }

    /**
     * To serilze the entier context heirarachy to a given location from top to bottom
     * @throws AxisFault
     */
    public synchronized void   serialize() {
        try {
             String serailzeLocaion =".";
            //output location
            Parameter parameter = engineContext.getAxisConfiguration().getParameter("seralizeLocation");
            if (parameter !=null) {
                serailzeLocaion = ((String)parameter.getValue()).trim();
            }
            FileOutputStream fileOut = new FileOutputStream(new File(serailzeLocaion,"Axis2.obj"));
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(engineContext);
        } catch (FileNotFoundException e) {
            //todo has to be improved
        } catch (IOException e) {
             //todo has to be improved
        }

    }

}
TOP

Related Classes of org.apache.axis2.engine.AxisEngine

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.