blob: 5cb74608ad02d045202c3e8cdca0b1044bd230c8 [file] [log] [blame]
/*
* 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;
}
}