blob: 25e169eb1830bb28072c20b04b3cd50aa19a13cf [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.om.util.UUIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.externalize.ActivateUtils;
import org.apache.axis2.context.externalize.ExternalizeConstants;
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.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.util.MetaDataEntry;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2004_Constants;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2006Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.namespace.QName;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
* An OperationContext represents a running "instance" of an operation, which is
* represented by an AxisOperation object. This concept is needed to allow
* messages to be grouped into operations as in WSDL 2.0-speak operations are
* essentially arbitrary message exchange patterns. So as messages are being
* exchanged the OperationContext remembers the state of where in the message
* exchange pattern it is in.
* <p/>
* The base implementation of OperationContext
* supports MEPs which have one input message and/or one output message. That
* is, it supports the all the MEPs that are in the WSDL 2.0 specification. In
* order to support another MEP one must extend this class and register its
* creation in the OperationContexFactory.
*/
public class OperationContext extends AbstractContext
implements Externalizable, SafeSerializable {
/*
* setup for logging
*/
private static final Log log = LogFactory.getLog(OperationContext.class);
private static final String myClassName = "OperationContext";
private boolean debugEnabled = log.isDebugEnabled();
/**
* An ID which can be used to correlate operations on an instance of
* this object in the log files
*/
private String logCorrelationIDString = null;
/**
* @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 = -7264782778333554350L;
/**
* @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;
/**
* @serial isComplete flag
*/
private boolean isComplete;
/**
* @serial key string
*/
//The key value of the operationContextMap;
private String key;
// the AxisOperation of which this is a running instance. The MEP of this
// AxisOperation must be one of the 8 predefined ones in WSDL 2.0.
private transient AxisOperation axisOperation;
/**
* the set of message contexts associated with this operation
*/
private transient HashMap<String, MessageContext> messageContexts;
//----------------------------------------------------------------
// 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;
/**
* Suppresses warning messages for activation
* when doing internal reconciliation
*/
private transient boolean suppressWarnings = false;
/**
* 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 ServiceContext metadata will be used during
* activate to match up with an existing object
*/
private transient ServiceContext metaParent = null;
/**
* This is used to hold information about message context objects
* that are in the messageContexts map. This allows message context
* objects to be isolated from the object graph so that duplicate
* copies of objects are not saved/restored.
*/
private HashMap metaMessageContextMap = null;
/**
* This is used to hold temporarily any message context objects
* that were isolated from the messageContexts map.
*/
private transient HashMap isolatedMessageContexts = null;
/**
* This is used to hold temporarily any message context objects
* from the messageContexts map for save/restore activities.
*/
private transient HashMap workingSet = null;
//----------------------------------------------------------------
// end MetaData section
//----------------------------------------------------------------
/**
* Simple constructor (needed for deserialization, shouldn't be used otherwise!)
*/
public OperationContext() {
super(null);
this.messageContexts = new HashMap<String, MessageContext>();
}
/**
* Constructs a new OperationContext.
*
* @param axisOperation the AxisOperation whose running instances' state this
* OperationContext represents.
* @param serviceContext the parent ServiceContext representing any state related to
* the set of all operations of the service.
*/
public OperationContext(AxisOperation axisOperation,
ServiceContext serviceContext) {
super(serviceContext);
this.messageContexts = new HashMap<String, MessageContext>();
this.axisOperation = axisOperation;
this.setParent(serviceContext);
}
/**
* When a new message is added to the <code>MEPContext</code> the logic
* should be included remove the MEPContext from the table in the
* <code>EngineContext</code>. Example: IN_IN_OUT At the second IN
* message the MEPContext should be removed from the AxisOperation.
*
* @param msgContext
*/
public void addMessageContext(MessageContext msgContext) throws AxisFault {
if (axisOperation != null) {
axisOperation.addMessageContext(msgContext, this);
touch();
}
}
/**
* Removes the pointers to this <code>OperationContext</code> in the
* <code>ConfigurationContext</code>'s OperationContextMap so that this
* <code>OperationContext</code> will eventually get garbage collected
* along with the <code>MessageContext</code>'s it contains. Note that if
* the caller wants to make sure its safe to clean up this OperationContext
* he should call isComplete() first. However, in cases like IN_OPTIONAL_OUT
* and OUT_OPTIONAL_IN, it is possibe this will get called without the MEP
* being complete due to the optional nature of the MEP.
*/
public void cleanup() {
ServiceContext serv = getServiceContext();
if (serv != null) {
serv.getConfigurationContext().unregisterOperationContext(key);
}
}
/**
* @return Returns the axisOperation.
*/
public AxisOperation getAxisOperation() {
if (needsToBeReconciled && !suppressWarnings && debugEnabled) {
log.debug(getLogCorrelationIDString() +
":getAxisOperation(): ****WARNING**** OperationContext.activate(configurationContext) needs to be invoked.");
}
return axisOperation;
}
/**
* Returns the EngineContext in which the parent ServiceContext lives.
*
* @return Returns parent ServiceContext's parent EngineContext.
*/
public ConfigurationContext getConfigurationContext() {
if (parent != null) {
return ((ServiceContext) parent).getConfigurationContext();
} else {
return null;
}
}
/**
* @param messageLabel
* @return Returns MessageContext.
* @throws AxisFault
*/
public MessageContext getMessageContext(String messageLabel)
throws AxisFault {
if (messageContexts == null) {
return null;
}
return (MessageContext) messageContexts.get(messageLabel);
}
/**
* Remove the indicated message context.
* Example Usage: The exchange is aborted and we need to
* undo the work and free resources.
* @param label
* @throws AxisFault
*/
public void removeMessageContext(String label) throws AxisFault {
MessageContext mc = getMessageContext(label);
if (mc != null) {
messageContexts.remove(mc);
setComplete(false);
touch();
}
}
public HashMap<String, MessageContext> getMessageContexts() {
return messageContexts;
}
/**
* Returns the ServiceContext in which this OperationContext lives.
*
* @return Returns parent ServiceContext.
*/
public ServiceContext getServiceContext() {
return (ServiceContext) parent;
}
/**
* Checks to see if the MEP is complete. i.e. whether all the messages that
* are associated with the MEP has arrived and MEP is complete.
*/
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public void setKey(String key) {
this.key = key;
}
/* ===============================================================
* Externalizable support
* ===============================================================
*/
/**
* Save the contents of this object.
* <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 out The stream to write the object contents to
* @throws IOException
*/
public void writeExternal(ObjectOutput o) throws IOException {
SafeObjectOutputStream out = SafeObjectOutputStream.install(o);
//---------------------------------------------------------
// 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
//---------------------------------------------------------
out.writeLong(getLastTouchedTime());
out.writeBoolean(isComplete);
out.writeObject(key);
out.writeObject(logCorrelationIDString);
//---------------------------------------------------------
// properties
//---------------------------------------------------------
out.writeUTF("properties"); // write marker
out.writeMap(getProperties());
//---------------------------------------------------------
// AxisOperation axisOperation
//---------------------------------------------------------
out.writeUTF("metaAxisOperation"); // write marker
metaAxisOperation = null;
if (axisOperation != null) {
metaAxisOperation = new MetaDataEntry(axisOperation.getClass().getName(),
axisOperation.getName().toString());
}
out.writeObject(metaAxisOperation);
//---------------------------------------------------------
// AxisOperation axisService
//---------------------------------------------------------
// save the meta data for the corresponding axis service to better
// match up the axis operation
out.writeUTF("metaAxisService"); // write marker
metaAxisService = null;
AxisService axisService = axisOperation.getAxisService();
if (axisService != null) {
metaAxisService =
new MetaDataEntry(axisService.getClass().getName(), axisService.getName());
}
out.writeObject(metaAxisService);
//---------------------------------------------------------
// parent
//---------------------------------------------------------
out.writeUTF("parent"); // write marker
out.writeObject(this.getServiceContext());
//---------------------------------------------------------
// HashMap messageContexts table
//---------------------------------------------------------
// NOTES: The assumption is that the table contains message contexts
// that are in the OperationContext hierarchy. To reduce overlap
// of object information that is being saved, extract the
// message context objects from the hierachy before saving.
// When the OperationContext is restored, the "slimmed down"
// message context objects are plugged back into the hierachy
// using the restored OperationContext as a basis.
// first deal with the original messageContexts table
HashMap tmpMsgCtxMap = null;
if ((messageContexts != null) && (!messageContexts.isEmpty())) {
// create a table of the non-isolated message contexts
workingSet = new HashMap();
tmpMsgCtxMap = new HashMap();
Set keySet = messageContexts.keySet();
Iterator itKeys = keySet.iterator();
while (itKeys.hasNext()) {
// expect the key to be a string
String keyObj = (String) itKeys.next();
// get the message context associated with that label
MessageContext value = (MessageContext) messageContexts.get(keyObj);
boolean addToWorkingSet = true;
// check to see if this message context was isolated
if (isolatedMessageContexts != null) {
if (!isolatedMessageContexts.isEmpty()) {
// see if the message context was previously isolated
MessageContext valueIsolated =
(MessageContext) isolatedMessageContexts.get(keyObj);
if (valueIsolated != null) {
String idIsol = valueIsolated.getMessageID();
if (idIsol != null) {
if (idIsol.equals(value.getMessageID())) {
// don't add to working set
addToWorkingSet = false;
}
}
}
}
}
if (addToWorkingSet) {
// put the meta data entry in the list
workingSet.put(keyObj, value);
}
}
// now we have a working set
Set keySet2 = workingSet.keySet();
Iterator itKeys2 = keySet2.iterator();
while (itKeys2.hasNext()) {
// expect the key to be a string
String keyObj2 = (String) itKeys2.next();
// get the message context associated with that label
MessageContext mc = (MessageContext) workingSet.get(keyObj2);
// construct a copy of the message context
// that has been extracted from the object hierarchy
MessageContext copyMC = mc.extractCopyMessageContext();
// Don't persist the message of the other message contexts
copyMC.setEnvelope(null);
// put the modified entry in the list
tmpMsgCtxMap.put(keyObj2, copyMC);
// trace point
if (log.isTraceEnabled()) {
log.trace(getLogCorrelationIDString() +
":writeExternal(): getting working set entry key [" + keyObj2 +
"] message context ID[" + copyMC.getMessageID() + "]");
}
}
}
out.writeUTF("messagecontexts"); // write marker
out.writeMap(tmpMsgCtxMap);
out.writeUTF("metaMessageContextMap");
out.writeMap(metaMessageContextMap);
//---------------------------------------------------------
// done
//---------------------------------------------------------
}
/**
* Restore the contents of the object 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 in The stream to read the object contents from
* @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
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
//---------------------------------------------------------
long time = in.readLong();
setLastTouchedTime(time);
isComplete = in.readBoolean();
key = (String) in.readObject();
logCorrelationIDString = (String) in.readObject();
// trace point
if (log.isTraceEnabled()) {
log.trace(myClassName + ":readExternal(): reading input stream for [" +
getLogCorrelationIDString() + "] ");
}
//---------------------------------------------------------
// properties
//---------------------------------------------------------
in.readUTF(); // read marker
properties = in.readMap(new HashMapUpdateLockable());
//---------------------------------------------------------
// axis operation meta data
//---------------------------------------------------------
// axisOperation is not usable until the meta data has been reconciled
axisOperation = null;
in.readUTF(); // read marker
metaAxisOperation = (MetaDataEntry) in.readObject();
//---------------------------------------------------------
// axis service meta data
//---------------------------------------------------------
// axisService is not usable until the meta data has been reconciled
in.readUTF(); // read marker
metaAxisService = (MetaDataEntry) in.readObject();
//---------------------------------------------------------
// parent
//---------------------------------------------------------
// ServiceContext is not usable until it has been activated
in.readUTF(); // read marker
metaParent = (ServiceContext) in.readObject();
//---------------------------------------------------------
// HashMap messageContexts table
//---------------------------------------------------------
// set to empty until this can be activiated
messageContexts = new HashMap();
in.readUTF(); // read marker
workingSet = in.readHashMap();
in.readUTF(); // read marker
metaMessageContextMap = in.readHashMap();
//---------------------------------------------------------
// done
//---------------------------------------------------------
}
/**
* 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;
}
// get the axis configuration
AxisConfiguration axisConfig = cc.getAxisConfiguration();
// We previously saved metaAxisService; restore it
AxisService axisService = null;
if (metaAxisService != null) {
axisService = ActivateUtils.findService(axisConfig, metaAxisService.getClassName(),
metaAxisService.getQNameAsString());
}
// We previously saved metaAxisOperation; restore it
if (metaAxisOperation != null) {
if (axisService != null) {
this.axisOperation = ActivateUtils.findOperation(axisService,
metaAxisOperation.getClassName(),
metaAxisOperation.getQName());
} else {
this.axisOperation = ActivateUtils.findOperation(axisConfig,
metaAxisOperation.getClassName(),
metaAxisOperation.getQName());
}
}
// the parent ServiceContext object was saved
// either use the restored object or sync up with
// an existing ServiceContext object
if (metaParent != null) {
// find out if a copy of the ServiceContext object exists on this
// engine where this OperationContext is being restored/activated
// if so, use that object instead of the restored object
// in order to make sure that future changes to service-level
// properties are preserved for future operations
String groupName = metaParent.getGroupName();
String serviceName = metaParent.getName();
ServiceContext existingSC = null;
// first look for the ServiceContext via the ServiceContextGroup
ServiceGroupContext sgc = cc.getServiceGroupContext(groupName);
if (sgc != null) {
existingSC = sgc.findServiceContext(serviceName);
}
if (existingSC == null) {
// we couldn't find the ServiceContext via the ServiceContextGroup
// try via the set of existing operation contexts
OperationContext existingOC =
cc.findOperationContext(getOperationName(), serviceName, groupName);
if (existingOC != null) {
existingSC = (ServiceContext) existingOC.getParent();
}
}
if (existingSC == null) {
// could not find an existing ServiceContext
// use the restored object
metaParent.activate(cc);
// set parent
this.setParent(metaParent);
} else {
// switch over to the existing object
this.setParent(existingSC);
// do a copy of the properties from the restored object
// to the existing ServiceContext
// Should the copy be a non-destructive one? That is,
// if the key already exists in the properties table of the
// existing object, should the value be overwritten from the
// restored ojbect? For now, the decision is that the state
// that has been preserved for a saved context object is
// is important to be restored.
metaParent.putContextProperties(existingSC, true);
}
} else {
// set parent to null
this.setParent(metaParent);
}
// reseed the operation context map
ServiceContext serv = getServiceContext();
ConfigurationContext activeCC;
if (serv != null) {
activeCC = serv.getConfigurationContext();
} else {
activeCC = cc;
}
if (key != null) {
// We only want to (re)register this if it's an outbound message
String mepString = getAxisOperation().getMessageExchangePattern();
if (mepString.equals(WSDL20_2006Constants.MEP_URI_OUT_ONLY)
|| mepString.equals(WSDL20_2004_Constants.MEP_URI_OUT_ONLY)
|| ((mepString.equals(WSDL20_2006Constants.MEP_URI_OUT_IN)
|| mepString.equals(WSDL20_2004_Constants.MEP_URI_OUT_IN))
&& !isComplete)) {
// make sure this OperationContext object is registered in the
// list maintained by the ConfigurationContext object
boolean registrationSuceeded = activeCC.registerOperationContext(key, this, true);
if (!registrationSuceeded) {
// trace point
if (log.isTraceEnabled()) {
log.trace(getLogCorrelationIDString()+ ":activate(): " +
"OperationContext key [" + key
+ "] already exists in ConfigurationContext map. " +
"This OperationContext ["
+ this.toString() + "] was not added to the table.");
}
}
}
}
//-------------------------------------------------------
// update the modified entries in the messageContexts table
//-------------------------------------------------------
// NOTE: an entry in the metaMessageContextMap must wait
// for its corresponding active message context object
// to call this operation context object so we don't
// need to handle the metaMessagecontextMap table here
if ((workingSet != null) && (!workingSet.isEmpty())) {
Set keySet = workingSet.keySet();
Iterator itKeys = keySet.iterator();
while (itKeys.hasNext()) {
// expect the key to be a string
String keyObj = (String) itKeys.next();
// get the message context associated with that label
MessageContext value = (MessageContext) workingSet.get((Object) keyObj);
// activate that object
if (value != null) {
// trace point
if (log.isTraceEnabled()) {
log.trace(getLogCorrelationIDString() + ":activate(): key [" + keyObj +
"] message id [" + value.getMessageID() + "]");
}
suppressWarnings = true;
value.activateWithOperationContext(this);
suppressWarnings = false;
if (messageContexts == null) {
messageContexts = new HashMap();
}
}
// put the entry in the "real" table
// note that the key or the value could be null
messageContexts.put(keyObj, value);
}
}
//-------------------------------------------------------
// done, reset the flag
//-------------------------------------------------------
needsToBeReconciled = false;
}
/**
* Isolate the specified message context object
* to prepare for serialization. Instead of
* saving the entire message context object,
* just setup some metadata about the message
* context.
* <p/>
* Note: this will remove the specified
* message context object from the message context
* table.
*
* @param mc The message context object
*/
public void isolateMessageContext(MessageContext mc) {
if (mc == null) {
return;
}
if ((messageContexts == null) || (messageContexts.isEmpty())) {
return;
}
// get the message ID from the message context
String messageID = mc.getMessageID();
if (messageID == null) {
// can't locate it without identification
return;
}
Iterator it = messageContexts.keySet().iterator();
while (it.hasNext()) {
// get the key
Object keyObj = it.next();
// get the value associated with that key
MessageContext value = (MessageContext) messageContexts.get(keyObj);
if (value != null) {
String valueID = value.getMessageID();
if ((valueID != null) && valueID.equals(messageID)) {
// found the input message context in our table
if (metaMessageContextMap == null) {
metaMessageContextMap = new HashMap();
}
// build a meta data entry
// MessageContext class name
// MessageContext messageID
// key used in the original hashmap that is associated with this MessageContext
// note: this is typically something like "In", "Out", "Fault"
//
MetaDataEntry metaData = new MetaDataEntry(value.getClass().getName(),
value.getMessageID(),
keyObj.toString());
// put the meta data entry in the list
// note that if the entry was already in the list,
// this will replace that entry
metaMessageContextMap.put(keyObj, metaData);
// don't change the original table - there's potentially lots of areas that
// grab the table
// // now remove the original entry from the messageContexts table
// messageContexts.remove(keyObj);
// put the original entry in the temporary list
if (isolatedMessageContexts == null) {
isolatedMessageContexts = new HashMap();
}
// note that if the entry was already in the list,
// this will replace that entry
isolatedMessageContexts.put(keyObj, value);
// trace point
if (log.isTraceEnabled()) {
log.trace(getLogCorrelationIDString() +
":isolateMessageContext(): set up message context id[" + valueID +
"] with key [" + keyObj.toString() +
"] from messageContexts table to prepare for serialization.");
}
break;
}
}
}
}
/**
* Restore the specified MessageContext object in the
* table used to hold the message contexts associated
* with this operation.
*
* @param msg The message context object
*/
public void restoreMessageContext(MessageContext msg) {
// see if the activation has been done
if (needsToBeReconciled) {
// nope, need to do the activation first
if (debugEnabled) {
log.debug(getLogCorrelationIDString() +
":restoreMessageContext(): *** WARNING : need to invoke activate() prior to restoring the MessageContext to the list.");
}
return;
}
if (msg == null) {
return;
}
String msgID = msg.getMessageID();
if (msgID == null) {
if (debugEnabled) {
// can't identify message context
log.debug(getLogCorrelationIDString() +
":restoreMessageContext(): *** WARNING : MessageContext does not have a message ID.");
}
return;
}
// first check the metaMessageContextMap to see if
// the specified message context object matches any
// of the metadata entries.
if ((metaMessageContextMap != null) && (!metaMessageContextMap.isEmpty())) {
Iterator itMeta = metaMessageContextMap.keySet().iterator();
while (itMeta.hasNext()) {
String keyM = (String) itMeta.next();
MetaDataEntry valueM = (MetaDataEntry) metaMessageContextMap.get(keyM);
String valueM_ID;
if (valueM != null) {
valueM_ID = valueM.getQNameAsString();
if (msgID.equals(valueM_ID)) {
String label = valueM.getExtraName();
if (messageContexts == null) {
messageContexts = new HashMap();
}
// put the message context into the messageContexts table
messageContexts.put(label, msg);
// remove the metadata from the metadata table
metaMessageContextMap.remove(keyM);
if (log.isTraceEnabled()) {
log.trace(getLogCorrelationIDString() +
":restoreMessageContext(): restored label [" + label +
"] message ID [" + msg.getMessageID() + "]");
}
break;
}
}
}
} else
// see if we can put the msg directly in the messageContexts table
if ((messageContexts != null) && (!messageContexts.isEmpty())) {
Iterator itList = messageContexts.keySet().iterator();
while (itList.hasNext()) {
String key = (String) itList.next();
MessageContext value = (MessageContext) messageContexts.get(key);
String valueID;
if (value != null) {
valueID = value.getMessageID();
if (msgID.equals(valueID)) {
// update the entry
messageContexts.put(key, msg);
}
}
}
}
}
/**
* Get the name associated with the operation.
*
* @return The name String
*/
public String getOperationName() {
String opName = null;
if (axisOperation != null) {
QName qname = axisOperation.getName();
if (qname != null) {
opName = qname.getLocalPart();
}
}
return opName;
}
/**
* Get the name associated with the service.
*
* @return The name String
*/
public String getServiceName() {
String srvName = null;
ServiceContext sc = (ServiceContext) getParent();
if (sc == null) {
sc = metaParent;
}
if (sc != null) {
srvName = sc.getName();
}
return srvName;
}
/**
* Get the name associated with the service group.
*
* @return The name String
*/
public String getServiceGroupName() {
String srvGroupName = null;
ServiceContext sc = (ServiceContext) getParent();
if (sc == null) {
sc = metaParent;
}
if (sc != null) {
srvGroupName = sc.getGroupName();
}
return srvGroupName;
}
/**
* Compares key parts of the state from the current instance of
* this class with the specified instance to see if they are
* equivalent.
* <p/>
* This differs from the java.lang.Object.equals() method in
* that the equals() method generally looks at both the
* object identity (location in memory) and the object state
* (data).
* <p/>
*
* @param ctx The object to compare with
* @return TRUE if this object is equivalent with the specified object
* that is, key fields match
* FALSE, otherwise
*/
public boolean isEquivalent(OperationContext ctx) {
// NOTE: the input object is expected to exist (ie, be non-null)
if (this.isComplete != ctx.isComplete()) {
return false;
}
if (!this.axisOperation.equals(ctx.getAxisOperation())) {
return false;
}
// TODO: consider checking the parent objects for equivalency
// TODO: consider checking fields from the super class for equivalency
return true;
}
/**
* Get the ID associated with this object instance.
*
* @return A string that can be output to a log file as an identifier
* for this object instance. It is suitable for matching related log
* entries.
*/
public String getLogCorrelationIDString() {
if (logCorrelationIDString == null) {
logCorrelationIDString = myClassName + "@" + UUIDGenerator.getUUID();
}
return logCorrelationIDString;
}
public ConfigurationContext getRootContext() {
return this.getConfigurationContext();
}
}