/*
 * 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.context;

import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.util.DetachableInputStream;
import org.apache.axiom.om.util.UUIDGenerator;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.Constants.Configuration;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.RelatesTo;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.externalize.ActivateUtils;
import org.apache.axis2.context.externalize.ExternalizeConstants;
import org.apache.axis2.context.externalize.MessageExternalizeUtils;
import org.apache.axis2.context.externalize.SafeObjectInputStream;
import org.apache.axis2.context.externalize.SafeObjectOutputStream;
import org.apache.axis2.context.externalize.SafeSerializable;
import org.apache.axis2.description.AxisBinding;
import org.apache.axis2.description.AxisBindingMessage;
import org.apache.axis2.description.AxisBindingOperation;
import org.apache.axis2.description.AxisEndpoint;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.HandlerDescription;
import org.apache.axis2.description.ModuleConfiguration;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportInDescription;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.AxisError;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.engine.Phase;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.LoggingControl;
import org.apache.axis2.util.MetaDataEntry;
import org.apache.axis2.util.SelfManagedDataHolder;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;

import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * <p>Axis2 states are held in two information models, called description hierarchy
 *  and context hierarchy. Description hierarchy hold deployment configuration 
 *  and it's values does not change unless deployment configuration change 
 *  occurs where Context hierarchy hold run time information. Both hierarchies 
 *  consists four levels, Global, Service Group, Operation and Message. Please 
 *  look at "Information Model" section  of "Axis2 Architecture Guide" for more 
 *  information.</p>
 *  <p>MessageContext hold run time information about one Message invocation. It 
 *  hold reference to OperationContext, ServiceGroupContext, and Configuration 
 *  Context tied with current message. For an example if you need accesses to other 
 *  messages of the current invocation, you can get to them via OperationContext. 
 *  Addition to class attributes define in Message context, message context stores 
 *  the information as name value pairs. Those name value pairs,and class attributes 
 *  tweak the execution behavior of message context and some of them can be find in 
 *  org.apache.axis2.Constants class. (TODO we should provide list of supported 
 *  options). You may set them at any level of context hierarchy and they will 
 *  affect invocations related to their child elements. </p>
 */
