0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: */
0019:
0020: package org.apache.axis2.context;
0021:
0022: import org.apache.axiom.attachments.Attachments;
0023: import org.apache.axiom.om.OMOutputFormat;
0024: import org.apache.axiom.om.impl.MTOMConstants;
0025: import org.apache.axiom.om.impl.builder.StAXBuilder;
0026: import org.apache.axiom.om.util.StAXUtils;
0027: import org.apache.axiom.om.util.UUIDGenerator;
0028: import org.apache.axiom.soap.SOAP11Constants;
0029: import org.apache.axiom.soap.SOAP12Constants;
0030: import org.apache.axiom.soap.SOAPEnvelope;
0031: import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
0032: import org.apache.axis2.AxisFault;
0033: import org.apache.axis2.addressing.EndpointReference;
0034: import org.apache.axis2.addressing.RelatesTo;
0035: import org.apache.axis2.builder.BuilderUtil;
0036: import org.apache.axis2.client.Options;
0037: import org.apache.axis2.description.AxisMessage;
0038: import org.apache.axis2.description.AxisModule;
0039: import org.apache.axis2.description.AxisOperation;
0040: import org.apache.axis2.description.AxisService;
0041: import org.apache.axis2.description.AxisServiceGroup;
0042: import org.apache.axis2.description.HandlerDescription;
0043: import org.apache.axis2.description.ModuleConfiguration;
0044: import org.apache.axis2.description.Parameter;
0045: import org.apache.axis2.description.TransportInDescription;
0046: import org.apache.axis2.description.TransportOutDescription;
0047: import org.apache.axis2.engine.AxisConfiguration;
0048: import org.apache.axis2.engine.Handler;
0049: import org.apache.axis2.engine.Phase;
0050: import org.apache.axis2.engine.AxisError;
0051: import org.apache.axis2.util.LoggingControl;
0052: import org.apache.axis2.util.MetaDataEntry;
0053: import org.apache.axis2.util.ObjectStateUtils;
0054: import org.apache.axis2.util.SelfManagedDataHolder;
0055: import org.apache.axis2.util.JavaUtils;
0056: import org.apache.commons.logging.Log;
0057: import org.apache.commons.logging.LogFactory;
0058: import org.apache.neethi.Policy;
0059:
0060: import javax.activation.DataHandler;
0061: import javax.xml.namespace.QName;
0062: import javax.xml.stream.XMLStreamReader;
0063: import java.io.ByteArrayInputStream;
0064: import java.io.ByteArrayOutputStream;
0065: import java.io.Externalizable;
0066: import java.io.IOException;
0067: import java.io.ObjectInput;
0068: import java.io.ObjectOutput;
0069: import java.util.ArrayList;
0070: import java.util.Collections;
0071: import java.util.HashMap;
0072: import java.util.Iterator;
0073: import java.util.LinkedHashMap;
0074: import java.util.LinkedList;
0075: import java.util.Map;
0076:
0077: /**
0078: * <p>Axis2 states are held in two information models, called description hierarchy
0079: * and context hierarchy. Description hierarchy hold deployment configuration
0080: * and it's values does not change unless deployment configuration change
0081: * occurs where Context hierarchy hold run time information. Both hierarchies
0082: * consists four levels, Global, Service Group, Operation and Message. Please
0083: * look at "Information Model" section of "Axis2 Architecture Guide" for more
0084: * information.</p>
0085: * <p>MessageContext hold run time information about one Message invocation. It
0086: * hold reference to OperationContext, ServiceGroupContext, and Configuration
0087: * Context tied with current message. For an example if you need accesses to other
0088: * messages of the current invocation, you can get to them via OperationContext.
0089: * Addition to class attributes define in Message context, message context stores
0090: * the information as name value pairs. Those name value pairs,and class attributes
0091: * tweak the execution behavior of message context and some of them can be find in
0092: * org.apache.axis2.Constants class. (TODO we should provide list of supported
0093: * options). You may set them at any level of context hierarchy and they will
0094: * affect invocations related to their child elements. </p>
0095: */
0096: public class MessageContext extends AbstractContext implements
0097: Externalizable {
0098:
0099: /*
0100: * setup for logging
0101: */
0102: private static final Log log = LogFactory
0103: .getLog(MessageContext.class);
0104:
0105: /**
0106: * @serial An ID which can be used to correlate operations on a single
0107: * message in the log files, irrespective of thread switches, persistence,
0108: * etc.
0109: */
0110: private String logCorrelationID = null;
0111:
0112: /**
0113: * This string will be used to hold a form of the logCorrelationID that
0114: * is more suitable for output than its generic form.
0115: */
0116: private transient String logCorrelationIDString = null;
0117:
0118: private static final String myClassName = "MessageContext";
0119:
0120: /**
0121: * @serial The serialization version ID tracks the version of the class.
0122: * If a class definition changes, then the serialization/externalization
0123: * of the class is affected. If a change to the class is made which is
0124: * not compatible with the serialization/externalization of the class,
0125: * then the serialization version ID should be updated.
0126: * Refer to the "serialVer" utility to compute a serialization
0127: * version ID.
0128: */
0129: private static final long serialVersionUID = -7753637088257391858L;
0130:
0131: /**
0132: * @serial Tracks the revision level of a class to identify changes to the
0133: * class definition that are compatible to serialization/externalization.
0134: * If a class definition changes, then the serialization/externalization
0135: * of the class is affected.
0136: * Refer to the writeExternal() and readExternal() methods.
0137: */
0138: // supported revision levels, add a new level to manage compatible changes
0139: private static final int REVISION_1 = 1;
0140: // current revision level of this object
0141: private static final int revisionID = REVISION_1;
0142:
0143: /**
0144: * A place to store the current MessageContext
0145: */
0146: public static ThreadLocal currentMessageContext = new ThreadLocal();
0147:
0148: public static MessageContext getCurrentMessageContext() {
0149: return (MessageContext) currentMessageContext.get();
0150: }
0151:
0152: public static void setCurrentMessageContext(MessageContext ctx) {
0153: currentMessageContext.set(ctx);
0154: }
0155:
0156: /**
0157: * @serial Options on the message
0158: */
0159: protected Options options;
0160:
0161: public final static int IN_FLOW = 1;
0162: public final static int IN_FAULT_FLOW = 3;
0163:
0164: public final static int OUT_FLOW = 2;
0165: public final static int OUT_FAULT_FLOW = 4;
0166:
0167: public static final String REMOTE_ADDR = "REMOTE_ADDR";
0168: public static final String TRANSPORT_ADDR = "TRANSPORT_ADDR";
0169: public static final String TRANSPORT_HEADERS = "TRANSPORT_HEADERS";
0170:
0171: /**
0172: * message attachments
0173: * NOTE: Serialization of message attachments is handled as part of the
0174: * overall message serialization. If this needs to change, then
0175: * investigate having the Attachment class implement the
0176: * java.io.Externalizable interface.
0177: */
0178: public transient Attachments attachments;
0179:
0180: /**
0181: * Field TRANSPORT_OUT
0182: */
0183: public static final String TRANSPORT_OUT = "TRANSPORT_OUT";
0184:
0185: /**
0186: * Field TRANSPORT_IN
0187: */
0188: public static final String TRANSPORT_IN = "TRANSPORT_IN";
0189:
0190: /**
0191: * Field CHARACTER_SET_ENCODING
0192: */
0193: public static final String CHARACTER_SET_ENCODING = "CHARACTER_SET_ENCODING";
0194:
0195: /**
0196: * Field UTF_8. This is the 'utf-8' value for CHARACTER_SET_ENCODING
0197: * property.
0198: */
0199: public static final String UTF_8 = "UTF-8";
0200:
0201: /**
0202: * Field UTF_16. This is the 'utf-16' value for CHARACTER_SET_ENCODING
0203: * property.
0204: */
0205: public static final String UTF_16 = "utf-16";
0206:
0207: /**
0208: * Field TRANSPORT_SUCCEED
0209: */
0210: public static final String TRANSPORT_SUCCEED = "TRANSPORT_SUCCEED";
0211:
0212: /**
0213: * Field DEFAULT_CHAR_SET_ENCODING. This is the default value for
0214: * CHARACTER_SET_ENCODING property.
0215: */
0216: public static final String DEFAULT_CHAR_SET_ENCODING = UTF_8;
0217:
0218: /**
0219: * @serial The direction flow in use to figure out which path the message is in
0220: * (send or receive)
0221: */
0222: public int FLOW = IN_FLOW;
0223:
0224: /**
0225: * To invoke fireAndforget method we have to hand over transport sending logic to a thread
0226: * other wise user has to wait till it get transport response (in the case of HTTP its HTTP
0227: * 202)
0228: */
0229: public static final String TRANSPORT_NON_BLOCKING = "transportNonBlocking";
0230:
0231: /**
0232: * This property allows someone (e.g. RM) to disable an async callback from
0233: * being invoked if a fault occurs during message transmission. If this is
0234: * not set, it can be assumed that the fault will be delivered via
0235: * Callback.onError(...).
0236: */
0237: public static final String DISABLE_ASYNC_CALLBACK_ON_TRANSPORT_ERROR = "disableTransmissionErrorCallback";
0238:
0239: /**
0240: * @serial processingFault
0241: */
0242: private boolean processingFault;
0243:
0244: /**
0245: * @serial paused
0246: */
0247: private boolean paused;
0248:
0249: /**
0250: * @serial outputWritten
0251: */
0252: public boolean outputWritten;
0253:
0254: /**
0255: * @serial newThreadRequired
0256: */
0257: private boolean newThreadRequired;
0258:
0259: /**
0260: * @serial isSOAP11
0261: */
0262: private boolean isSOAP11 = true;
0263:
0264: /**
0265: * @serial The chain of Handlers/Phases for processing this message
0266: */
0267: private ArrayList executionChain;
0268:
0269: /**
0270: * @serial The chain of executed Handlers/Phases from processing
0271: */
0272: private LinkedList executedPhases;
0273:
0274: /**
0275: * @serial Flag to indicate if we are doing REST
0276: */
0277: private boolean doingREST;
0278:
0279: /**
0280: * @serial Flag to indicate if we are doing MTOM
0281: */
0282: private boolean doingMTOM;
0283:
0284: /**
0285: * @serial Flag to indicate if we are doing SWA
0286: */
0287: private boolean doingSwA;
0288:
0289: /**
0290: * AxisMessage associated with this message context
0291: */
0292: private transient AxisMessage axisMessage;
0293:
0294: /**
0295: * AxisOperation associated with this message context
0296: */
0297: private transient AxisOperation axisOperation;
0298:
0299: /**
0300: * AxisService
0301: */
0302: private transient AxisService axisService;
0303:
0304: /**
0305: * AxisServiceGroup
0306: * <p/>
0307: * Note the service group can be set independently of the service
0308: * so the service might not match up with this serviceGroup
0309: */
0310: private transient AxisServiceGroup axisServiceGroup;
0311:
0312: /**
0313: * ConfigurationContext
0314: */
0315: private transient ConfigurationContext configurationContext;
0316:
0317: /**
0318: * @serial Index into the executuion chain of the currently executing handler
0319: */
0320: private int currentHandlerIndex;
0321:
0322: /**
0323: * @serial Index into the current Phase of the currently executing handler (if any)
0324: */
0325: private int currentPhaseIndex;
0326:
0327: /**
0328: * If we're processing this MC due to flowComplete() being called in the case
0329: * of an Exception, this will hold the Exception which caused the problem.
0330: */
0331: private Exception failureReason;
0332:
0333: /**
0334: * @serial SOAP envelope
0335: */
0336: private SOAPEnvelope envelope;
0337:
0338: /**
0339: * @serial OperationContext
0340: */
0341: private OperationContext operationContext;
0342:
0343: /**
0344: * @serial responseWritten
0345: */
0346: private boolean responseWritten;
0347:
0348: /**
0349: * @serial serverSide
0350: */
0351: private boolean serverSide;
0352:
0353: /**
0354: * @serial ServiceContext
0355: */
0356: private ServiceContext serviceContext;
0357:
0358: /**
0359: * @serial service context ID
0360: */
0361: private String serviceContextID;
0362:
0363: /**
0364: * @serial service group context
0365: */
0366: private ServiceGroupContext serviceGroupContext;
0367:
0368: /**
0369: * @serial Holds a key to retrieve the correct ServiceGroupContext.
0370: */
0371: private String serviceGroupContextId;
0372:
0373: /**
0374: * @serial sessionContext
0375: */
0376: private SessionContext sessionContext;
0377:
0378: /**
0379: * transport out description
0380: */
0381: private transient TransportOutDescription transportOut;
0382:
0383: /**
0384: * transport in description
0385: */
0386: private transient TransportInDescription transportIn;
0387:
0388: /**
0389: * @serial incoming transport name
0390: */
0391: //The value will be set by the transport receiver and there will be validation for the transport
0392: //at the dispatch phase (its post condition)
0393: private String incomingTransportName;
0394:
0395: /*
0396: * SelfManagedData will hold message-specific data set by handlers
0397: * Note that this list is not explicitly saved by the MessageContext, but
0398: * rather through the SelfManagedDataManager interface implemented by handlers
0399: */
0400: private transient LinkedHashMap selfManagedDataMap = null;
0401:
0402: //-------------------------------------------------------------------------
0403: // MetaData for data to be restored in activate() after readExternal()
0404: //-------------------------------------------------------------------------
0405:
0406: /**
0407: * Indicates whether the message context has been reconstituted
0408: * and needs to have its object references reconciled
0409: */
0410: private transient boolean needsToBeReconciled = false;
0411:
0412: /**
0413: * selfManagedDataHandlerCount is a count of the number of handlers
0414: * that actually saved data during serialization
0415: */
0416: private transient int selfManagedDataHandlerCount = 0;
0417:
0418: /**
0419: * SelfManagedData cannot be restored until the configurationContext
0420: * is available, so we have to hold the data from readExternal until
0421: * activate is called.
0422: */
0423: private transient ArrayList selfManagedDataListHolder = null;
0424:
0425: /**
0426: * The ordered list of metadata for handlers/phases
0427: * used during re-constitution of the message context
0428: */
0429: private transient ArrayList metaExecutionChain = null;
0430:
0431: /**
0432: * The ordered list of metadata for executed phases
0433: * used during re-constitution of the message context
0434: */
0435: private transient LinkedList metaExecuted = null;
0436:
0437: /**
0438: * Index into the executuion chain of the currently executing handler
0439: */
0440: private transient int metaHandlerIndex = 0;
0441:
0442: /**
0443: * Index into the current Phase of the currently executing handler (if any)
0444: */
0445: private transient int metaPhaseIndex = 0;
0446:
0447: /**
0448: * The AxisOperation metadata will be used during
0449: * activate to match up with an existing object
0450: */
0451: private transient MetaDataEntry metaAxisOperation = null;
0452:
0453: /**
0454: * The AxisService metadata will be used during
0455: * activate to match up with an existing object
0456: */
0457: private transient MetaDataEntry metaAxisService = null;
0458:
0459: /**
0460: * The AxisServiceGroup metadata will be used during
0461: * activate to match up with an existing object
0462: */
0463: private transient MetaDataEntry metaAxisServiceGroup = null;
0464:
0465: /**
0466: * The TransportOutDescription metadata will be used during
0467: * activate to match up with an existing object
0468: */
0469: private transient MetaDataEntry metaTransportOut = null;
0470:
0471: /**
0472: * The TransportInDescription metadata will be used during
0473: * activate to match up with an existing object
0474: */
0475: private transient MetaDataEntry metaTransportIn = null;
0476:
0477: /**
0478: * The AxisMessage metadata will be used during
0479: * activate to match up with an existing object
0480: */
0481: private transient MetaDataEntry metaAxisMessage = null;
0482:
0483: /**
0484: * Indicates whether this message context has an
0485: * AxisMessage object associated with it that needs to
0486: * be reconciled
0487: */
0488: private transient boolean reconcileAxisMessage = false;
0489:
0490: /**
0491: * Indicates whether the executed phase list
0492: * was reset before the restored list has been reconciled
0493: */
0494: private transient boolean executedPhasesReset = false;
0495:
0496: //----------------------------------------------------------------
0497: // end MetaData section
0498: //----------------------------------------------------------------
0499:
0500: /**
0501: * Constructor
0502: */
0503: public MessageContext() {
0504: super (null);
0505: options = new Options();
0506: }
0507:
0508: /**
0509: * Constructor has package access
0510: *
0511: * @param configContext the associated ConfigurationContext
0512: */
0513: MessageContext(ConfigurationContext configContext) {
0514: this ();
0515: setConfigurationContext(configContext);
0516: }
0517:
0518: public String toString() {
0519: return getLogIDString();
0520: }
0521:
0522: /**
0523: * Get a "raw" version of the logCorrelationID. The logCorrelationID
0524: * is guaranteed to be unique and may be persisted along with the rest
0525: * of the message context.
0526: *
0527: * @return A string that can be output to a log file as an identifier
0528: * for this MessageContext. It is suitable for matching related log
0529: * entries.
0530: */
0531: public String getLogCorrelationID() {
0532: if (logCorrelationID == null) {
0533: logCorrelationID = UUIDGenerator.getUUID();
0534: }
0535: return logCorrelationID;
0536: }
0537:
0538: /**
0539: * Get a formatted version of the logCorrelationID.
0540: *
0541: * @return A string that can be output to a log file as an identifier
0542: * for this MessageContext. It is suitable for matching related log
0543: * entries.
0544: */
0545: public String getLogIDString() {
0546: if (logCorrelationIDString == null) {
0547: logCorrelationIDString = "[MessageContext: logID="
0548: + getLogCorrelationID() + "]";
0549: }
0550: return logCorrelationIDString;
0551: }
0552:
0553: /**
0554: * Pause the execution of the current handler chain
0555: */
0556: public void pause() {
0557: paused = true;
0558: }
0559:
0560: public AxisOperation getAxisOperation() {
0561: if (LoggingControl.debugLoggingAllowed) {
0562: checkActivateWarning("getAxisOperation");
0563: }
0564: return axisOperation;
0565: }
0566:
0567: public AxisService getAxisService() {
0568: if (LoggingControl.debugLoggingAllowed) {
0569: checkActivateWarning("getAxisService");
0570: }
0571: return axisService;
0572: }
0573:
0574: /*
0575: * <P>
0576: * Note the service group can be set independently of the service
0577: * so the service might not match up with this serviceGroup
0578: */
0579: public AxisServiceGroup getAxisServiceGroup() {
0580: if (LoggingControl.debugLoggingAllowed) {
0581: checkActivateWarning("getAxisServiceGroup");
0582: }
0583: return axisServiceGroup;
0584: }
0585:
0586: public ConfigurationContext getConfigurationContext() {
0587: if (LoggingControl.debugLoggingAllowed) {
0588: checkActivateWarning("getConfigurationContext");
0589: }
0590: return configurationContext;
0591: }
0592:
0593: public int getCurrentHandlerIndex() {
0594: return currentHandlerIndex;
0595: }
0596:
0597: public int getCurrentPhaseIndex() {
0598: return currentPhaseIndex;
0599: }
0600:
0601: /**
0602: * @return Returns SOAPEnvelope.
0603: */
0604: public SOAPEnvelope getEnvelope() {
0605: return envelope;
0606: }
0607:
0608: public ArrayList getExecutionChain() {
0609: if (LoggingControl.debugLoggingAllowed) {
0610: checkActivateWarning("getExecutionChain");
0611: }
0612: return executionChain;
0613: }
0614:
0615: /**
0616: * Add a Phase to the collection of executed phases for the path.
0617: * Phases will be inserted in a LIFO data structure.
0618: *
0619: * @param phase The phase to add to the list.
0620: */
0621: public void addExecutedPhase(Handler phase) {
0622: if (executedPhases == null) {
0623: executedPhases = new LinkedList();
0624: }
0625: executedPhases.addFirst(phase);
0626: }
0627:
0628: /**
0629: * Remove the first Phase in the collection of executed phases
0630: */
0631: public void removeFirstExecutedPhase() {
0632: if (executedPhases != null) {
0633: executedPhases.removeFirst();
0634: }
0635: }
0636:
0637: /**
0638: * Get an iterator over the executed phase list.
0639: *
0640: * @return An Iterator over the LIFO data structure.
0641: */
0642: public Iterator getExecutedPhases() {
0643: if (LoggingControl.debugLoggingAllowed) {
0644: checkActivateWarning("getExecutedPhases");
0645: }
0646: if (executedPhases == null) {
0647: executedPhases = new LinkedList();
0648: }
0649: return executedPhases.iterator();
0650: }
0651:
0652: /**
0653: * Reset the list of executed phases.
0654: * This is needed because the OutInAxisOperation currently invokes
0655: * receive() even when a fault occurs, and we will have already executed
0656: * the flowComplete on those before receiveFault() is called.
0657: */
0658: public void resetExecutedPhases() {
0659: executedPhasesReset = true;
0660: executedPhases = new LinkedList();
0661: }
0662:
0663: /**
0664: * @return Returns EndpointReference.
0665: */
0666: public EndpointReference getFaultTo() {
0667: return options.getFaultTo();
0668: }
0669:
0670: /**
0671: * @return Returns EndpointReference.
0672: */
0673: public EndpointReference getFrom() {
0674: return options.getFrom();
0675: }
0676:
0677: /**
0678: * @return Returns message id.
0679: */
0680: public String getMessageID() {
0681: return options.getMessageId();
0682: }
0683:
0684: /**
0685: * Retrieves both module specific configuration parameters as well as other
0686: * parameters. The order of search is as follows:
0687: * <ol>
0688: * <li> Search in module configurations inside corresponding operation
0689: * description if its there </li>
0690: * <li> Search in corresponding operation if its there </li>
0691: * <li> Search in module configurations inside corresponding service
0692: * description if its there </li>
0693: * <li> Next search in Corresponding Service description if its there </li>
0694: * <li> Next search in module configurations inside axisConfiguration </li>
0695: * <li> Search in AxisConfiguration for parameters </li>
0696: * <li> Next get the corresponding module and search for the parameters
0697: * </li>
0698: * <li> Search in HandlerDescription for the parameter </li>
0699: * </ol>
0700: * <p/> and the way of specifying module configuration is as follows
0701: * <moduleConfig name="addressing"> <parameter name="addressingPara"
0702: * >N/A</parameter> </moduleConfig>
0703: *
0704: * @param key :
0705: * Parameter Name
0706: * @param moduleName :
0707: * Name of the module
0708: * @param handler <code>HandlerDescription</code>
0709: * @return Parameter <code>Parameter</code>
0710: */
0711: public Parameter getModuleParameter(String key, String moduleName,
0712: HandlerDescription handler) {
0713: Parameter param;
0714: ModuleConfiguration moduleConfig;
0715:
0716: AxisOperation opDesc = getAxisOperation();
0717:
0718: if (opDesc != null) {
0719:
0720: moduleConfig = opDesc.getModuleConfig(moduleName);
0721:
0722: if (moduleConfig != null) {
0723: param = moduleConfig.getParameter(key);
0724:
0725: if (param != null) {
0726: return param;
0727: } else {
0728: param = opDesc.getParameter(key);
0729:
0730: if (param != null) {
0731: return param;
0732: }
0733: }
0734: }
0735: }
0736:
0737: AxisService axisService = getAxisService();
0738:
0739: if (axisService != null) {
0740:
0741: moduleConfig = axisService.getModuleConfig(moduleName);
0742:
0743: if (moduleConfig != null) {
0744: param = moduleConfig.getParameter(key);
0745:
0746: if (param != null) {
0747: return param;
0748: } else {
0749: param = axisService.getParameter(key);
0750:
0751: if (param != null) {
0752: return param;
0753: }
0754: }
0755: }
0756: }
0757:
0758: AxisServiceGroup axisServiceDesc = getAxisServiceGroup();
0759:
0760: if (axisServiceDesc != null) {
0761:
0762: moduleConfig = axisServiceDesc.getModuleConfig(moduleName);
0763:
0764: if (moduleConfig != null) {
0765: param = moduleConfig.getParameter(key);
0766:
0767: if (param != null) {
0768: return param;
0769: } else {
0770: param = axisServiceDesc.getParameter(key);
0771:
0772: if (param != null) {
0773: return param;
0774: }
0775: }
0776: }
0777: }
0778:
0779: AxisConfiguration baseConfig = configurationContext
0780: .getAxisConfiguration();
0781:
0782: moduleConfig = baseConfig.getModuleConfig(moduleName);
0783:
0784: if (moduleConfig != null) {
0785: param = moduleConfig.getParameter(key);
0786:
0787: if (param != null) {
0788: return param;
0789: } else {
0790: param = baseConfig.getParameter(key);
0791:
0792: if (param != null) {
0793: return param;
0794: }
0795: }
0796: }
0797:
0798: AxisModule module = baseConfig.getModule(moduleName);
0799:
0800: if (module != null) {
0801: param = module.getParameter(key);
0802:
0803: if (param != null) {
0804: return param;
0805: }
0806: }
0807:
0808: param = handler.getParameter(key);
0809:
0810: return param;
0811: }
0812:
0813: public OperationContext getOperationContext() {
0814: if (LoggingControl.debugLoggingAllowed) {
0815: checkActivateWarning("getOperationContext");
0816: }
0817: return operationContext;
0818: }
0819:
0820: /**
0821: * Retrieves configuration descriptor parameters at any level. The order of
0822: * search is as follows:
0823: * <ol>
0824: * <li> Search in operation description if it exists </li>
0825: * <li> If parameter is not found or if operationContext is null, search in
0826: * AxisService </li>
0827: * <li> If parameter is not found or if axisService is null, search in
0828: * AxisConfiguration </li>
0829: * </ol>
0830: *
0831: * @param key name of desired parameter
0832: * @return Parameter <code>Parameter</code>
0833: */
0834: public Parameter getParameter(String key) {
0835: if (axisOperation != null) {
0836: return axisOperation.getParameter(key);
0837: }
0838:
0839: if (axisService != null) {
0840: return axisService.getParameter(key);
0841: }
0842:
0843: if (axisServiceGroup != null) {
0844: return axisServiceGroup.getParameter(key);
0845: }
0846:
0847: if (configurationContext != null) {
0848: AxisConfiguration baseConfig = configurationContext
0849: .getAxisConfiguration();
0850: return baseConfig.getParameter(key);
0851: }
0852: return null;
0853: }
0854:
0855: /**
0856: * Retrieves a property value. The order of search is as follows: search in
0857: * my own options and then look in my context hierarchy. Since its possible
0858: * that the entire hierarchy is not present, I will start at whatever level
0859: * has been set and start there.
0860: *
0861: * @param name name of the property to search for
0862: * @return the value of the property, or null if the property is not found
0863: */
0864: public Object getProperty(String name) {
0865: if (LoggingControl.debugLoggingAllowed) {
0866: checkActivateWarning("getProperty");
0867: }
0868:
0869: // search in my own options
0870: Object obj = super .getProperty(name);
0871: if (obj != null) {
0872: return obj;
0873: }
0874:
0875: obj = options.getProperty(name);
0876: if (obj != null) {
0877: return obj;
0878: }
0879:
0880: // My own context hierarchy may not all be present. So look for whatever
0881: // nearest level is present and ask that to find the property.
0882: if (operationContext != null) {
0883: return operationContext.getProperty(name);
0884: }
0885: if (serviceContext != null) {
0886: return serviceContext.getProperty(name);
0887: }
0888: if (serviceGroupContext != null) {
0889: return serviceGroupContext.getProperty(name);
0890: }
0891: if (configurationContext != null) {
0892: return configurationContext.getProperty(name);
0893: }
0894:
0895: // tough
0896: return null;
0897: }
0898:
0899: /**
0900: * Check if a given property is true. Will return false if the property
0901: * does not exist or is not an explicit "true" value.
0902: *
0903: * @param name name of the property to check
0904: * @return true if the property exists and is Boolean.TRUE, "true", 1, etc.
0905: */
0906: public boolean isPropertyTrue(String name) {
0907: return isPropertyTrue(name, false);
0908: }
0909:
0910: /**
0911: * Check if a given property is true. Will return the passed default if the property
0912: * does not exist.
0913: *
0914: * @param name name of the property to check
0915: * @param defaultVal the default value if the property doesn't exist
0916: * @return true if the property exists and is Boolean.TRUE, "true", 1, etc.
0917: */
0918: public boolean isPropertyTrue(String name, boolean defaultVal) {
0919: return JavaUtils
0920: .isTrueExplicitly(getProperty(name), defaultVal);
0921: }
0922:
0923: /**
0924: * Retrieves all property values. The order of search is as follows: search in
0925: * my own options and then look in my context hierarchy. Since its possible
0926: * that the entire hierarchy is not present, it will start at whatever level
0927: * has been set and start there.
0928: * The returned map is unmodifiable, so any changes to the properties have
0929: * to be done by calling {@link #setProperty(String,Object)}. In addition,
0930: * any changes to the properties are not reflected on this map.
0931: *
0932: * @return An unmodifiable map containing the combination of all available
0933: * properties or an empty map.
0934: */
0935: public Map getProperties() {
0936: final Map resultMap = new HashMap();
0937:
0938: // My own context hierarchy may not all be present. So look for whatever
0939: // nearest level is present and add the properties
0940: // We have to access the contexts in reverse order, in order to allow
0941: // a nearer context to overwrite values from a more distant context
0942: if (configurationContext != null) {
0943: resultMap.putAll(configurationContext.getProperties());
0944: }
0945: if (serviceGroupContext != null) {
0946: resultMap.putAll(serviceGroupContext.getProperties());
0947: }
0948: if (serviceContext != null) {
0949: resultMap.putAll(serviceContext.getProperties());
0950: }
0951: if (operationContext != null) {
0952: resultMap.putAll(operationContext.getProperties());
0953: }
0954: // and now add options
0955: resultMap.putAll(options.getProperties());
0956: return Collections.unmodifiableMap(resultMap);
0957: }
0958:
0959: /**
0960: * @return Returns RelatesTo array.
0961: */
0962: public RelatesTo[] getRelationships() {
0963: return options.getRelationships();
0964: }
0965:
0966: /**
0967: * Get any RelatesTos of a particular type associated with this MessageContext
0968: * TODO: Shouldn't this return a List?
0969: *
0970: * @param type the relationship type
0971: * @return Returns RelatesTo.
0972: */
0973: public RelatesTo getRelatesTo(String type) {
0974: return options.getRelatesTo(type);
0975: }
0976:
0977: /**
0978: * @return Returns RelatesTo.
0979: */
0980: public RelatesTo getRelatesTo() {
0981: return options.getRelatesTo();
0982: }
0983:
0984: /**
0985: * @return Returns EndpointReference.
0986: */
0987: public EndpointReference getReplyTo() {
0988: return options.getReplyTo();
0989: }
0990:
0991: /**
0992: * @return Returns ServiceContext.
0993: */
0994: public ServiceContext getServiceContext() {
0995: if (LoggingControl.debugLoggingAllowed) {
0996: checkActivateWarning("getServiceContext");
0997: }
0998: return serviceContext;
0999: }
1000:
1001: /**
1002: * @return Returns the serviceContextID.
1003: */
1004: public String getServiceContextID() {
1005: return serviceContextID;
1006: }
1007:
1008: public ServiceGroupContext getServiceGroupContext() {
1009: if (LoggingControl.debugLoggingAllowed) {
1010: checkActivateWarning("getServiceGroupContext");
1011: }
1012: return serviceGroupContext;
1013: }
1014:
1015: public String getServiceGroupContextId() {
1016: return serviceGroupContextId;
1017: }
1018:
1019: /**
1020: * @return Returns SessionContext.
1021: */
1022: public SessionContext getSessionContext() {
1023: return sessionContext;
1024: }
1025:
1026: public void setSessionContext(SessionContext sessionContext) {
1027: this .sessionContext = sessionContext;
1028: }
1029:
1030: /**
1031: * @return Returns soap action.
1032: */
1033: public String getSoapAction() {
1034: return options.getAction();
1035: }
1036:
1037: /**
1038: * @return Returns EndpointReference.
1039: */
1040: public EndpointReference getTo() {
1041: return options.getTo();
1042: }
1043:
1044: /**
1045: * @return Returns TransportInDescription.
1046: */
1047: public TransportInDescription getTransportIn() {
1048: if (LoggingControl.debugLoggingAllowed) {
1049: checkActivateWarning("getTransportIn");
1050: }
1051: return transportIn;
1052: }
1053:
1054: /**
1055: * @return Returns TransportOutDescription.
1056: */
1057: public TransportOutDescription getTransportOut() {
1058: if (LoggingControl.debugLoggingAllowed) {
1059: checkActivateWarning("getTransportOut");
1060: }
1061: return transportOut;
1062: }
1063:
1064: public String getWSAAction() {
1065: return options.getAction();
1066: }
1067:
1068: /**
1069: * @return Returns boolean.
1070: */
1071: public boolean isDoingMTOM() {
1072: return doingMTOM;
1073: }
1074:
1075: /**
1076: * @return Returns boolean.
1077: */
1078: public boolean isDoingREST() {
1079: return doingREST;
1080: }
1081:
1082: /**
1083: * @return Returns boolean.
1084: */
1085: public boolean isDoingSwA() {
1086: return doingSwA;
1087: }
1088:
1089: /**
1090: * @return Returns boolean.
1091: */
1092: public boolean isNewThreadRequired() {
1093: return newThreadRequired;
1094: }
1095:
1096: /**
1097: * @return Returns boolean.
1098: */
1099: public boolean isOutputWritten() {
1100: return outputWritten;
1101: }
1102:
1103: /**
1104: * @return Returns boolean.
1105: */
1106: public boolean isPaused() {
1107: return paused;
1108: }
1109:
1110: public void setPaused(boolean paused) {
1111: this .paused = paused;
1112: }
1113:
1114: /**
1115: * @return Returns boolean.
1116: */
1117: public boolean isProcessingFault() {
1118: return processingFault;
1119: }
1120:
1121: /**
1122: * @return Returns boolean.
1123: */
1124: public boolean isResponseWritten() {
1125: return responseWritten;
1126: }
1127:
1128: public boolean isSOAP11() {
1129: return isSOAP11;
1130: }
1131:
1132: /**
1133: * @return Returns boolean.
1134: */
1135: public boolean isServerSide() {
1136: return serverSide;
1137: }
1138:
1139: public AxisMessage getAxisMessage() {
1140: if (reconcileAxisMessage) {
1141: if (LoggingControl.debugLoggingAllowed
1142: && log.isWarnEnabled()) {
1143: log
1144: .warn(this .getLogIDString()
1145: + ":getAxisMessage(): ****WARNING**** MessageContext.activate(configurationContext) needs to be invoked.");
1146: }
1147: }
1148:
1149: return axisMessage;
1150: }
1151:
1152: public void setAxisMessage(AxisMessage axisMessage) {
1153: this .axisMessage = axisMessage;
1154: }
1155:
1156: public void setAxisOperation(AxisOperation axisOperation) {
1157: this .axisOperation = axisOperation;
1158: }
1159:
1160: public void setAxisService(AxisService axisService) {
1161: this .axisService = axisService;
1162: if (this .axisService != null) {
1163: this .axisServiceGroup = axisService.getAxisServiceGroup();
1164: } else {
1165: this .axisServiceGroup = null;
1166: }
1167: }
1168:
1169: /*
1170: * note setAxisServiceGroup() does not verify that the service is associated with the service group!
1171: */
1172: public void setAxisServiceGroup(AxisServiceGroup axisServiceGroup) {
1173: // need to set the axis service group object to null when necessary
1174: // for example, when extracting the message context object from
1175: // the object graph
1176: this .axisServiceGroup = axisServiceGroup;
1177: }
1178:
1179: /**
1180: * @param context
1181: */
1182: public void setConfigurationContext(ConfigurationContext context) {
1183: configurationContext = context;
1184: }
1185:
1186: public void setCurrentHandlerIndex(int currentHandlerIndex) {
1187: this .currentHandlerIndex = currentHandlerIndex;
1188: }
1189:
1190: public void setCurrentPhaseIndex(int currentPhaseIndex) {
1191: this .currentPhaseIndex = currentPhaseIndex;
1192: }
1193:
1194: /**
1195: * @param b
1196: */
1197: public void setDoingMTOM(boolean b) {
1198: doingMTOM = b;
1199: }
1200:
1201: /**
1202: * @param b
1203: */
1204: public void setDoingREST(boolean b) {
1205: doingREST = b;
1206: }
1207:
1208: /**
1209: * @param b
1210: */
1211: public void setDoingSwA(boolean b) {
1212: doingSwA = b;
1213: }
1214:
1215: /**
1216: * @param envelope
1217: */
1218: public void setEnvelope(SOAPEnvelope envelope) throws AxisFault {
1219: this .envelope = envelope;
1220:
1221: if (this .envelope != null) {
1222: String soapNamespaceURI = envelope.getNamespace()
1223: .getNamespaceURI();
1224:
1225: if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI
1226: .equals(soapNamespaceURI)) {
1227: isSOAP11 = false;
1228: } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI
1229: .equals(soapNamespaceURI)) {
1230: isSOAP11 = true;
1231: } else {
1232: throw new AxisFault(
1233: "Unknown SOAP Version. Current Axis handles only SOAP 1.1 and SOAP 1.2 messages");
1234: }
1235: }
1236: }
1237:
1238: /**
1239: * Set the execution chain of Handler in this MessageContext. Doing this
1240: * causes the current handler/phase indexes to reset to 0, since we have new
1241: * Handlers to execute (this usually only happens at initialization and when
1242: * a fault occurs).
1243: *
1244: * @param executionChain
1245: */
1246: public void setExecutionChain(ArrayList executionChain) {
1247: this .executionChain = executionChain;
1248: currentHandlerIndex = -1;
1249: currentPhaseIndex = 0;
1250: }
1251:
1252: /**
1253: * @param reference
1254: */
1255: public void setFaultTo(EndpointReference reference) {
1256: options.setFaultTo(reference);
1257: }
1258:
1259: /**
1260: * @param reference
1261: */
1262: public void setFrom(EndpointReference reference) {
1263: options.setFrom(reference);
1264: }
1265:
1266: /**
1267: * @param messageId
1268: */
1269: public void setMessageID(String messageId) {
1270: options.setMessageId(messageId);
1271: }
1272:
1273: /**
1274: * @param b
1275: */
1276: public void setNewThreadRequired(boolean b) {
1277: newThreadRequired = b;
1278: }
1279:
1280: /**
1281: * @param context The OperationContext
1282: */
1283: public void setOperationContext(OperationContext context) {
1284: // allow setting the fields to null
1285: // useful when extracting the messge context from the object graph
1286: operationContext = context;
1287:
1288: this .setParent(operationContext);
1289:
1290: if (operationContext != null) {
1291: if (serviceContext == null) {
1292: setServiceContext(operationContext.getServiceContext());
1293: } else {
1294: if (operationContext.getParent() != serviceContext) {
1295: throw new AxisError(
1296: "ServiceContext in OperationContext does not match !");
1297: }
1298: }
1299:
1300: this .setAxisOperation(operationContext.getAxisOperation());
1301: }
1302: }
1303:
1304: /**
1305: * @param b
1306: */
1307: public void setOutputWritten(boolean b) {
1308: outputWritten = b;
1309: }
1310:
1311: /**
1312: * @param b
1313: */
1314: public void setProcessingFault(boolean b) {
1315: processingFault = b;
1316: }
1317:
1318: /**
1319: * Add a RelatesTo
1320: *
1321: * @param reference RelatesTo describing how we relate to another message
1322: */
1323: public void addRelatesTo(RelatesTo reference) {
1324: options.addRelatesTo(reference);
1325: }
1326:
1327: /**
1328: * Set ReplyTo destination
1329: *
1330: * @param reference the ReplyTo EPR
1331: */
1332: public void setReplyTo(EndpointReference reference) {
1333: options.setReplyTo(reference);
1334: }
1335:
1336: /**
1337: * @param b
1338: */
1339: public void setResponseWritten(boolean b) {
1340: responseWritten = b;
1341: }
1342:
1343: /**
1344: * @param b
1345: */
1346: public void setServerSide(boolean b) {
1347: serverSide = b;
1348: }
1349:
1350: /**
1351: * @param context
1352: */
1353: public void setServiceContext(ServiceContext context) {
1354:
1355: // allow the service context to be set to null
1356: // this allows the message context object to be extraced from
1357: // the object graph
1358:
1359: serviceContext = context;
1360:
1361: if (serviceContext != null) {
1362: if ((operationContext != null)
1363: && (operationContext.getParent() != context)) {
1364: throw new AxisError(
1365: "ServiceContext and OperationContext.parent do not match!");
1366: }
1367: // setting configcontext using configuration context in service context
1368: if (configurationContext == null) {
1369: // setting configcontext
1370: configurationContext = context
1371: .getConfigurationContext();
1372: }
1373: if (serviceGroupContext == null) {
1374: // setting service group context
1375: serviceGroupContext = context.getServiceGroupContext();
1376: }
1377: this .setAxisService(context.getAxisService());
1378: }
1379: }
1380:
1381: /**
1382: * Sets the service context id.
1383: *
1384: * @param serviceContextID
1385: */
1386: public void setServiceContextID(String serviceContextID) {
1387: this .serviceContextID = serviceContextID;
1388: }
1389:
1390: public void setServiceGroupContext(
1391: ServiceGroupContext serviceGroupContext) {
1392: // allow the service group context to be set to null
1393: // this allows the message context object to be extraced from
1394: // the object graph
1395:
1396: this .serviceGroupContext = serviceGroupContext;
1397:
1398: if (this .serviceGroupContext != null) {
1399: this .axisServiceGroup = serviceGroupContext
1400: .getDescription();
1401: }
1402: }
1403:
1404: public void setServiceGroupContextId(String serviceGroupContextId) {
1405: this .serviceGroupContextId = serviceGroupContextId;
1406: }
1407:
1408: /**
1409: * @param soapAction
1410: */
1411: public void setSoapAction(String soapAction) {
1412: options.setAction(soapAction);
1413: }
1414:
1415: /**
1416: * @param to
1417: */
1418: public void setTo(EndpointReference to) {
1419: options.setTo(to);
1420: }
1421:
1422: /**
1423: * @param in
1424: */
1425: public void setTransportIn(TransportInDescription in) {
1426: this .transportIn = in;
1427: }
1428:
1429: /**
1430: * @param out
1431: */
1432: public void setTransportOut(TransportOutDescription out) {
1433: transportOut = out;
1434: }
1435:
1436: /**
1437: * setWSAAction
1438: */
1439: public void setWSAAction(String actionURI) {
1440: options.setAction(actionURI);
1441: }
1442:
1443: public void setWSAMessageId(String messageID) {
1444: options.setMessageId(messageID);
1445: }
1446:
1447: // to get the flow inwhich the execution chain below
1448: public int getFLOW() {
1449: return FLOW;
1450: }
1451:
1452: public void setFLOW(int FLOW) {
1453: this .FLOW = FLOW;
1454: }
1455:
1456: public Options getOptions() {
1457: if (LoggingControl.debugLoggingAllowed) {
1458: checkActivateWarning("getOptions");
1459: }
1460: return options;
1461: }
1462:
1463: /**
1464: * Set the options for myself. I make the given options my own options'
1465: * parent so that that becomes the default. That allows the user to override
1466: * specific options on a given message context and not affect the overall
1467: * options.
1468: *
1469: * @param options the options to set
1470: */
1471: public void setOptions(Options options) {
1472: this .options.setParent(options);
1473: }
1474:
1475: public String getIncomingTransportName() {
1476: return incomingTransportName;
1477: }
1478:
1479: public void setIncomingTransportName(String incomingTransportName) {
1480: this .incomingTransportName = incomingTransportName;
1481: }
1482:
1483: public void setRelationships(RelatesTo[] list) {
1484: options.setRelationships(list);
1485: }
1486:
1487: public Policy getEffectivePolicy() {
1488: if (LoggingControl.debugLoggingAllowed) {
1489: checkActivateWarning("getEffectivePolicy");
1490: }
1491: if (axisMessage != null) {
1492: return axisMessage.getPolicyInclude().getEffectivePolicy();
1493: }
1494: if (axisOperation != null) {
1495: return axisOperation.getPolicyInclude()
1496: .getEffectivePolicy();
1497: }
1498: if (axisService != null) {
1499: return axisService.getPolicyInclude().getEffectivePolicy();
1500: }
1501: return configurationContext.getAxisConfiguration()
1502: .getPolicyInclude().getEffectivePolicy();
1503: }
1504:
1505: public boolean isEngaged(String moduleName) {
1506: if (LoggingControl.debugLoggingAllowed) {
1507: checkActivateWarning("isEngaged");
1508: }
1509: boolean enegage;
1510: if (configurationContext != null) {
1511: AxisConfiguration axisConfig = configurationContext
1512: .getAxisConfiguration();
1513: AxisModule module = axisConfig.getModule(moduleName);
1514: if (module == null) {
1515: return false;
1516: }
1517: enegage = axisConfig.isEngaged(module);
1518: if (enegage) {
1519: return true;
1520: }
1521: if (axisServiceGroup != null) {
1522: enegage = axisServiceGroup.isEngaged(module);
1523: if (enegage) {
1524: return true;
1525: }
1526: }
1527: if (axisService != null) {
1528: enegage = axisService.isEngaged(module);
1529: if (enegage) {
1530: return true;
1531: }
1532: }
1533: if (axisOperation != null) {
1534: enegage = axisOperation.isEngaged(module);
1535: if (enegage) {
1536: return true;
1537: }
1538: }
1539: }
1540: return false;
1541: }
1542:
1543: /**
1544: * Gets the first child of the envelope, check if it is a soap:Body, which means there is no header.
1545: * We do this basically to make sure we don't parse and build the om tree of the whole envelope
1546: * looking for the soap header. If this method returns true, there still is no guarantee that there is
1547: * a soap:Header present, use getHeader() and also check for null on getHeader() to be absolutely sure.
1548: *
1549: * @return boolean
1550: * @deprecated The bonus you used to get from this is now built in to SOAPEnvelope.getHeader()
1551: */
1552: public boolean isHeaderPresent() {
1553: // If there's no envelope there can't be a header.
1554: if (this .envelope == null) {
1555: return false;
1556: }
1557: return (this .envelope.getHeader() != null);
1558: }
1559:
1560: /**
1561: * Setting of the attachments map should be performed at the receipt of a
1562: * message only. This method is only meant to be used by the Axis2
1563: * internals.
1564: *
1565: * @param attachments
1566: */
1567: public void setAttachmentMap(Attachments attachments) {
1568: this .attachments = attachments;
1569: }
1570:
1571: /**
1572: * You can directly access the attachment map of the message context from
1573: * here. Returned attachment map can be empty.
1574: *
1575: * @return attachment
1576: */
1577: public Attachments getAttachmentMap() {
1578: if (attachments == null) {
1579: attachments = new Attachments();
1580: }
1581: return attachments;
1582: }
1583:
1584: /**
1585: * Adds an attachment to the attachment Map of this message context. This
1586: * attachment gets serialised as a MIME attachment when sending the message
1587: * if SOAP with Attachments is enabled.
1588: *
1589: * @param contentID :
1590: * will be the content ID of the MIME part
1591: * @param dataHandler
1592: */
1593: public void addAttachment(String contentID, DataHandler dataHandler) {
1594: if (attachments == null) {
1595: attachments = new Attachments();
1596: }
1597: attachments.addDataHandler(contentID, dataHandler);
1598: }
1599:
1600: /**
1601: * Adds an attachment to the attachment Map of this message context. This
1602: * attachment gets serialised as a MIME attachment when sending the message
1603: * if SOAP with Attachments is enabled. Content ID of the MIME part will be
1604: * auto generated by Axis2.
1605: *
1606: * @param dataHandler
1607: * @return the auto generated content ID of the MIME attachment
1608: */
1609: public String addAttachment(DataHandler dataHandler) {
1610: String contentID = UUIDGenerator.getUUID();
1611: addAttachment(contentID, dataHandler);
1612: return contentID;
1613: }
1614:
1615: /**
1616: * Access the DataHandler of the attachment contained in the map corresponding to the given
1617: * content ID. Returns "NULL" if a attachment cannot be found by the given content ID.
1618: *
1619: * @param contentID :
1620: * Content ID of the MIME attachment
1621: * @return Data handler of the attachment
1622: */
1623: public DataHandler getAttachment(String contentID) {
1624: if (attachments == null) {
1625: attachments = new Attachments();
1626: }
1627: return attachments.getDataHandler(contentID);
1628: }
1629:
1630: /**
1631: * Removes the attachment with the given content ID from the Attachments Map
1632: * Do nothing if a attachment cannot be found by the given content ID.
1633: *
1634: * @param contentID of the attachment
1635: */
1636: public void removeAttachment(String contentID) {
1637: if (attachments != null) {
1638: attachments.removeDataHandler(contentID);
1639: }
1640: }
1641:
1642: /*
1643: * ===============================================================
1644: * SelfManagedData Section
1645: * ===============================================================
1646: */
1647:
1648: /*
1649: * character to delimit strings
1650: */
1651: private String selfManagedDataDelimiter = "*";
1652:
1653: /**
1654: * Set up a unique key in the form of
1655: * <OL>
1656: * <LI>the class name for the class that owns the key
1657: * <LI>delimitor
1658: * <LI>the key as a string
1659: * <LI>delimitor
1660: * <LI>the key's hash code as a string
1661: * </OL>
1662: *
1663: * @param clazz The class that owns the supplied key
1664: * @param key The key
1665: * @return A string key
1666: */
1667: private String generateSelfManagedDataKey(Class clazz, Object key) {
1668: return clazz.getName() + selfManagedDataDelimiter
1669: + key.toString() + selfManagedDataDelimiter
1670: + Integer.toString(key.hashCode());
1671: }
1672:
1673: /**
1674: * Add a key-value pair of self managed data to the set associated with
1675: * this message context.
1676: * <p/>
1677: * This is primarily intended to allow handlers to manage their own
1678: * message-specific data when the message context is saved/restored.
1679: *
1680: * @param clazz The class of the caller that owns the key-value pair
1681: * @param key The key for this data object
1682: * @param value The data object
1683: */
1684: public void setSelfManagedData(Class clazz, Object key, Object value) {
1685: if (selfManagedDataMap == null) {
1686: selfManagedDataMap = new LinkedHashMap();
1687: }
1688:
1689: // make sure we have a unique key and a delimiter so we can
1690: // get the classname and hashcode for serialization/deserialization
1691: selfManagedDataMap.put(generateSelfManagedDataKey(clazz, key),
1692: value);
1693: }
1694:
1695: /**
1696: * Retrieve a value of self managed data previously saved with the specified key.
1697: *
1698: * @param clazz The class of the caller that owns the key-value pair
1699: * @param key The key for the data
1700: * @return The data object associated with the key, or NULL if not found
1701: */
1702: public Object getSelfManagedData(Class clazz, Object key) {
1703: if (selfManagedDataMap != null) {
1704: return selfManagedDataMap.get(generateSelfManagedDataKey(
1705: clazz, key));
1706: }
1707: return null;
1708: }
1709:
1710: /**
1711: * Check to see if the key for the self managed data is available
1712: *
1713: * @param clazz The class of the caller that owns the key-value pair
1714: * @param key The key to look for
1715: * @return TRUE if the key exists, FALSE otherwise
1716: */
1717: public boolean containsSelfManagedDataKey(Class clazz, Object key) {
1718: if (selfManagedDataMap == null) {
1719: return false;
1720: }
1721: return selfManagedDataMap
1722: .containsKey(generateSelfManagedDataKey(clazz, key));
1723: }
1724:
1725: /**
1726: * Removes the mapping of the specified key if the specified key
1727: * has been set for self managed data
1728: *
1729: * @param clazz The class of the caller that owns the key-value pair
1730: * @param key The key of the object to be removed
1731: */
1732: public void removeSelfManagedData(Class clazz, Object key) {
1733: if (selfManagedDataMap != null) {
1734: selfManagedDataMap.remove(generateSelfManagedDataKey(clazz,
1735: key));
1736: }
1737: }
1738:
1739: /**
1740: * Flatten the phase list into a list of just unique handler instances
1741: *
1742: * @param list the list of handlers
1743: * @param map users should pass null as this is just a holder for the recursion
1744: * @return a list of unigue object instances
1745: */
1746: private ArrayList flattenPhaseListToHandlers(ArrayList list,
1747: LinkedHashMap map) {
1748:
1749: if (map == null) {
1750: map = new LinkedHashMap();
1751: }
1752:
1753: Iterator it = list.iterator();
1754: while (it.hasNext()) {
1755: Handler handler = (Handler) it.next();
1756:
1757: String key = null;
1758: if (handler != null) {
1759: key = handler.getClass().getName() + "@"
1760: + handler.hashCode();
1761: }
1762:
1763: if (handler instanceof Phase) {
1764: // add its handlers to the list
1765: flattenHandlerList(((Phase) handler).getHandlers(), map);
1766: } else {
1767: // if the same object is already in the list,
1768: // then it won't be in the list multiple times
1769: map.put(key, handler);
1770: }
1771: }
1772:
1773: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
1774: Iterator it2 = map.keySet().iterator();
1775: while (it2.hasNext()) {
1776: Object key = it2.next();
1777: Handler value = (Handler) map.get(key);
1778: String name = value.getName();
1779: log.trace(getLogIDString()
1780: + ":flattenPhaseListToHandlers(): key [" + key
1781: + "] handler name [" + name + "]");
1782: }
1783: }
1784:
1785: return new ArrayList(map.values());
1786: }
1787:
1788: /**
1789: * Flatten the handler list into just unique handler instances
1790: * including phase instances.
1791: *
1792: * @param list the list of handlers/phases
1793: * @param map users should pass null as this is just a holder for the recursion
1794: * @return a list of unigue object instances
1795: */
1796: private ArrayList flattenHandlerList(ArrayList list,
1797: LinkedHashMap map) {
1798:
1799: if (map == null) {
1800: map = new LinkedHashMap();
1801: }
1802:
1803: Iterator it = list.iterator();
1804: while (it.hasNext()) {
1805: Handler handler = (Handler) it.next();
1806:
1807: String key = null;
1808: if (handler != null) {
1809: key = handler.getClass().getName() + "@"
1810: + handler.hashCode();
1811: }
1812:
1813: if (handler instanceof Phase) {
1814: // put the phase in the list
1815: map.put(key, handler);
1816:
1817: // add its handlers to the list
1818: flattenHandlerList(((Phase) handler).getHandlers(), map);
1819: } else {
1820: // if the same object is already in the list,
1821: // then it won't be in the list multiple times
1822: map.put(key, handler);
1823: }
1824: }
1825:
1826: return new ArrayList(map.values());
1827: }
1828:
1829: /**
1830: * Calls the serializeSelfManagedData() method of each handler that
1831: * implements the <bold>SelfManagedDataManager</bold> interface.
1832: * Handlers for this message context are identified via the
1833: * executionChain list.
1834: *
1835: * @param out The output stream
1836: */
1837: private void serializeSelfManagedData(ObjectOutput out) {
1838: selfManagedDataHandlerCount = 0;
1839:
1840: try {
1841: if ((selfManagedDataMap == null)
1842: || (executionChain == null)
1843: || (selfManagedDataMap.size() == 0)
1844: || (executionChain.size() == 0)) {
1845: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
1846:
1847: if (LoggingControl.debugLoggingAllowed
1848: && log.isTraceEnabled()) {
1849: log
1850: .trace(getLogIDString()
1851: + ":serializeSelfManagedData(): No data : END");
1852: }
1853:
1854: return;
1855: }
1856:
1857: // let's create a temporary list with the handlers
1858: ArrayList flatExecChain = flattenPhaseListToHandlers(
1859: executionChain, null);
1860:
1861: //ArrayList selfManagedDataHolderList = serializeSelfManagedDataHelper(flatExecChain.iterator(), new ArrayList());
1862: ArrayList selfManagedDataHolderList = serializeSelfManagedDataHelper(flatExecChain);
1863:
1864: if (selfManagedDataHolderList.size() == 0) {
1865: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
1866:
1867: if (LoggingControl.debugLoggingAllowed
1868: && log.isTraceEnabled()) {
1869: log
1870: .trace(getLogIDString()
1871: + ":serializeSelfManagedData(): No data : END");
1872: }
1873:
1874: return;
1875: }
1876:
1877: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
1878:
1879: // SelfManagedData can be binary so won't be able to treat it as a
1880: // string - need to treat it as a byte []
1881:
1882: // how many handlers actually
1883: // returned serialized SelfManagedData
1884: out.writeInt(selfManagedDataHolderList.size());
1885:
1886: for (int i = 0; i < selfManagedDataHolderList.size(); i++) {
1887: out.writeObject(selfManagedDataHolderList.get(i));
1888: }
1889:
1890: } catch (IOException e) {
1891: if (LoggingControl.debugLoggingAllowed
1892: && log.isTraceEnabled()) {
1893: log.trace(
1894: "MessageContext:serializeSelfManagedData(): Exception ["
1895: + e.getClass().getName()
1896: + "] description [" + e.getMessage()
1897: + "]", e);
1898: }
1899: }
1900:
1901: }
1902:
1903: /**
1904: * This is the helper method to do the recursion for serializeSelfManagedData()
1905: *
1906: * @param handlers
1907: * @return ArrayList
1908: */
1909: private ArrayList serializeSelfManagedDataHelper(ArrayList handlers) {
1910: ArrayList selfManagedDataHolderList = new ArrayList();
1911: Iterator it = handlers.iterator();
1912:
1913: try {
1914: while (it.hasNext()) {
1915: Handler handler = (Handler) it.next();
1916:
1917: //if (handler instanceof Phase)
1918: //{
1919: // selfManagedDataHolderList = serializeSelfManagedDataHelper(((Phase)handler).getHandlers().iterator(), selfManagedDataHolderList);
1920: //}
1921: //else if (SelfManagedDataManager.class.isAssignableFrom(handler.getClass()))
1922: if (SelfManagedDataManager.class
1923: .isAssignableFrom(handler.getClass())) {
1924: // only call the handler's serializeSelfManagedData if it implements SelfManagedDataManager
1925:
1926: if (LoggingControl.debugLoggingAllowed
1927: && log.isTraceEnabled()) {
1928: log
1929: .trace("MessageContext:serializeSelfManagedDataHelper(): calling handler ["
1930: + handler.getClass().getName()
1931: + "] name ["
1932: + handler.getName()
1933: + "] serializeSelfManagedData method");
1934: }
1935:
1936: ByteArrayOutputStream baos_fromHandler = ((SelfManagedDataManager) handler)
1937: .serializeSelfManagedData(this );
1938:
1939: if (baos_fromHandler != null) {
1940: baos_fromHandler.close();
1941:
1942: try {
1943: SelfManagedDataHolder selfManagedDataHolder = new SelfManagedDataHolder(
1944: handler.getClass().getName(),
1945: handler.getName(), baos_fromHandler
1946: .toByteArray());
1947: selfManagedDataHolderList
1948: .add(selfManagedDataHolder);
1949: selfManagedDataHandlerCount++;
1950: } catch (Exception exc) {
1951: if (LoggingControl.debugLoggingAllowed
1952: && log.isTraceEnabled()) {
1953: log
1954: .trace(
1955: "MessageContext:serializeSelfManagedData(): exception ["
1956: + exc
1957: .getClass()
1958: .getName()
1959: + "]["
1960: + exc
1961: .getMessage()
1962: + "] in setting up SelfManagedDataHolder object for ["
1963: + handler
1964: .getClass()
1965: .getName()
1966: + " / "
1967: + handler
1968: .getName()
1969: + "] ", exc);
1970: }
1971: }
1972: }
1973: }
1974: }
1975:
1976: return selfManagedDataHolderList;
1977: } catch (Exception ex) {
1978: if (LoggingControl.debugLoggingAllowed
1979: && log.isTraceEnabled()) {
1980: log.trace(
1981: "MessageContext:serializeSelfManagedData(): exception ["
1982: + ex.getClass().getName() + "]["
1983: + ex.getMessage() + "]", ex);
1984: }
1985: return null;
1986: }
1987:
1988: }
1989:
1990: /**
1991: * During deserialization, the executionChain will be
1992: * re-constituted before the SelfManagedData is restored.
1993: * This means the handler instances are already available.
1994: * This method lets us find the handler instance from the
1995: * executionChain so we can call each one's
1996: * deserializeSelfManagedData method.
1997: *
1998: * @param it The iterator from the executionChain object
1999: * @param classname The class name
2000: * @param qNameAsString The QName in string form
2001: * @return SelfManagedDataManager handler
2002: */
2003: private SelfManagedDataManager deserialize_getHandlerFromExecutionChain(
2004: Iterator it, String classname, String qNameAsString) {
2005: SelfManagedDataManager handler_toreturn = null;
2006:
2007: try {
2008: while ((it.hasNext()) && (handler_toreturn == null)) {
2009: Handler handler = (Handler) it.next();
2010:
2011: if (handler instanceof Phase) {
2012: handler_toreturn = deserialize_getHandlerFromExecutionChain(
2013: ((Phase) handler).getHandlers().iterator(),
2014: classname, qNameAsString);
2015: } else if ((handler.getClass().getName()
2016: .equals(classname))
2017: && (handler.getName().equals(qNameAsString))) {
2018: handler_toreturn = (SelfManagedDataManager) handler;
2019: }
2020: }
2021: return handler_toreturn;
2022: } catch (ClassCastException e) {
2023: // Doesn't seem likely to happen, but just in case...
2024: // A handler classname in the executionChain matched up with our parameter
2025: // classname, but the existing class in the executionChain is a different
2026: // implementation than the one we saved during serializeSelfManagedData.
2027: // NOTE: the exception gets absorbed!
2028:
2029: if (LoggingControl.debugLoggingAllowed
2030: && log.isTraceEnabled()) {
2031: log
2032: .trace(
2033: "MessageContext:deserialize_getHandlerFromExecutionChain(): ClassCastException thrown: "
2034: + e.getMessage(), e);
2035: }
2036: return null;
2037: }
2038: }
2039:
2040: /*
2041: * We don't need to create new instances of the handlers
2042: * since the executionChain is rebuilt after readExternal().
2043: * We just have to find them in the executionChain and
2044: * call each handler's deserializeSelfManagedData method.
2045: */
2046: private void deserializeSelfManagedData() throws IOException {
2047: try {
2048: for (int i = 0; (selfManagedDataListHolder != null)
2049: && (i < selfManagedDataListHolder.size()); i++) {
2050: SelfManagedDataHolder selfManagedDataHolder = (SelfManagedDataHolder) selfManagedDataListHolder
2051: .get(i);
2052:
2053: String classname = selfManagedDataHolder.getClassname();
2054: String qNameAsString = selfManagedDataHolder.getId();
2055:
2056: SelfManagedDataManager handler = deserialize_getHandlerFromExecutionChain(
2057: executionChain.iterator(), classname,
2058: qNameAsString);
2059:
2060: if (handler == null) {
2061: if (LoggingControl.debugLoggingAllowed
2062: && log.isTraceEnabled()) {
2063: log
2064: .trace(getLogIDString()
2065: + ":deserializeSelfManagedData(): ["
2066: + classname
2067: + "] was not found in the executionChain associated with the message context.");
2068: }
2069:
2070: throw new IOException(
2071: "The class ["
2072: + classname
2073: + "] was not found in the executionChain associated with the message context.");
2074: }
2075:
2076: ByteArrayInputStream handlerData = new ByteArrayInputStream(
2077: selfManagedDataHolder.getData());
2078:
2079: // the handler implementing SelfManagedDataManager is responsible for repopulating
2080: // the SelfManagedData in the MessageContext (this)
2081:
2082: if (LoggingControl.debugLoggingAllowed
2083: && log.isTraceEnabled()) {
2084: log
2085: .trace(getLogIDString()
2086: + ":deserializeSelfManagedData(): calling handler ["
2087: + classname
2088: + "] ["
2089: + qNameAsString
2090: + "] deserializeSelfManagedData method");
2091: }
2092:
2093: handler.deserializeSelfManagedData(handlerData, this );
2094: handler.restoreTransientData(this );
2095: }
2096: } catch (IOException ioe) {
2097: if (LoggingControl.debugLoggingAllowed
2098: && log.isTraceEnabled()) {
2099: log
2100: .trace(
2101: getLogIDString()
2102: + ":deserializeSelfManagedData(): IOException thrown: "
2103: + ioe.getMessage(), ioe);
2104: }
2105: throw ioe;
2106: }
2107:
2108: }
2109:
2110: /* ===============================================================
2111: * Externalizable support
2112: * ===============================================================
2113: */
2114:
2115: /**
2116: * Save the contents of this MessageContext instance.
2117: * <p/>
2118: * NOTE: Transient fields and static fields are not saved.
2119: * Also, objects that represent "static" data are
2120: * not saved, except for enough information to be
2121: * able to find matching objects when the message
2122: * context is re-constituted.
2123: *
2124: * @param out The stream to write the object contents to
2125: * @throws IOException
2126: */
2127: public void writeExternal(ObjectOutput out) throws IOException {
2128: String logCorrelationIDString = getLogIDString();
2129:
2130: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2131: log.trace(logCorrelationIDString
2132: + ":writeExternal(): writing to output stream");
2133: }
2134:
2135: //---------------------------------------------------------
2136: // in order to handle future changes to the message
2137: // context definition, be sure to maintain the
2138: // object level identifiers
2139: //---------------------------------------------------------
2140: // serialization version ID
2141: out.writeLong(serialVersionUID);
2142:
2143: // revision ID
2144: out.writeInt(revisionID);
2145:
2146: //---------------------------------------------------------
2147: // various simple fields
2148: //---------------------------------------------------------
2149:
2150: // the type of execution flow for the message context
2151: out.writeInt(FLOW);
2152:
2153: // various flags
2154: out.writeBoolean(processingFault);
2155: out.writeBoolean(paused);
2156: out.writeBoolean(outputWritten);
2157: out.writeBoolean(newThreadRequired);
2158: out.writeBoolean(isSOAP11);
2159: out.writeBoolean(doingREST);
2160: out.writeBoolean(doingMTOM);
2161: out.writeBoolean(doingSwA);
2162: out.writeBoolean(responseWritten);
2163: out.writeBoolean(serverSide);
2164:
2165: out.writeLong(getLastTouchedTime());
2166:
2167: ObjectStateUtils.writeString(out, this .getLogCorrelationID(),
2168: "logCorrelationID");
2169:
2170: boolean persistWithOptimizedMTOM = (getProperty(MTOMConstants.ATTACHMENTS) != null);
2171: out.writeBoolean(persistWithOptimizedMTOM);
2172:
2173: //---------------------------------------------------------
2174: // message
2175: //---------------------------------------------------------
2176:
2177: // Just in case anything else is added here, notice that in the case
2178: // of MTOM, something is written to the stream in middle of the envelope
2179: // serialization logic below
2180:
2181: // make sure message attachments are handled
2182:
2183: if (envelope != null) {
2184: String msgClass = envelope.getClass().getName();
2185:
2186: ByteArrayOutputStream msgBuffer = new ByteArrayOutputStream();
2187:
2188: try {
2189: // use a non-destructive method on the soap message
2190:
2191: // We don't need to write to a separate byte array
2192: // unless we want to log the message
2193: ByteArrayOutputStream msgData = new ByteArrayOutputStream();
2194:
2195: OMOutputFormat outputFormat = new OMOutputFormat();
2196: outputFormat.setAutoCloseWriter(true);
2197:
2198: outputFormat.setSOAP11(isSOAP11);
2199:
2200: if (persistWithOptimizedMTOM) {
2201: outputFormat.setDoOptimize(true);
2202:
2203: //Notice that we're writing this next bit out to the
2204: //serialized stream and not the baos
2205: out.writeUTF(outputFormat.getContentType());
2206: }
2207:
2208: // this will be expensive because it builds the OM tree
2209: envelope.serialize(msgData, outputFormat);
2210:
2211: msgBuffer.write(msgData.toByteArray(), 0, msgData
2212: .size());
2213:
2214: if (LoggingControl.debugLoggingAllowed
2215: && log.isTraceEnabled()) {
2216: log.trace(logCorrelationIDString
2217: + ":writeExternal(): msg data [" + msgData
2218: + "]");
2219: }
2220:
2221: } catch (Exception e) {
2222: if (LoggingControl.debugLoggingAllowed
2223: && log.isTraceEnabled()) {
2224: log
2225: .trace(logCorrelationIDString
2226: + ":writeExternal(): can not serialize the SOAP message ***Exception*** ["
2227: + e.getClass().getName() + " : "
2228: + e.getMessage() + "]");
2229: }
2230: }
2231:
2232: //---------------------------------------------
2233: // get the character encoding for the message
2234: //---------------------------------------------
2235: String charSetEnc = (String) getProperty(MessageContext.CHARACTER_SET_ENCODING);
2236:
2237: if (charSetEnc == null) {
2238: OperationContext opContext = getOperationContext();
2239: if (opContext != null) {
2240: charSetEnc = (String) opContext
2241: .getProperty(MessageContext.CHARACTER_SET_ENCODING);
2242: }
2243: }
2244:
2245: if (charSetEnc == null) {
2246: charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
2247: }
2248:
2249: //---------------------------------------------
2250: // get the soap namespace uri
2251: //---------------------------------------------
2252: String namespaceURI = envelope.getNamespace()
2253: .getNamespaceURI();
2254:
2255: // write out the following information, IN ORDER:
2256: // the class name
2257: // the active or empty flag
2258: // the data length
2259: // the data
2260: out.writeUTF(msgClass);
2261:
2262: int msgSize = msgBuffer.size();
2263:
2264: if (msgSize != 0) {
2265: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2266: out.writeUTF(charSetEnc);
2267: out.writeUTF(namespaceURI);
2268: out.writeInt(msgSize);
2269: out.write(msgBuffer.toByteArray());
2270:
2271: if (LoggingControl.debugLoggingAllowed
2272: && log.isTraceEnabled()) {
2273: log.trace(logCorrelationIDString
2274: + ":writeExternal(): msg charSetEnc=["
2275: + charSetEnc + "] namespaceURI=["
2276: + namespaceURI + "] msgSize=[" + msgSize
2277: + "]");
2278: }
2279: } else {
2280: // the envelope is null
2281: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2282:
2283: if (LoggingControl.debugLoggingAllowed
2284: && log.isTraceEnabled()) {
2285: log.trace(logCorrelationIDString
2286: + ":writeExternal(): msg is Empty");
2287: }
2288: }
2289:
2290: // close out internal stream
2291: msgBuffer.close();
2292: } else {
2293: // the envelope is null
2294: out.writeUTF("MessageContext.envelope");
2295: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2296:
2297: if (LoggingControl.debugLoggingAllowed
2298: && log.isTraceEnabled()) {
2299: log.trace(logCorrelationIDString
2300: + ":writeExternal(): msg is Empty");
2301: }
2302: }
2303:
2304: //---------------------------------------------------------
2305: // ArrayList executionChain
2306: // handler and phase related data
2307: //---------------------------------------------------------
2308: // The strategy is to save some metadata about each
2309: // member of the list and the order of the list.
2310: // Then when the message context is re-constituted,
2311: // try to match up with phases and handlers on the
2312: // engine.
2313: //
2314: // Non-null list:
2315: // UTF - description string
2316: // boolean - active flag
2317: // int - current handler index
2318: // int - current phase index
2319: // int - expected number of entries in the list
2320: // objects - MetaDataEntry object per list entry
2321: // last entry will be empty MetaDataEntry
2322: // with MetaDataEntry.LAST_ENTRY marker
2323: // int - adjusted number of entries in the list
2324: // includes the last empty entry
2325: //
2326: // Empty list:
2327: // UTF - description string
2328: // boolean - empty flag
2329: //---------------------------------------------------------
2330: String execChainDesc = logCorrelationIDString
2331: + ".executionChain";
2332:
2333: int listSize = 0;
2334:
2335: if (executionChain != null) {
2336: listSize = executionChain.size();
2337: }
2338:
2339: if (listSize > 0) {
2340: // start writing data to the output stream
2341: out.writeUTF(execChainDesc);
2342: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2343: out.writeInt(currentHandlerIndex);
2344: out.writeInt(currentPhaseIndex);
2345: out.writeInt(listSize);
2346:
2347: // put the metadata on each member of the list into a buffer
2348:
2349: // match the current index with the actual saved list
2350: int nextIndex = 0;
2351:
2352: Iterator i = executionChain.iterator();
2353:
2354: while (i.hasNext()) {
2355: Object obj = i.next();
2356: String objClass = obj.getClass().getName();
2357: // start the meta data entry for this object
2358: MetaDataEntry mdEntry = new MetaDataEntry();
2359: mdEntry.setClassName(objClass);
2360:
2361: // get the correct object-specific name
2362: String qnameAsString;
2363:
2364: if (obj instanceof Phase) {
2365: Phase phaseObj = (Phase) obj;
2366: qnameAsString = phaseObj.getName();
2367:
2368: // add the list of handlers to the meta data
2369: setupPhaseList(phaseObj, mdEntry);
2370: } else if (obj instanceof Handler) {
2371: Handler handlerObj = (Handler) obj;
2372: qnameAsString = handlerObj.getName();
2373: } else {
2374: // TODO: will there be any other kinds of objects in the execution Chain?
2375: qnameAsString = "NULL";
2376: }
2377:
2378: mdEntry.setQName(qnameAsString);
2379:
2380: // update the index for the entry in the chain
2381:
2382: if (LoggingControl.debugLoggingAllowed
2383: && log.isTraceEnabled()) {
2384: log
2385: .trace(logCorrelationIDString
2386: + ":writeExternal(): ***BEFORE OBJ WRITE*** executionChain entry class ["
2387: + objClass + "] qname ["
2388: + qnameAsString + "]");
2389: }
2390:
2391: ObjectStateUtils.writeObject(out, mdEntry,
2392: logCorrelationIDString
2393: + ".executionChain:entry class ["
2394: + objClass + "] qname ["
2395: + qnameAsString + "]");
2396:
2397: // update the index so that the index
2398: // now indicates the next entry that
2399: // will be attempted
2400: nextIndex++;
2401:
2402: if (LoggingControl.debugLoggingAllowed
2403: && log.isTraceEnabled()) {
2404: log
2405: .trace(logCorrelationIDString
2406: + ":writeExternal(): ***AFTER OBJ WRITE*** executionChain entry class ["
2407: + objClass + "] qname ["
2408: + qnameAsString + "]");
2409: }
2410:
2411: } // end while entries in execution chain
2412:
2413: // done with the entries in the execution chain
2414: // add the end-of-list marker
2415: MetaDataEntry lastEntry = new MetaDataEntry();
2416: lastEntry.setClassName(MetaDataEntry.END_OF_LIST);
2417:
2418: ObjectStateUtils.writeObject(out, lastEntry,
2419: logCorrelationIDString
2420: + ".executionChain: last entry ");
2421: nextIndex++;
2422:
2423: // nextIndex also gives us the number of entries
2424: // that were actually saved as opposed to the
2425: // number of entries in the executionChain
2426: out.writeInt(nextIndex);
2427:
2428: } else {
2429: // general case: handle "null" or "empty"
2430:
2431: out.writeUTF(execChainDesc);
2432: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2433:
2434: if (LoggingControl.debugLoggingAllowed
2435: && log.isTraceEnabled()) {
2436: log.trace(logCorrelationIDString
2437: + ":writeExternal(): executionChain is NULL");
2438: }
2439: }
2440:
2441: //---------------------------------------------------------
2442: // LinkedList executedPhases
2443: //---------------------------------------------------------
2444: // The strategy is to save some metadata about each
2445: // member of the list and the order of the list.
2446: // Then when the message context is re-constituted,
2447: // try to match up with phases and handlers on the
2448: // engine.
2449: //
2450: // Non-null list:
2451: // UTF - description string
2452: // boolean - active flag
2453: // int - expected number of entries in the list
2454: // objects - MetaDataEntry object per list entry
2455: // last entry will be empty MetaDataEntry
2456: // with MetaDataEntry.LAST_ENTRY marker
2457: // int - adjusted number of entries in the list
2458: // includes the last empty entry
2459: //
2460: // Empty list:
2461: // UTF - description string
2462: // boolean - empty flag
2463: //---------------------------------------------------------
2464: String execListDesc = logCorrelationIDString
2465: + ".executedPhases";
2466:
2467: int execListSize = 0;
2468:
2469: if (executedPhases != null) {
2470: execListSize = executedPhases.size();
2471: }
2472:
2473: if (execListSize > 0) {
2474: // start writing data to the output stream
2475: out.writeUTF(execListDesc);
2476: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2477: out.writeInt(execListSize);
2478:
2479: // put the metadata on each member of the list into a buffer
2480:
2481: int execNextIndex = 0;
2482:
2483: Iterator iterator = executedPhases.iterator();
2484:
2485: while (iterator.hasNext()) {
2486: Object obj = iterator.next();
2487: String objClass = obj.getClass().getName();
2488: // start the meta data entry for this object
2489: MetaDataEntry mdEntry = new MetaDataEntry();
2490: mdEntry.setClassName(objClass);
2491:
2492: // get the correct object-specific name
2493: String qnameAsString;
2494:
2495: if (obj instanceof Phase) {
2496: Phase inPhaseObj = (Phase) obj;
2497: qnameAsString = inPhaseObj.getName();
2498:
2499: // add the list of handlers to the meta data
2500: setupPhaseList(inPhaseObj, mdEntry);
2501: } else if (obj instanceof Handler) {
2502: Handler inHandlerObj = (Handler) obj;
2503: qnameAsString = inHandlerObj.getName();
2504: } else {
2505: // TODO: will there be any other kinds of objects in the list
2506: qnameAsString = "NULL";
2507: }
2508:
2509: mdEntry.setQName(qnameAsString);
2510:
2511: if (LoggingControl.debugLoggingAllowed
2512: && log.isTraceEnabled()) {
2513: log
2514: .trace(logCorrelationIDString
2515: + ":writeExternal(): ***BEFORE Executed List OBJ WRITE*** executedPhases entry class ["
2516: + objClass + "] qname ["
2517: + qnameAsString + "]");
2518: }
2519:
2520: ObjectStateUtils.writeObject(out, mdEntry,
2521: logCorrelationIDString
2522: + ".executedPhases:entry class ["
2523: + objClass + "] qname ["
2524: + qnameAsString + "]");
2525:
2526: // update the index so that the index
2527: // now indicates the next entry that
2528: // will be attempted
2529: execNextIndex++;
2530:
2531: if (LoggingControl.debugLoggingAllowed
2532: && log.isTraceEnabled()) {
2533: log.trace(logCorrelationIDString
2534: + ":writeExternal(): "
2535: + "***AFTER Executed List OBJ WRITE*** "
2536: + "executedPhases entry class [" + objClass
2537: + "] " + "qname [" + qnameAsString + "]");
2538: }
2539: } // end while entries in execution chain
2540:
2541: // done with the entries in the execution chain
2542: // add the end-of-list marker
2543: MetaDataEntry lastEntry = new MetaDataEntry();
2544: lastEntry.setClassName(MetaDataEntry.END_OF_LIST);
2545:
2546: ObjectStateUtils.writeObject(out, lastEntry,
2547: logCorrelationIDString
2548: + ".executedPhases: last entry ");
2549: execNextIndex++;
2550:
2551: // execNextIndex also gives us the number of entries
2552: // that were actually saved as opposed to the
2553: // number of entries in the executedPhases
2554: out.writeInt(execNextIndex);
2555:
2556: } else {
2557: // general case: handle "null" or "empty"
2558:
2559: out.writeUTF(execListDesc);
2560: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2561:
2562: if (LoggingControl.debugLoggingAllowed
2563: && log.isTraceEnabled()) {
2564: log.trace(logCorrelationIDString
2565: + ":writeExternal(): executedPhases is NULL");
2566: }
2567: }
2568:
2569: //---------------------------------------------------------
2570: // options
2571: //---------------------------------------------------------
2572: // before saving the Options, make sure there is a message ID
2573: String tmpID = getMessageID();
2574: if (tmpID == null) {
2575: // get an id to use when restoring this object
2576: tmpID = UUIDGenerator.getUUID();
2577: setMessageID(tmpID);
2578: }
2579:
2580: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2581: log.trace(logCorrelationIDString
2582: + ":writeExternal(): message ID [" + tmpID + "]");
2583: }
2584:
2585: ObjectStateUtils.writeObject(out, options,
2586: logCorrelationIDString + ".options for ["
2587: + options.getLogCorrelationIDString() + "]");
2588:
2589: //---------------------------------------------------------
2590: // operation
2591: //---------------------------------------------------------
2592: // axis operation
2593: //---------------------------------------------------------
2594: String axisOpMarker = logCorrelationIDString + ".axisOperation";
2595: ObjectStateUtils.writeString(out, axisOpMarker, axisOpMarker);
2596:
2597: if (axisOperation == null) {
2598: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2599: } else {
2600: // TODO: may need to include the meta data for the axis service that is
2601: // the parent of the axis operation
2602:
2603: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2604:
2605: // make sure the axis operation has a name associated with it
2606: QName aoTmpQName = axisOperation.getName();
2607:
2608: if (aoTmpQName == null) {
2609: aoTmpQName = new QName(ObjectStateUtils.EMPTY_MARKER);
2610: axisOperation.setName(aoTmpQName);
2611: }
2612:
2613: metaAxisOperation = new MetaDataEntry(axisOperation
2614: .getClass().getName(), axisOperation.getName()
2615: .toString());
2616: ObjectStateUtils.writeObject(out, metaAxisOperation,
2617: logCorrelationIDString + ".metaAxisOperation");
2618: }
2619:
2620: //---------------------------------------------------------
2621: // operation context
2622: //---------------------------------------------------------
2623: // The OperationContext has pointers to MessageContext objects.
2624: // In order to avoid having multiple copies of the object graph
2625: // being saved at different points in the serialization,
2626: // it is important to isolate this message context object.
2627: String oc_desc = logCorrelationIDString + ".operationContext";
2628: if (operationContext != null) {
2629: operationContext.isolateMessageContext(this );
2630: oc_desc = oc_desc + " for ["
2631: + operationContext.getLogCorrelationIDString()
2632: + "]";
2633: }
2634:
2635: // NOTE: expect this to be the parent of the message context
2636: ObjectStateUtils.writeObject(out, operationContext, oc_desc);
2637:
2638: //---------------------------------------------------------
2639: // service
2640: //---------------------------------------------------------
2641: // axis service
2642: //-------------------------
2643: // this is expected to be the parent of the axis operation object
2644: String axisServMarker = logCorrelationIDString + ".axisService";
2645: ObjectStateUtils.writeString(out, axisServMarker,
2646: axisServMarker);
2647:
2648: if (axisService == null) {
2649: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2650: } else {
2651: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2652: metaAxisService = new MetaDataEntry(axisService.getClass()
2653: .getName(), axisService.getName());
2654: ObjectStateUtils.writeObject(out, metaAxisService,
2655: logCorrelationIDString + ".metaAxisService");
2656: }
2657:
2658: //-------------------------
2659: // serviceContextID string
2660: //-------------------------
2661: ObjectStateUtils.writeString(out, serviceContextID,
2662: logCorrelationIDString + ".serviceContextID");
2663:
2664: //-------------------------
2665: // serviceContext
2666: //-------------------------
2667: // is this the same as the parent of the OperationContext?
2668: boolean isParent = false;
2669:
2670: if (operationContext != null) {
2671: ServiceContext opctxParent = operationContext
2672: .getServiceContext();
2673:
2674: if (serviceContext != null) {
2675: if (serviceContext.equals(opctxParent)) {
2676: // the ServiceContext is the parent of the OperationContext
2677: isParent = true;
2678: }
2679: }
2680: }
2681:
2682: String servCtxMarker = logCorrelationIDString
2683: + ".serviceContext";
2684: ObjectStateUtils.writeString(out, servCtxMarker, servCtxMarker);
2685:
2686: if (serviceContext == null) {
2687: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2688: } else {
2689: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2690: out.writeBoolean(isParent);
2691:
2692: // only write out the object if it is not the parent
2693: if (!isParent) {
2694: ObjectStateUtils.writeObject(out, serviceContext,
2695: logCorrelationIDString + ".serviceContext");
2696: }
2697: }
2698:
2699: //---------------------------------------------------------
2700: // axisServiceGroup
2701: //---------------------------------------------------------
2702:
2703: String axisServGrpMarker = logCorrelationIDString
2704: + ".axisServiceGroup";
2705: ObjectStateUtils.writeString(out, axisServGrpMarker,
2706: axisServGrpMarker);
2707:
2708: if (axisServiceGroup == null) {
2709: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2710: } else {
2711: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2712: metaAxisServiceGroup = new MetaDataEntry(axisServiceGroup
2713: .getClass().getName(), axisServiceGroup
2714: .getServiceGroupName());
2715: ObjectStateUtils.writeObject(out, metaAxisServiceGroup,
2716: logCorrelationIDString + ".metaAxisServiceGroup");
2717: }
2718:
2719: //-----------------------------
2720: // serviceGroupContextId string
2721: //-----------------------------
2722: ObjectStateUtils.writeString(out, serviceGroupContextId,
2723: logCorrelationIDString + ".serviceGroupContextId");
2724:
2725: //-------------------------
2726: // serviceGroupContext
2727: //-------------------------
2728:
2729: // is this the same as the parent of the ServiceContext?
2730: isParent = false;
2731:
2732: if (serviceContext != null) {
2733: ServiceGroupContext srvgrpctxParent = (ServiceGroupContext) serviceContext
2734: .getParent();
2735:
2736: if (serviceGroupContext != null) {
2737: if (serviceGroupContext.equals(srvgrpctxParent)) {
2738: // the ServiceGroupContext is the parent of the ServiceContext
2739: isParent = true;
2740: }
2741: }
2742: }
2743:
2744: String servGrpCtxMarker = logCorrelationIDString
2745: + ".serviceGroupContext";
2746: ObjectStateUtils.writeString(out, servGrpCtxMarker,
2747: servGrpCtxMarker);
2748:
2749: if (serviceGroupContext == null) {
2750: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2751: } else {
2752: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2753: out.writeBoolean(isParent);
2754:
2755: // only write out the object if it is not the parent
2756: if (!isParent) {
2757: ObjectStateUtils
2758: .writeObject(out, serviceGroupContext,
2759: logCorrelationIDString
2760: + ".serviceGroupContext");
2761: }
2762: }
2763:
2764: //---------------------------------------------------------
2765: // axis message
2766: //---------------------------------------------------------
2767: String axisMsgMarker = logCorrelationIDString + ".axisMessage";
2768: ObjectStateUtils.writeString(out, axisMsgMarker, axisMsgMarker);
2769:
2770: if (axisMessage == null) {
2771: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
2772: } else {
2773: // This AxisMessage is expected to belong to the AxisOperation
2774: // that has already been recorded for this MessageContext.
2775: // If an AxisMessage associated with this Messagecontext is
2776: // associated with a different AxisOperation, then more
2777: // meta information would need to be saved
2778:
2779: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
2780:
2781: // make sure the axis message has a name associated with it
2782: String amTmpName = axisMessage.getName();
2783:
2784: if (amTmpName == null) {
2785: amTmpName = ObjectStateUtils.EMPTY_MARKER;
2786: axisMessage.setName(amTmpName);
2787: }
2788:
2789: // get the element name if there is one
2790: QName amTmpElementQName = axisMessage.getElementQName();
2791: String amTmpElemQNameString = null;
2792:
2793: if (amTmpElementQName != null) {
2794: amTmpElemQNameString = amTmpElementQName.toString();
2795: }
2796:
2797: metaAxisMessage = new MetaDataEntry(axisMessage.getClass()
2798: .getName(), axisMessage.getName(),
2799: amTmpElemQNameString);
2800:
2801: ObjectStateUtils.writeObject(out, metaAxisMessage,
2802: logCorrelationIDString + ".metaAxisMessage");
2803: }
2804:
2805: //---------------------------------------------------------
2806: // configuration context
2807: //---------------------------------------------------------
2808:
2809: // NOTE: Currently, there does not seem to be any
2810: // runtime data important to this message context
2811: // in the configuration context.
2812: // if so, then need to save that runtime data and reconcile
2813: // it with the configuration context on the system when
2814: // this message context object is restored
2815:
2816: //---------------------------------------------------------
2817: // session context
2818: //---------------------------------------------------------
2819: ObjectStateUtils.writeObject(out, sessionContext,
2820: logCorrelationIDString + ".sessionContext");
2821:
2822: //---------------------------------------------------------
2823: // transport
2824: //---------------------------------------------------------
2825:
2826: //------------------------------
2827: // incomingTransportName string
2828: //------------------------------
2829: ObjectStateUtils.writeString(out, incomingTransportName,
2830: logCorrelationIDString + ".incomingTransportName");
2831:
2832: // TransportInDescription transportIn
2833: if (transportIn != null) {
2834: metaTransportIn = new MetaDataEntry(null, transportIn
2835: .getName());
2836: } else {
2837: metaTransportIn = null;
2838: }
2839: ObjectStateUtils.writeObject(out, metaTransportIn,
2840: logCorrelationIDString + ".transportIn");
2841:
2842: // TransportOutDescription transportOut
2843: if (transportOut != null) {
2844: metaTransportOut = new MetaDataEntry(null, transportOut
2845: .getName());
2846: } else {
2847: metaTransportOut = null;
2848: }
2849: ObjectStateUtils.writeObject(out, metaTransportOut,
2850: logCorrelationIDString + ".transportOut");
2851:
2852: //---------------------------------------------------------
2853: // properties
2854: //---------------------------------------------------------
2855: Map tmpMap = properties;
2856:
2857: HashMap tmpHashMap = null;
2858:
2859: if ((tmpMap != null) && (!tmpMap.isEmpty())) {
2860: tmpHashMap = new HashMap(tmpMap);
2861: }
2862:
2863: ObjectStateUtils.writeHashMap(out, tmpHashMap,
2864: logCorrelationIDString + ".properties");
2865:
2866: //---------------------------------------------------------
2867: // special data
2868: //---------------------------------------------------------
2869:
2870: String selfManagedDataMarker = logCorrelationIDString
2871: + ".selfManagedData";
2872: ObjectStateUtils.writeString(out, selfManagedDataMarker,
2873: selfManagedDataMarker);
2874:
2875: // save the data, which the handlers themselves will serialize
2876: //ByteArrayOutputStream baos_fromSelfManagedData = serializeSelfManagedData();
2877: serializeSelfManagedData(out);
2878:
2879: //---------------------------------------------------------
2880: // done
2881: //---------------------------------------------------------
2882:
2883: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2884: log
2885: .trace(logCorrelationIDString
2886: + ":writeExternal(): completed writing to output stream for "
2887: + logCorrelationIDString);
2888: }
2889:
2890: }
2891:
2892: /**
2893: * Restore the contents of the MessageContext that was
2894: * previously saved.
2895: * <p/>
2896: * NOTE: The field data must read back in the same order and type
2897: * as it was written. Some data will need to be validated when
2898: * resurrected.
2899: *
2900: * @param in The stream to read the object contents from
2901: * @throws IOException
2902: * @throws ClassNotFoundException
2903: */
2904: public void readExternal(ObjectInput in) throws IOException,
2905: ClassNotFoundException {
2906: // set the flag to indicate that the message context is being
2907: // reconstituted and will need to have certain object references
2908: // to be reconciled with the current engine setup
2909: needsToBeReconciled = true;
2910:
2911: // trace point
2912: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2913: log
2914: .trace(myClassName
2915: + ":readExternal(): BEGIN bytes available in stream ["
2916: + in.available() + "] ");
2917: }
2918:
2919: //---------------------------------------------------------
2920: // object level identifiers
2921: //---------------------------------------------------------
2922:
2923: // serialization version ID
2924: long suid = in.readLong();
2925:
2926: // revision ID
2927: int revID = in.readInt();
2928:
2929: // make sure the object data is in a version we can handle
2930: if (suid != serialVersionUID) {
2931: throw new ClassNotFoundException(
2932: ObjectStateUtils.UNSUPPORTED_SUID);
2933: }
2934:
2935: // make sure the object data is in a revision level we can handle
2936: if (revID != REVISION_1) {
2937: throw new ClassNotFoundException(
2938: ObjectStateUtils.UNSUPPORTED_REVID);
2939: }
2940:
2941: //---------------------------------------------------------
2942: // various simple fields
2943: //---------------------------------------------------------
2944:
2945: // the type of execution flow for the message context
2946: FLOW = in.readInt();
2947:
2948: // various flags
2949: processingFault = in.readBoolean();
2950: paused = in.readBoolean();
2951: outputWritten = in.readBoolean();
2952: newThreadRequired = in.readBoolean();
2953: isSOAP11 = in.readBoolean();
2954: doingREST = in.readBoolean();
2955: doingMTOM = in.readBoolean();
2956: doingSwA = in.readBoolean();
2957: responseWritten = in.readBoolean();
2958: serverSide = in.readBoolean();
2959:
2960: long time = in.readLong();
2961: setLastTouchedTime(time);
2962:
2963: logCorrelationID = ObjectStateUtils.readString(in,
2964: "logCorrelationID");
2965: logCorrelationIDString = "[MessageContext: logID="
2966: + logCorrelationID + "]";
2967:
2968: // trace point
2969: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2970: log
2971: .trace(myClassName
2972: + ":readExternal(): reading the input stream for "
2973: + logCorrelationIDString);
2974: }
2975:
2976: boolean persistedWithOptimizedMTOM = in.readBoolean();
2977:
2978: String contentType = null;
2979: if (persistedWithOptimizedMTOM) {
2980: contentType = in.readUTF();
2981: }
2982:
2983: //---------------------------------------------------------
2984: // message
2985: //---------------------------------------------------------
2986:
2987: in.readUTF();
2988: boolean gotMsg = in.readBoolean();
2989:
2990: if (gotMsg == ObjectStateUtils.ACTIVE_OBJECT) {
2991: String charSetEnc = in.readUTF();
2992: String namespaceURI = in.readUTF();
2993:
2994: int msgSize = in.readInt();
2995: byte[] buffer = new byte[msgSize];
2996:
2997: int bytesRead = 0;
2998: int numberOfBytesLastRead;
2999:
3000: while (bytesRead < msgSize) {
3001: numberOfBytesLastRead = in.read(buffer, bytesRead,
3002: msgSize - bytesRead);
3003:
3004: if (numberOfBytesLastRead == -1) {
3005: // TODO: What should we do if the reconstitution fails?
3006: // For now, log the event
3007: if (LoggingControl.debugLoggingAllowed
3008: && log.isTraceEnabled()) {
3009: log
3010: .trace(logCorrelationIDString
3011: + ":readExternal(): ***WARNING*** unexpected end to message bytesRead ["
3012: + bytesRead + "] msgSize ["
3013: + msgSize + "]");
3014: }
3015: break;
3016: }
3017:
3018: bytesRead += numberOfBytesLastRead;
3019: }
3020:
3021: String tmpMsg = new String(buffer);
3022:
3023: if (LoggingControl.debugLoggingAllowed
3024: && log.isTraceEnabled()) {
3025: log.trace(logCorrelationIDString
3026: + ":readExternal(): msg charSetEnc=["
3027: + charSetEnc + "] namespaceURI=["
3028: + namespaceURI + "] msgSize=[" + msgSize
3029: + "] bytesRead [" + bytesRead + "]");
3030: log.trace(logCorrelationIDString
3031: + ":readExternal(): msg [" + tmpMsg + "]");
3032: }
3033:
3034: ByteArrayInputStream msgBuffer;
3035:
3036: if (bytesRead > 0) {
3037: msgBuffer = new ByteArrayInputStream(buffer);
3038:
3039: // convert what was saved into the soap envelope
3040:
3041: XMLStreamReader xmlreader = null;
3042:
3043: try {
3044: if (persistedWithOptimizedMTOM) {
3045: boolean isSOAP = true;
3046: StAXBuilder builder = BuilderUtil
3047: .getAttachmentsBuilder(this , msgBuffer,
3048: contentType, isSOAP);
3049: envelope = (SOAPEnvelope) builder
3050: .getDocumentElement();
3051: // build the OM in order to free the input stream
3052: envelope.buildWithAttachments();
3053: } else {
3054: xmlreader = StAXUtils.createXMLStreamReader(
3055: msgBuffer, charSetEnc);
3056: StAXBuilder builder = new StAXSOAPModelBuilder(
3057: xmlreader, namespaceURI);
3058: envelope = (SOAPEnvelope) builder
3059: .getDocumentElement();
3060: // build the OM in order to free the input stream
3061: envelope.build();
3062: }
3063: } catch (Exception ex) {
3064: // TODO: what to do if can't get the XML stream reader
3065: // For now, log the event
3066: log
3067: .error(
3068: logCorrelationIDString
3069: + ":readExternal(): Error when deserializing persisted envelope: ["
3070: + ex.getClass().getName()
3071: + " : "
3072: + ex.getLocalizedMessage()
3073: + "]", ex);
3074: envelope = null;
3075: }
3076:
3077: if (xmlreader != null) {
3078: try {
3079: xmlreader.close();
3080: } catch (Exception xmlex) {
3081: // Can't close down the xml stream reader
3082: log
3083: .error(
3084: logCorrelationIDString
3085: + ":readExternal(): Error when closing XMLStreamReader for envelope: ["
3086: + xmlex.getClass()
3087: .getName()
3088: + " : "
3089: + xmlex
3090: .getLocalizedMessage()
3091: + "]", xmlex);
3092: }
3093: }
3094:
3095: msgBuffer.close();
3096: } else {
3097: // no message
3098: envelope = null;
3099:
3100: if (LoggingControl.debugLoggingAllowed
3101: && log.isTraceEnabled()) {
3102: log
3103: .trace(logCorrelationIDString
3104: + ":readExternal(): no message from the input stream");
3105: }
3106: }
3107:
3108: } else {
3109: // no message
3110: envelope = null;
3111:
3112: if (LoggingControl.debugLoggingAllowed
3113: && log.isTraceEnabled()) {
3114: log.trace(logCorrelationIDString
3115: + ":readExternal(): no message present");
3116: }
3117: }
3118:
3119: //---------------------------------------------------------
3120: // ArrayList executionChain
3121: // handler and phase related data
3122: //---------------------------------------------------------
3123: // Restore the metadata about each member of the list
3124: // and the order of the list.
3125: // This metadata will be used to match up with phases
3126: // and handlers on the engine.
3127: //
3128: // Non-null list:
3129: // UTF - description string
3130: // boolean - active flag
3131: // int - current handler index
3132: // int - current phase index
3133: // int - expected number of entries in the list
3134: // not including the last entry marker
3135: // objects - MetaDataEntry object per list entry
3136: // last entry will be empty MetaDataEntry
3137: // with MetaDataEntry.LAST_ENTRY marker
3138: // int - adjusted number of entries in the list
3139: // includes the last empty entry
3140: //
3141: // Empty list:
3142: // UTF - description string
3143: // boolean - empty flag
3144: //---------------------------------------------------------
3145:
3146: // the local chain is not enabled until the
3147: // list has been reconstituted
3148: executionChain = null;
3149: currentHandlerIndex = -1;
3150: currentPhaseIndex = 0;
3151: metaExecutionChain = null;
3152:
3153: in.readUTF();
3154: boolean gotChain = in.readBoolean();
3155:
3156: if (gotChain == ObjectStateUtils.ACTIVE_OBJECT) {
3157: metaHandlerIndex = in.readInt();
3158: metaPhaseIndex = in.readInt();
3159:
3160: int expectedNumberEntries = in.readInt();
3161:
3162: if (LoggingControl.debugLoggingAllowed
3163: && log.isTraceEnabled()) {
3164: log
3165: .trace(logCorrelationIDString
3166: + ":readExternal(): execution chain: expected number of entries ["
3167: + expectedNumberEntries + "]");
3168: }
3169:
3170: // setup the list
3171: metaExecutionChain = new ArrayList();
3172:
3173: // process the objects
3174: boolean keepGoing = true;
3175: int count = 0;
3176:
3177: while (keepGoing) {
3178: // stop when we get to the end-of-list marker
3179:
3180: // get the object
3181: Object tmpObj = ObjectStateUtils
3182: .readObject(in,
3183: "MessageContext.metaExecutionChain MetaDataEntry");
3184:
3185: count++;
3186:
3187: MetaDataEntry mdObj = (MetaDataEntry) tmpObj;
3188:
3189: // get the class name, then add it to the list
3190: String tmpClassNameStr;
3191: String tmpQNameAsStr;
3192:
3193: if (mdObj != null) {
3194: tmpClassNameStr = mdObj.getClassName();
3195:
3196: if (tmpClassNameStr
3197: .equalsIgnoreCase(MetaDataEntry.END_OF_LIST)) {
3198: // this is the last entry
3199: keepGoing = false;
3200: } else {
3201: // add the entry to the meta data list
3202: metaExecutionChain.add(mdObj);
3203:
3204: tmpQNameAsStr = mdObj.getQNameAsString();
3205:
3206: if (LoggingControl.debugLoggingAllowed
3207: && log.isTraceEnabled()) {
3208: String tmpHasList = mdObj.isListEmpty() ? "no children"
3209: : "has children";
3210:
3211: log
3212: .trace(logCorrelationIDString
3213: + ":readExternal(): meta data class ["
3214: + tmpClassNameStr
3215: + "] qname ["
3216: + tmpQNameAsStr
3217: + "] index [" + count
3218: + "] [" + tmpHasList
3219: + "]");
3220: }
3221: }
3222: } else {
3223: // some error occurred
3224: keepGoing = false;
3225: }
3226:
3227: } // end while keep going
3228:
3229: int adjustedNumberEntries = in.readInt();
3230:
3231: if (LoggingControl.debugLoggingAllowed
3232: && log.isTraceEnabled()) {
3233: log
3234: .trace(logCorrelationIDString
3235: + ":readExternal(): adjusted number of entries ExecutionChain ["
3236: + adjustedNumberEntries + "] ");
3237: }
3238: }
3239:
3240: if ((metaExecutionChain == null)
3241: || (metaExecutionChain.isEmpty())) {
3242: if (LoggingControl.debugLoggingAllowed
3243: && log.isTraceEnabled()) {
3244: log
3245: .trace(logCorrelationIDString
3246: + ":readExternal(): meta data for Execution Chain is NULL");
3247: }
3248: }
3249:
3250: //---------------------------------------------------------
3251: // LinkedList executedPhases
3252: //---------------------------------------------------------
3253: // Restore the metadata about each member of the list
3254: // and the order of the list.
3255: // This metadata will be used to match up with phases
3256: // and handlers on the engine.
3257: //
3258: // Non-null list:
3259: // UTF - description string
3260: // boolean - active flag
3261: // int - expected number of entries in the list
3262: // not including the last entry marker
3263: // objects - MetaDataEntry object per list entry
3264: // last entry will be empty MetaDataEntry
3265: // with MetaDataEntry.LAST_ENTRY marker
3266: // int - adjusted number of entries in the list
3267: // includes the last empty entry
3268: //
3269: // Empty list:
3270: // UTF - description string
3271: // boolean - empty flag
3272: //---------------------------------------------------------
3273:
3274: // the local chain is not enabled until the
3275: // list has been reconstituted
3276: executedPhases = null;
3277: metaExecuted = null;
3278:
3279: in.readUTF();
3280: boolean gotInExecList = in.readBoolean();
3281:
3282: if (gotInExecList == ObjectStateUtils.ACTIVE_OBJECT) {
3283: int expectedNumberInExecList = in.readInt();
3284:
3285: if (LoggingControl.debugLoggingAllowed
3286: && log.isTraceEnabled()) {
3287: log
3288: .trace(logCorrelationIDString
3289: + ":readExternal(): executed phases: expected number of entries ["
3290: + expectedNumberInExecList + "]");
3291: }
3292:
3293: // setup the list
3294: metaExecuted = new LinkedList();
3295:
3296: // process the objects
3297: boolean keepGoing = true;
3298: int count = 0;
3299:
3300: while (keepGoing) {
3301: // stop when we get to the end-of-list marker
3302:
3303: // get the object
3304: Object tmpObj = ObjectStateUtils.readObject(in,
3305: "MessageContext.metaExecuted MetaDataEntry");
3306:
3307: count++;
3308:
3309: MetaDataEntry mdObj = (MetaDataEntry) tmpObj;
3310:
3311: // get the class name, then add it to the list
3312: String tmpClassNameStr;
3313: String tmpQNameAsStr;
3314: String tmpHasList = "no list";
3315:
3316: if (mdObj != null) {
3317: tmpClassNameStr = mdObj.getClassName();
3318:
3319: if (tmpClassNameStr
3320: .equalsIgnoreCase(MetaDataEntry.END_OF_LIST)) {
3321: // this is the last entry
3322: keepGoing = false;
3323: } else {
3324: // add the entry to the meta data list
3325: metaExecuted.add(mdObj);
3326:
3327: tmpQNameAsStr = mdObj.getQNameAsString();
3328:
3329: if (!mdObj.isListEmpty()) {
3330: tmpHasList = "has list";
3331: }
3332:
3333: if (LoggingControl.debugLoggingAllowed
3334: && log.isTraceEnabled()) {
3335: log
3336: .trace(logCorrelationIDString
3337: + ":readExternal(): meta data class ["
3338: + tmpClassNameStr
3339: + "] qname ["
3340: + tmpQNameAsStr
3341: + "] index [" + count
3342: + "] [" + tmpHasList
3343: + "]");
3344: }
3345: }
3346: } else {
3347: // some error occurred
3348: keepGoing = false;
3349: }
3350:
3351: } // end while keep going
3352:
3353: int adjustedNumberInExecList = in.readInt();
3354:
3355: if (LoggingControl.debugLoggingAllowed
3356: && log.isTraceEnabled()) {
3357: log
3358: .trace(logCorrelationIDString
3359: + ":readExternal(): adjusted number of entries executedPhases ["
3360: + adjustedNumberInExecList + "] ");
3361: }
3362: }
3363:
3364: if ((metaExecuted == null) || (metaExecuted.isEmpty())) {
3365: if (LoggingControl.debugLoggingAllowed
3366: && log.isTraceEnabled()) {
3367: log
3368: .trace(logCorrelationIDString
3369: + ":readExternal(): meta data for executedPhases list is NULL");
3370: }
3371: }
3372:
3373: //---------------------------------------------------------
3374: // options
3375: //---------------------------------------------------------
3376:
3377: options = (Options) ObjectStateUtils.readObject(in,
3378: "MessageContext.options");
3379:
3380: if (options != null) {
3381: if (LoggingControl.debugLoggingAllowed
3382: && log.isTraceEnabled()) {
3383: log.trace(logCorrelationIDString
3384: + ":readExternal(): restored Options ["
3385: + options.getLogCorrelationIDString() + "]");
3386: }
3387: }
3388:
3389: //---------------------------------------------------------
3390: // operation
3391: //---------------------------------------------------------
3392:
3393: // axisOperation is not usable until the meta data has been reconciled
3394: axisOperation = null;
3395:
3396: ObjectStateUtils.readString(in, "MessageContext.axisOperation");
3397:
3398: boolean metaAxisOperationIsActive = in.readBoolean();
3399:
3400: if (metaAxisOperationIsActive == ObjectStateUtils.ACTIVE_OBJECT) {
3401: metaAxisOperation = (MetaDataEntry) ObjectStateUtils
3402: .readObject(in, "MessageContext.metaAxisOperation");
3403: } else {
3404: metaAxisOperation = null;
3405: }
3406:
3407: // operation context is not usable until it has been activated
3408: // NOTE: expect this to be the parent
3409: operationContext = (OperationContext) ObjectStateUtils
3410: .readObject(in, "MessageContext.operationContext");
3411:
3412: if (operationContext != null) {
3413: if (LoggingControl.debugLoggingAllowed
3414: && log.isTraceEnabled()) {
3415: log
3416: .trace(logCorrelationIDString
3417: + ":readExternal(): restored OperationContext ["
3418: + operationContext
3419: .getLogCorrelationIDString()
3420: + "]");
3421: }
3422: }
3423:
3424: //---------------------------------------------------------
3425: // service
3426: //---------------------------------------------------------
3427:
3428: // axisService is not usable until the meta data has been reconciled
3429: axisService = null;
3430:
3431: ObjectStateUtils.readString(in, "MessageContext.axisService");
3432:
3433: boolean metaAxisServiceIsActive = in.readBoolean();
3434:
3435: if (metaAxisServiceIsActive == ObjectStateUtils.ACTIVE_OBJECT) {
3436: metaAxisService = (MetaDataEntry) ObjectStateUtils
3437: .readObject(in, "MessageContext.metaAxisService");
3438: } else {
3439: metaAxisService = null;
3440: }
3441:
3442: //-------------------------
3443: // serviceContextID string
3444: //-------------------------
3445:
3446: serviceContextID = ObjectStateUtils.readString(in,
3447: "MessageContext.serviceContextID");
3448:
3449: //-------------------------
3450: // serviceContext
3451: //-------------------------
3452:
3453: ObjectStateUtils
3454: .readString(in, "MessageContext.serviceContext");
3455:
3456: boolean servCtxActive = in.readBoolean();
3457:
3458: if (servCtxActive == ObjectStateUtils.EMPTY_OBJECT) {
3459: // empty object
3460:
3461: serviceContext = null;
3462: } else {
3463: // active object
3464:
3465: boolean isParent = in.readBoolean();
3466:
3467: // there's an object to read in if it is not the parent of the operation context
3468: if (!isParent) {
3469: serviceContext = (ServiceContext) ObjectStateUtils
3470: .readObject(in, "MessageContext.serviceContext");
3471: } else {
3472: // the service context is the parent of the operation context
3473: // so get it from the operation context during activate
3474: serviceContext = null;
3475: }
3476: }
3477:
3478: //---------------------------------------------------------
3479: // serviceGroup
3480: //---------------------------------------------------------
3481:
3482: // axisServiceGroup is not usable until the meta data has been reconciled
3483: axisServiceGroup = null;
3484:
3485: ObjectStateUtils.readString(in,
3486: "MessageContext.axisServiceGroup");
3487:
3488: boolean metaAxisServiceGrpIsActive = in.readBoolean();
3489:
3490: if (metaAxisServiceGrpIsActive == ObjectStateUtils.ACTIVE_OBJECT) {
3491: metaAxisServiceGroup = (MetaDataEntry) ObjectStateUtils
3492: .readObject(in,
3493: "MessageContext.metaAxisServiceGroup");
3494: } else {
3495: metaAxisServiceGroup = null;
3496: }
3497:
3498: //-----------------------------
3499: // serviceGroupContextId string
3500: //-----------------------------
3501: serviceGroupContextId = ObjectStateUtils.readString(in,
3502: "MessageContext.serviceGroupContextId");
3503:
3504: //-----------------------------
3505: // serviceGroupContext
3506: //-----------------------------
3507:
3508: ObjectStateUtils.readString(in,
3509: "MessageContext.serviceGroupContext");
3510:
3511: boolean servGrpCtxActive = in.readBoolean();
3512:
3513: if (servGrpCtxActive == ObjectStateUtils.EMPTY_OBJECT) {
3514: // empty object
3515:
3516: serviceGroupContext = null;
3517: } else {
3518: // active object
3519:
3520: boolean isParentSGC = in.readBoolean();
3521:
3522: // there's an object to read in if it is not the parent of the service group context
3523: if (!isParentSGC) {
3524: serviceGroupContext = (ServiceGroupContext) ObjectStateUtils
3525: .readObject(in,
3526: "MessageContext.serviceGroupContext");
3527: } else {
3528: // the service group context is the parent of the service context
3529: // so get it from the service context during activate
3530: serviceGroupContext = null;
3531: }
3532: }
3533:
3534: //---------------------------------------------------------
3535: // axis message
3536: //---------------------------------------------------------
3537:
3538: // axisMessage is not usable until the meta data has been reconciled
3539: axisMessage = null;
3540:
3541: ObjectStateUtils.readString(in, "MessageContext.axisMessage");
3542:
3543: boolean metaAxisMessageIsActive = in.readBoolean();
3544:
3545: if (metaAxisMessageIsActive == ObjectStateUtils.ACTIVE_OBJECT) {
3546: metaAxisMessage = (MetaDataEntry) ObjectStateUtils
3547: .readObject(in, "MessageContext.metaAxisMessage");
3548: reconcileAxisMessage = true;
3549: } else {
3550: metaAxisMessage = null;
3551: reconcileAxisMessage = false;
3552: }
3553:
3554: //---------------------------------------------------------
3555: // configuration context
3556: //---------------------------------------------------------
3557:
3558: // TODO: check to see if there is any runtime data important to this
3559: // message context in the configuration context
3560: // if so, then need to restore the saved runtime data and reconcile
3561: // it with the configuration context on the system when
3562: // this message context object is restored
3563:
3564: //---------------------------------------------------------
3565: // session context
3566: //---------------------------------------------------------
3567:
3568: sessionContext = (SessionContext) ObjectStateUtils.readObject(
3569: in, "MessageContext.sessionContext");
3570:
3571: //---------------------------------------------------------
3572: // transport
3573: //---------------------------------------------------------
3574:
3575: //------------------------------
3576: // incomingTransportName string
3577: //------------------------------
3578: incomingTransportName = ObjectStateUtils.readString(in,
3579: "MessageContext.incomingTransportName");
3580:
3581: // TransportInDescription transportIn
3582: // is not usable until the meta data has been reconciled
3583: transportIn = null;
3584: metaTransportIn = (MetaDataEntry) ObjectStateUtils.readObject(
3585: in, "MessageContext.metaTransportIn");
3586:
3587: // TransportOutDescription transportOut
3588: // is not usable until the meta data has been reconciled
3589: transportOut = null;
3590: metaTransportOut = (MetaDataEntry) ObjectStateUtils.readObject(
3591: in, "MessageContext.metaTransportOut");
3592:
3593: //---------------------------------------------------------
3594: // properties
3595: //---------------------------------------------------------
3596:
3597: HashMap tmpHashMap = ObjectStateUtils.readHashMap(in,
3598: "MessageContext.properties");
3599:
3600: properties = new HashMap();
3601: if (tmpHashMap != null) {
3602: setProperties(tmpHashMap);
3603: }
3604:
3605: //---------------------------------------------------------
3606: // special data
3607: //---------------------------------------------------------
3608:
3609: ObjectStateUtils.readString(in,
3610: "MessageContext.selfManagedData");
3611:
3612: boolean gotSelfManagedData = in.readBoolean();
3613:
3614: if (gotSelfManagedData == ObjectStateUtils.ACTIVE_OBJECT) {
3615: selfManagedDataHandlerCount = in.readInt();
3616:
3617: if (selfManagedDataListHolder == null) {
3618: selfManagedDataListHolder = new ArrayList();
3619: } else {
3620: selfManagedDataListHolder.clear();
3621: }
3622:
3623: for (int i = 0; i < selfManagedDataHandlerCount; i++) {
3624: selfManagedDataListHolder.add(in.readObject());
3625: }
3626: }
3627:
3628: //---------------------------------------------------------
3629: // done
3630: //---------------------------------------------------------
3631:
3632: // trace point
3633: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3634: log
3635: .trace(logCorrelationIDString
3636: + ":readExternal(): message context object created for "
3637: + logCorrelationIDString);
3638: }
3639: }
3640:
3641: /**
3642: * This method checks to see if additional work needs to be
3643: * done in order to complete the object reconstitution.
3644: * Some parts of the object restored from the readExternal()
3645: * cannot be completed until we have a configurationContext
3646: * from the active engine. The configurationContext is used
3647: * to help this object to plug back into the engine's
3648: * configuration and deployment objects.
3649: *
3650: * @param cc The configuration context object representing the active configuration
3651: */
3652: public void activate(ConfigurationContext cc) {
3653: // see if there's any work to do
3654: if (!needsToBeReconciled) {
3655: // return quick
3656: return;
3657: }
3658:
3659: // use the supplied configuration context
3660: setConfigurationContext(cc);
3661:
3662: // get the axis configuration
3663: AxisConfiguration axisConfig = configurationContext
3664: .getAxisConfiguration();
3665:
3666: // We previously saved metaAxisService; restore it
3667: if (metaAxisService != null) {
3668: this .setAxisService(ObjectStateUtils.findService(
3669: axisConfig, metaAxisService.getClassName(),
3670: metaAxisService.getQNameAsString()));
3671: }
3672:
3673: // We previously saved metaAxisServiceGroup; restore it
3674: if (metaAxisServiceGroup != null) {
3675: this .setAxisServiceGroup(ObjectStateUtils.findServiceGroup(
3676: axisConfig, metaAxisServiceGroup.getClassName(),
3677: metaAxisServiceGroup.getQNameAsString()));
3678: }
3679:
3680: // We previously saved metaAxisOperation; restore it
3681: if (metaAxisOperation != null) {
3682: AxisService serv = axisService;
3683:
3684: if (serv != null) {
3685: // TODO: check for the empty name
3686: this .setAxisOperation(ObjectStateUtils.findOperation(
3687: serv, metaAxisOperation.getClassName(),
3688: metaAxisOperation.getQName()));
3689: } else {
3690: this .setAxisOperation(ObjectStateUtils.findOperation(
3691: axisConfig, metaAxisOperation.getClassName(),
3692: metaAxisOperation.getQName()));
3693: }
3694: }
3695:
3696: // We previously saved metaAxisMessage; restore it
3697: if (metaAxisMessage != null) {
3698: AxisOperation op = axisOperation;
3699:
3700: if (op != null) {
3701: // TODO: check for the empty name
3702: this .setAxisMessage(ObjectStateUtils.findMessage(op,
3703: metaAxisMessage.getQNameAsString(),
3704: metaAxisMessage.getExtraName()));
3705: }
3706: }
3707:
3708: //---------------------------------------------------------------------
3709: // operation context
3710: //---------------------------------------------------------------------
3711: // this will do a full hierarchy, so do it first
3712: // then we can re-use its objects
3713:
3714: if (operationContext != null) {
3715: operationContext.activate(cc);
3716:
3717: // this will be set as the parent of the message context
3718: // after the other context objects have been activated
3719: }
3720:
3721: //---------------------------------------------------------------------
3722: // service context
3723: //---------------------------------------------------------------------
3724:
3725: if (serviceContext == null) {
3726: // get the parent serviceContext of the operationContext
3727: if (operationContext != null) {
3728: serviceContext = operationContext.getServiceContext();
3729: }
3730: }
3731:
3732: // if we have a service context, make sure it is usable
3733: if (serviceContext != null) {
3734: // for some reason, the service context might be set differently from
3735: // the operation context parent
3736: serviceContext.activate(cc);
3737: }
3738:
3739: //---------------------------------------------------------------------
3740: // service group context
3741: //---------------------------------------------------------------------
3742:
3743: if (serviceGroupContext == null) {
3744: // get the parent serviceGroupContext of the serviceContext
3745: if (serviceContext != null) {
3746: serviceGroupContext = (ServiceGroupContext) serviceContext
3747: .getParent();
3748: }
3749: }
3750:
3751: // if we have a service group context, make sure it is usable
3752: if (serviceGroupContext != null) {
3753: // for some reason, the service group context might be set differently from
3754: // the service context parent
3755: serviceGroupContext.activate(cc);
3756: }
3757:
3758: //---------------------------------------------------------------------
3759: // other context-related reconciliation
3760: //---------------------------------------------------------------------
3761:
3762: this .setParent(operationContext);
3763:
3764: //---------------------------------------------------------------------
3765: // options
3766: //---------------------------------------------------------------------
3767: if (options != null) {
3768: options.activate(cc);
3769: }
3770:
3771: String tmpID = getMessageID();
3772: String logCorrelationIDString = getLogIDString();
3773:
3774: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3775: log.trace(logCorrelationIDString
3776: + ":activate(): message ID [" + tmpID + "] for "
3777: + logCorrelationIDString);
3778: }
3779:
3780: //---------------------------------------------------------------------
3781: // transports
3782: //---------------------------------------------------------------------
3783:
3784: // We previously saved metaTransportIn; restore it
3785: if (metaTransportIn != null) {
3786: QName qin = metaTransportIn.getQName();
3787: TransportInDescription tmpIn = null;
3788: try {
3789: tmpIn = axisConfig.getTransportIn(qin.getLocalPart());
3790: } catch (Exception exin) {
3791: // if a fault is thrown, log it and continue
3792: log
3793: .trace(logCorrelationIDString
3794: + "activate(): exception caught when getting the TransportInDescription ["
3795: + qin.toString()
3796: + "] from the AxisConfiguration ["
3797: + exin.getClass().getName() + " : "
3798: + exin.getMessage() + "]");
3799: }
3800:
3801: if (tmpIn != null) {
3802: transportIn = tmpIn;
3803: } else {
3804: transportIn = null;
3805: }
3806: } else {
3807: transportIn = null;
3808: }
3809:
3810: // We previously saved metaTransportOut; restore it
3811: if (metaTransportOut != null) {
3812: // TODO : Check if this should really be a QName?
3813: QName qout = metaTransportOut.getQName();
3814: TransportOutDescription tmpOut = null;
3815: try {
3816: tmpOut = axisConfig
3817: .getTransportOut(qout.getLocalPart());
3818: } catch (Exception exout) {
3819: // if a fault is thrown, log it and continue
3820: if (LoggingControl.debugLoggingAllowed
3821: && log.isTraceEnabled()) {
3822: log
3823: .trace(logCorrelationIDString
3824: + "activate(): exception caught when getting the TransportOutDescription ["
3825: + qout.toString()
3826: + "] from the AxisConfiguration ["
3827: + exout.getClass().getName()
3828: + " : " + exout.getMessage() + "]");
3829: }
3830: }
3831:
3832: if (tmpOut != null) {
3833: transportOut = tmpOut;
3834: } else {
3835: transportOut = null;
3836: }
3837: } else {
3838: transportOut = null;
3839: }
3840:
3841: //-------------------------------------------------------
3842: // reconcile the execution chain
3843: //-------------------------------------------------------
3844: if (metaExecutionChain != null) {
3845: if (LoggingControl.debugLoggingAllowed
3846: && log.isTraceEnabled()) {
3847: log
3848: .trace(logCorrelationIDString
3849: + ":activate(): reconciling the execution chain...");
3850: }
3851:
3852: currentHandlerIndex = metaHandlerIndex;
3853: currentPhaseIndex = metaPhaseIndex;
3854:
3855: executionChain = restoreHandlerList(metaExecutionChain);
3856:
3857: try {
3858: deserializeSelfManagedData();
3859: } catch (Exception ex) {
3860: // log the exception
3861: if (LoggingControl.debugLoggingAllowed
3862: && log.isTraceEnabled()) {
3863: log
3864: .trace(
3865: logCorrelationIDString
3866: + ":activate(): *** WARNING *** deserializing the self managed data encountered Exception ["
3867: + ex.getClass().getName()
3868: + " : " + ex.getMessage()
3869: + "]", ex);
3870: }
3871: }
3872: }
3873:
3874: //-------------------------------------------------------
3875: // reconcile the lists for the executed phases
3876: //-------------------------------------------------------
3877: if (metaExecuted != null) {
3878: if (LoggingControl.debugLoggingAllowed
3879: && log.isTraceEnabled()) {
3880: log
3881: .trace(logCorrelationIDString
3882: + ":activate(): reconciling the executed chain...");
3883: }
3884:
3885: if (!(executedPhasesReset)) {
3886: executedPhases = restoreExecutedList(executedPhases,
3887: metaExecuted);
3888: }
3889: }
3890:
3891: if (executedPhases == null) {
3892: executedPhases = new LinkedList();
3893: }
3894:
3895: //-------------------------------------------------------
3896: // finish up remaining links
3897: //-------------------------------------------------------
3898: if (operationContext != null) {
3899: operationContext.restoreMessageContext(this );
3900: }
3901:
3902: //-------------------------------------------------------
3903: // done, reset the flag
3904: //-------------------------------------------------------
3905: needsToBeReconciled = false;
3906:
3907: }
3908:
3909: /**
3910: * This method checks to see if additional work needs to be
3911: * done in order to complete the object reconstitution.
3912: * Some parts of the object restored from the readExternal()
3913: * cannot be completed until we have an object that gives us
3914: * a view of the active object graph from the active engine.
3915: * <p/>
3916: * NOTE: when activating an object, you only need to call
3917: * one of the activate methods (activate() or activateWithOperationContext())
3918: * but not both.
3919: *
3920: * @param operationCtx The operation context object that is a member of the active object graph
3921: */
3922: public void activateWithOperationContext(
3923: OperationContext operationCtx) {
3924: // see if there's any work to do
3925: if (!(needsToBeReconciled)) {
3926: // return quick
3927: return;
3928: }
3929:
3930: String logCorrelationIDString = getLogIDString();
3931: // trace point
3932: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3933: log.trace(logCorrelationIDString
3934: + ":activateWithOperationContext(): BEGIN");
3935: }
3936:
3937: if (operationCtx == null) {
3938: // won't be able to finish
3939: if (LoggingControl.debugLoggingAllowed
3940: && log.isTraceEnabled()) {
3941: log
3942: .trace(logCorrelationIDString
3943: + ":activateWithOperationContext(): *** WARNING *** No active OperationContext object is available.");
3944: }
3945: return;
3946: }
3947:
3948: //---------------------------------------------------------------------
3949: // locate the objects in the object graph
3950: //---------------------------------------------------------------------
3951: ConfigurationContext configCtx = operationCtx
3952: .getConfigurationContext();
3953:
3954: if (configCtx == null) {
3955: // won't be able to finish
3956: if (LoggingControl.debugLoggingAllowed
3957: && log.isTraceEnabled()) {
3958: log
3959: .trace(logCorrelationIDString
3960: + ":activateWithOperationContext(): *** WARNING *** No active ConfigurationContext object is available.");
3961: }
3962: return;
3963: }
3964:
3965: AxisConfiguration axisCfg = configCtx.getAxisConfiguration();
3966:
3967: AxisOperation axisOp = operationCtx.getAxisOperation();
3968: ServiceContext serviceCtx = operationCtx.getServiceContext();
3969:
3970: ServiceGroupContext serviceGroupCtx = null;
3971: AxisService axisSrv = null;
3972: AxisServiceGroup axisSG = null;
3973:
3974: if (serviceCtx != null) {
3975: serviceGroupCtx = serviceCtx.getServiceGroupContext();
3976: axisSrv = serviceCtx.getAxisService();
3977: }
3978:
3979: if (serviceGroupCtx != null) {
3980: axisSG = serviceGroupCtx.getDescription();
3981: }
3982:
3983: //---------------------------------------------------------------------
3984: // link to the objects in the object graph
3985: //---------------------------------------------------------------------
3986:
3987: setConfigurationContext(configCtx);
3988:
3989: setAxisOperation(axisOp);
3990: setAxisService(axisSrv);
3991: setAxisServiceGroup(axisSG);
3992:
3993: setServiceGroupContext(serviceGroupCtx);
3994: setServiceContext(serviceCtx);
3995: setOperationContext(operationCtx);
3996:
3997: //---------------------------------------------------------------------
3998: // reconcile the remaining objects
3999: //---------------------------------------------------------------------
4000:
4001: // We previously saved metaAxisMessage; restore it
4002: if (metaAxisMessage != null) {
4003: if (axisOp != null) {
4004: // TODO: check for the empty name
4005: this .setAxisMessage(ObjectStateUtils.findMessage(
4006: axisOp, metaAxisMessage.getQNameAsString(),
4007: metaAxisMessage.getExtraName()));
4008: }
4009: }
4010:
4011: //---------------------------------------------------------------------
4012: // options
4013: //---------------------------------------------------------------------
4014: if (options != null) {
4015: options.activate(configCtx);
4016: }
4017:
4018: String tmpID = getMessageID();
4019:
4020: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
4021: log.trace(logCorrelationIDString
4022: + ":activateWithOperationContext(): message ID ["
4023: + tmpID + "]");
4024: }
4025:
4026: //---------------------------------------------------------------------
4027: // transports
4028: //---------------------------------------------------------------------
4029:
4030: // We previously saved metaTransportIn; restore it
4031: if (metaTransportIn != null) {
4032: QName qin = metaTransportIn.getQName();
4033: TransportInDescription tmpIn = null;
4034: try {
4035: tmpIn = axisCfg.getTransportIn(qin.getLocalPart());
4036: } catch (Exception exin) {
4037: // if a fault is thrown, log it and continue
4038: if (LoggingControl.debugLoggingAllowed
4039: && log.isTraceEnabled()) {
4040: log
4041: .trace(logCorrelationIDString
4042: + "activateWithOperationContext(): exception caught when getting the TransportInDescription ["
4043: + qin.toString()
4044: + "] from the AxisConfiguration ["
4045: + exin.getClass().getName() + " : "
4046: + exin.getMessage() + "]");
4047: }
4048:
4049: }
4050:
4051: if (tmpIn != null) {
4052: transportIn = tmpIn;
4053: } else {
4054: transportIn = null;
4055: }
4056: } else {
4057: transportIn = null;
4058: }
4059:
4060: // We previously saved metaTransportOut; restore it
4061: if (metaTransportOut != null) {
4062: QName qout = metaTransportOut.getQName();
4063: TransportOutDescription tmpOut = null;
4064: try {
4065: tmpOut = axisCfg.getTransportOut(qout.getLocalPart());
4066: } catch (Exception exout) {
4067: // if a fault is thrown, log it and continue
4068: if (LoggingControl.debugLoggingAllowed
4069: && log.isTraceEnabled()) {
4070: log
4071: .trace(logCorrelationIDString
4072: + "activateWithOperationContext(): exception caught when getting the TransportOutDescription ["
4073: + qout.toString()
4074: + "] from the AxisConfiguration ["
4075: + exout.getClass().getName()
4076: + " : " + exout.getMessage() + "]");
4077: }
4078: }
4079:
4080: if (tmpOut != null) {
4081: transportOut = tmpOut;
4082: } else {
4083: transportOut = null;
4084: }
4085: } else {
4086: transportOut = null;
4087: }
4088:
4089: //-------------------------------------------------------
4090: // reconcile the execution chain
4091: //-------------------------------------------------------
4092: if (metaExecutionChain != null) {
4093: if (LoggingControl.debugLoggingAllowed
4094: && log.isTraceEnabled()) {
4095: log
4096: .trace(logCorrelationIDString
4097: + ":activateWithOperationContext(): reconciling the execution chain...");
4098: }
4099:
4100: currentHandlerIndex = metaHandlerIndex;
4101: currentPhaseIndex = metaPhaseIndex;
4102:
4103: executionChain = restoreHandlerList(metaExecutionChain);
4104:
4105: try {
4106: deserializeSelfManagedData();
4107: } catch (Exception ex) {
4108: // log the exception
4109: if (LoggingControl.debugLoggingAllowed
4110: && log.isTraceEnabled()) {
4111: log
4112: .trace(
4113: logCorrelationIDString
4114: + ":activateWithOperationContext(): *** WARNING *** deserializing the self managed data encountered Exception ["
4115: + ex.getClass().getName()
4116: + " : " + ex.getMessage()
4117: + "]", ex);
4118: }
4119: }
4120: }
4121:
4122: //-------------------------------------------------------
4123: // reconcile the lists for the executed phases
4124: //-------------------------------------------------------
4125: if (metaExecuted != null) {
4126: if (LoggingControl.debugLoggingAllowed
4127: && log.isTraceEnabled()) {
4128: log
4129: .trace(logCorrelationIDString
4130: + ":activateWithOperationContext(): reconciling the executed chain...");
4131: }
4132:
4133: if (!(executedPhasesReset)) {
4134: executedPhases = restoreExecutedList(executedPhases,
4135: metaExecuted);
4136: }
4137: }
4138:
4139: if (executedPhases == null) {
4140: executedPhases = new LinkedList();
4141: }
4142:
4143: //-------------------------------------------------------
4144: // done, reset the flag
4145: //-------------------------------------------------------
4146: needsToBeReconciled = false;
4147:
4148: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
4149: log.trace(logCorrelationIDString
4150: + ":activateWithOperationContext(): END");
4151: }
4152: }
4153:
4154: /**
4155: * @param metaDataEntries ArrayList of MetaDataEntry objects
4156: * @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.
4157: */
4158: private ArrayList restoreHandlerList(ArrayList metaDataEntries) {
4159: AxisConfiguration axisConfig = configurationContext
4160: .getAxisConfiguration();
4161:
4162: ArrayList existingHandlers = null;
4163:
4164: // TODO: I'm using clone for the ArrayList returned from axisConfig object.
4165: // Does it do a deep clone of the Handlers held there? Does it matter?
4166: switch (FLOW) {
4167: case IN_FLOW:
4168: existingHandlers = (ArrayList) axisConfig.getInFlowPhases()
4169: .clone();
4170: break;
4171:
4172: case OUT_FLOW:
4173: existingHandlers = (ArrayList) axisConfig
4174: .getOutFlowPhases().clone();
4175: break;
4176:
4177: case IN_FAULT_FLOW:
4178: existingHandlers = (ArrayList) axisConfig
4179: .getInFaultFlowPhases().clone();
4180: break;
4181:
4182: case OUT_FAULT_FLOW:
4183: existingHandlers = (ArrayList) axisConfig
4184: .getOutFaultFlowPhases().clone();
4185: break;
4186: }
4187:
4188: existingHandlers = flattenHandlerList(existingHandlers, null);
4189:
4190: ArrayList handlerListToReturn = new ArrayList();
4191:
4192: for (int i = 0; i < metaDataEntries.size(); i++) {
4193: Handler handler = (Handler) ObjectStateUtils.findHandler(
4194: existingHandlers, (MetaDataEntry) metaDataEntries
4195: .get(i));
4196:
4197: if (handler != null) {
4198: handlerListToReturn.add(handler);
4199: }
4200: }
4201:
4202: return handlerListToReturn;
4203: }
4204:
4205: /**
4206: * Using meta data for phases/handlers, create a linked list of actual
4207: * phase/handler objects. The created list is composed of the objects
4208: * from the base list at the top of the created list followed by the
4209: * restored objects.
4210: *
4211: * @param base Linked list of phase/handler objects
4212: * @param metaDataEntries Linked list of MetaDataEntry objects
4213: * @return LinkedList of objects or NULL if none available
4214: */
4215: private LinkedList restoreExecutedList(LinkedList base,
4216: LinkedList metaDataEntries) {
4217: if (metaDataEntries == null) {
4218: return base;
4219: }
4220:
4221: // get a list of existing handler/phase objects for the restored objects
4222:
4223: ArrayList tmpMetaDataList = new ArrayList(metaDataEntries);
4224:
4225: ArrayList existingList = restoreHandlerList(tmpMetaDataList);
4226:
4227: if ((existingList == null) || (existingList.isEmpty())) {
4228: return base;
4229: }
4230:
4231: // set up a list to return
4232:
4233: LinkedList returnedList = new LinkedList();
4234:
4235: if (base != null) {
4236: returnedList.addAll(base);
4237: }
4238:
4239: returnedList.addAll(existingList);
4240:
4241: return returnedList;
4242: }
4243:
4244: /**
4245: * Process the list of handlers from the Phase object
4246: * into the appropriate meta data.
4247: *
4248: * @param phase The Phase object containing a list of handlers
4249: * @param mdPhase The meta data object associated with the specified Phase object
4250: */
4251: private void setupPhaseList(Phase phase, MetaDataEntry mdPhase) {
4252: // get the list from the phase object
4253: ArrayList handlers = phase.getHandlers();
4254:
4255: if (handlers.isEmpty()) {
4256: // done, make sure there is no list in the given meta data
4257: mdPhase.removeList();
4258: return;
4259: }
4260:
4261: // get the metadata on each member of the list
4262:
4263: int listSize = handlers.size();
4264:
4265: if (listSize > 0) {
4266:
4267: Iterator i = handlers.iterator();
4268:
4269: while (i.hasNext()) {
4270: Object obj = i.next();
4271: String objClass = obj.getClass().getName();
4272:
4273: // start the meta data entry for this object
4274: MetaDataEntry mdEntry = new MetaDataEntry();
4275: mdEntry.setClassName(objClass);
4276:
4277: // get the correct object-specific name
4278: String qnameAsString;
4279:
4280: if (obj instanceof Phase) {
4281: // nested condition, the phase object contains another phase!
4282: Phase phaseObj = (Phase) obj;
4283: qnameAsString = phaseObj.getName();
4284:
4285: // add the list of handlers to the meta data
4286: setupPhaseList(phaseObj, mdEntry);
4287: } else if (obj instanceof Handler) {
4288: Handler handlerObj = (Handler) obj;
4289: qnameAsString = handlerObj.getName();
4290: } else {
4291: // TODO: will there be any other kinds of objects
4292: // in the list?
4293: qnameAsString = "NULL";
4294: }
4295:
4296: mdEntry.setQName(qnameAsString);
4297:
4298: // done with setting up the meta data for the list entry
4299: // so add it to the parent
4300: mdPhase.addToList(mdEntry);
4301:
4302: if (LoggingControl.debugLoggingAllowed
4303: && log.isTraceEnabled()) {
4304: log.trace(getLogIDString()
4305: + ":setupPhaseList(): list entry class ["
4306: + objClass + "] qname [" + qnameAsString
4307: + "]");
4308: }
4309:
4310: } // end while entries in list
4311: } else {
4312: // a list with no entries
4313: // done, make sure there is no list in the given meta data
4314: mdPhase.removeList();
4315: }
4316: }
4317:
4318: /**
4319: * Return a Read-Only copy of this message context
4320: * that has been extracted from the object
4321: * hierachy. In other words, the message context
4322: * copy does not have links to the object graph.
4323: * <p/>
4324: * NOTE: The copy shares certain objects with the original.
4325: * The intent is to use the copy to read values but not
4326: * modify them, especially since the copy is not part
4327: * of the normal *Context and Axis* object graph.
4328: *
4329: * @return A copy of the message context that is not in the object graph
4330: */
4331: public MessageContext extractCopyMessageContext() {
4332: MessageContext copy = new MessageContext();
4333: String logCorrelationIDString = getLogIDString();
4334: if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
4335: log.trace(logCorrelationIDString
4336: + ":extractCopyMessageContext(): based on "
4337: + logCorrelationIDString + " into copy "
4338: + copy.getLogIDString());
4339: }
4340:
4341: //---------------------------------------------------------
4342: // various simple fields
4343: //---------------------------------------------------------
4344:
4345: copy.setFLOW(FLOW);
4346:
4347: copy.setProcessingFault(processingFault);
4348: copy.setPaused(paused);
4349: copy.setOutputWritten(outputWritten);
4350: copy.setNewThreadRequired(newThreadRequired);
4351: copy.setDoingREST(doingREST);
4352: copy.setDoingMTOM(doingMTOM);
4353: copy.setDoingSwA(doingSwA);
4354: copy.setResponseWritten(responseWritten);
4355: copy.setServerSide(serverSide);
4356:
4357: copy.setLastTouchedTime(getLastTouchedTime());
4358:
4359: //---------------------------------------------------------
4360: // message
4361: //---------------------------------------------------------
4362: try {
4363: copy.setEnvelope(envelope);
4364: } catch (Exception ex) {
4365: if (LoggingControl.debugLoggingAllowed
4366: && log.isTraceEnabled()) {
4367: log
4368: .trace(
4369: logCorrelationIDString
4370: + ":extractCopyMessageContext(): Exception caught when setting the copy with the envelope",
4371: ex);
4372: }
4373: }
4374:
4375: copy.setAttachmentMap(attachments);
4376:
4377: copy.setIsSOAP11Explicit(isSOAP11);
4378:
4379: //---------------------------------------------------------
4380: // ArrayList executionChain
4381: // handler and phase related data
4382: //---------------------------------------------------------
4383: copy.setExecutionChain(executionChain);
4384:
4385: // the setting of the execution chain is actually a reset
4386: // so copy the indices after putting in the execution chain
4387: copy.setCurrentHandlerIndex(currentHandlerIndex);
4388: copy.setCurrentPhaseIndex(currentPhaseIndex);
4389:
4390: //---------------------------------------------------------
4391: // LinkedList executedPhases
4392: //---------------------------------------------------------
4393: copy.setExecutedPhasesExplicit(executedPhases);
4394:
4395: //---------------------------------------------------------
4396: // options
4397: //---------------------------------------------------------
4398: copy.setOptionsExplicit(options);
4399:
4400: //---------------------------------------------------------
4401: // axis operation
4402: //---------------------------------------------------------
4403: copy.setAxisOperation(null);
4404:
4405: //---------------------------------------------------------
4406: // operation context
4407: //---------------------------------------------------------
4408: copy.setOperationContext(null);
4409:
4410: //---------------------------------------------------------
4411: // axis service
4412: //---------------------------------------------------------
4413: copy.setAxisService(null);
4414:
4415: //-------------------------
4416: // serviceContextID string
4417: //-------------------------
4418: copy.setServiceContextID(serviceContextID);
4419:
4420: //-------------------------
4421: // serviceContext
4422: //-------------------------
4423: copy.setServiceContext(null);
4424:
4425: //---------------------------------------------------------
4426: // serviceGroup
4427: //---------------------------------------------------------
4428: copy.setServiceGroupContext(null);
4429:
4430: //-----------------------------
4431: // serviceGroupContextId string
4432: //-----------------------------
4433: copy.setServiceGroupContextId(serviceGroupContextId);
4434:
4435: //---------------------------------------------------------
4436: // axis message
4437: //---------------------------------------------------------
4438: copy.setAxisMessage(axisMessage);
4439:
4440: //---------------------------------------------------------
4441: // configuration context
4442: //---------------------------------------------------------
4443: copy.setConfigurationContext(configurationContext);
4444:
4445: //---------------------------------------------------------
4446: // session context
4447: //---------------------------------------------------------
4448: copy.setSessionContext(sessionContext);
4449:
4450: //---------------------------------------------------------
4451: // transport
4452: //---------------------------------------------------------
4453:
4454: //------------------------------
4455: // incomingTransportName string
4456: //------------------------------
4457: copy.setIncomingTransportName(incomingTransportName);
4458:
4459: copy.setTransportIn(transportIn);
4460: copy.setTransportOut(transportOut);
4461:
4462: //---------------------------------------------------------
4463: // properties
4464: //---------------------------------------------------------
4465: copy.setProperties(getProperties());
4466:
4467: //---------------------------------------------------------
4468: // special data
4469: //---------------------------------------------------------
4470:
4471: copy.setSelfManagedDataMapExplicit(selfManagedDataMap);
4472:
4473: //---------------------------------------------------------
4474: // done
4475: //---------------------------------------------------------
4476:
4477: return copy;
4478: }
4479:
4480: //------------------------------------------------------------------------
4481: // additional setter methods needed to copy the message context object
4482: //------------------------------------------------------------------------
4483:
4484: public void setIsSOAP11Explicit(boolean t) {
4485: isSOAP11 = t;
4486: }
4487:
4488: public void setExecutedPhasesExplicit(LinkedList inb) {
4489: executedPhases = inb;
4490: }
4491:
4492: public void setSelfManagedDataMapExplicit(LinkedHashMap map) {
4493: selfManagedDataMap = map;
4494: }
4495:
4496: public void setOptionsExplicit(Options op) {
4497: this .options = op;
4498: }
4499:
4500: /**
4501: * Trace a warning message, if needed, indicating that this
4502: * object needs to be activated before accessing certain fields.
4503: *
4504: * @param methodname The method where the warning occurs
4505: */
4506: private void checkActivateWarning(String methodname) {
4507: if (needsToBeReconciled) {
4508: if (LoggingControl.debugLoggingAllowed
4509: && log.isWarnEnabled()) {
4510: log
4511: .warn(getLogIDString()
4512: + ":"
4513: + methodname
4514: + "(): ****WARNING**** "
4515: + myClassName
4516: + ".activate(configurationContext) needs to be invoked.");
4517: }
4518: }
4519: }
4520:
4521: public ConfigurationContext getRootContext() {
4522: return configurationContext;
4523: }
4524:
4525: public boolean isFault() {
4526: try {
4527: return getEnvelope().getBody().hasFault();
4528: } catch (Exception e) {
4529: // TODO: What should we be doing here? No envelope certainly seems bad....
4530: return false;
4531: }
4532: }
4533:
4534: /**
4535: * Obtain the Exception which caused the processing chain to halt.
4536: * @return null, or an Exception.
4537: */
4538: public Exception getFailureReason() {
4539: return failureReason;
4540: }
4541:
4542: /**
4543: * Set the failure reason. Only AxisEngine should ever do this.
4544: *
4545: * @param failureReason an Exception which caused processing to halt.
4546: */
4547: public void setFailureReason(Exception failureReason) {
4548: this.failureReason = failureReason;
4549: }
4550: }
|