public class MessageContext extends AbstractContext 
    implements Externalizable, SafeSerializable {

    /*
     * setup for logging
     */
    private static final Log log = LogFactory.getLog(MessageContext.class);

    /**
     * @serial An ID which can be used to correlate operations on a single
     * message in the log files, irrespective of thread switches, persistence,
     * etc.
     */
    private String logCorrelationID = null;

    /**
     * This string will be used to hold a form of the logCorrelationID that
     * is more suitable for output than its generic form.
     */
    private transient String logCorrelationIDString = null;

    private static final String myClassName = "MessageContext";

    /**
     * @serial The serialization version ID tracks the version of the class.
     * If a class definition changes, then the serialization/externalization
     * of the class is affected. If a change to the class is made which is
     * not compatible with the serialization/externalization of the class,
     * then the serialization version ID should be updated.
     * Refer to the "serialVer" utility to compute a serialization
     * version ID.
     */
    private static final long serialVersionUID = -7753637088257391858L;

    /**
     * @serial Tracks the revision level of a class to identify changes to the
     * class definition that are compatible to serialization/externalization.
     * If a class definition changes, then the serialization/externalization
     * of the class is affected.
     * Refer to the writeExternal() and readExternal() methods.
     */
    // supported revision levels, add a new level to manage compatible changes
    private static final int REVISION_2 = 2;
    // current revision level of this object
    private static final int revisionID = REVISION_2;


    /**
     * A place to store the current MessageContext
     */
    public static ThreadLocal<MessageContext> currentMessageContext = new ThreadLocal<MessageContext>();

    public static MessageContext getCurrentMessageContext() {
        return (MessageContext) currentMessageContext.get();
    }

    public static void setCurrentMessageContext(MessageContext ctx) {
        currentMessageContext.set(ctx);
    }


    /**
     * @serial Options on the message
     */
    protected Options options;

    public final static int IN_FLOW = 1;
    public final static int IN_FAULT_FLOW = 3;

    public final static int OUT_FLOW = 2;
    public final static int OUT_FAULT_FLOW = 4;

    public static final String REMOTE_ADDR = "REMOTE_ADDR";
    public static final String TRANSPORT_ADDR = "TRANSPORT_ADDR";
    public static final String TRANSPORT_HEADERS = "TRANSPORT_HEADERS";


    /**
     * message attachments
     * NOTE: Serialization of message attachments is handled as part of the
     * overall message serialization.  If this needs to change, then
     * investigate having the Attachment class implement the
     * java.io.Externalizable interface.
     */
    public transient Attachments attachments;

    /**
     * Field TRANSPORT_OUT
     */
    public static final String TRANSPORT_OUT = "TRANSPORT_OUT";

    /**
     * Field TRANSPORT_IN
     */
    public static final String TRANSPORT_IN = "TRANSPORT_IN";

    /**
     * Field CHARACTER_SET_ENCODING
     */
    public static final String CHARACTER_SET_ENCODING = "CHARACTER_SET_ENCODING";

    /**
     * Field UTF_8. This is the 'utf-8' value for CHARACTER_SET_ENCODING
     * property.
     */
    public static final String UTF_8 = "UTF-8";

    /**
     * Field UTF_16. This is the 'utf-16' value for CHARACTER_SET_ENCODING
     * property.
     */
    public static final String UTF_16 = "utf-16";

    /**
     * Field TRANSPORT_SUCCEED
     */
    public static final String TRANSPORT_SUCCEED = "TRANSPORT_SUCCEED";

    /**
     * Field DEFAULT_CHAR_SET_ENCODING. This is the default value for
     * CHARACTER_SET_ENCODING property.
     */
    public static final String DEFAULT_CHAR_SET_ENCODING = UTF_8;

    /**
     * @serial The direction flow in use to figure out which path the message is in
     * (send or receive)
     */
    public int FLOW = IN_FLOW;

    /**
     * To invoke fireAndforget method we have to hand over transport sending logic to a thread
     * other wise user has to wait till it get transport response (in the case of HTTP its HTTP
     * 202)
     */
    public static final String TRANSPORT_NON_BLOCKING = "transportNonBlocking";

    /**
     * This property allows someone (e.g. RM) to disable an async callback from
     * being invoked if a fault occurs during message transmission.  If this is
     * not set, it can be assumed that the fault will be delivered via
     * Callback.onError(...).
     */
    public static final String DISABLE_ASYNC_CALLBACK_ON_TRANSPORT_ERROR =
            "disableTransmissionErrorCallback";

    /**
     * @serial processingFault
     */
    private boolean processingFault;

    /**
     * @serial paused
     */
    private boolean paused;

    /**
     * @serial outputWritten
     */
    public boolean outputWritten;

    /**
     * @serial newThreadRequired
     */
    private boolean newThreadRequired;

    /**
     * @serial isSOAP11
     */
    private boolean isSOAP11 = true;

    /**
     * @serial The chain of Handlers/Phases for processing this message
     */
    private ArrayList<Handler> executionChain;

    /**
     * @serial The chain of executed Handlers/Phases from processing
     */
    private LinkedList<Handler> executedPhases;

    /**
     * @serial Flag to indicate if we are doing REST
     */
    private boolean doingREST;

    /**
     * @serial Flag to indicate if we are doing MTOM
     */
    private boolean doingMTOM;

    /**
     * @serial Flag to indicate if we are doing SWA
     */
    private boolean doingSwA;

    /**
     * AxisMessage associated with this message context
     */
    private transient AxisMessage axisMessage;

    /**
     * AxisOperation associated with this message context
     */
    private transient AxisOperation axisOperation;

    /**
     * AxisService
     */
    private transient AxisService axisService;

    /**
     * AxisServiceGroup
     * <p/>
     * Note the service group can be set independently of the service
     * so the service might not match up with this serviceGroup
     */
    private transient AxisServiceGroup axisServiceGroup;

    /**
     * ConfigurationContext
     */
    private transient ConfigurationContext configurationContext;

    /**
     * @serial Index into the executuion chain of the currently executing handler
     */
    private int currentHandlerIndex;

    /**
     * @serial Index into the current Phase of the currently executing handler (if any)
     */
    private int currentPhaseIndex;

    /**
     * If we're processing this MC due to flowComplete() being called in the case
     * of an Exception, this will hold the Exception which caused the problem.
     */
    private Exception failureReason;

    /**
     * @serial SOAP envelope
     */
    private SOAPEnvelope envelope;

    /**
     * @serial OperationContext
     */
    private OperationContext operationContext;

    /**
     * @serial responseWritten
     */
    private boolean responseWritten;

    /**
     * @serial serverSide
     */
    private boolean serverSide;

    /**
     * @serial ServiceContext
     */
    private ServiceContext serviceContext;

    /**
     * @serial service context ID
     */
    private String serviceContextID;

    /**
     * @serial service group context
     */
    private ServiceGroupContext serviceGroupContext;

    /**
     * @serial Holds a key to retrieve the correct ServiceGroupContext.
     */
    private String serviceGroupContextId;

    /**
     * @serial sessionContext
     */
    private SessionContext sessionContext;


    /**
     * transport out description
     */
    private transient TransportOutDescription transportOut;

    /**
     * transport in description
     */
    private transient TransportInDescription transportIn;


    /**
     * @serial incoming transport name
     */
    //The value will be set by the transport receiver and there will be validation for the transport
    //at the dispatch phase (its post condition)
    private String incomingTransportName;


    /*
     * SelfManagedData will hold message-specific data set by handlers
     * Note that this list is not explicitly saved by the MessageContext, but
     * rather through the SelfManagedDataManager interface implemented by handlers
     */
    private transient LinkedHashMap<String, Object> selfManagedDataMap = null;

    //-------------------------------------------------------------------------
    // MetaData for data to be restored in activate() after readExternal()
    //-------------------------------------------------------------------------

    /**
     * Indicates whether the message context has been reconstituted
     * and needs to have its object references reconciled
     */
    private transient boolean needsToBeReconciled = false;

    /**
     * selfManagedDataHandlerCount is a count of the number of handlers
     * that actually saved data during serialization
     */
    private transient int selfManagedDataHandlerCount = 0;

    /**
     * SelfManagedData cannot be restored until the configurationContext
     * is available, so we have to hold the data from readExternal until
     * activate is called.
     */
    private transient ArrayList<SelfManagedDataHolder> selfManagedDataListHolder = null;

    /**
     * The ordered list of metadata for handlers/phases
     * used during re-constitution of the message context
     */
    private transient ArrayList<MetaDataEntry> metaExecutionChain = null;

    /**
     * The ordered list of metadata for executed phases
     * used during re-constitution of the message context
     */
    private transient LinkedList<MetaDataEntry> metaExecuted = null;

    /**
     * Index into the executuion chain of the currently executing handler
     */
    private transient int metaHandlerIndex = 0;

    /**
     * Index into the current Phase of the currently executing handler (if any)
     */
    private transient int metaPhaseIndex = 0;

    /**
     * The AxisOperation metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaAxisOperation = null;

    /**
     * The AxisService metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaAxisService = null;

    /**
     * The AxisServiceGroup metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaAxisServiceGroup = null;

    /**
     * The TransportOutDescription metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaTransportOut = null;

    /**
     * The TransportInDescription metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaTransportIn = null;

    /**
     * The AxisMessage metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaAxisMessage = null;

    /**
     * Indicates whether this message context has an
     * AxisMessage object associated with it that needs to
     * be reconciled
     */
    private transient boolean reconcileAxisMessage = false;

    /**
     * Indicates whether the executed phase list
     * was reset before the restored list has been reconciled
     */
    private transient boolean executedPhasesReset = false;

    //----------------------------------------------------------------
    // end MetaData section
    //----------------------------------------------------------------


    /**
     * Constructor
     */
    public MessageContext() {
        super(null);
        options = new Options();
    }

    /**
     * Constructor has package access
     *
     * @param configContext the associated ConfigurationContext
     */
    MessageContext(ConfigurationContext configContext) {
        this();
        setConfigurationContext(configContext);
    }

    public String toString() {
        return getLogIDString();
    }

    /**
     * Get a "raw" version of the logCorrelationID.  The logCorrelationID
     * is guaranteed to be unique and may be persisted along with the rest
     * of the message context.
     *
     * @return A string that can be output to a log file as an identifier
     *         for this MessageContext.  It is suitable for matching related log
     *         entries.
     */
    public String getLogCorrelationID() {
        if (logCorrelationID == null) {
            logCorrelationID = UUIDGenerator.getUUID();
        }
        return logCorrelationID;
    }

    /**
     * Get a formatted version of the logCorrelationID.
     *
     * @return A string that can be output to a log file as an identifier
     *         for this MessageContext.  It is suitable for matching related log
     *         entries.
     */
    public String getLogIDString() {
        if (logCorrelationIDString == null) {
            logCorrelationIDString = "[MessageContext: logID=" + getLogCorrelationID() + "]";
        }
        return logCorrelationIDString;
    }


    /**
     * Pause the execution of the current handler chain
     */
    public void pause() {
        paused = true;
    }

    public AxisOperation getAxisOperation() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getAxisOperation");
        }
        return axisOperation;
    }

    public AxisService getAxisService() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getAxisService");
        }
        return axisService;
    }

    /*
     * <P>
     * Note the service group can be set independently of the service
     * so the service might not match up with this serviceGroup
    */
    public AxisServiceGroup getAxisServiceGroup() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getAxisServiceGroup");
        }
        return axisServiceGroup;
    }

    public ConfigurationContext getConfigurationContext() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getConfigurationContext");
        }
        return configurationContext;
    }

    public int getCurrentHandlerIndex() {
        return currentHandlerIndex;
    }

    public int getCurrentPhaseIndex() {
        return currentPhaseIndex;
    }

    /**
     * @return Returns SOAPEnvelope.
     */
    public SOAPEnvelope getEnvelope() {
        return envelope;
    }

    public ArrayList<Handler> getExecutionChain() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getExecutionChain");
        }
        return executionChain;
    }

    /**
     * Add a Phase to the collection of executed phases for the path.
     * Phases will be inserted in a LIFO data structure.
     *
     * @param phase The phase to add to the list.
     */
    public void addExecutedPhase(Handler phase) {
        if (executedPhases == null) {
            executedPhases = new LinkedList<Handler>();
        }
        executedPhases.addFirst(phase);
    }

    /**
     * Remove the first Phase in the collection of executed phases
     */
    public void removeFirstExecutedPhase() {
        if (executedPhases != null) {
            executedPhases.removeFirst();
        }
    }

    /**
     * Get an iterator over the executed phase list.
     *
     * @return An Iterator over the LIFO data structure.
     */
    public Iterator<Handler> getExecutedPhases() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getExecutedPhases");
        }
        if (executedPhases == null) {
            executedPhases = new LinkedList<Handler>();
        }
        return executedPhases.iterator();
    }

    /**
     * Reset the list of executed phases.
     * This is needed because the OutInAxisOperation currently invokes
     * receive() even when a fault occurs, and we will have already executed
     * the flowComplete on those before receiveFault() is called.
     */
    public void resetExecutedPhases() {
        executedPhasesReset = true;
        executedPhases = new LinkedList<Handler>();
    }

    /**
     * @return Returns EndpointReference.
     */
    public EndpointReference getFaultTo() {
        return options.getFaultTo();
    }

    /**
     * @return Returns EndpointReference.
     */
    public EndpointReference getFrom() {
        return options.getFrom();
    }

    /**
     * @return Returns message id.
     */
    public String getMessageID() {
        return options.getMessageId();
    }

    /**
     * Retrieves both module specific configuration parameters as well as other
     * parameters. The order of search is as follows:
     * <ol>
     * <li> Search in module configurations inside corresponding operation
     * description if its there </li>
     * <li> Search in corresponding operation if its there </li>
     * <li> Search in module configurations inside corresponding service
     * description if its there </li>
     * <li> Next search in Corresponding Service description if its there </li>
     * <li> Next search in module configurations inside axisConfiguration </li>
     * <li> Search in AxisConfiguration for parameters </li>
     * <li> Next get the corresponding module and search for the parameters
     * </li>
     * <li> Search in HandlerDescription for the parameter </li>
     * </ol>
     * <p/> and the way of specifying module configuration is as follows
     * <moduleConfig name="addressing"> <parameter name="addressingPara"
     * >N/A</parameter> </moduleConfig>
     *
     * @param key        :
     *                   Parameter Name
     * @param moduleName :
     *                   Name of the module
     * @param handler    <code>HandlerDescription</code>
     * @return Parameter <code>Parameter</code>
     */
    public Parameter getModuleParameter(String key, String moduleName,
                                        HandlerDescription handler) {
        Parameter param;
        ModuleConfiguration moduleConfig;

        AxisOperation opDesc = getAxisOperation();

        if (opDesc != null) {

            moduleConfig = opDesc.getModuleConfig(moduleName);

            if (moduleConfig != null) {
                param = moduleConfig.getParameter(key);

                if (param != null) {
                    return param;
                } else {
                    param = opDesc.getParameter(key);

                    if (param != null) {
                        return param;
                    }
                }
            }
        }

        AxisService axisService = getAxisService();

        if (axisService != null) {

            moduleConfig = axisService.getModuleConfig(moduleName);

            if (moduleConfig != null) {
                param = moduleConfig.getParameter(key);

                if (param != null) {
                    return param;
                } else {
                    param = axisService.getParameter(key);

                    if (param != null) {
                        return param;
                    }
                }
            }
        }

        AxisServiceGroup axisServiceDesc = getAxisServiceGroup();

        if (axisServiceDesc != null) {

            moduleConfig = axisServiceDesc.getModuleConfig(moduleName);

            if (moduleConfig != null) {
                param = moduleConfig.getParameter(key);

                if (param != null) {
                    return param;
                } else {
                    param = axisServiceDesc.getParameter(key);

                    if (param != null) {
                        return param;
                    }
                }
            }
        }

        AxisConfiguration baseConfig = configurationContext.getAxisConfiguration();

        moduleConfig = baseConfig.getModuleConfig(moduleName);

        if (moduleConfig != null) {
            param = moduleConfig.getParameter(key);

            if (param != null) {
                return param;
            } else {
                param = baseConfig.getParameter(key);

                if (param != null) {
                    return param;
                }
            }
        }

        AxisModule module = baseConfig.getModule(moduleName);

        if (module != null) {
            param = module.getParameter(key);

            if (param != null) {
                return param;
            }
        }

        param = handler.getParameter(key);

        return param;
    }

    public OperationContext getOperationContext() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getOperationContext");
        }
        return operationContext;
    }

    /**
     * Retrieves configuration descriptor parameters at any level. The order of
     * search is as follows:
     * <ol>
     * <li> Search in message description if it exists </li>
     * <li> If parameter is not found or if axisMessage is null, search in
     * AxisOperation </li>
     * <li> If parameter is not found or if operationContext is null, search in
     * AxisService </li>
     * <li> If parameter is not found or if axisService is null, search in
     * AxisConfiguration </li>
     * </ol>
     *
     * @param key name of desired parameter
     * @return Parameter <code>Parameter</code>
     */
    public Parameter getParameter(String key) {
        
        if( axisMessage != null ) {
            return axisMessage.getParameter(key);
        }
        
        if (axisOperation != null) {
            return axisOperation.getParameter(key);
        }

        if (axisService != null) {
            return axisService.getParameter(key);
        }

        if (axisServiceGroup != null) {
            return axisServiceGroup.getParameter(key);
        }

        if (configurationContext != null) {
            AxisConfiguration baseConfig = configurationContext
                    .getAxisConfiguration();
            return baseConfig.getParameter(key);
        }
        return null;
    }

    /**
     * Retrieves a property value. The order of search is as follows: search in
     * my own map and then look at my options. Does not search up the hierarchy.
     *
     * @param name name of the property to search for
     * @return the value of the property, or null if the property is not found
     */
    public Object getLocalProperty(String name) {
        return getLocalProperty(name, true);
    }
    public Object getLocalProperty(String name, boolean searchOptions) {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getProperty");
        }

        // search in my own options
        Object obj = super.getLocalProperty(name);
        if (obj != null) {
            return obj;
        }

        if (searchOptions) {
            obj = options.getProperty(name);
            if (obj != null) {
                return obj;
            }
        }

        // tough
        return null;
    }
    
    /**
     * Retrieves a property value. The order of search is as follows: search in
     * my own map and then look in my context hierarchy, and then in options. 
     * Since its possible
     * that the entire hierarchy is not present, I will start at whatever level
     * has been set.
     *
     * @param name name of the property to search for
     * @return the value of the property, or null if the property is not found
     */
    public Object getProperty(String name) {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getProperty");
        }

        // search in my own options
        Object obj = super.getProperty(name);
        if (obj != null) {
            return obj;
        }

        obj = options.getProperty(name);
        if (obj != null) {
            return obj;
        }

        // My own context hierarchy may not all be present. So look for whatever
        // nearest level is present and ask that to find the property.
        //
        // If the context is already an ancestor, it was checked during
        // the super.getProperty call.  In such cases, the second check 
        // is not performed.
        if (operationContext != null) {
            if (!isAncestor(operationContext)) {
                obj = operationContext.getProperty(name);
            }
        } else if (serviceContext != null) {
            if (!isAncestor(serviceContext)) {
                obj = serviceContext.getProperty(name);
            }
        } else if (serviceGroupContext != null) {
            if (!isAncestor(serviceGroupContext)) {
                obj =  serviceGroupContext.getProperty(name);
            }
        } else if (configurationContext != null) {
            if (!isAncestor(configurationContext)) {
                obj = configurationContext.getProperty(name);
            }
        }

        return obj;
    }

    /**
     * Check if a given property is true.  Will return false if the property
     * does not exist or is not an explicit "true" value.
     *
     * @param name name of the property to check
     * @return true if the property exists and is Boolean.TRUE, "true", 1, etc.
     */
    public boolean isPropertyTrue(String name) {
        return isPropertyTrue(name, false);
    }

    /**
     * Check if a given property is true.  Will return the passed default if the property
     * does not exist.
     *
     * @param name name of the property to check
     * @param defaultVal the default value if the property doesn't exist
     * @return true if the property exists and is Boolean.TRUE, "true", 1, etc.
     */
    public boolean isPropertyTrue(String name, boolean defaultVal) {
        return JavaUtils.isTrueExplicitly(getProperty(name), defaultVal);
    }
    
    /**
     * Retrieves all property values. The order of search is as follows: search in
     * my own options and then look in my context hierarchy. Since its possible
     * that the entire hierarchy is not present, it will start at whatever level
     * has been set and start there.
     * The returned map is unmodifiable, so any changes to the properties have
     * to be done by calling {@link #setProperty(String,Object)}. In addition,
     * any changes to the properties are not reflected on this map.
     *
     * @return An unmodifiable map containing the combination of all available
     *         properties or an empty map.
     */
    public Map<String, Object> getProperties() {
        final Map<String, Object> resultMap = new HashMap<String, Object>();

        // My own context hierarchy may not all be present. So look for whatever
        // nearest level is present and add the properties
        // We have to access the contexts in reverse order, in order to allow
        // a nearer context to overwrite values from a more distant context
        if (configurationContext != null) {
            resultMap.putAll(configurationContext.getProperties());
        }
        if (serviceGroupContext != null) {
            resultMap.putAll(serviceGroupContext.getProperties());
        }
        if (serviceContext != null) {
            resultMap.putAll(serviceContext.getProperties());
        }
        if (operationContext != null) {
            resultMap.putAll(operationContext.getProperties());
        }
        // and now add options
        resultMap.putAll(options.getProperties());
        return Collections.unmodifiableMap(resultMap);
    }

    /**
     * @return Returns RelatesTo array.
     */
    public RelatesTo[] getRelationships() {
        return options.getRelationships();
    }

    /**
     * Get any RelatesTos of a particular type associated with this MessageContext
     * TODO: Shouldn't this return a List?
     *
     * @param type the relationship type
     * @return Returns RelatesTo.
     */
    public RelatesTo getRelatesTo(String type) {
        return options.getRelatesTo(type);
    }

    /**
     * @return Returns RelatesTo.
     */
    public RelatesTo getRelatesTo() {
        return options.getRelatesTo();
    }

    /**
     * @return Returns EndpointReference.
     */
    public EndpointReference getReplyTo() {
        return options.getReplyTo();
    }

    /**
     * @return Returns ServiceContext.
     */
    public ServiceContext getServiceContext() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getServiceContext");
        }
        return serviceContext;
    }

    /**
     * @return Returns the serviceContextID.
     */
    public String getServiceContextID() {
        return serviceContextID;
    }

    public ServiceGroupContext getServiceGroupContext() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getServiceGroupContext");
        }
        return serviceGroupContext;
    }

    public String getServiceGroupContextId() {
        return serviceGroupContextId;
    }

    /**
     * @return Returns SessionContext.
     */
    public SessionContext getSessionContext() {
        return sessionContext;
    }

    public void setSessionContext(SessionContext sessionContext) {
        this.sessionContext = sessionContext;
    }


    /**
     * @return Returns soap action.
     */
    public String getSoapAction() {
        return options.getAction();
    }

    /**
     * @return Returns EndpointReference.
     */
    public EndpointReference getTo() {
        return options.getTo();
    }

    /**
     * @return Returns TransportInDescription.
     */
    public TransportInDescription getTransportIn() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getTransportIn");
        }
        return transportIn;
    }

    /**
     * @return Returns TransportOutDescription.
     */
    public TransportOutDescription getTransportOut() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getTransportOut");
        }
        return transportOut;
    }

    public String getWSAAction() {
        return options.getAction();
    }

    /**
     * @return Returns boolean.
     */
    public boolean isDoingMTOM() {
        return doingMTOM;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isDoingREST() {
        return doingREST;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isDoingSwA() {
        return doingSwA;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isNewThreadRequired() {
        return newThreadRequired;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isOutputWritten() {
        return outputWritten;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isPaused() {
        return paused;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isProcessingFault() {
        return processingFault;
    }

    /**
     * @return Returns boolean.
     */
    public boolean isResponseWritten() {
        return responseWritten;
    }

    public boolean isSOAP11() {
        return isSOAP11;
    }

    /**
     * @return inbound content length of 0
     */
    public long getInboundContentLength() throws IOException {
        // If there is an attachment map, the Attachments keep track
        // of the inbound content length.
        if (attachments != null) {
//            return attachments.getContentLength();
        } 
        
        // Otherwise the length is accumulated by the DetachableInputStream.
        DetachableInputStream dis = 
            (DetachableInputStream) getProperty(Constants.DETACHABLE_INPUT_STREAM);
        if (dis != null) {
            return dis.length();
        }
        return 0;
    }
    /**
     * @return Returns boolean.
     */
    public boolean isServerSide() {
        return serverSide;
    }

    public AxisMessage getAxisMessage() {
        if (reconcileAxisMessage) {
            if (LoggingControl.debugLoggingAllowed && log.isWarnEnabled()) {
                log.warn(this.getLogIDString() +
                    ":getAxisMessage(): ****WARNING**** MessageContext.activate(configurationContext) needs to be invoked.");
            }
        }

        return axisMessage;
    }

    public void setAxisMessage(AxisMessage axisMessage) {
        this.axisMessage = axisMessage;
    }

    public void setAxisOperation(AxisOperation axisOperation) {
        this.axisOperation = axisOperation;
    }

    public void setAxisService(AxisService axisService) {
        this.axisService = axisService;
        if (this.axisService != null) {
            this.axisServiceGroup = axisService.getAxisServiceGroup();
        } else {
            this.axisServiceGroup = null;
        }
    }

    /*
     * note setAxisServiceGroup() does not verify that the service is associated with the service group!
     */
    public void setAxisServiceGroup(AxisServiceGroup axisServiceGroup) {
        // need to set the axis service group object to null when necessary
        // for example, when extracting the message context object from
        // the object graph
        this.axisServiceGroup = axisServiceGroup;
    }

    /**
     * @param context
     */
    public void setConfigurationContext(ConfigurationContext context) {
        configurationContext = context;
    }

    public void setCurrentHandlerIndex(int currentHandlerIndex) {
        this.currentHandlerIndex = currentHandlerIndex;
    }

    public void setCurrentPhaseIndex(int currentPhaseIndex) {
        this.currentPhaseIndex = currentPhaseIndex;
    }

    /**
     * @param b
     */
    public void setDoingMTOM(boolean b) {
        doingMTOM = b;
    }

    /**
     * @param b
     */
    public void setDoingREST(boolean b) {
        doingREST = b;
    }

    /**
     * @param b
     */
    public void setDoingSwA(boolean b) {
        doingSwA = b;
    }

    /**
     * @param envelope
     */
    public void setEnvelope(SOAPEnvelope envelope) throws AxisFault {
        this.envelope = envelope;

        if (this.envelope != null) {
            String soapNamespaceURI = envelope.getNamespace().getNamespaceURI();

            if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI
                    .equals(soapNamespaceURI)) {
                isSOAP11 = false;
            } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI
                    .equals(soapNamespaceURI)) {
                isSOAP11 = true;
            } else {
                throw new AxisFault(
                        "Unknown SOAP Version. Current Axis handles only SOAP 1.1 and SOAP 1.2 messages");
            }
            // Inform the listeners of an attach envelope event
            if (getAxisService() != null) {
                getAxisService().attachEnvelopeEvent(this);
            }
        }
    }

    /**
     * Set the execution chain of Handler in this MessageContext. Doing this
     * causes the current handler/phase indexes to reset to 0, since we have new
     * Handlers to execute (this usually only happens at initialization and when
     * a fault occurs).
     *
     * @param executionChain
     */
    public void setExecutionChain(ArrayList<Handler> executionChain) {
        this.executionChain = executionChain;
        currentHandlerIndex = -1;
        currentPhaseIndex = 0;
    }

    /**
     * @param reference
     */
    public void setFaultTo(EndpointReference reference) {
        options.setFaultTo(reference);
    }

    /**
     * @param reference
     */
    public void setFrom(EndpointReference reference) {
        options.setFrom(reference);
    }

    /**
     * @param messageId
     */
    public void setMessageID(String messageId) {
        options.setMessageId(messageId);
    }

    /**
     * @param b
     */
    public void setNewThreadRequired(boolean b) {
        newThreadRequired = b;
    }

    /**
     * @param context The OperationContext
     */
    public void setOperationContext(OperationContext context) {
        // allow setting the fields to null
        // useful when extracting the messge context from the object graph
        operationContext = context;

        this.setParent(operationContext);

        if (operationContext != null) {
            if (serviceContext == null) {
                setServiceContext(operationContext.getServiceContext());
            } else {
                if (operationContext.getParent() != serviceContext) {
                    throw new AxisError("ServiceContext in OperationContext does not match !");
                }
            }

            this.setAxisOperation(operationContext.getAxisOperation());
        }
    }

    /**
     * @param b
     */
    public void setOutputWritten(boolean b) {
        outputWritten = b;
    }

    /**
     * @param b
     */
    public void setProcessingFault(boolean b) {
        processingFault = b;
    }

    /**
     * Add a RelatesTo
     *
     * @param reference RelatesTo describing how we relate to another message
     */
    public void addRelatesTo(RelatesTo reference) {
        options.addRelatesTo(reference);
    }

    /**
     * Set ReplyTo destination
     *
     * @param reference the ReplyTo EPR
     */
    public void setReplyTo(EndpointReference reference) {
        options.setReplyTo(reference);
    }

    /**
     * @param b
     */
    public void setResponseWritten(boolean b) {
        responseWritten = b;
    }

    /**
     * @param b
     */
    public void setServerSide(boolean b) {
        serverSide = b;
    }

    /**
     * @param context
     */
    public void setServiceContext(ServiceContext context) {

        // allow the service context to be set to null
        // this allows the message context object to be extraced from
        // the object graph

        serviceContext = context;

        if (serviceContext != null) {
            if ((operationContext != null)
                    && (operationContext.getParent() != context)) {
                throw new AxisError("ServiceContext and OperationContext.parent do not match!");
            }
            // setting configcontext using configuration context in service context
            if (configurationContext == null) {
                // setting configcontext
                configurationContext = context.getConfigurationContext();
            }
            if (serviceGroupContext == null) {
                // setting service group context
                serviceGroupContext = context.getServiceGroupContext();
            }
            AxisService axisService = context.getAxisService();
            this.setAxisService(axisService);
            
            // Inform the listeners of an attach event
            if (axisService != null) {
                axisService.attachServiceContextEvent(serviceContext, this);
            }
        }
    }

    /**
     * Sets the service context id.
     *
     * @param serviceContextID
     */
    public void setServiceContextID(String serviceContextID) {
        this.serviceContextID = serviceContextID;
    }

    public void setServiceGroupContext(ServiceGroupContext serviceGroupContext) {
        // allow the service group context to be set to null
        // this allows the message context object to be extraced from
        // the object graph

        this.serviceGroupContext = serviceGroupContext;

        if (this.serviceGroupContext != null) {
            this.axisServiceGroup = serviceGroupContext.getDescription();
        }
    }

    public void setServiceGroupContextId(String serviceGroupContextId) {
        this.serviceGroupContextId = serviceGroupContextId;
    }

    /**
     * @param soapAction
     */
    public void setSoapAction(String soapAction) {
        options.setAction(soapAction);
    }

    /**
     * @param to
     */
    public void setTo(EndpointReference to) {
        options.setTo(to);
    }

    /**
     * @param in
     */
    public void setTransportIn(TransportInDescription in) {
        this.transportIn = in;
    }

    /**
     * @param out
     */
    public void setTransportOut(TransportOutDescription out) {
        transportOut = out;
    }

    /**
     * setWSAAction
     */
    public void setWSAAction(String actionURI) {
        options.setAction(actionURI);
    }

    public void setWSAMessageId(String messageID) {
        options.setMessageId(messageID);
    }

    // to get the flow inwhich the execution chain below
    public int getFLOW() {
        return FLOW;
    }

    public void setFLOW(int FLOW) {
        this.FLOW = FLOW;
    }

    public Options getOptions() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getOptions");
        }
        return options;
    }

    /**
     * Set the options for myself. I make the given options my own options'
     * parent so that that becomes the default. That allows the user to override
     * specific options on a given message context and not affect the overall
     * options.
     *
     * @param options the options to set
     */
    public void setOptions(Options options) {
        this.options.setParent(options);
    }

    public String getIncomingTransportName() {
        return incomingTransportName;
    }

    public void setIncomingTransportName(String incomingTransportName) {
        this.incomingTransportName = incomingTransportName;
    }

    public void setRelationships(RelatesTo[] list) {
        options.setRelationships(list);
    }


    public Policy getEffectivePolicy() {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("getEffectivePolicy");
        }
        
        AxisBindingMessage bindingMessage = 
        	(AxisBindingMessage) getProperty(Constants.AXIS_BINDING_MESSAGE);
        
        // If AxisBindingMessage is not set, try to find the binding message from the AxisService
        if (bindingMessage == null) {
        	bindingMessage = findBindingMessage();
        }
        
        if (bindingMessage != null) {
            return bindingMessage.getEffectivePolicy();
        // If we can't find the AxisBindingMessage, then try the AxisMessage   
        } else if (axisMessage != null) {
        		return axisMessage.getEffectivePolicy();        		
        } else {
        		return null;
        }
    }
 
    private AxisBindingMessage findBindingMessage() {
    	if (axisService != null && axisOperation != null ) {
			if (axisService.getEndpointName() != null) {
				AxisEndpoint axisEndpoint = axisService
						.getEndpoint(axisService.getEndpointName());
				if (axisEndpoint != null) {
					AxisBinding axisBinding = axisEndpoint.getBinding();
                    AxisBindingOperation axisBindingOperation = (AxisBindingOperation) axisBinding
							.getChild(axisOperation.getName());

                    //If Binding Operation is not found, just return null
                    if (axisBindingOperation == null) {
                       return null;
                    }

                    String direction;
                    if (axisMessage != null) {
                        direction = axisMessage.getDirection();
                    } else {
                        if ((FLOW == IN_FLOW) || (FLOW == IN_FAULT_FLOW)) {
                            direction = WSDLConstants.WSDL_MESSAGE_DIRECTION_IN;
                        } else {
                            direction = WSDLConstants.WSDL_MESSAGE_DIRECTION_OUT;
                        }
                    }
					AxisBindingMessage axisBindingMessage;
					if (WSDLConstants.WSDL_MESSAGE_DIRECTION_IN
							.equals(direction)
							&& WSDLUtil
									.isInputPresentForMEP(axisOperation
											.getMessageExchangePattern())) {
						axisBindingMessage = (AxisBindingMessage) axisBindingOperation
								.getChild(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
						return axisBindingMessage;
						
					} else if (WSDLConstants.WSDL_MESSAGE_DIRECTION_OUT
							.equals(direction)
							&& WSDLUtil
									.isOutputPresentForMEP(axisOperation
											.getMessageExchangePattern())) {
						axisBindingMessage = (AxisBindingMessage) axisBindingOperation
								.getChild(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
						return axisBindingMessage;
					}
				}

			}
		}
    	return null;
    }


    public boolean isEngaged(String moduleName) {
        if (LoggingControl.debugLoggingAllowed) {
            checkActivateWarning("isEngaged");
        }
        boolean enegage;
        if (configurationContext != null) {
            AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();
            AxisModule module = axisConfig.getModule(moduleName);
            if (module == null) {
                return false;
            }
            enegage = axisConfig.isEngaged(module);
            if (enegage) {
                return true;
            }
            if (axisServiceGroup != null) {
                enegage = axisServiceGroup.isEngaged(module);
                if (enegage) {
                    return true;
                }
            }
            if (axisService != null) {
                enegage = axisService.isEngaged(module);
                if (enegage) {
                    return true;
                }
            }
            if (axisOperation != null) {
                enegage = axisOperation.isEngaged(module);
                if (enegage) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Gets the first child of the envelope, check if it is a soap:Body, which means there is no header.
     * We do this basically to make sure we don't parse and build the om tree of the whole envelope
     * looking for the soap header. If this method returns true, there still is no guarantee that there is
     * a soap:Header present, use getHeader() and also check for null on getHeader() to be absolutely sure.
     *
     * @return boolean
     * @deprecated The bonus you used to get from this is now built in to SOAPEnvelope.getHeader()
     */
    public boolean isHeaderPresent() {
        // If there's no envelope there can't be a header.
        if (this.envelope == null) {
            return false;
        }
        return (this.envelope.getHeader() != null);
    }

    /**
     * Setting of the attachments map should be performed at the receipt of a
     * message only. This method is only meant to be used by the Axis2
     * internals.
     *
     * @param attachments
     */
    public void setAttachmentMap(Attachments attachments) {
        this.attachments = attachments;
    }

    /**
     * You can directly access the attachment map of the message context from
     * here. Returned attachment map can be empty.
     *
     * @return attachment
     */
    public Attachments getAttachmentMap() {
        if (attachments == null) {
            attachments = new Attachments();
        }
        return attachments;
    }

    /**
     * Adds an attachment to the attachment Map of this message context. This
     * attachment gets serialised as a MIME attachment when sending the message
     * if SOAP with Attachments is enabled.
     *
     * @param contentID   :
     *                    will be the content ID of the MIME part (without the "cid:" prefix)
     * @param dataHandler
     */
    public void addAttachment(String contentID, DataHandler dataHandler) {
        if (attachments == null) {
            attachments = new Attachments();
        }
        attachments.addDataHandler(contentID, dataHandler);
    }

    /**
     * Adds an attachment to the attachment Map of this message context. This
     * attachment gets serialised as a MIME attachment when sending the message
     * if SOAP with Attachments is enabled. Content ID of the MIME part will be
     * auto generated by Axis2.
     *
     * @param dataHandler
     * @return the auto generated content ID of the MIME attachment
     */
    public String addAttachment(DataHandler dataHandler) {
        String contentID = UUIDGenerator.getUUID();
        addAttachment(contentID, dataHandler);
        return contentID;
    }

    /**
     * Access the DataHandler of the attachment contained in the map corresponding to the given
     * content ID. Returns "NULL" if a attachment cannot be found by the given content ID.
     *
     * @param contentID :
     *                  Content ID of the MIME attachment (without the "cid:" prefix)
     * @return Data handler of the attachment
     */
    public DataHandler getAttachment(String contentID) {
        if (attachments == null) {
            attachments = new Attachments();
        }
        return attachments.getDataHandler(contentID);
    }

    /**
     * Removes the attachment with the given content ID from the Attachments Map
     * Do nothing if a attachment cannot be found by the given content ID.
     *
     * @param contentID of the attachment (without the "cid:" prefix)
     */
    public void removeAttachment(String contentID) {
        if (attachments != null) {
            attachments.removeDataHandler(contentID);
        }
    }

    /*
     * ===============================================================
     * SelfManagedData Section
     * ===============================================================
     */

    /*
    * character to delimit strings
    */
    private String selfManagedDataDelimiter = "*";


    /**
     * Set up a unique key in the form of
     * <OL>
     * <LI>the class name for the class that owns the key
     * <LI>delimitor
     * <LI>the key as a string
     * <LI>delimitor
     * <LI>the key's hash code as a string
     * </OL>
     *
     * @param clazz The class that owns the supplied key
     * @param key   The key
     * @return A string key
     */
    private String generateSelfManagedDataKey(Class clazz, Object key) {
        return clazz.getName() + selfManagedDataDelimiter + key.toString() +
                selfManagedDataDelimiter + Integer.toString(key.hashCode());
    }

    /**
     * Add a key-value pair of self managed data to the set associated with
     * this message context.
     * <p/>
     * This is primarily intended to allow handlers to manage their own
     * message-specific data when the message context is saved/restored.
     *
     * @param clazz The class of the caller that owns the key-value pair
     * @param key   The key for this data object
     * @param value The data object
     */
    public void setSelfManagedData(Class clazz, Object key, Object value) {
        if (selfManagedDataMap == null) {
            selfManagedDataMap = new LinkedHashMap<String, Object>();
        }

        // make sure we have a unique key and a delimiter so we can
        // get the classname and hashcode for serialization/deserialization
        selfManagedDataMap.put(generateSelfManagedDataKey(clazz, key), value);
    }

    /**
     * Retrieve a value of self managed data previously saved with the specified key.
     *
     * @param clazz The class of the caller that owns the key-value pair
     * @param key   The key for the data
     * @return The data object associated with the key, or NULL if not found
     */
    public Object getSelfManagedData(Class clazz, Object key) {
        if (selfManagedDataMap != null) {
            return selfManagedDataMap.get(generateSelfManagedDataKey(clazz, key));
        }
        return null;
    }

    /**
     * Check to see if the key for the self managed data is available
     *
     * @param clazz The class of the caller that owns the key-value pair
     * @param key   The key to look for
     * @return TRUE if the key exists, FALSE otherwise
     */
    public boolean containsSelfManagedDataKey(Class clazz, Object key) {
        if (selfManagedDataMap == null) {
            return false;
        }
        return selfManagedDataMap.containsKey(generateSelfManagedDataKey(clazz, key));
    }

    /**
     * Removes the mapping of the specified key if the specified key
     * has been set for self managed data
     *
     * @param clazz The class of the caller that owns the key-value pair
     * @param key   The key of the object to be removed
     */
    public void removeSelfManagedData(Class clazz, Object key) {
        if (selfManagedDataMap != null) {
            selfManagedDataMap.remove(generateSelfManagedDataKey(clazz, key));
        }
    }

    /**
     * Flatten the phase list into a list of just unique handler instances
     *
     * @param list the list of handlers
     * @param map  users should pass null as this is just a holder for the recursion
     * @return a list of unigue object instances
     */
    private ArrayList<Handler> flattenPhaseListToHandlers(ArrayList<Handler> list, LinkedHashMap<String, Handler> map) {

        if (map == null) {
            map = new LinkedHashMap<String, Handler>();
        }

        Iterator<Handler> it = list.iterator();
        while (it.hasNext()) {
            Handler handler = (Handler) it.next();

            String key = null;
            if (handler != null) {
                key = handler.getClass().getName() + "@" + handler.hashCode();
            }

            if (handler instanceof Phase) {
                // add its handlers to the list
                flattenHandlerList(((Phase) handler).getHandlers(), map);
            } else {
                // if the same object is already in the list,
                // then it won't be in the list multiple times
                map.put(key, handler);
            }
        }

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            Iterator<String> it2 = map.keySet().iterator();
            while (it2.hasNext()) {
                Object key = it2.next();
                Handler value = (Handler) map.get(key);
                String name = value.getName();
                log.trace(getLogIDString() + ":flattenPhaseListToHandlers():  key [" + key +
                        "]    handler name [" + name + "]");
            }
        }


        return new ArrayList<Handler>(map.values());
    }


    /**
     * Flatten the handler list into just unique handler instances
     * including phase instances.
     *
     * @param list the list of handlers/phases
     * @param map  users should pass null as this is just a holder for the recursion
     * @return a list of unigue object instances
     */
    private ArrayList<Handler> flattenHandlerList(List<Handler> list, LinkedHashMap<String, Handler> map) {

        if (map == null) {
            map = new LinkedHashMap<String, Handler>();
        }

        Iterator<Handler> it = list.iterator();
        while (it.hasNext()) {
            Handler handler = (Handler) it.next();

            String key = null;
            if (handler != null) {
                key = handler.getClass().getName() + "@" + handler.hashCode();
            }

            if (handler instanceof Phase) {
                // put the phase in the list
                map.put(key, handler);

                // add its handlers to the list
                flattenHandlerList(((Phase) handler).getHandlers(), map);
            } else {
                // if the same object is already in the list,
                // then it won't be in the list multiple times
                map.put(key, handler);
            }
        }

        return new ArrayList<Handler>(map.values());
    }


    /**
     * Calls the serializeSelfManagedData() method of each handler that
     * implements the <bold>SelfManagedDataManager</bold> interface.
     * Handlers for this message context are identified via the
     * executionChain list.
     *
     * @param out The output stream
     */
    private void serializeSelfManagedData(ObjectOutput out) {
        selfManagedDataHandlerCount = 0;

        try {
            if ((selfManagedDataMap == null)
                    || (executionChain == null)
                    || (selfManagedDataMap.size() == 0)
                    || (executionChain.size() == 0)) {
                out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(getLogIDString() + ":serializeSelfManagedData(): No data : END");
                }

                return;
            }

            // let's create a temporary list with the handlers
            ArrayList<Handler> flatExecChain = flattenPhaseListToHandlers(executionChain, null);

            //ArrayList selfManagedDataHolderList = serializeSelfManagedDataHelper(flatExecChain.iterator(), new ArrayList());
            ArrayList<SelfManagedDataHolder> selfManagedDataHolderList = serializeSelfManagedDataHelper(flatExecChain);

            if (selfManagedDataHolderList.size() == 0) {
                out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(getLogIDString() + ":serializeSelfManagedData(): No data : END");
                }

                return;
            }

            out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);

            // SelfManagedData can be binary so won't be able to treat it as a
            // string - need to treat it as a byte []

            // how many handlers actually
            // returned serialized SelfManagedData
            out.writeInt(selfManagedDataHolderList.size());

            for (int i = 0; i < selfManagedDataHolderList.size(); i++) {
                out.writeObject(selfManagedDataHolderList.get(i));
            }

        }
        catch (IOException e) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace("MessageContext:serializeSelfManagedData(): Exception [" +
                    e.getClass().getName() + "]  description [" + e.getMessage() + "]", e);
            }
        }

    }


    /**
     * This is the helper method to do the recursion for serializeSelfManagedData()
     *
     * @param handlers
     * @return ArrayList
     */
    private ArrayList<SelfManagedDataHolder> serializeSelfManagedDataHelper(ArrayList<Handler> handlers) {
        ArrayList<SelfManagedDataHolder> selfManagedDataHolderList = new ArrayList<SelfManagedDataHolder>();
        Iterator<Handler> it = handlers.iterator();

        try {
            while (it.hasNext()) {
                Handler handler = (Handler) it.next();

                //if (handler instanceof Phase)
                //{
                //    selfManagedDataHolderList = serializeSelfManagedDataHelper(((Phase)handler).getHandlers().iterator(), selfManagedDataHolderList);
                //}
                //else if (SelfManagedDataManager.class.isAssignableFrom(handler.getClass()))
                if (SelfManagedDataManager.class.isAssignableFrom(handler.getClass())) {
                    // only call the handler's serializeSelfManagedData if it implements SelfManagedDataManager

                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace(
                                "MessageContext:serializeSelfManagedDataHelper(): calling handler  [" +
                                        handler.getClass().getName() + "]  name [" +
                                        handler.getName() + "]   serializeSelfManagedData method");
                    }

                    ByteArrayOutputStream baos_fromHandler =
                            ((SelfManagedDataManager) handler).serializeSelfManagedData(this);

                    if (baos_fromHandler != null) {
                        baos_fromHandler.close();

                        try {
                            SelfManagedDataHolder selfManagedDataHolder = new SelfManagedDataHolder(
                                    handler.getClass().getName(), handler.getName(),
                                    baos_fromHandler.toByteArray());
                            selfManagedDataHolderList.add(selfManagedDataHolder);
                            selfManagedDataHandlerCount++;
                        }
                        catch (Exception exc) {
                            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                                log.trace("MessageContext:serializeSelfManagedData(): exception [" +
                                    exc.getClass().getName() + "][" + exc.getMessage() +
                                    "]  in setting up SelfManagedDataHolder object for [" +
                                    handler.getClass().getName() + " / " + handler.getName() + "] ",
                                      exc);
                            }
                        }
                    }
                }
            }

            return selfManagedDataHolderList;
        }
        catch (Exception ex) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace("MessageContext:serializeSelfManagedData(): exception [" +
                    ex.getClass().getName() + "][" + ex.getMessage() + "]", ex);
            }
            return null;
        }

    }

    /**
     * During deserialization, the executionChain will be
     * re-constituted before the SelfManagedData is restored.
     * This means the handler instances are already available.
     * This method lets us find the handler instance from the
     * executionChain so we can call each one's
     * deserializeSelfManagedData method.
     *
     * @param it            The iterator from the executionChain object
     * @param classname     The class name
     * @param qNameAsString The QName in string form
     * @return SelfManagedDataManager handler
     */
    private SelfManagedDataManager deserialize_getHandlerFromExecutionChain(Iterator<Handler> it,
                                                                            String classname,
                                                                            String qNameAsString) {
        SelfManagedDataManager handler_toreturn = null;

        try {
            while ((it.hasNext()) && (handler_toreturn == null)) {
                Handler handler = (Handler) it.next();

                if (handler instanceof Phase) {
                    handler_toreturn = deserialize_getHandlerFromExecutionChain(
                            ((Phase) handler).getHandlers().iterator(), classname, qNameAsString);
                } else if ((handler.getClass().getName().equals(classname))
                        && (handler.getName().equals(qNameAsString))) {
                    handler_toreturn = (SelfManagedDataManager) handler;
                }
            }
            return handler_toreturn;
        }
        catch (ClassCastException e) {
            // Doesn't seem likely to happen, but just in case...
            // A handler classname in the executionChain matched up with our parameter
            // classname, but the existing class in the executionChain is a different
            // implementation than the one we saved during serializeSelfManagedData.
            // NOTE: the exception gets absorbed!

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(
                    "MessageContext:deserialize_getHandlerFromExecutionChain(): ClassCastException thrown: " +
                            e.getMessage(), e);
            }
            return null;
        }
    }


    /*
    * We don't need to create new instances of the handlers
    * since the executionChain is rebuilt after readExternal().
    * We just have to find them in the executionChain and
    * call each handler's deserializeSelfManagedData method.
    */
    private void deserializeSelfManagedData() throws IOException {
        try {
            for (int i = 0;
                 (selfManagedDataListHolder != null) && (i < selfManagedDataListHolder.size()); i++)
            {
                SelfManagedDataHolder selfManagedDataHolder =
                        (SelfManagedDataHolder) selfManagedDataListHolder.get(i);

                String classname = selfManagedDataHolder.getClassname();
                String qNameAsString = selfManagedDataHolder.getId();

                SelfManagedDataManager handler = deserialize_getHandlerFromExecutionChain(
                        executionChain.iterator(), classname, qNameAsString);

                if (handler == null) {
                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace(getLogIDString() + ":deserializeSelfManagedData():  [" +
                                classname +
                                "]  was not found in the executionChain associated with the message context.");
                    }

                    throw new IOException("The class [" + classname +
                            "] was not found in the executionChain associated with the message context.");
                }

                ByteArrayInputStream handlerData =
                        new ByteArrayInputStream(selfManagedDataHolder.getData());

                // the handler implementing SelfManagedDataManager is responsible for repopulating
                // the SelfManagedData in the MessageContext (this)

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(getLogIDString() +
                            ":deserializeSelfManagedData(): calling handler [" + classname + "] [" +
                            qNameAsString + "]  deserializeSelfManagedData method");
                }

                handler.deserializeSelfManagedData(handlerData, this);
                handler.restoreTransientData(this);
            }
        }
        catch (IOException ioe) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() + ":deserializeSelfManagedData(): IOException thrown: " +
                        ioe.getMessage(), ioe);
            }
            throw ioe;
        }

    }

    /* ===============================================================
    * Externalizable support
    * ===============================================================
    */


    /**
     * Save the contents of this MessageContext instance.
     * <p/>
     * NOTE: Transient fields and static fields are not saved.
     * Also, objects that represent "static" data are
     * not saved, except for enough information to be
     * able to find matching objects when the message
     * context is re-constituted.
     *
     * @param o The stream to write the object contents to
     * @throws IOException
     */
    public void writeExternal(ObjectOutput o) throws IOException {
        SafeObjectOutputStream out = SafeObjectOutputStream.install(o);
        String logCorrelationIDString = getLogIDString();

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":writeExternal(): writing to output stream");
        }

        //---------------------------------------------------------
        // in order to handle future changes to the message
        // context definition, be sure to maintain the
        // object level identifiers
        //---------------------------------------------------------
        // serialization version ID
        out.writeLong(serialVersionUID);

        // revision ID
        out.writeInt(revisionID);

        //---------------------------------------------------------
        // various simple fields
        //---------------------------------------------------------

        // the type of execution flow for the message context
        out.writeInt(FLOW);

        // various flags
        out.writeBoolean(processingFault);
        out.writeBoolean(paused);
        out.writeBoolean(outputWritten);
        out.writeBoolean(newThreadRequired);
        out.writeBoolean(isSOAP11);
        out.writeBoolean(doingREST);
        out.writeBoolean(doingMTOM);
        out.writeBoolean(doingSwA);
        out.writeBoolean(responseWritten);
        out.writeBoolean(serverSide);

        out.writeLong(getLastTouchedTime());
        out.writeObject(getLogCorrelationID());

        //-----------------------------------------------------------------------
        // Create and initialize the OMOutputFormat for Message Externalization
        //-----------------------------------------------------------------------
        
        OMOutputFormat outputFormat= new OMOutputFormat();
        outputFormat.setSOAP11(isSOAP11);
        boolean persistOptimized = getPersistOptimized();
        if (persistOptimized) {
            outputFormat.setDoOptimize(true);
        }
        String charSetEnc = (String) getProperty(MessageContext.CHARACTER_SET_ENCODING);
        if (charSetEnc == null) {
            OperationContext opContext = getOperationContext();
            if (opContext != null) {
                charSetEnc =
                        (String) opContext.getProperty(MessageContext.CHARACTER_SET_ENCODING);
            }
        }
        if (charSetEnc == null) {
            charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
        }
        outputFormat.setCharSetEncoding(charSetEnc);

        // ----------------------------------------------------------
        // Externalize the Message
        // ----------------------------------------------------------
        MessageExternalizeUtils.writeExternal(out, this, logCorrelationIDString, outputFormat);

        // ---------------------------------------------------------
        // ArrayList executionChain
        //     handler and phase related data
        //---------------------------------------------------------
        // The strategy is to save some metadata about each
        // member of the list and the order of the list.
        // Then when the message context is re-constituted,
        // try to match up with phases and handlers on the
        // engine.
        //
        // Non-null list:
        //    UTF          - description string
        //    boolean      - active flag
        //    int          - current handler index
        //    int          - current phase index
        //    int          - expected number of entries in the list
        //    objects      - MetaDataEntry object per list entry
        //                        last entry will be empty MetaDataEntry
        //                        with MetaDataEntry.LAST_ENTRY marker
        //    int          - adjusted number of entries in the list
        //                        includes the last empty entry
        //
        // Empty list:
        //    UTF          - description string
        //    boolean      - empty flag
        //---------------------------------------------------------
        out.writeUTF("executionChain");
        if (executionChain != null && executionChain.size() > 0) {
            // start writing data to the output stream
            out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
            out.writeInt(currentHandlerIndex);
            out.writeInt(currentPhaseIndex);
            out.writeInt(executionChain.size());

            // put the metadata on each member of the list into a buffer

            // match the current index with the actual saved list
            int nextIndex = 0;

            Iterator<Handler> i = executionChain.iterator();

            while (i.hasNext()) {
                Object obj = i.next();
                String objClass = obj.getClass().getName();
                // start the meta data entry for this object
                MetaDataEntry mdEntry = new MetaDataEntry();
                mdEntry.setClassName(objClass);

                // get the correct object-specific name
                String qnameAsString;

                if (obj instanceof Phase) {
                    Phase phaseObj = (Phase) obj;
                    qnameAsString = phaseObj.getName();

                    // add the list of handlers to the meta data
                    setupPhaseList(phaseObj, mdEntry);
                } else if (obj instanceof Handler) {
                    Handler handlerObj = (Handler) obj;
                    qnameAsString = handlerObj.getName();
                } else {
                    // TODO: will there be any other kinds of objects in the execution Chain?
                    qnameAsString = "NULL";
                }

                mdEntry.setQName(qnameAsString);

                // update the index for the entry in the chain

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                            ":writeExternal(): ***BEFORE OBJ WRITE*** executionChain entry class [" +
                            objClass + "] qname [" + qnameAsString + "]");
                }

                out.writeObject(mdEntry);

                // update the index so that the index
                // now indicates the next entry that
                // will be attempted
                nextIndex++;

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                            ":writeExternal(): ***AFTER OBJ WRITE*** executionChain entry class [" +
                            objClass + "] qname [" + qnameAsString + "]");
                }

            } // end while entries in execution chain

            // done with the entries in the execution chain
            // add the end-of-list marker
            MetaDataEntry lastEntry = new MetaDataEntry();
            lastEntry.setClassName(MetaDataEntry.END_OF_LIST);

            out.writeObject(lastEntry);
            nextIndex++;

            // nextIndex also gives us the number of entries
            // that were actually saved as opposed to the
            // number of entries in the executionChain
            out.writeInt(nextIndex);

        } else {
            // general case: handle "null" or "empty"
            out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString + ":writeExternal(): executionChain is NULL");
            }
        }

        //---------------------------------------------------------
        // LinkedList executedPhases
        //---------------------------------------------------------
        // The strategy is to save some metadata about each
        // member of the list and the order of the list.
        // Then when the message context is re-constituted,
        // try to match up with phases and handlers on the
        // engine.
        //
        // Non-null list:
        //    UTF          - description string
        //    boolean      - active flag
        //    int          - expected number of entries in the list
        //    objects      - MetaDataEntry object per list entry
        //                        last entry will be empty MetaDataEntry
        //                        with MetaDataEntry.LAST_ENTRY marker
        //    int          - adjusted number of entries in the list
        //                        includes the last empty entry
        //
        // Empty list:
        //    UTF          - description string
        //    boolean      - empty flag
        //---------------------------------------------------------
        out.writeUTF("executedPhases");
        if (executedPhases != null && executedPhases.size() > 0) {
        
            // start writing data to the output stream
            out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
            out.writeInt(executedPhases.size());

            // put the metadata on each member of the list into a buffer

            int execNextIndex = 0;

            Iterator<Handler> iterator = executedPhases.iterator();

            while (iterator.hasNext()) {
                Object obj = iterator.next();
                String objClass = obj.getClass().getName();
                // start the meta data entry for this object
                MetaDataEntry mdEntry = new MetaDataEntry();
                mdEntry.setClassName(objClass);

                // get the correct object-specific name
                String qnameAsString;

                if (obj instanceof Phase) {
                    Phase inPhaseObj = (Phase) obj;
                    qnameAsString = inPhaseObj.getName();

                    // add the list of handlers to the meta data
                    setupPhaseList(inPhaseObj, mdEntry);
                } else if (obj instanceof Handler) {
                    Handler inHandlerObj = (Handler) obj;
                    qnameAsString = inHandlerObj.getName();
                } else {
                    // TODO: will there be any other kinds of objects in the list
                    qnameAsString = "NULL";
                }

                mdEntry.setQName(qnameAsString);

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                            ":writeExternal(): ***BEFORE Executed List OBJ WRITE*** executedPhases entry class [" +
                            objClass + "] qname [" + qnameAsString + "]");
                }

                out.writeObject(mdEntry);

                // update the index so that the index
                // now indicates the next entry that
                // will be attempted
                execNextIndex++;

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString + ":writeExternal(): " +
                            "***AFTER Executed List OBJ WRITE*** " +
                            "executedPhases entry class [" + objClass + "] " +
                            "qname [" + qnameAsString + "]");
                }
            } // end while entries in execution chain

            // done with the entries in the execution chain
            // add the end-of-list marker
            MetaDataEntry lastEntry = new MetaDataEntry();
            lastEntry.setClassName(MetaDataEntry.END_OF_LIST);

            out.writeObject(lastEntry);
            execNextIndex++;

            // execNextIndex also gives us the number of entries
            // that were actually saved as opposed to the
            // number of entries in the executedPhases
            out.writeInt(execNextIndex);

        } else {
            // general case: handle "null" or "empty"
            out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(
                        logCorrelationIDString + ":writeExternal(): executedPhases is NULL");
            }
        }

        //---------------------------------------------------------
        // options
        //---------------------------------------------------------
        // before saving the Options, make sure there is a message ID
        String tmpID = getMessageID();
        if (tmpID == null) {
            // get an id to use when restoring this object
            tmpID = UUIDGenerator.getUUID();
            setMessageID(tmpID);
        }

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":writeExternal():   message ID [" + tmpID + "]");
        }

        out.writeUTF("options");
        out.writeObject(options);
        
        //---------------------------------------------------------
        // operation
        //---------------------------------------------------------
        // axis operation
        //---------------------------------------------------------
        out.writeUTF("axisOperation");
        metaAxisOperation = null;
        if (axisOperation != null) {
            // TODO: may need to include the meta data for the axis service that is
            //       the parent of the axis operation
            // make sure the axis operation has a name associated with it
            QName aoTmpQName = axisOperation.getName();

            if (aoTmpQName == null) {
                aoTmpQName = new QName(ExternalizeConstants.EMPTY_MARKER);
                axisOperation.setName(aoTmpQName);
            }

            metaAxisOperation = new MetaDataEntry(axisOperation.getClass().getName(),
                                                  axisOperation.getName().toString());
        }
        out.writeObject(metaAxisOperation);

        //---------------------------------------------------------
        // operation context
        //---------------------------------------------------------
        // The OperationContext has pointers to MessageContext objects.
        // In order to avoid having multiple copies of the object graph
        // being saved at different points in the serialization,
        // it is important to isolate this message context object.
        out.writeUTF("operationContext");
        if (operationContext != null) {
            operationContext.isolateMessageContext(this);
        }

        out.writeObject(operationContext);
   

        //---------------------------------------------------------
        // service
        //---------------------------------------------------------
        // axis service
        //-------------------------
        // this is expected to be the parent of the axis operation object
        out.writeUTF("axisService");
        metaAxisService = null;
        if (axisService != null) {
            metaAxisService = new MetaDataEntry(axisService.getClass().getName(), 
                                                axisService.getName());
        }
        out.writeObject(metaAxisService);

        //-------------------------
        // serviceContextID string
        //-------------------------
        out.writeObject(serviceContextID);

        //-------------------------
        // serviceContext
        //-------------------------
        // is this the same as the parent of the OperationContext?
        boolean isParent = false;
        out.writeUTF("serviceContext");

        if (operationContext != null) {
            ServiceContext opctxParent = operationContext.getServiceContext();

            if (serviceContext != null) {
                if (serviceContext.equals(opctxParent)) {
                    // the ServiceContext is the parent of the OperationContext
                    isParent = true;
                }
            }
        }

        if (serviceContext == null) {
            out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
        } else {
            out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
            out.writeBoolean(isParent);

            // only write out the object if it is not the parent
            if (!isParent) {
                out.writeObject(serviceContext);
            }
        }

        //---------------------------------------------------------
        // axisServiceGroup
        //---------------------------------------------------------
        out.writeUTF("axisServiceGroup");
        metaAxisServiceGroup = null;
        if (axisServiceGroup != null) {
            metaAxisServiceGroup = new MetaDataEntry(axisServiceGroup.getClass().getName(),
                                                     axisServiceGroup.getServiceGroupName());
        }
        out.writeObject(metaAxisServiceGroup);

        //-----------------------------
        // serviceGroupContextId string
        //-----------------------------
        out.writeObject(serviceGroupContextId);

        //-------------------------
        // serviceGroupContext
        //-------------------------
        // is this the same as the parent of the ServiceContext?
        isParent = false;
        out.writeUTF("serviceGroupContext");

        if (serviceContext != null) {
            ServiceGroupContext srvgrpctxParent = (ServiceGroupContext) serviceContext.getParent();

            if (serviceGroupContext != null) {
                if (serviceGroupContext.equals(srvgrpctxParent)) {
                    // the ServiceGroupContext is the parent of the ServiceContext
                    isParent = true;
                }
            }
        }

        if (serviceGroupContext == null) {
            out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
        } else {
            out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
            out.writeBoolean(isParent);

            // only write out the object if it is not the parent
            if (!isParent) {
                out.writeObject(serviceGroupContext);
            }
        }

        //---------------------------------------------------------
        // axis message
        //---------------------------------------------------------
        out.writeUTF("axisMessage");
        metaAxisMessage = null;
        if (axisMessage != null) {
            // This AxisMessage is expected to belong to the AxisOperation
            // that has already been recorded for this MessageContext.
            // If an AxisMessage associated with this Messagecontext is
            // associated with a different AxisOperation, then more
            // meta information would need to be saved

            // make sure the axis message has a name associated with it
            String amTmpName = axisMessage.getName();

            if (amTmpName == null) {
                amTmpName = ExternalizeConstants.EMPTY_MARKER;
                axisMessage.setName(amTmpName);
            }

            // get the element name if there is one
            QName amTmpElementQName = axisMessage.getElementQName();
            String amTmpElemQNameString = null;

            if (amTmpElementQName != null) {
                amTmpElemQNameString = amTmpElementQName.toString();
            }

            metaAxisMessage = new MetaDataEntry(axisMessage.getClass().getName(),
                                                axisMessage.getName(), amTmpElemQNameString);

        }
        out.writeObject(metaAxisMessage);

        //---------------------------------------------------------
        // configuration context
        //---------------------------------------------------------

        // NOTE: Currently, there does not seem to be any
        //       runtime data important to this message context
        //       in the configuration context.
        //       if so, then need to save that runtime data and reconcile
        //       it with the configuration context on the system when
        //       this message context object is restored

        //---------------------------------------------------------
        // session context
        //---------------------------------------------------------
        out.writeObject(sessionContext);

        //---------------------------------------------------------
        // transport
        //---------------------------------------------------------

        //------------------------------
        // incomingTransportName string
        //------------------------------
        out.writeObject(incomingTransportName);

        // TransportInDescription transportIn
        metaTransportIn = null;
        if (transportIn != null) {
            metaTransportIn = new MetaDataEntry(null, transportIn.getName());
        } 
        out.writeObject(metaTransportIn);

        // TransportOutDescription transportOut
        metaTransportOut = null;
        if (transportOut != null) {
            metaTransportOut = new MetaDataEntry(null, transportOut.getName());
        }
        out.writeObject(metaTransportOut);
        

        //---------------------------------------------------------
        // properties
        //---------------------------------------------------------
        // Write out the local properties on the MessageContext
        // Don't write out the properties from other hierarchical layers.
        // (i.e. don't use getProperties())
        out.writeUTF("properties"); // write marker
        out.writeMap(properties);

        //---------------------------------------------------------
        // special data
        //---------------------------------------------------------
        out.writeUTF("selfManagedData");
        serializeSelfManagedData(out);

        //---------------------------------------------------------
        // done
        //---------------------------------------------------------

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString +
                    ":writeExternal(): completed writing to output stream for " +
                    logCorrelationIDString);
        }

    }
    
    /**
     * @return true if the data should be persisted as optimized attachments
     */
    private boolean getPersistOptimized() {
        boolean persistOptimized = false;
        if (attachments != null && attachments.getContentIDList().size() > 1) {
            persistOptimized = true;
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
                log.trace(getLogIDString()
                        + ":getPersistOptimized(): attachments present; persist optimized");
        }
        if (!persistOptimized) {
            Object property = getProperty(Configuration.ENABLE_MTOM);
            if (property != null && JavaUtils.isTrueExplicitly(property)) {
                persistOptimized = true;
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
                    log.trace(getLogIDString()
                            + ":getPersistOptimized(): ENBABLE_MTOM is set; persist optimized");
            }
        }
        if (!persistOptimized) {
            Object property = getProperty(Configuration.ENABLE_SWA);
            if (property != null && JavaUtils.isTrueExplicitly(property)) {
                persistOptimized = true;
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
                    log.trace(getLogIDString()
                            + ":getPersistOptimized(): ENBABLE_SWA is set; persist optimized");
            }
        }
        if (!persistOptimized && LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
            log.trace(getLogIDString()
                    + ":getPersistOptimized(): No attachments or attachment settings; persist non-optimized");
        return persistOptimized;
    }


    /**
     * Restore the contents of the MessageContext that was
     * previously saved.
     * <p/>
     * NOTE: The field data must read back in the same order and type
     * as it was written.  Some data will need to be validated when
     * resurrected.
     *
     * @param inObject
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public void readExternal(ObjectInput inObject) throws IOException, ClassNotFoundException {        
        SafeObjectInputStream in = SafeObjectInputStream.install(inObject);
        // set the flag to indicate that the message context is being
        // reconstituted and will need to have certain object references
        // to be reconciled with the current engine setup
        needsToBeReconciled = true;

        // trace point
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(myClassName + ":readExternal():  BEGIN  bytes available in stream [" +
                    in.available() + "]  ");
        }

        //---------------------------------------------------------
        // object level identifiers
        //---------------------------------------------------------

        // serialization version ID
        long suid = in.readLong();

        // revision ID
        int revID = in.readInt();

        // make sure the object data is in a version we can handle
        if (suid != serialVersionUID) {
            throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_SUID);
        }

        // make sure the object data is in a revision level we can handle
        if (revID != REVISION_2) {
            throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_REVID);
        }

        //---------------------------------------------------------
        // various simple fields
        //---------------------------------------------------------

        // the type of execution flow for the message context
        FLOW = in.readInt();

        // various flags
        processingFault = in.readBoolean();
        paused = in.readBoolean();
        outputWritten = in.readBoolean();
        newThreadRequired = in.readBoolean();
        isSOAP11 = in.readBoolean();
        doingREST = in.readBoolean();
        doingMTOM = in.readBoolean();
        doingSwA = in.readBoolean();
        responseWritten = in.readBoolean();
        serverSide = in.readBoolean();

        long time = in.readLong();
        setLastTouchedTime(time);
        logCorrelationID = (String) in.readObject();

        // trace point
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            logCorrelationIDString = "[MessageContext: logID=" + getLogCorrelationID() + "]";
            log.trace(myClassName + ":readExternal():  reading the input stream for  " +
                      getLogIDString());
        }

        //---------------------------------------------------------
        // Message
        // Read the message and attachments
        //---------------------------------------------------------
        envelope = MessageExternalizeUtils.readExternal(in, this, getLogIDString());

        //---------------------------------------------------------
        // ArrayList executionChain
        //     handler and phase related data
        //---------------------------------------------------------
        // Restore the metadata about each member of the list
        // and the order of the list.
        // This metadata will be used to match up with phases
        // and handlers on the engine.
        //
        // Non-null list:
        //    UTF          - description string
        //    boolean      - active flag
        //    int          - current handler index
        //    int          - current phase index
        //    int          - expected number of entries in the list
        //                        not including the last entry marker
        //    objects      - MetaDataEntry object per list entry
        //                        last entry will be empty MetaDataEntry
        //                        with MetaDataEntry.LAST_ENTRY marker
        //    int          - adjusted number of entries in the list
        //                        includes the last empty entry
        //
        // Empty list:
        //    UTF          - description string
        //    boolean      - empty flag
        //---------------------------------------------------------

        // the local chain is not enabled until the
        // list has been reconstituted
        executionChain = null;
        currentHandlerIndex = -1;
        currentPhaseIndex = 0;
        metaExecutionChain = null;

        String marker = in.readUTF();
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read executionChain, marker is: " + marker);
        }
        boolean gotChain = in.readBoolean();

        if (gotChain == ExternalizeConstants.ACTIVE_OBJECT) {
            metaHandlerIndex = in.readInt();
            metaPhaseIndex = in.readInt();

            int expectedNumberEntries = in.readInt();

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() +
                        ":readExternal(): execution chain:  expected number of entries [" +
                        expectedNumberEntries + "]");
            }

            // setup the list
            metaExecutionChain = new ArrayList<MetaDataEntry>();

            // process the objects
            boolean keepGoing = true;
            int count = 0;

            while (keepGoing) {
                // stop when we get to the end-of-list marker

                // get the object
                Object tmpObj = in.readObject();

                count++;

                MetaDataEntry mdObj = (MetaDataEntry) tmpObj;

                // get the class name, then add it to the list
                String tmpClassNameStr;
                String tmpQNameAsStr;

                if (mdObj != null) {
                    tmpClassNameStr = mdObj.getClassName();

                    if (tmpClassNameStr.equalsIgnoreCase(MetaDataEntry.END_OF_LIST)) {
                        // this is the last entry
                        keepGoing = false;
                    } else {
                        // add the entry to the meta data list
                        metaExecutionChain.add(mdObj);

                        tmpQNameAsStr = mdObj.getQNameAsString();

                        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                            String tmpHasList = mdObj.isListEmpty() ? "no children" : "has children";

                            if (log.isTraceEnabled()) {
                                log.trace(getLogIDString() +
                                    ":readExternal(): meta data class [" + tmpClassNameStr +
                                    "] qname [" + tmpQNameAsStr + "]  index [" + count + "]   [" +
                                    tmpHasList + "]");
                            }
                        }
                    }
                } else {
                    // some error occurred
                    keepGoing = false;
                }

            } // end while keep going

            int adjustedNumberEntries = in.readInt();

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() +
                        ":readExternal(): adjusted number of entries ExecutionChain [" +
                        adjustedNumberEntries + "]    ");
            }
        }

        if ((metaExecutionChain == null) || (metaExecutionChain.isEmpty())) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() +
                        ":readExternal(): meta data for Execution Chain is NULL");
            }
        }

        //---------------------------------------------------------
        // LinkedList executedPhases
        //
        // Note that in previous versions of Axis2, this was
        // represented by two lists: "inboundExecutedPhases", "outboundExecutedPhases",
        // however since the message context itself represents a flow
        // direction, one of these lists was always null.  This was changed
        // around 2007-06-08 revision r545615.  For backward compatability
        // with streams saved in previous versions of Axis2, we need
        // to be able to process both the old style and new style.
        //---------------------------------------------------------
        // Restore the metadata about each member of the list
        // and the order of the list.
        // This metadata will be used to match up with phases
        // and handlers on the engine.
        //
        // Non-null list:
        //    UTF          - description string
        //    boolean      - active flag
        //    int          - expected number of entries in the list
        //                        not including the last entry marker
        //    objects      - MetaDataEntry object per list entry
        //                        last entry will be empty MetaDataEntry
        //                        with MetaDataEntry.LAST_ENTRY marker
        //    int          - adjusted number of entries in the list
        //                        includes the last empty entry
        //
        // Empty list:
        //    UTF          - description string
        //    boolean      - empty flag
        //---------------------------------------------------------

        // the local chain is not enabled until the
        // list has been reconstituted
        executedPhases = null;
        metaExecuted = null;

        marker = in.readUTF();
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read executedPhases, marker is: " + marker);
        }
        
        // Previous versions of Axis2 saved two phases in the stream, although one should 
        // always have been null.  The two phases and their associated markers are, in this order:
        // "inboundExecutedPhases", "outboundExecutedPhases".
        boolean gotInExecList = in.readBoolean();
        boolean oldStyleExecutedPhases = false;
        if (marker.equals("inboundExecutedPhases")) {
            oldStyleExecutedPhases = true;
        }
        
        if (oldStyleExecutedPhases && (gotInExecList == ExternalizeConstants.EMPTY_OBJECT)) {
            // There are an inboundExecutedPhases and an outboundExecutedPhases and this one
            // is empty, so skip over it and read the next one
            marker = in.readUTF();
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() + 
                          ": readExternal(): Skipping over oldStyle empty inboundExecutedPhases");
                log.trace(getLogIDString() + 
                          ": readExternal(): About to read executedPhases, marker is: " + marker);
            }
            gotInExecList = in.readBoolean();
        }
        
        /*
         * At this point, the stream should point to either "executedPhases" if this is the 
         * new style of serialization.  If it is the oldStyle, it should point to whichever 
         * of "inbound" or "outbound" executed phases contains an active object, since only one
         * should
         */
        if (gotInExecList == ExternalizeConstants.ACTIVE_OBJECT) {
            int expectedNumberInExecList = in.readInt();

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() +
                        ":readExternal(): executed phases:  expected number of entries [" +
                        expectedNumberInExecList + "]");
            }

            // setup the list
            metaExecuted = new LinkedList<MetaDataEntry>();

            // process the objects
            boolean keepGoing = true;
            int count = 0;

            while (keepGoing) {
                // stop when we get to the end-of-list marker

                // get the object
                Object tmpObj = in.readObject();

                count++;

                MetaDataEntry mdObj = (MetaDataEntry) tmpObj;

                // get the class name, then add it to the list
                String tmpClassNameStr;
                String tmpQNameAsStr;
                String tmpHasList = "no list";

                if (mdObj != null) {
                    tmpClassNameStr = mdObj.getClassName();

                    if (tmpClassNameStr.equalsIgnoreCase(MetaDataEntry.END_OF_LIST)) {
                        // this is the last entry
                        keepGoing = false;
                    } else {
                        // add the entry to the meta data list
                        metaExecuted.add(mdObj);

                        tmpQNameAsStr = mdObj.getQNameAsString();

                        if (!mdObj.isListEmpty()) {
                            tmpHasList = "has list";
                        }

                        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                            log.trace(getLogIDString() +
                                    ":readExternal(): meta data class [" + tmpClassNameStr +
                                    "] qname [" + tmpQNameAsStr + "]  index [" + count + "]   [" +
                                    tmpHasList + "]");
                        }
                    }
                } else {
                    // some error occurred
                    keepGoing = false;
                }

            } // end while keep going

            int adjustedNumberInExecList = in.readInt();

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() +
                        ":readExternal(): adjusted number of entries executedPhases [" +
                        adjustedNumberInExecList + "]    ");
            }
        }
        
        if ((metaExecuted == null) || (metaExecuted.isEmpty())) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() +
                        ":readExternal(): meta data for executedPhases list is NULL");
            }
        }
        
        marker = in.readUTF(); // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): After reading executedPhases, marker is: " + marker);
        }

        // If this is an oldStyle that contained both an inbound and outbound executed phases, 
        // and the outbound phases wasn't read above, then we need to skip over it
        if (marker.equals("outboundExecutedPhases")) {
            Boolean gotOutExecList = in.readBoolean();
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() + 
                          ": readExternal(): Skipping over outboundExecutedPhases, marker is: " + marker + 
                          ", is list an active object: " + gotOutExecList);
            }
            if (gotOutExecList != ExternalizeConstants.EMPTY_OBJECT) {
                throw new IOException("Both inboundExecutedPhases and outboundExecutedPhases had active objects");
            }
            
            marker = in.readUTF();
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() + 
                          ": readExternal(): After skipping ooutboundExecutePhases, marker is: " + marker);
            }
        }

        //---------------------------------------------------------
        // options
        //---------------------------------------------------------
        
        options = (Options) in.readObject();

        if (options != null) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() + ":readExternal(): restored Options [" +
                        options.getLogCorrelationIDString() + "]");
            }
        }

        //---------------------------------------------------------
        // operation
        //---------------------------------------------------------

        // axisOperation is not usable until the meta data has been reconciled
        axisOperation = null;
        marker = in.readUTF();  // Read Marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read axisOperation, marker is: " + marker);
        }
        metaAxisOperation = (MetaDataEntry) in.readObject();

        // operation context is not usable until it has been activated
        // NOTE: expect this to be the parent
        marker = in.readUTF();  // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read operationContext, marker is: " + marker);
        }
        operationContext = (OperationContext) in.readObject();

        if (operationContext != null) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(getLogIDString() + ":readExternal(): restored OperationContext [" +
                        operationContext.getLogCorrelationIDString() + "]");
            }
        }

        //---------------------------------------------------------
        // service
        //---------------------------------------------------------

        // axisService is not usable until the meta data has been reconciled
        axisService = null;
        marker = in.readUTF(); // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read axisService, marker is: " + marker);
        }
        metaAxisService = (MetaDataEntry) in.readObject();

        //-------------------------
        // serviceContextID string
        //-------------------------
        serviceContextID = (String) in.readObject();
        
        //-------------------------
        // serviceContext
        //-------------------------
        marker = in.readUTF(); // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read serviceContext, marker is: " + marker);
        }

        boolean servCtxActive = in.readBoolean();

        if (servCtxActive == ExternalizeConstants.EMPTY_OBJECT) {
            // empty object

            serviceContext = null;
        } else {
            // active object

            boolean isParent = in.readBoolean();

            // there's an object to read in if it is not the parent of the operation context
            if (!isParent) {
                serviceContext = (ServiceContext) in.readObject();
            } else {
                // the service context is the parent of the operation context
                // so get it from the operation context during activate
                serviceContext = null;
            }
        }

        //---------------------------------------------------------
        // serviceGroup
        //---------------------------------------------------------

        // axisServiceGroup is not usable until the meta data has been reconciled
        axisServiceGroup = null;
        marker = in.readUTF(); // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read AxisServiceGroup, marker is: " + marker);
        }
        metaAxisServiceGroup = (MetaDataEntry) in.readObject();

        //-----------------------------
        // serviceGroupContextId string
        //-----------------------------
        serviceGroupContextId = (String) in.readObject();

        //-----------------------------
        // serviceGroupContext
        //-----------------------------
        marker = in.readUTF();
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read ServiceGroupContext, marker is: " + marker);
        }

        boolean servGrpCtxActive = in.readBoolean();

        if (servGrpCtxActive == ExternalizeConstants.EMPTY_OBJECT) {
            // empty object

            serviceGroupContext = null;
        } else {
            // active object

            boolean isParentSGC = in.readBoolean();

            // there's an object to read in if it is not the parent of the service group context
            if (!isParentSGC) {
                serviceGroupContext = (ServiceGroupContext) in.readObject();
            } else {
                // the service group context is the parent of the service context
                // so get it from the service context during activate
                serviceGroupContext = null;
            }
        }

        //---------------------------------------------------------
        // axis message
        //---------------------------------------------------------

        // axisMessage is not usable until the meta data has been reconciled
        axisMessage = null;
        marker = in.readUTF();  // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read AxisMessage, marker is: " + marker);
        }
        metaAxisMessage = (MetaDataEntry) in.readObject();
        reconcileAxisMessage = (metaAxisMessage != null);


        //---------------------------------------------------------
        // configuration context
        //---------------------------------------------------------

        // TODO: check to see if there is any runtime data important to this
        //       message context in the configuration context
        //       if so, then need to restore the saved runtime data and reconcile
        //       it with the configuration context on the system when
        //       this message context object is restored

        //---------------------------------------------------------
        // session context
        //---------------------------------------------------------
        sessionContext = (SessionContext) in.readObject();

        //---------------------------------------------------------
        // transport
        //---------------------------------------------------------

        //------------------------------
        // incomingTransportName string
        //------------------------------
        incomingTransportName = (String) in.readObject();

        // TransportInDescription transportIn
        // is not usable until the meta data has been reconciled
        transportIn = null;
        metaTransportIn = (MetaDataEntry) in.readObject();

        // TransportOutDescription transportOut
        // is not usable until the meta data has been reconciled
        transportOut = null;
        metaTransportOut = (MetaDataEntry) in.readObject();

        //---------------------------------------------------------
        // properties
        //---------------------------------------------------------
        // read local properties
        marker = in.readUTF(); // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read properties, marker is: " + marker);
        }
        properties = in.readMap(new HashMapUpdateLockable());


        //---------------------------------------------------------
        // special data
        //---------------------------------------------------------
        marker = in.readUTF(); // Read marker
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() + 
                      ": readExternal(): About to read SpecialData, marker is: " + marker);
        }

        boolean gotSelfManagedData = in.readBoolean();

        if (gotSelfManagedData == ExternalizeConstants.ACTIVE_OBJECT) {
            selfManagedDataHandlerCount = in.readInt();

            if (selfManagedDataListHolder == null) {
                selfManagedDataListHolder = new ArrayList<SelfManagedDataHolder>();
            } else {
                selfManagedDataListHolder.clear();
            }

            for (int i = 0; i < selfManagedDataHandlerCount; i++) {
                selfManagedDataListHolder.add((SelfManagedDataHolder) in.readObject());
            }
        }

        //---------------------------------------------------------
        // done
        //---------------------------------------------------------

        // trace point
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(getLogIDString() +
                    ":readExternal():  message context object created for  " +
                    getLogIDString());
        }
    }


    /**
     * This method checks to see if additional work needs to be
     * done in order to complete the object reconstitution.
     * Some parts of the object restored from the readExternal()
     * cannot be completed until we have a configurationContext
     * from the active engine. The configurationContext is used
     * to help this object to plug back into the engine's
     * configuration and deployment objects.
     *
     * @param cc The configuration context object representing the active configuration
     */
    public void activate(ConfigurationContext cc) {
        // see if there's any work to do
        if (!needsToBeReconciled) {
            // return quick
            return;
        }

        // use the supplied configuration context
        setConfigurationContext(cc);

        // get the axis configuration
        AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();

        // We previously saved metaAxisService; restore it
        if (metaAxisService != null) {
            this.setAxisService(ActivateUtils.findService(axisConfig,
                                                metaAxisService.getClassName(),
                                                metaAxisService.getQNameAsString()));
        }

        // We previously saved metaAxisServiceGroup; restore it
        if (metaAxisServiceGroup != null) {
            this.setAxisServiceGroup(
                                     ActivateUtils.findServiceGroup(axisConfig,
                                                metaAxisServiceGroup.getClassName(),
                                                metaAxisServiceGroup.getQNameAsString()));
        }

        // We previously saved metaAxisOperation; restore it
        if (metaAxisOperation != null) {
            AxisService serv = axisService;

            if (serv != null) {
                // TODO: check for the empty name
                this.setAxisOperation(ActivateUtils.findOperation(serv,
                                                                  metaAxisOperation.getClassName(),
                                                                  metaAxisOperation.getQName()));
            } else {
                this.setAxisOperation(ActivateUtils.findOperation(axisConfig,
                                                                  metaAxisOperation.getClassName(),
                                                                  metaAxisOperation.getQName()));
            }
        }

        // We previously saved metaAxisMessage; restore it
        if (metaAxisMessage != null) {
            AxisOperation op = axisOperation;

            if (op != null) {
                // TODO: check for the empty name
                this.setAxisMessage(ActivateUtils.findMessage(op,
                                                              metaAxisMessage.getQNameAsString(),
                                                              metaAxisMessage.getExtraName()));
            }
        }

        //---------------------------------------------------------------------
        // operation context
        //---------------------------------------------------------------------
        // this will do a full hierarchy, so do it first
        // then we can re-use its objects

        if (operationContext != null) {
            operationContext.activate(cc);

            // this will be set as the parent of the message context
            // after the other context objects have been activated
        }

        //---------------------------------------------------------------------
        // service context
        //---------------------------------------------------------------------

        if (serviceContext == null) {
            // get the parent serviceContext of the operationContext
            if (operationContext != null) {
                serviceContext = operationContext.getServiceContext();
            }
        }

        // if we have a service context, make sure it is usable
        if (serviceContext != null) {
            // for some reason, the service context might be set differently from
            // the operation context parent
            serviceContext.activate(cc);
        }

        //---------------------------------------------------------------------
        // service group context
        //---------------------------------------------------------------------

        if (serviceGroupContext == null) {
            // get the parent serviceGroupContext of the serviceContext
            if (serviceContext != null) {
                serviceGroupContext = (ServiceGroupContext) serviceContext.getParent();
            }
        }

        // if we have a service group context, make sure it is usable
        if (serviceGroupContext != null) {
            // for some reason, the service group context might be set differently from
            // the service context parent
            serviceGroupContext.activate(cc);
        }

        //---------------------------------------------------------------------
        // other context-related reconciliation
        //---------------------------------------------------------------------

        this.setParent(operationContext);

        //---------------------------------------------------------------------
        // options
        //---------------------------------------------------------------------
        if (options != null) {
            options.activate(cc);
        }

        String tmpID = getMessageID();
        String logCorrelationIDString = getLogIDString();

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":activate():   message ID [" + tmpID + "] for " +
                    logCorrelationIDString);
        }

        //---------------------------------------------------------------------
        // transports
        //---------------------------------------------------------------------

        // We previously saved metaTransportIn; restore it
        if (metaTransportIn != null) {
            QName qin = metaTransportIn.getQName();
            TransportInDescription tmpIn = null;
            try {
                tmpIn = axisConfig.getTransportIn(qin.getLocalPart());
            }
            catch (Exception exin) {
                // if a fault is thrown, log it and continue
                log.trace(logCorrelationIDString +
                        "activate():  exception caught when getting the TransportInDescription [" +
                        qin.toString() + "]  from the AxisConfiguration [" +
                        exin.getClass().getName() + " : " + exin.getMessage() + "]");
            }

            if (tmpIn != null) {
                transportIn = tmpIn;
            } else {
                transportIn = null;
            }
        } else {
            transportIn = null;
        }

        // We previously saved metaTransportOut; restore it
        if (metaTransportOut != null) {
            // TODO : Check if this should really be a QName?
            QName qout = metaTransportOut.getQName();
            TransportOutDescription tmpOut = null;
            try {
                tmpOut = axisConfig.getTransportOut(qout.getLocalPart());
            }
            catch (Exception exout) {
                // if a fault is thrown, log it and continue
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                        "activate():  exception caught when getting the TransportOutDescription [" +
                        qout.toString() + "]  from the AxisConfiguration [" +
                        exout.getClass().getName() + " : " + exout.getMessage() + "]");
                }
            }

            if (tmpOut != null) {
                transportOut = tmpOut;
            } else {
                transportOut = null;
            }
        } else {
            transportOut = null;
        }

        //-------------------------------------------------------
        // reconcile the execution chain
        //-------------------------------------------------------
        if (metaExecutionChain != null) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(
                        logCorrelationIDString + ":activate(): reconciling the execution chain...");
            }

            currentHandlerIndex = metaHandlerIndex;
            currentPhaseIndex = metaPhaseIndex;

            executionChain = restoreHandlerList(metaExecutionChain);

            try {
                deserializeSelfManagedData();
            }
            catch (Exception ex) {
                // log the exception
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                        ":activate(): *** WARNING *** deserializing the self managed data encountered Exception [" +
                        ex.getClass().getName() + " : " + ex.getMessage() + "]", ex);
                }
            }
        }

        //-------------------------------------------------------
        // reconcile the lists for the executed phases
        //-------------------------------------------------------
        if (metaExecuted != null) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString +
                        ":activate(): reconciling the executed chain...");
            }

            if (!(executedPhasesReset)) {
                executedPhases =
                        restoreExecutedList(executedPhases, metaExecuted);
            }
        }

        if (executedPhases == null) {
            executedPhases = new LinkedList<Handler>();
        }


        //-------------------------------------------------------
        // finish up remaining links
        //-------------------------------------------------------
        if (operationContext != null) {
            operationContext.restoreMessageContext(this);
        }

        //-------------------------------------------------------
        // done, reset the flag
        //-------------------------------------------------------
        needsToBeReconciled = false;

    }


    /**
     * This method checks to see if additional work needs to be
     * done in order to complete the object reconstitution.
     * Some parts of the object restored from the readExternal()
     * cannot be completed until we have an object that gives us
     * a view of the active object graph from the active engine.
     * <p/>
     * NOTE: when activating an object, you only need to call
     * one of the activate methods (activate() or activateWithOperationContext())
     * but not both.
     *
     * @param operationCtx The operation context object that is a member of the active object graph
     */
    public void activateWithOperationContext(OperationContext operationCtx) {
        // see if there's any work to do
        if (!(needsToBeReconciled)) {
            // return quick
            return;
        }

        String logCorrelationIDString = getLogIDString();
        // trace point
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":activateWithOperationContext():  BEGIN");
        }

        if (operationCtx == null) {
            // won't be able to finish
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString +
                    ":activateWithOperationContext():  *** WARNING ***  No active OperationContext object is available.");
            }
            return;
        }

        //---------------------------------------------------------------------
        // locate the objects in the object graph
        //---------------------------------------------------------------------
        ConfigurationContext configCtx = operationCtx.getConfigurationContext();

        if (configCtx == null) {
            // won't be able to finish
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString +
                    ":activateWithOperationContext():  *** WARNING ***  No active ConfigurationContext object is available.");
            }
            return;
        }

        AxisConfiguration axisCfg = configCtx.getAxisConfiguration();

        AxisOperation axisOp = operationCtx.getAxisOperation();
        ServiceContext serviceCtx = operationCtx.getServiceContext();

        ServiceGroupContext serviceGroupCtx = null;
        AxisService axisSrv = null;
        AxisServiceGroup axisSG = null;

        if (serviceCtx != null) {
            serviceGroupCtx = serviceCtx.getServiceGroupContext();
            axisSrv = serviceCtx.getAxisService();
        }

        if (serviceGroupCtx != null) {
            axisSG = serviceGroupCtx.getDescription();
        }

        //---------------------------------------------------------------------
        // link to the objects in the object graph
        //---------------------------------------------------------------------

        setConfigurationContext(configCtx);

        setAxisOperation(axisOp);
        setAxisService(axisSrv);
        setAxisServiceGroup(axisSG);

        setServiceGroupContext(serviceGroupCtx);
        setServiceContext(serviceCtx);
        setOperationContext(operationCtx);

        //---------------------------------------------------------------------
        // reconcile the remaining objects
        //---------------------------------------------------------------------

        // We previously saved metaAxisMessage; restore it
        if (metaAxisMessage != null) {
            if (axisOp != null) {
                // TODO: check for the empty name
                this.setAxisMessage(ActivateUtils.findMessage(axisOp,
                                                 metaAxisMessage.getQNameAsString(),
                                                 metaAxisMessage.getExtraName()));
            }
        }

        //---------------------------------------------------------------------
        // options
        //---------------------------------------------------------------------
        if (options != null) {
            options.activate(configCtx);
        }

        String tmpID = getMessageID();

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":activateWithOperationContext():   message ID [" +
                    tmpID + "]");
        }

        //---------------------------------------------------------------------
        // transports
        //---------------------------------------------------------------------

        // We previously saved metaTransportIn; restore it
        if (metaTransportIn != null) {
            QName qin = metaTransportIn.getQName();
            TransportInDescription tmpIn = null;
            try {
                tmpIn = axisCfg.getTransportIn(qin.getLocalPart());
            }
            catch (Exception exin) {
                // if a fault is thrown, log it and continue
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                        "activateWithOperationContext():  exception caught when getting the TransportInDescription [" +
                        qin.toString() + "]  from the AxisConfiguration [" +
                        exin.getClass().getName() + " : " + exin.getMessage() + "]");
                }

            }

            if (tmpIn != null) {
                transportIn = tmpIn;
            } else {
                transportIn = null;
            }
        } else {
            transportIn = null;
        }

        // We previously saved metaTransportOut; restore it
        if (metaTransportOut != null) {
            QName qout = metaTransportOut.getQName();
            TransportOutDescription tmpOut = null;
            try {
                tmpOut = axisCfg.getTransportOut(qout.getLocalPart());
            }
            catch (Exception exout) {
                // if a fault is thrown, log it and continue
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                        "activateWithOperationContext():  exception caught when getting the TransportOutDescription [" +
                        qout.toString() + "]  from the AxisConfiguration [" +
                        exout.getClass().getName() + " : " + exout.getMessage() + "]");
                }
            }

            if (tmpOut != null) {
                transportOut = tmpOut;
            } else {
                transportOut = null;
            }
        } else {
            transportOut = null;
        }

        //-------------------------------------------------------
        // reconcile the execution chain
        //-------------------------------------------------------
        if (metaExecutionChain != null) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString +
                        ":activateWithOperationContext(): reconciling the execution chain...");
            }

            currentHandlerIndex = metaHandlerIndex;
            currentPhaseIndex = metaPhaseIndex;

            executionChain = restoreHandlerList(metaExecutionChain);

            try {
                deserializeSelfManagedData();
            }
            catch (Exception ex) {
                // log the exception
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(logCorrelationIDString +
                        ":activateWithOperationContext(): *** WARNING *** deserializing the self managed data encountered Exception [" +
                        ex.getClass().getName() + " : " + ex.getMessage() + "]", ex);
                }
            }
        }

        //-------------------------------------------------------
        // reconcile the lists for the executed phases
        //-------------------------------------------------------
        if (metaExecuted != null) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString +
                        ":activateWithOperationContext(): reconciling the executed chain...");
            }

            if (!(executedPhasesReset)) {
                executedPhases =
                        restoreExecutedList(executedPhases, metaExecuted);
            }
        }

        if (executedPhases == null) {
            executedPhases = new LinkedList<Handler>();
        }

        //-------------------------------------------------------
        // done, reset the flag
        //-------------------------------------------------------
        needsToBeReconciled = false;

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":activateWithOperationContext():  END");
        }
    }


    /**
     * @param metaDataEntries ArrayList of MetaDataEntry objects
     * @return ArrayList of Handlers based on our list of handlers from the reconstituted deserialized list, and the existing handlers in the AxisConfiguration object.  May return null.
     */
    private ArrayList<Handler> restoreHandlerList(ArrayList<MetaDataEntry> metaDataEntries) {
        AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();

        List<Handler> existingHandlers = new ArrayList<Handler>();

        // TODO: I'm using clone for the ArrayList returned from axisConfig object.
        //     Does it do a deep clone of the Handlers held there?  Does it matter?
        switch (FLOW) {
            case IN_FLOW:
                existingHandlers.addAll(axisConfig.getInFlowPhases());
                break;

            case OUT_FLOW:
            	existingHandlers.addAll(axisConfig.getOutFlowPhases());
                break;

            case IN_FAULT_FLOW:
            	existingHandlers.addAll(axisConfig.getInFaultFlowPhases());
                break;

            case OUT_FAULT_FLOW:
            	existingHandlers.addAll(axisConfig.getOutFaultFlowPhases());
                break;
        }

        existingHandlers = flattenHandlerList(existingHandlers, null);

        ArrayList<Handler> handlerListToReturn = new ArrayList<Handler>();

        for (int i = 0; i < metaDataEntries.size(); i++) {
            Handler handler = (Handler) ActivateUtils
                    .findHandler(existingHandlers, (MetaDataEntry) metaDataEntries.get(i));

            if (handler != null) {
                handlerListToReturn.add(handler);
            }
        }

        return handlerListToReturn;
    }


    /**
     * Using meta data for phases/handlers, create a linked list of actual
     * phase/handler objects.  The created list is composed of the objects
     * from the base list at the top of the created list followed by the
     * restored objects.
     *
     * @param base            Linked list of phase/handler objects
     * @param metaDataEntries Linked list of MetaDataEntry objects
     * @return LinkedList of objects or NULL if none available
     */
    private LinkedList<Handler> restoreExecutedList(LinkedList<Handler> base, LinkedList<MetaDataEntry> metaDataEntries) {
        if (metaDataEntries == null) {
            return base;
        }

        // get a list of existing handler/phase objects for the restored objects

        ArrayList<MetaDataEntry> tmpMetaDataList = new ArrayList<MetaDataEntry>(metaDataEntries);

        ArrayList<Handler> existingList = restoreHandlerList(tmpMetaDataList);

        if ((existingList == null) || (existingList.isEmpty())) {
            return base;
        }

        // set up a list to return

        LinkedList<Handler> returnedList = new LinkedList<Handler>();

        if (base != null) {
            returnedList.addAll(base);
        }

        returnedList.addAll(existingList);

        return returnedList;
    }


    /**
     * Process the list of handlers from the Phase object
     * into the appropriate meta data.
     *
     * @param phase   The Phase object containing a list of handlers
     * @param mdPhase The meta data object associated with the specified Phase object
     */
    private void setupPhaseList(Phase phase, MetaDataEntry mdPhase) {
        // get the list from the phase object
        List<Handler> handlers = phase.getHandlers();

        if (handlers.isEmpty()) {
            // done, make sure there is no list in the given meta data
            mdPhase.removeList();
            return;
        }

        // get the metadata on each member of the list

        int listSize = handlers.size();

        if (listSize > 0) {

            Iterator<Handler> i = handlers.iterator();

            while (i.hasNext()) {
                Object obj = i.next();
                String objClass = obj.getClass().getName();

                // start the meta data entry for this object
                MetaDataEntry mdEntry = new MetaDataEntry();
                mdEntry.setClassName(objClass);

                // get the correct object-specific name
                String qnameAsString;

                if (obj instanceof Phase) {
                    // nested condition, the phase object contains another phase!
                    Phase phaseObj = (Phase) obj;
                    qnameAsString = phaseObj.getName();

                    // add the list of handlers to the meta data
                    setupPhaseList(phaseObj, mdEntry);
                } else if (obj instanceof Handler) {
                    Handler handlerObj = (Handler) obj;
                    qnameAsString = handlerObj.getName();
                } else {
                    // TODO: will there be any other kinds of objects
                    // in the list?
                    qnameAsString = "NULL";
                }

                mdEntry.setQName(qnameAsString);

                // done with setting up the meta data for the list entry
                // so add it to the parent
                mdPhase.addToList(mdEntry);

                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(getLogIDString() + ":setupPhaseList(): list entry class [" +
                            objClass + "] qname [" + qnameAsString + "]");
                }

            } // end while entries in list
        } else {
            // a list with no entries
            // done, make sure there is no list in the given meta data
            mdPhase.removeList();
        }
    }


    /**
     * Return a Read-Only copy of this message context
     * that has been extracted from the object
     * hierachy.  In other words, the message context
     * copy does not have links to the object graph.
     * <p/>
     * NOTE: The copy shares certain objects with the original.
     * The intent is to use the copy to read values but not
     * modify them, especially since the copy is not part
     * of the normal *Context and Axis* object graph.
     *
     * @return A copy of the message context that is not in the object graph
     */
    public MessageContext extractCopyMessageContext() {
        MessageContext copy = new MessageContext();
        String logCorrelationIDString = getLogIDString();
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace(logCorrelationIDString + ":extractCopyMessageContext():  based on " +
                    logCorrelationIDString + "   into copy " + copy.getLogIDString());
        }

        //---------------------------------------------------------
        // various simple fields
        //---------------------------------------------------------

        copy.setFLOW(FLOW);

        copy.setProcessingFault(processingFault);
        copy.setPaused(paused);
        copy.setOutputWritten(outputWritten);
        copy.setNewThreadRequired(newThreadRequired);
        copy.setDoingREST(doingREST);
        copy.setDoingMTOM(doingMTOM);
        copy.setDoingSwA(doingSwA);
        copy.setResponseWritten(responseWritten);
        copy.setServerSide(serverSide);

        copy.setLastTouchedTime(getLastTouchedTime());

        //---------------------------------------------------------
        // message
        //---------------------------------------------------------
        try {
            copy.setEnvelope(envelope);
        }
        catch (Exception ex) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(logCorrelationIDString +
                    ":extractCopyMessageContext():  Exception caught when setting the copy with the envelope",
                      ex);
            }
        }

        copy.setAttachmentMap(attachments);

        copy.setIsSOAP11Explicit(isSOAP11);

        //---------------------------------------------------------
        // ArrayList executionChain
        //     handler and phase related data
        //---------------------------------------------------------
        copy.setExecutionChain(executionChain);

        // the setting of the execution chain is actually a reset
        // so copy the indices after putting in the execution chain
        copy.setCurrentHandlerIndex(currentHandlerIndex);
        copy.setCurrentPhaseIndex(currentPhaseIndex);

        //---------------------------------------------------------
        // LinkedList executedPhases
        //---------------------------------------------------------
        copy.setExecutedPhasesExplicit(executedPhases);

        //---------------------------------------------------------
        // options
        //---------------------------------------------------------
        copy.setOptionsExplicit(options);

        //---------------------------------------------------------
        // axis operation
        //---------------------------------------------------------
        copy.setAxisOperation(null);

        //---------------------------------------------------------
        // operation context
        //---------------------------------------------------------
        copy.setOperationContext(null);

        //---------------------------------------------------------
        // axis service
        //---------------------------------------------------------
        copy.setAxisService(null);

        //-------------------------
        // serviceContextID string
        //-------------------------
        copy.setServiceContextID(serviceContextID);

        //-------------------------
        // serviceContext
        //-------------------------
        copy.setServiceContext(null);

        //---------------------------------------------------------
        // serviceGroup
        //---------------------------------------------------------
        copy.setServiceGroupContext(null);

        //-----------------------------
        // serviceGroupContextId string
        //-----------------------------
        copy.setServiceGroupContextId(serviceGroupContextId);

        //---------------------------------------------------------
        // axis message
        //---------------------------------------------------------
        copy.setAxisMessage(axisMessage);

        //---------------------------------------------------------
        // configuration context
        //---------------------------------------------------------
        copy.setConfigurationContext(configurationContext);

        //---------------------------------------------------------
        // session context
        //---------------------------------------------------------
        copy.setSessionContext(sessionContext);

        //---------------------------------------------------------
        // transport
        //---------------------------------------------------------

        //------------------------------
        // incomingTransportName string
        //------------------------------
        copy.setIncomingTransportName(incomingTransportName);

        copy.setTransportIn(transportIn);
        copy.setTransportOut(transportOut);

        //---------------------------------------------------------
        // properties
        //---------------------------------------------------------
        // Only set the local properties (i.e. don't use getProperties())
        copy.setProperties(properties);

        //---------------------------------------------------------
        // special data
        //---------------------------------------------------------

        copy.setSelfManagedDataMapExplicit(selfManagedDataMap);

        //---------------------------------------------------------
        // done
        //---------------------------------------------------------

        return copy;
    }

    //------------------------------------------------------------------------
    // additional setter methods needed to copy the message context object
    //------------------------------------------------------------------------

    public void setIsSOAP11Explicit(boolean t) {
        isSOAP11 = t;
    }

    public void setExecutedPhasesExplicit(LinkedList<Handler> inb) {
        executedPhases = inb;
    }

    public void setSelfManagedDataMapExplicit(LinkedHashMap<String, Object> map) {
        selfManagedDataMap = map;
    }

    public void setOptionsExplicit(Options op) {
        this.options = op;
    }


    /**
     * Trace a warning message, if needed, indicating that this
     * object needs to be activated before accessing certain fields.
     *
     * @param methodname The method where the warning occurs
     */
    private void checkActivateWarning(String methodname) {
        if (needsToBeReconciled) {
            if (LoggingControl.debugLoggingAllowed && log.isWarnEnabled()) {
                log.warn(getLogIDString() + ":" + methodname + "(): ****WARNING**** " + myClassName +
                    ".activate(configurationContext) needs to be invoked.");
            }
        }
    }

    public ConfigurationContext getRootContext() {
        return configurationContext;
    }

    public boolean isFault() {
        try {
            return getEnvelope().hasFault();
        } catch (Exception e) {
            // TODO: What should we be doing here?  No envelope certainly seems bad....
            return false;
        }
    }


    /**
     * Obtain the Exception which caused the processing chain to halt.
     * @return null, or an Exception.
     */
    public Exception getFailureReason() {
        return failureReason;
    }

    /**
     * Set the failure reason.  Only AxisEngine should ever do this.
     *
     * @param failureReason an Exception which caused processing to halt.
     */
    public void setFailureReason(Exception failureReason) {
        this.failureReason = failureReason;
    }
}
