1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 package org.apache.axis2.context;
21
22 import org.apache.axiom.attachments.Attachments;
23 import org.apache.axiom.om.OMOutputFormat;
24 import org.apache.axiom.om.util.DetachableInputStream;
25 import org.apache.axiom.om.util.UUIDGenerator;
26 import org.apache.axiom.soap.SOAP11Constants;
27 import org.apache.axiom.soap.SOAP12Constants;
28 import org.apache.axiom.soap.SOAPEnvelope;
29 import org.apache.axis2.AxisFault;
30 import org.apache.axis2.Constants;
31 import org.apache.axis2.Constants.Configuration;
32 import org.apache.axis2.addressing.EndpointReference;
33 import org.apache.axis2.addressing.RelatesTo;
34 import org.apache.axis2.client.Options;
35 import org.apache.axis2.context.externalize.ActivateUtils;
36 import org.apache.axis2.context.externalize.ExternalizeConstants;
37 import org.apache.axis2.context.externalize.MessageExternalizeUtils;
38 import org.apache.axis2.context.externalize.SafeObjectInputStream;
39 import org.apache.axis2.context.externalize.SafeObjectOutputStream;
40 import org.apache.axis2.context.externalize.SafeSerializable;
41 import org.apache.axis2.description.AxisBinding;
42 import org.apache.axis2.description.AxisBindingMessage;
43 import org.apache.axis2.description.AxisBindingOperation;
44 import org.apache.axis2.description.AxisEndpoint;
45 import org.apache.axis2.description.AxisMessage;
46 import org.apache.axis2.description.AxisModule;
47 import org.apache.axis2.description.AxisOperation;
48 import org.apache.axis2.description.AxisService;
49 import org.apache.axis2.description.AxisServiceGroup;
50 import org.apache.axis2.description.HandlerDescription;
51 import org.apache.axis2.description.ModuleConfiguration;
52 import org.apache.axis2.description.Parameter;
53 import org.apache.axis2.description.TransportInDescription;
54 import org.apache.axis2.description.TransportOutDescription;
55 import org.apache.axis2.engine.AxisConfiguration;
56 import org.apache.axis2.engine.AxisError;
57 import org.apache.axis2.engine.Handler;
58 import org.apache.axis2.engine.Phase;
59 import org.apache.axis2.util.JavaUtils;
60 import org.apache.axis2.util.LoggingControl;
61 import org.apache.axis2.util.MetaDataEntry;
62 import org.apache.axis2.util.SelfManagedDataHolder;
63 import org.apache.axis2.wsdl.WSDLConstants;
64 import org.apache.axis2.wsdl.WSDLUtil;
65 import org.apache.commons.logging.Log;
66 import org.apache.commons.logging.LogFactory;
67 import org.apache.neethi.Policy;
68
69 import javax.activation.DataHandler;
70 import javax.xml.namespace.QName;
71 import java.io.ByteArrayInputStream;
72 import java.io.ByteArrayOutputStream;
73 import java.io.Externalizable;
74 import java.io.IOException;
75 import java.io.ObjectInput;
76 import java.io.ObjectOutput;
77 import java.util.ArrayList;
78 import java.util.Collections;
79 import java.util.HashMap;
80 import java.util.Iterator;
81 import java.util.LinkedHashMap;
82 import java.util.LinkedList;
83 import java.util.List;
84 import java.util.Map;
85
86 /**
87 * <p>Axis2 states are held in two information models, called description hierarchy
88 * and context hierarchy. Description hierarchy hold deployment configuration
89 * and it's values does not change unless deployment configuration change
90 * occurs where Context hierarchy hold run time information. Both hierarchies
91 * consists four levels, Global, Service Group, Operation and Message. Please
92 * look at "Information Model" section of "Axis2 Architecture Guide" for more
93 * information.</p>
94 * <p>MessageContext hold run time information about one Message invocation. It
95 * hold reference to OperationContext, ServiceGroupContext, and Configuration
96 * Context tied with current message. For an example if you need accesses to other
97 * messages of the current invocation, you can get to them via OperationContext.
98 * Addition to class attributes define in Message context, message context stores
99 * the information as name value pairs. Those name value pairs,and class attributes
100 * tweak the execution behavior of message context and some of them can be find in
101 * org.apache.axis2.Constants class. (TODO we should provide list of supported
102 * options). You may set them at any level of context hierarchy and they will
103 * affect invocations related to their child elements. </p>
104 */
105 public class MessageContext extends AbstractContext
106 implements Externalizable, SafeSerializable {
107
108 /*
109 * setup for logging
110 */
111 private static final Log log = LogFactory.getLog(MessageContext.class);
112
113 /**
114 * @serial An ID which can be used to correlate operations on a single
115 * message in the log files, irrespective of thread switches, persistence,
116 * etc.
117 */
118 private String logCorrelationID = null;
119
120 /**
121 * This string will be used to hold a form of the logCorrelationID that
122 * is more suitable for output than its generic form.
123 */
124 private transient String logCorrelationIDString = null;
125
126 private static final String myClassName = "MessageContext";
127
128 /**
129 * @serial The serialization version ID tracks the version of the class.
130 * If a class definition changes, then the serialization/externalization
131 * of the class is affected. If a change to the class is made which is
132 * not compatible with the serialization/externalization of the class,
133 * then the serialization version ID should be updated.
134 * Refer to the "serialVer" utility to compute a serialization
135 * version ID.
136 */
137 private static final long serialVersionUID = -7753637088257391858L;
138
139 /**
140 * @serial Tracks the revision level of a class to identify changes to the
141 * class definition that are compatible to serialization/externalization.
142 * If a class definition changes, then the serialization/externalization
143 * of the class is affected.
144 * Refer to the writeExternal() and readExternal() methods.
145 */
146 // supported revision levels, add a new level to manage compatible changes
147 private static final int REVISION_2 = 2;
148 // current revision level of this object
149 private static final int revisionID = REVISION_2;
150
151
152 /**
153 * A place to store the current MessageContext
154 */
155 public static ThreadLocal<MessageContext> currentMessageContext = new ThreadLocal<MessageContext>();
156
157 public static MessageContext getCurrentMessageContext() {
158 return (MessageContext) currentMessageContext.get();
159 }
160
161 public static void setCurrentMessageContext(MessageContext ctx) {
162 currentMessageContext.set(ctx);
163 }
164
165
166 /**
167 * @serial Options on the message
168 */
169 protected Options options;
170
171 public final static int IN_FLOW = 1;
172 public final static int IN_FAULT_FLOW = 3;
173
174 public final static int OUT_FLOW = 2;
175 public final static int OUT_FAULT_FLOW = 4;
176
177 public static final String REMOTE_ADDR = "REMOTE_ADDR";
178 public static final String TRANSPORT_ADDR = "TRANSPORT_ADDR";
179 public static final String TRANSPORT_HEADERS = "TRANSPORT_HEADERS";
180
181
182 /**
183 * message attachments
184 * NOTE: Serialization of message attachments is handled as part of the
185 * overall message serialization. If this needs to change, then
186 * investigate having the Attachment class implement the
187 * java.io.Externalizable interface.
188 */
189 public transient Attachments attachments;
190
191 /**
192 * Field TRANSPORT_OUT
193 */
194 public static final String TRANSPORT_OUT = "TRANSPORT_OUT";
195
196 /**
197 * Field TRANSPORT_IN
198 */
199 public static final String TRANSPORT_IN = "TRANSPORT_IN";
200
201 /**
202 * Field CHARACTER_SET_ENCODING
203 */
204 public static final String CHARACTER_SET_ENCODING = "CHARACTER_SET_ENCODING";
205
206 /**
207 * Field UTF_8. This is the 'utf-8' value for CHARACTER_SET_ENCODING
208 * property.
209 */
210 public static final String UTF_8 = "UTF-8";
211
212 /**
213 * Field UTF_16. This is the 'utf-16' value for CHARACTER_SET_ENCODING
214 * property.
215 */
216 public static final String UTF_16 = "utf-16";
217
218 /**
219 * Field TRANSPORT_SUCCEED
220 */
221 public static final String TRANSPORT_SUCCEED = "TRANSPORT_SUCCEED";
222
223 /**
224 * Field DEFAULT_CHAR_SET_ENCODING. This is the default value for
225 * CHARACTER_SET_ENCODING property.
226 */
227 public static final String DEFAULT_CHAR_SET_ENCODING = UTF_8;
228
229 /**
230 * @serial The direction flow in use to figure out which path the message is in
231 * (send or receive)
232 */
233 public int FLOW = IN_FLOW;
234
235 /**
236 * To invoke fireAndforget method we have to hand over transport sending logic to a thread
237 * other wise user has to wait till it get transport response (in the case of HTTP its HTTP
238 * 202)
239 */
240 public static final String TRANSPORT_NON_BLOCKING = "transportNonBlocking";
241
242 /**
243 * This property allows someone (e.g. RM) to disable an async callback from
244 * being invoked if a fault occurs during message transmission. If this is
245 * not set, it can be assumed that the fault will be delivered via
246 * Callback.onError(...).
247 */
248 public static final String DISABLE_ASYNC_CALLBACK_ON_TRANSPORT_ERROR =
249 "disableTransmissionErrorCallback";
250
251 /**
252 * @serial processingFault
253 */
254 private boolean processingFault;
255
256 /**
257 * @serial paused
258 */
259 private boolean paused;
260
261 /**
262 * @serial outputWritten
263 */
264 public boolean outputWritten;
265
266 /**
267 * @serial newThreadRequired
268 */
269 private boolean newThreadRequired;
270
271 /**
272 * @serial isSOAP11
273 */
274 private boolean isSOAP11 = true;
275
276 /**
277 * @serial The chain of Handlers/Phases for processing this message
278 */
279 private ArrayList<Handler> executionChain;
280
281 /**
282 * @serial The chain of executed Handlers/Phases from processing
283 */
284 private LinkedList<Handler> executedPhases;
285
286 /**
287 * @serial Flag to indicate if we are doing REST
288 */
289 private boolean doingREST;
290
291 /**
292 * @serial Flag to indicate if we are doing MTOM
293 */
294 private boolean doingMTOM;
295
296 /**
297 * @serial Flag to indicate if we are doing SWA
298 */
299 private boolean doingSwA;
300
301 /**
302 * AxisMessage associated with this message context
303 */
304 private transient AxisMessage axisMessage;
305
306 /**
307 * AxisOperation associated with this message context
308 */
309 private transient AxisOperation axisOperation;
310
311 /**
312 * AxisService
313 */
314 private transient AxisService axisService;
315
316 /**
317 * AxisServiceGroup
318 * <p/>
319 * Note the service group can be set independently of the service
320 * so the service might not match up with this serviceGroup
321 */
322 private transient AxisServiceGroup axisServiceGroup;
323
324 /**
325 * ConfigurationContext
326 */
327 private transient ConfigurationContext configurationContext;
328
329 /**
330 * @serial Index into the executuion chain of the currently executing handler
331 */
332 private int currentHandlerIndex;
333
334 /**
335 * @serial Index into the current Phase of the currently executing handler (if any)
336 */
337 private int currentPhaseIndex;
338
339 /**
340 * If we're processing this MC due to flowComplete() being called in the case
341 * of an Exception, this will hold the Exception which caused the problem.
342 */
343 private Exception failureReason;
344
345 /**
346 * @serial SOAP envelope
347 */
348 private SOAPEnvelope envelope;
349
350 /**
351 * @serial OperationContext
352 */
353 private OperationContext operationContext;
354
355 /**
356 * @serial responseWritten
357 */
358 private boolean responseWritten;
359
360 /**
361 * @serial serverSide
362 */
363 private boolean serverSide;
364
365 /**
366 * @serial ServiceContext
367 */
368 private ServiceContext serviceContext;
369
370 /**
371 * @serial service context ID
372 */
373 private String serviceContextID;
374
375 /**
376 * @serial service group context
377 */
378 private ServiceGroupContext serviceGroupContext;
379
380 /**
381 * @serial Holds a key to retrieve the correct ServiceGroupContext.
382 */
383 private String serviceGroupContextId;
384
385 /**
386 * @serial sessionContext
387 */
388 private SessionContext sessionContext;
389
390
391 /**
392 * transport out description
393 */
394 private transient TransportOutDescription transportOut;
395
396 /**
397 * transport in description
398 */
399 private transient TransportInDescription transportIn;
400
401
402 /**
403 * @serial incoming transport name
404 */
405 //The value will be set by the transport receiver and there will be validation for the transport
406 //at the dispatch phase (its post condition)
407 private String incomingTransportName;
408
409
410 /*
411 * SelfManagedData will hold message-specific data set by handlers
412 * Note that this list is not explicitly saved by the MessageContext, but
413 * rather through the SelfManagedDataManager interface implemented by handlers
414 */
415 private transient LinkedHashMap<String, Object> selfManagedDataMap = null;
416
417 //-------------------------------------------------------------------------
418 // MetaData for data to be restored in activate() after readExternal()
419 //-------------------------------------------------------------------------
420
421 /**
422 * Indicates whether the message context has been reconstituted
423 * and needs to have its object references reconciled
424 */
425 private transient boolean needsToBeReconciled = false;
426
427 /**
428 * selfManagedDataHandlerCount is a count of the number of handlers
429 * that actually saved data during serialization
430 */
431 private transient int selfManagedDataHandlerCount = 0;
432
433 /**
434 * SelfManagedData cannot be restored until the configurationContext
435 * is available, so we have to hold the data from readExternal until
436 * activate is called.
437 */
438 private transient ArrayList<SelfManagedDataHolder> selfManagedDataListHolder = null;
439
440 /**
441 * The ordered list of metadata for handlers/phases
442 * used during re-constitution of the message context
443 */
444 private transient ArrayList<MetaDataEntry> metaExecutionChain = null;
445
446 /**
447 * The ordered list of metadata for executed phases
448 * used during re-constitution of the message context
449 */
450 private transient LinkedList<MetaDataEntry> metaExecuted = null;
451
452 /**
453 * Index into the executuion chain of the currently executing handler
454 */
455 private transient int metaHandlerIndex = 0;
456
457 /**
458 * Index into the current Phase of the currently executing handler (if any)
459 */
460 private transient int metaPhaseIndex = 0;
461
462 /**
463 * The AxisOperation metadata will be used during
464 * activate to match up with an existing object
465 */
466 private transient MetaDataEntry metaAxisOperation = null;
467
468 /**
469 * The AxisService metadata will be used during
470 * activate to match up with an existing object
471 */
472 private transient MetaDataEntry metaAxisService = null;
473
474 /**
475 * The AxisServiceGroup metadata will be used during
476 * activate to match up with an existing object
477 */
478 private transient MetaDataEntry metaAxisServiceGroup = null;
479
480 /**
481 * The TransportOutDescription metadata will be used during
482 * activate to match up with an existing object
483 */
484 private transient MetaDataEntry metaTransportOut = null;
485
486 /**
487 * The TransportInDescription metadata will be used during
488 * activate to match up with an existing object
489 */
490 private transient MetaDataEntry metaTransportIn = null;
491
492 /**
493 * The AxisMessage metadata will be used during
494 * activate to match up with an existing object
495 */
496 private transient MetaDataEntry metaAxisMessage = null;
497
498 /**
499 * Indicates whether this message context has an
500 * AxisMessage object associated with it that needs to
501 * be reconciled
502 */
503 private transient boolean reconcileAxisMessage = false;
504
505 /**
506 * Indicates whether the executed phase list
507 * was reset before the restored list has been reconciled
508 */
509 private transient boolean executedPhasesReset = false;
510
511 //----------------------------------------------------------------
512 // end MetaData section
513 //----------------------------------------------------------------
514
515
516 /**
517 * Constructor
518 */
519 public MessageContext() {
520 super(null);
521 options = new Options();
522 }
523
524 /**
525 * Constructor has package access
526 *
527 * @param configContext the associated ConfigurationContext
528 */
529 MessageContext(ConfigurationContext configContext) {
530 this();
531 setConfigurationContext(configContext);
532 }
533
534 public String toString() {
535 return getLogIDString();
536 }
537
538 /**
539 * Get a "raw" version of the logCorrelationID. The logCorrelationID
540 * is guaranteed to be unique and may be persisted along with the rest
541 * of the message context.
542 *
543 * @return A string that can be output to a log file as an identifier
544 * for this MessageContext. It is suitable for matching related log
545 * entries.
546 */
547 public String getLogCorrelationID() {
548 if (logCorrelationID == null) {
549 logCorrelationID = UUIDGenerator.getUUID();
550 }
551 return logCorrelationID;
552 }
553
554 /**
555 * Get a formatted version of the logCorrelationID.
556 *
557 * @return A string that can be output to a log file as an identifier
558 * for this MessageContext. It is suitable for matching related log
559 * entries.
560 */
561 public String getLogIDString() {
562 if (logCorrelationIDString == null) {
563 logCorrelationIDString = "[MessageContext: logID=" + getLogCorrelationID() + "]";
564 }
565 return logCorrelationIDString;
566 }
567
568
569 /**
570 * Pause the execution of the current handler chain
571 */
572 public void pause() {
573 paused = true;
574 }
575
576 public AxisOperation getAxisOperation() {
577 if (LoggingControl.debugLoggingAllowed) {
578 checkActivateWarning("getAxisOperation");
579 }
580 return axisOperation;
581 }
582
583 public AxisService getAxisService() {
584 if (LoggingControl.debugLoggingAllowed) {
585 checkActivateWarning("getAxisService");
586 }
587 return axisService;
588 }
589
590 /*
591 * <P>
592 * Note the service group can be set independently of the service
593 * so the service might not match up with this serviceGroup
594 */
595 public AxisServiceGroup getAxisServiceGroup() {
596 if (LoggingControl.debugLoggingAllowed) {
597 checkActivateWarning("getAxisServiceGroup");
598 }
599 return axisServiceGroup;
600 }
601
602 public ConfigurationContext getConfigurationContext() {
603 if (LoggingControl.debugLoggingAllowed) {
604 checkActivateWarning("getConfigurationContext");
605 }
606 return configurationContext;
607 }
608
609 public int getCurrentHandlerIndex() {
610 return currentHandlerIndex;
611 }
612
613 public int getCurrentPhaseIndex() {
614 return currentPhaseIndex;
615 }
616
617 /**
618 * @return Returns SOAPEnvelope.
619 */
620 public SOAPEnvelope getEnvelope() {
621 return envelope;
622 }
623
624 public ArrayList<Handler> getExecutionChain() {
625 if (LoggingControl.debugLoggingAllowed) {
626 checkActivateWarning("getExecutionChain");
627 }
628 return executionChain;
629 }
630
631 /**
632 * Add a Phase to the collection of executed phases for the path.
633 * Phases will be inserted in a LIFO data structure.
634 *
635 * @param phase The phase to add to the list.
636 */
637 public void addExecutedPhase(Handler phase) {
638 if (executedPhases == null) {
639 executedPhases = new LinkedList<Handler>();
640 }
641 executedPhases.addFirst(phase);
642 }
643
644 /**
645 * Remove the first Phase in the collection of executed phases
646 */
647 public void removeFirstExecutedPhase() {
648 if (executedPhases != null) {
649 executedPhases.removeFirst();
650 }
651 }
652
653 /**
654 * Get an iterator over the executed phase list.
655 *
656 * @return An Iterator over the LIFO data structure.
657 */
658 public Iterator<Handler> getExecutedPhases() {
659 if (LoggingControl.debugLoggingAllowed) {
660 checkActivateWarning("getExecutedPhases");
661 }
662 if (executedPhases == null) {
663 executedPhases = new LinkedList<Handler>();
664 }
665 return executedPhases.iterator();
666 }
667
668 /**
669 * Reset the list of executed phases.
670 * This is needed because the OutInAxisOperation currently invokes
671 * receive() even when a fault occurs, and we will have already executed
672 * the flowComplete on those before receiveFault() is called.
673 */
674 public void resetExecutedPhases() {
675 executedPhasesReset = true;
676 executedPhases = new LinkedList<Handler>();
677 }
678
679 /**
680 * @return Returns EndpointReference.
681 */
682 public EndpointReference getFaultTo() {
683 return options.getFaultTo();
684 }
685
686 /**
687 * @return Returns EndpointReference.
688 */
689 public EndpointReference getFrom() {
690 return options.getFrom();
691 }
692
693 /**
694 * @return Returns message id.
695 */
696 public String getMessageID() {
697 return options.getMessageId();
698 }
699
700 /**
701 * Retrieves both module specific configuration parameters as well as other
702 * parameters. The order of search is as follows:
703 * <ol>
704 * <li> Search in module configurations inside corresponding operation
705 * description if its there </li>
706 * <li> Search in corresponding operation if its there </li>
707 * <li> Search in module configurations inside corresponding service
708 * description if its there </li>
709 * <li> Next search in Corresponding Service description if its there </li>
710 * <li> Next search in module configurations inside axisConfiguration </li>
711 * <li> Search in AxisConfiguration for parameters </li>
712 * <li> Next get the corresponding module and search for the parameters
713 * </li>
714 * <li> Search in HandlerDescription for the parameter </li>
715 * </ol>
716 * <p/> and the way of specifying module configuration is as follows
717 * <moduleConfig name="addressing"> <parameter name="addressingPara"
718 * >N/A</parameter> </moduleConfig>
719 *
720 * @param key :
721 * Parameter Name
722 * @param moduleName :
723 * Name of the module
724 * @param handler <code>HandlerDescription</code>
725 * @return Parameter <code>Parameter</code>
726 */
727 public Parameter getModuleParameter(String key, String moduleName,
728 HandlerDescription handler) {
729 Parameter param;
730 ModuleConfiguration moduleConfig;
731
732 AxisOperation opDesc = getAxisOperation();
733
734 if (opDesc != null) {
735
736 moduleConfig = opDesc.getModuleConfig(moduleName);
737
738 if (moduleConfig != null) {
739 param = moduleConfig.getParameter(key);
740
741 if (param != null) {
742 return param;
743 } else {
744 param = opDesc.getParameter(key);
745
746 if (param != null) {
747 return param;
748 }
749 }
750 }
751 }
752
753 AxisService axisService = getAxisService();
754
755 if (axisService != null) {
756
757 moduleConfig = axisService.getModuleConfig(moduleName);
758
759 if (moduleConfig != null) {
760 param = moduleConfig.getParameter(key);
761
762 if (param != null) {
763 return param;
764 } else {
765 param = axisService.getParameter(key);
766
767 if (param != null) {
768 return param;
769 }
770 }
771 }
772 }
773
774 AxisServiceGroup axisServiceDesc = getAxisServiceGroup();
775
776 if (axisServiceDesc != null) {
777
778 moduleConfig = axisServiceDesc.getModuleConfig(moduleName);
779
780 if (moduleConfig != null) {
781 param = moduleConfig.getParameter(key);
782
783 if (param != null) {
784 return param;
785 } else {
786 param = axisServiceDesc.getParameter(key);
787
788 if (param != null) {
789 return param;
790 }
791 }
792 }
793 }
794
795 AxisConfiguration baseConfig = configurationContext.getAxisConfiguration();
796
797 moduleConfig = baseConfig.getModuleConfig(moduleName);
798
799 if (moduleConfig != null) {
800 param = moduleConfig.getParameter(key);
801
802 if (param != null) {
803 return param;
804 } else {
805 param = baseConfig.getParameter(key);
806
807 if (param != null) {
808 return param;
809 }
810 }
811 }
812
813 AxisModule module = baseConfig.getModule(moduleName);
814
815 if (module != null) {
816 param = module.getParameter(key);
817
818 if (param != null) {
819 return param;
820 }
821 }
822
823 param = handler.getParameter(key);
824
825 return param;
826 }
827
828 public OperationContext getOperationContext() {
829 if (LoggingControl.debugLoggingAllowed) {
830 checkActivateWarning("getOperationContext");
831 }
832 return operationContext;
833 }
834
835 /**
836 * Retrieves configuration descriptor parameters at any level. The order of
837 * search is as follows:
838 * <ol>
839 * <li> Search in message description if it exists </li>
840 * <li> If parameter is not found or if axisMessage is null, search in
841 * AxisOperation </li>
842 * <li> If parameter is not found or if operationContext is null, search in
843 * AxisService </li>
844 * <li> If parameter is not found or if axisService is null, search in
845 * AxisConfiguration </li>
846 * </ol>
847 *
848 * @param key name of desired parameter
849 * @return Parameter <code>Parameter</code>
850 */
851 public Parameter getParameter(String key) {
852
853 if( axisMessage != null ) {
854 return axisMessage.getParameter(key);
855 }
856
857 if (axisOperation != null) {
858 return axisOperation.getParameter(key);
859 }
860
861 if (axisService != null) {
862 return axisService.getParameter(key);
863 }
864
865 if (axisServiceGroup != null) {
866 return axisServiceGroup.getParameter(key);
867 }
868
869 if (configurationContext != null) {
870 AxisConfiguration baseConfig = configurationContext
871 .getAxisConfiguration();
872 return baseConfig.getParameter(key);
873 }
874 return null;
875 }
876
877 /**
878 * Retrieves a property value. The order of search is as follows: search in
879 * my own map and then look at my options. Does not search up the hierarchy.
880 *
881 * @param name name of the property to search for
882 * @return the value of the property, or null if the property is not found
883 */
884 public Object getLocalProperty(String name) {
885 return getLocalProperty(name, true);
886 }
887 public Object getLocalProperty(String name, boolean searchOptions) {
888 if (LoggingControl.debugLoggingAllowed) {
889 checkActivateWarning("getProperty");
890 }
891
892 // search in my own options
893 Object obj = super.getLocalProperty(name);
894 if (obj != null) {
895 return obj;
896 }
897
898 if (searchOptions) {
899 obj = options.getProperty(name);
900 if (obj != null) {
901 return obj;
902 }
903 }
904
905 // tough
906 return null;
907 }
908
909 /**
910 * Retrieves a property value. The order of search is as follows: search in
911 * my own map and then look in my context hierarchy, and then in options.
912 * Since its possible
913 * that the entire hierarchy is not present, I will start at whatever level
914 * has been set.
915 *
916 * @param name name of the property to search for
917 * @return the value of the property, or null if the property is not found
918 */
919 public Object getProperty(String name) {
920 if (LoggingControl.debugLoggingAllowed) {
921 checkActivateWarning("getProperty");
922 }
923
924 // search in my own options
925 Object obj = super.getProperty(name);
926 if (obj != null) {
927 return obj;
928 }
929
930 obj = options.getProperty(name);
931 if (obj != null) {
932 return obj;
933 }
934
935 // My own context hierarchy may not all be present. So look for whatever
936 // nearest level is present and ask that to find the property.
937 //
938 // If the context is already an ancestor, it was checked during
939 // the super.getProperty call. In such cases, the second check
940 // is not performed.
941 if (operationContext != null) {
942 if (!isAncestor(operationContext)) {
943 obj = operationContext.getProperty(name);
944 }
945 } else if (serviceContext != null) {
946 if (!isAncestor(serviceContext)) {
947 obj = serviceContext.getProperty(name);
948 }
949 } else if (serviceGroupContext != null) {
950 if (!isAncestor(serviceGroupContext)) {
951 obj = serviceGroupContext.getProperty(name);
952 }
953 } else if (configurationContext != null) {
954 if (!isAncestor(configurationContext)) {
955 obj = configurationContext.getProperty(name);
956 }
957 }
958
959 return obj;
960 }
961
962 /**
963 * Check if a given property is true. Will return false if the property
964 * does not exist or is not an explicit "true" value.
965 *
966 * @param name name of the property to check
967 * @return true if the property exists and is Boolean.TRUE, "true", 1, etc.
968 */
969 public boolean isPropertyTrue(String name) {
970 return isPropertyTrue(name, false);
971 }
972
973 /**
974 * Check if a given property is true. Will return the passed default if the property
975 * does not exist.
976 *
977 * @param name name of the property to check
978 * @param defaultVal the default value if the property doesn't exist
979 * @return true if the property exists and is Boolean.TRUE, "true", 1, etc.
980 */
981 public boolean isPropertyTrue(String name, boolean defaultVal) {
982 return JavaUtils.isTrueExplicitly(getProperty(name), defaultVal);
983 }
984
985 /**
986 * Retrieves all property values. The order of search is as follows: search in
987 * my own options and then look in my context hierarchy. Since its possible
988 * that the entire hierarchy is not present, it will start at whatever level
989 * has been set and start there.
990 * The returned map is unmodifiable, so any changes to the properties have
991 * to be done by calling {@link #setProperty(String,Object)}. In addition,
992 * any changes to the properties are not reflected on this map.
993 *
994 * @return An unmodifiable map containing the combination of all available
995 * properties or an empty map.
996 */
997 public Map<String, Object> getProperties() {
998 final Map<String, Object> resultMap = new HashMap<String, Object>();
999
1000 // My own context hierarchy may not all be present. So look for whatever
1001 // nearest level is present and add the properties
1002 // We have to access the contexts in reverse order, in order to allow
1003 // a nearer context to overwrite values from a more distant context
1004 if (configurationContext != null) {
1005 resultMap.putAll(configurationContext.getProperties());
1006 }
1007 if (serviceGroupContext != null) {
1008 resultMap.putAll(serviceGroupContext.getProperties());
1009 }
1010 if (serviceContext != null) {
1011 resultMap.putAll(serviceContext.getProperties());
1012 }
1013 if (operationContext != null) {
1014 resultMap.putAll(operationContext.getProperties());
1015 }
1016 // and now add options
1017 resultMap.putAll(options.getProperties());
1018 return Collections.unmodifiableMap(resultMap);
1019 }
1020
1021 /**
1022 * @return Returns RelatesTo array.
1023 */
1024 public RelatesTo[] getRelationships() {
1025 return options.getRelationships();
1026 }
1027
1028 /**
1029 * Get any RelatesTos of a particular type associated with this MessageContext
1030 * TODO: Shouldn't this return a List?
1031 *
1032 * @param type the relationship type
1033 * @return Returns RelatesTo.
1034 */
1035 public RelatesTo getRelatesTo(String type) {
1036 return options.getRelatesTo(type);
1037 }
1038
1039 /**
1040 * @return Returns RelatesTo.
1041 */
1042 public RelatesTo getRelatesTo() {
1043 return options.getRelatesTo();
1044 }
1045
1046 /**
1047 * @return Returns EndpointReference.
1048 */
1049 public EndpointReference getReplyTo() {
1050 return options.getReplyTo();
1051 }
1052
1053 /**
1054 * @return Returns ServiceContext.
1055 */
1056 public ServiceContext getServiceContext() {
1057 if (LoggingControl.debugLoggingAllowed) {
1058 checkActivateWarning("getServiceContext");
1059 }
1060 return serviceContext;
1061 }
1062
1063 /**
1064 * @return Returns the serviceContextID.
1065 */
1066 public String getServiceContextID() {
1067 return serviceContextID;
1068 }
1069
1070 public ServiceGroupContext getServiceGroupContext() {
1071 if (LoggingControl.debugLoggingAllowed) {
1072 checkActivateWarning("getServiceGroupContext");
1073 }
1074 return serviceGroupContext;
1075 }
1076
1077 public String getServiceGroupContextId() {
1078 return serviceGroupContextId;
1079 }
1080
1081 /**
1082 * @return Returns SessionContext.
1083 */
1084 public SessionContext getSessionContext() {
1085 return sessionContext;
1086 }
1087
1088 public void setSessionContext(SessionContext sessionContext) {
1089 this.sessionContext = sessionContext;
1090 }
1091
1092
1093 /**
1094 * @return Returns soap action.
1095 */
1096 public String getSoapAction() {
1097 return options.getAction();
1098 }
1099
1100 /**
1101 * @return Returns EndpointReference.
1102 */
1103 public EndpointReference getTo() {
1104 return options.getTo();
1105 }
1106
1107 /**
1108 * @return Returns TransportInDescription.
1109 */
1110 public TransportInDescription getTransportIn() {
1111 if (LoggingControl.debugLoggingAllowed) {
1112 checkActivateWarning("getTransportIn");
1113 }
1114 return transportIn;
1115 }
1116
1117 /**
1118 * @return Returns TransportOutDescription.
1119 */
1120 public TransportOutDescription getTransportOut() {
1121 if (LoggingControl.debugLoggingAllowed) {
1122 checkActivateWarning("getTransportOut");
1123 }
1124 return transportOut;
1125 }
1126
1127 public String getWSAAction() {
1128 return options.getAction();
1129 }
1130
1131 /**
1132 * @return Returns boolean.
1133 */
1134 public boolean isDoingMTOM() {
1135 return doingMTOM;
1136 }
1137
1138 /**
1139 * @return Returns boolean.
1140 */
1141 public boolean isDoingREST() {
1142 return doingREST;
1143 }
1144
1145 /**
1146 * @return Returns boolean.
1147 */
1148 public boolean isDoingSwA() {
1149 return doingSwA;
1150 }
1151
1152 /**
1153 * @return Returns boolean.
1154 */
1155 public boolean isNewThreadRequired() {
1156 return newThreadRequired;
1157 }
1158
1159 /**
1160 * @return Returns boolean.
1161 */
1162 public boolean isOutputWritten() {
1163 return outputWritten;
1164 }
1165
1166 /**
1167 * @return Returns boolean.
1168 */
1169 public boolean isPaused() {
1170 return paused;
1171 }
1172
1173 public void setPaused(boolean paused) {
1174 this.paused = paused;
1175 }
1176
1177 /**
1178 * @return Returns boolean.
1179 */
1180 public boolean isProcessingFault() {
1181 return processingFault;
1182 }
1183
1184 /**
1185 * @return Returns boolean.
1186 */
1187 public boolean isResponseWritten() {
1188 return responseWritten;
1189 }
1190
1191 public boolean isSOAP11() {
1192 return isSOAP11;
1193 }
1194
1195 /**
1196 * @return inbound content length of 0
1197 */
1198 public long getInboundContentLength() throws IOException {
1199 // If there is an attachment map, the Attachments keep track
1200 // of the inbound content length.
1201 if (attachments != null) {
1202 // return attachments.getContentLength();
1203 }
1204
1205 // Otherwise the length is accumulated by the DetachableInputStream.
1206 DetachableInputStream dis =
1207 (DetachableInputStream) getProperty(Constants.DETACHABLE_INPUT_STREAM);
1208 if (dis != null) {
1209 return dis.length();
1210 }
1211 return 0;
1212 }
1213 /**
1214 * @return Returns boolean.
1215 */
1216 public boolean isServerSide() {
1217 return serverSide;
1218 }
1219
1220 public AxisMessage getAxisMessage() {
1221 if (reconcileAxisMessage) {
1222 if (LoggingControl.debugLoggingAllowed && log.isWarnEnabled()) {
1223 log.warn(this.getLogIDString() +
1224 ":getAxisMessage(): ****WARNING**** MessageContext.activate(configurationContext) needs to be invoked.");
1225 }
1226 }
1227
1228 return axisMessage;
1229 }
1230
1231 public void setAxisMessage(AxisMessage axisMessage) {
1232 this.axisMessage = axisMessage;
1233 }
1234
1235 public void setAxisOperation(AxisOperation axisOperation) {
1236 this.axisOperation = axisOperation;
1237 }
1238
1239 public void setAxisService(AxisService axisService) {
1240 this.axisService = axisService;
1241 if (this.axisService != null) {
1242 this.axisServiceGroup = axisService.getAxisServiceGroup();
1243 } else {
1244 this.axisServiceGroup = null;
1245 }
1246 }
1247
1248 /*
1249 * note setAxisServiceGroup() does not verify that the service is associated with the service group!
1250 */
1251 public void setAxisServiceGroup(AxisServiceGroup axisServiceGroup) {
1252 // need to set the axis service group object to null when necessary
1253 // for example, when extracting the message context object from
1254 // the object graph
1255 this.axisServiceGroup = axisServiceGroup;
1256 }
1257
1258 /**
1259 * @param context
1260 */
1261 public void setConfigurationContext(ConfigurationContext context) {
1262 configurationContext = context;
1263 }
1264
1265 public void setCurrentHandlerIndex(int currentHandlerIndex) {
1266 this.currentHandlerIndex = currentHandlerIndex;
1267 }
1268
1269 public void setCurrentPhaseIndex(int currentPhaseIndex) {
1270 this.currentPhaseIndex = currentPhaseIndex;
1271 }
1272
1273 /**
1274 * @param b
1275 */
1276 public void setDoingMTOM(boolean b) {
1277 doingMTOM = b;
1278 }
1279
1280 /**
1281 * @param b
1282 */
1283 public void setDoingREST(boolean b) {
1284 doingREST = b;
1285 }
1286
1287 /**
1288 * @param b
1289 */
1290 public void setDoingSwA(boolean b) {
1291 doingSwA = b;
1292 }
1293
1294 /**
1295 * @param envelope
1296 */
1297 public void setEnvelope(SOAPEnvelope envelope) throws AxisFault {
1298 this.envelope = envelope;
1299
1300 if (this.envelope != null) {
1301 String soapNamespaceURI = envelope.getNamespace().getNamespaceURI();
1302
1303 if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI
1304 .equals(soapNamespaceURI)) {
1305 isSOAP11 = false;
1306 } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI
1307 .equals(soapNamespaceURI)) {
1308 isSOAP11 = true;
1309 } else {
1310 throw new AxisFault(
1311 "Unknown SOAP Version. Current Axis handles only SOAP 1.1 and SOAP 1.2 messages");
1312 }
1313 // Inform the listeners of an attach envelope event
1314 if (getAxisService() != null) {
1315 getAxisService().attachEnvelopeEvent(this);
1316 }
1317 }
1318 }
1319
1320 /**
1321 * Set the execution chain of Handler in this MessageContext. Doing this
1322 * causes the current handler/phase indexes to reset to 0, since we have new
1323 * Handlers to execute (this usually only happens at initialization and when
1324 * a fault occurs).
1325 *
1326 * @param executionChain
1327 */
1328 public void setExecutionChain(ArrayList<Handler> executionChain) {
1329 this.executionChain = executionChain;
1330 currentHandlerIndex = -1;
1331 currentPhaseIndex = 0;
1332 }
1333
1334 /**
1335 * @param reference
1336 */
1337 public void setFaultTo(EndpointReference reference) {
1338 options.setFaultTo(reference);
1339 }
1340
1341 /**
1342 * @param reference
1343 */
1344 public void setFrom(EndpointReference reference) {
1345 options.setFrom(reference);
1346 }
1347
1348 /**
1349 * @param messageId
1350 */
1351 public void setMessageID(String messageId) {
1352 options.setMessageId(messageId);
1353 }
1354
1355 /**
1356 * @param b
1357 */
1358 public void setNewThreadRequired(boolean b) {
1359 newThreadRequired = b;
1360 }
1361
1362 /**
1363 * @param context The OperationContext
1364 */
1365 public void setOperationContext(OperationContext context) {
1366 // allow setting the fields to null
1367 // useful when extracting the messge context from the object graph
1368 operationContext = context;
1369
1370 this.setParent(operationContext);
1371
1372 if (operationContext != null) {
1373 if (serviceContext == null) {
1374 setServiceContext(operationContext.getServiceContext());
1375 } else {
1376 if (operationContext.getParent() != serviceContext) {
1377 throw new AxisError("ServiceContext in OperationContext does not match !");
1378 }
1379 }
1380
1381 this.setAxisOperation(operationContext.getAxisOperation());
1382 }
1383 }
1384
1385 /**
1386 * @param b
1387 */
1388 public void setOutputWritten(boolean b) {
1389 outputWritten = b;
1390 }
1391
1392 /**
1393 * @param b
1394 */
1395 public void setProcessingFault(boolean b) {
1396 processingFault = b;
1397 }
1398
1399 /**
1400 * Add a RelatesTo
1401 *
1402 * @param reference RelatesTo describing how we relate to another message
1403 */
1404 public void addRelatesTo(RelatesTo reference) {
1405 options.addRelatesTo(reference);
1406 }
1407
1408 /**
1409 * Set ReplyTo destination
1410 *
1411 * @param reference the ReplyTo EPR
1412 */
1413 public void setReplyTo(EndpointReference reference) {
1414 options.setReplyTo(reference);
1415 }
1416
1417 /**
1418 * @param b
1419 */
1420 public void setResponseWritten(boolean b) {
1421 responseWritten = b;
1422 }
1423
1424 /**
1425 * @param b
1426 */
1427 public void setServerSide(boolean b) {
1428 serverSide = b;
1429 }
1430
1431 /**
1432 * @param context
1433 */
1434 public void setServiceContext(ServiceContext context) {
1435
1436 // allow the service context to be set to null
1437 // this allows the message context object to be extraced from
1438 // the object graph
1439
1440 serviceContext = context;
1441
1442 if (serviceContext != null) {
1443 if ((operationContext != null)
1444 && (operationContext.getParent() != context)) {
1445 throw new AxisError("ServiceContext and OperationContext.parent do not match!");
1446 }
1447 // setting configcontext using configuration context in service context
1448 if (configurationContext == null) {
1449 // setting configcontext
1450 configurationContext = context.getConfigurationContext();
1451 }
1452 if (serviceGroupContext == null) {
1453 // setting service group context
1454 serviceGroupContext = context.getServiceGroupContext();
1455 }
1456 AxisService axisService = context.getAxisService();
1457 this.setAxisService(axisService);
1458
1459 // Inform the listeners of an attach event
1460 if (axisService != null) {
1461 axisService.attachServiceContextEvent(serviceContext, this);
1462 }
1463 }
1464 }
1465
1466 /**
1467 * Sets the service context id.
1468 *
1469 * @param serviceContextID
1470 */
1471 public void setServiceContextID(String serviceContextID) {
1472 this.serviceContextID = serviceContextID;
1473 }
1474
1475 public void setServiceGroupContext(ServiceGroupContext serviceGroupContext) {
1476 // allow the service group context to be set to null
1477 // this allows the message context object to be extraced from
1478 // the object graph
1479
1480 this.serviceGroupContext = serviceGroupContext;
1481
1482 if (this.serviceGroupContext != null) {
1483 this.axisServiceGroup = serviceGroupContext.getDescription();
1484 }
1485 }
1486
1487 public void setServiceGroupContextId(String serviceGroupContextId) {
1488 this.serviceGroupContextId = serviceGroupContextId;
1489 }
1490
1491 /**
1492 * @param soapAction
1493 */
1494 public void setSoapAction(String soapAction) {
1495 options.setAction(soapAction);
1496 }
1497
1498 /**
1499 * @param to
1500 */
1501 public void setTo(EndpointReference to) {
1502 options.setTo(to);
1503 }
1504
1505 /**
1506 * @param in
1507 */
1508 public void setTransportIn(TransportInDescription in) {
1509 this.transportIn = in;
1510 }
1511
1512 /**
1513 * @param out
1514 */
1515 public void setTransportOut(TransportOutDescription out) {
1516 transportOut = out;
1517 }
1518
1519 /**
1520 * setWSAAction
1521 */
1522 public void setWSAAction(String actionURI) {
1523 options.setAction(actionURI);
1524 }
1525
1526 public void setWSAMessageId(String messageID) {
1527 options.setMessageId(messageID);
1528 }
1529
1530 // to get the flow inwhich the execution chain below
1531 public int getFLOW() {
1532 return FLOW;
1533 }
1534
1535 public void setFLOW(int FLOW) {
1536 this.FLOW = FLOW;
1537 }
1538
1539 public Options getOptions() {
1540 if (LoggingControl.debugLoggingAllowed) {
1541 checkActivateWarning("getOptions");
1542 }
1543 return options;
1544 }
1545
1546 /**
1547 * Set the options for myself. I make the given options my own options'
1548 * parent so that that becomes the default. That allows the user to override
1549 * specific options on a given message context and not affect the overall
1550 * options.
1551 *
1552 * @param options the options to set
1553 */
1554 public void setOptions(Options options) {
1555 this.options.setParent(options);
1556 }
1557
1558 public String getIncomingTransportName() {
1559 return incomingTransportName;
1560 }
1561
1562 public void setIncomingTransportName(String incomingTransportName) {
1563 this.incomingTransportName = incomingTransportName;
1564 }
1565
1566 public void setRelationships(RelatesTo[] list) {
1567 options.setRelationships(list);
1568 }
1569
1570
1571 public Policy getEffectivePolicy() {
1572 if (LoggingControl.debugLoggingAllowed) {
1573 checkActivateWarning("getEffectivePolicy");
1574 }
1575
1576 AxisBindingMessage bindingMessage =
1577 (AxisBindingMessage) getProperty(Constants.AXIS_BINDING_MESSAGE);
1578
1579 // If AxisBindingMessage is not set, try to find the binding message from the AxisService
1580 if (bindingMessage == null) {
1581 bindingMessage = findBindingMessage();
1582 }
1583
1584 if (bindingMessage != null) {
1585 return bindingMessage.getEffectivePolicy();
1586 // If we can't find the AxisBindingMessage, then try the AxisMessage
1587 } else if (axisMessage != null) {
1588 return axisMessage.getEffectivePolicy();
1589 } else {
1590 return null;
1591 }
1592 }
1593
1594 private AxisBindingMessage findBindingMessage() {
1595 if (axisService != null && axisOperation != null ) {
1596 if (axisService.getEndpointName() != null) {
1597 AxisEndpoint axisEndpoint = axisService
1598 .getEndpoint(axisService.getEndpointName());
1599 if (axisEndpoint != null) {
1600 AxisBinding axisBinding = axisEndpoint.getBinding();
1601 AxisBindingOperation axisBindingOperation = (AxisBindingOperation) axisBinding
1602 .getChild(axisOperation.getName());
1603
1604 //If Binding Operation is not found, just return null
1605 if (axisBindingOperation == null) {
1606 return null;
1607 }
1608
1609 String direction = axisMessage.getDirection();
1610 AxisBindingMessage axisBindingMessage = null;
1611 if (WSDLConstants.WSDL_MESSAGE_DIRECTION_IN
1612 .equals(direction)
1613 && WSDLUtil
1614 .isInputPresentForMEP(axisOperation
1615 .getMessageExchangePattern())) {
1616 axisBindingMessage = (AxisBindingMessage) axisBindingOperation
1617 .getChild(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
1618 return axisBindingMessage;
1619
1620 } else if (WSDLConstants.WSDL_MESSAGE_DIRECTION_OUT
1621 .equals(direction)
1622 && WSDLUtil
1623 .isOutputPresentForMEP(axisOperation
1624 .getMessageExchangePattern())) {
1625 axisBindingMessage = (AxisBindingMessage) axisBindingOperation
1626 .getChild(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
1627 return axisBindingMessage;
1628 }
1629 }
1630
1631 }
1632 }
1633 return null;
1634 }
1635
1636
1637 public boolean isEngaged(String moduleName) {
1638 if (LoggingControl.debugLoggingAllowed) {
1639 checkActivateWarning("isEngaged");
1640 }
1641 boolean enegage;
1642 if (configurationContext != null) {
1643 AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();
1644 AxisModule module = axisConfig.getModule(moduleName);
1645 if (module == null) {
1646 return false;
1647 }
1648 enegage = axisConfig.isEngaged(module);
1649 if (enegage) {
1650 return true;
1651 }
1652 if (axisServiceGroup != null) {
1653 enegage = axisServiceGroup.isEngaged(module);
1654 if (enegage) {
1655 return true;
1656 }
1657 }
1658 if (axisService != null) {
1659 enegage = axisService.isEngaged(module);
1660 if (enegage) {
1661 return true;
1662 }
1663 }
1664 if (axisOperation != null) {
1665 enegage = axisOperation.isEngaged(module);
1666 if (enegage) {
1667 return true;
1668 }
1669 }
1670 }
1671 return false;
1672 }
1673
1674 /**
1675 * Gets the first child of the envelope, check if it is a soap:Body, which means there is no header.
1676 * We do this basically to make sure we don't parse and build the om tree of the whole envelope
1677 * looking for the soap header. If this method returns true, there still is no guarantee that there is
1678 * a soap:Header present, use getHeader() and also check for null on getHeader() to be absolutely sure.
1679 *
1680 * @return boolean
1681 * @deprecated The bonus you used to get from this is now built in to SOAPEnvelope.getHeader()
1682 */
1683 public boolean isHeaderPresent() {
1684 // If there's no envelope there can't be a header.
1685 if (this.envelope == null) {
1686 return false;
1687 }
1688 return (this.envelope.getHeader() != null);
1689 }
1690
1691 /**
1692 * Setting of the attachments map should be performed at the receipt of a
1693 * message only. This method is only meant to be used by the Axis2
1694 * internals.
1695 *
1696 * @param attachments
1697 */
1698 public void setAttachmentMap(Attachments attachments) {
1699 this.attachments = attachments;
1700 }
1701
1702 /**
1703 * You can directly access the attachment map of the message context from
1704 * here. Returned attachment map can be empty.
1705 *
1706 * @return attachment
1707 */
1708 public Attachments getAttachmentMap() {
1709 if (attachments == null) {
1710 attachments = new Attachments();
1711 }
1712 return attachments;
1713 }
1714
1715 /**
1716 * Adds an attachment to the attachment Map of this message context. This
1717 * attachment gets serialised as a MIME attachment when sending the message
1718 * if SOAP with Attachments is enabled.
1719 *
1720 * @param contentID :
1721 * will be the content ID of the MIME part (without the "cid:" prefix)
1722 * @param dataHandler
1723 */
1724 public void addAttachment(String contentID, DataHandler dataHandler) {
1725 if (attachments == null) {
1726 attachments = new Attachments();
1727 }
1728 attachments.addDataHandler(contentID, dataHandler);
1729 }
1730
1731 /**
1732 * Adds an attachment to the attachment Map of this message context. This
1733 * attachment gets serialised as a MIME attachment when sending the message
1734 * if SOAP with Attachments is enabled. Content ID of the MIME part will be
1735 * auto generated by Axis2.
1736 *
1737 * @param dataHandler
1738 * @return the auto generated content ID of the MIME attachment
1739 */
1740 public String addAttachment(DataHandler dataHandler) {
1741 String contentID = UUIDGenerator.getUUID();
1742 addAttachment(contentID, dataHandler);
1743 return contentID;
1744 }
1745
1746 /**
1747 * Access the DataHandler of the attachment contained in the map corresponding to the given
1748 * content ID. Returns "NULL" if a attachment cannot be found by the given content ID.
1749 *
1750 * @param contentID :
1751 * Content ID of the MIME attachment (without the "cid:" prefix)
1752 * @return Data handler of the attachment
1753 */
1754 public DataHandler getAttachment(String contentID) {
1755 if (attachments == null) {
1756 attachments = new Attachments();
1757 }
1758 return attachments.getDataHandler(contentID);
1759 }
1760
1761 /**
1762 * Removes the attachment with the given content ID from the Attachments Map
1763 * Do nothing if a attachment cannot be found by the given content ID.
1764 *
1765 * @param contentID of the attachment (without the "cid:" prefix)
1766 */
1767 public void removeAttachment(String contentID) {
1768 if (attachments != null) {
1769 attachments.removeDataHandler(contentID);
1770 }
1771 }
1772
1773 /*
1774 * ===============================================================
1775 * SelfManagedData Section
1776 * ===============================================================
1777 */
1778
1779 /*
1780 * character to delimit strings
1781 */
1782 private String selfManagedDataDelimiter = "*";
1783
1784
1785 /**
1786 * Set up a unique key in the form of
1787 * <OL>
1788 * <LI>the class name for the class that owns the key
1789 * <LI>delimitor
1790 * <LI>the key as a string
1791 * <LI>delimitor
1792 * <LI>the key's hash code as a string
1793 * </OL>
1794 *
1795 * @param clazz The class that owns the supplied key
1796 * @param key The key
1797 * @return A string key
1798 */
1799 private String generateSelfManagedDataKey(Class clazz, Object key) {
1800 return clazz.getName() + selfManagedDataDelimiter + key.toString() +
1801 selfManagedDataDelimiter + Integer.toString(key.hashCode());
1802 }
1803
1804 /**
1805 * Add a key-value pair of self managed data to the set associated with
1806 * this message context.
1807 * <p/>
1808 * This is primarily intended to allow handlers to manage their own
1809 * message-specific data when the message context is saved/restored.
1810 *
1811 * @param clazz The class of the caller that owns the key-value pair
1812 * @param key The key for this data object
1813 * @param value The data object
1814 */
1815 public void setSelfManagedData(Class clazz, Object key, Object value) {
1816 if (selfManagedDataMap == null) {
1817 selfManagedDataMap = new LinkedHashMap<String, Object>();
1818 }
1819
1820 // make sure we have a unique key and a delimiter so we can
1821 // get the classname and hashcode for serialization/deserialization
1822 selfManagedDataMap.put(generateSelfManagedDataKey(clazz, key), value);
1823 }
1824
1825 /**
1826 * Retrieve a value of self managed data previously saved with the specified key.
1827 *
1828 * @param clazz The class of the caller that owns the key-value pair
1829 * @param key The key for the data
1830 * @return The data object associated with the key, or NULL if not found
1831 */
1832 public Object getSelfManagedData(Class clazz, Object key) {
1833 if (selfManagedDataMap != null) {
1834 return selfManagedDataMap.get(generateSelfManagedDataKey(clazz, key));
1835 }
1836 return null;
1837 }
1838
1839 /**
1840 * Check to see if the key for the self managed data is available
1841 *
1842 * @param clazz The class of the caller that owns the key-value pair
1843 * @param key The key to look for
1844 * @return TRUE if the key exists, FALSE otherwise
1845 */
1846 public boolean containsSelfManagedDataKey(Class clazz, Object key) {
1847 if (selfManagedDataMap == null) {
1848 return false;
1849 }
1850 return selfManagedDataMap.containsKey(generateSelfManagedDataKey(clazz, key));
1851 }
1852
1853 /**
1854 * Removes the mapping of the specified key if the specified key
1855 * has been set for self managed data
1856 *
1857 * @param clazz The class of the caller that owns the key-value pair
1858 * @param key The key of the object to be removed
1859 */
1860 public void removeSelfManagedData(Class clazz, Object key) {
1861 if (selfManagedDataMap != null) {
1862 selfManagedDataMap.remove(generateSelfManagedDataKey(clazz, key));
1863 }
1864 }
1865
1866 /**
1867 * Flatten the phase list into a list of just unique handler instances
1868 *
1869 * @param list the list of handlers
1870 * @param map users should pass null as this is just a holder for the recursion
1871 * @return a list of unigue object instances
1872 */
1873 private ArrayList<Handler> flattenPhaseListToHandlers(ArrayList<Handler> list, LinkedHashMap<String, Handler> map) {
1874
1875 if (map == null) {
1876 map = new LinkedHashMap<String, Handler>();
1877 }
1878
1879 Iterator<Handler> it = list.iterator();
1880 while (it.hasNext()) {
1881 Handler handler = (Handler) it.next();
1882
1883 String key = null;
1884 if (handler != null) {
1885 key = handler.getClass().getName() + "@" + handler.hashCode();
1886 }
1887
1888 if (handler instanceof Phase) {
1889 // add its handlers to the list
1890 flattenHandlerList(((Phase) handler).getHandlers(), map);
1891 } else {
1892 // if the same object is already in the list,
1893 // then it won't be in the list multiple times
1894 map.put(key, handler);
1895 }
1896 }
1897
1898 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
1899 Iterator<String> it2 = map.keySet().iterator();
1900 while (it2.hasNext()) {
1901 Object key = it2.next();
1902 Handler value = (Handler) map.get(key);
1903 String name = value.getName();
1904 log.trace(getLogIDString() + ":flattenPhaseListToHandlers(): key [" + key +
1905 "] handler name [" + name + "]");
1906 }
1907 }
1908
1909
1910 return new ArrayList<Handler>(map.values());
1911 }
1912
1913
1914 /**
1915 * Flatten the handler list into just unique handler instances
1916 * including phase instances.
1917 *
1918 * @param list the list of handlers/phases
1919 * @param map users should pass null as this is just a holder for the recursion
1920 * @return a list of unigue object instances
1921 */
1922 private ArrayList<Handler> flattenHandlerList(List<Handler> list, LinkedHashMap<String, Handler> map) {
1923
1924 if (map == null) {
1925 map = new LinkedHashMap<String, Handler>();
1926 }
1927
1928 Iterator<Handler> it = list.iterator();
1929 while (it.hasNext()) {
1930 Handler handler = (Handler) it.next();
1931
1932 String key = null;
1933 if (handler != null) {
1934 key = handler.getClass().getName() + "@" + handler.hashCode();
1935 }
1936
1937 if (handler instanceof Phase) {
1938 // put the phase in the list
1939 map.put(key, handler);
1940
1941 // add its handlers to the list
1942 flattenHandlerList(((Phase) handler).getHandlers(), map);
1943 } else {
1944 // if the same object is already in the list,
1945 // then it won't be in the list multiple times
1946 map.put(key, handler);
1947 }
1948 }
1949
1950 return new ArrayList<Handler>(map.values());
1951 }
1952
1953
1954 /**
1955 * Calls the serializeSelfManagedData() method of each handler that
1956 * implements the <bold>SelfManagedDataManager</bold> interface.
1957 * Handlers for this message context are identified via the
1958 * executionChain list.
1959 *
1960 * @param out The output stream
1961 */
1962 private void serializeSelfManagedData(ObjectOutput out) {
1963 selfManagedDataHandlerCount = 0;
1964
1965 try {
1966 if ((selfManagedDataMap == null)
1967 || (executionChain == null)
1968 || (selfManagedDataMap.size() == 0)
1969 || (executionChain.size() == 0)) {
1970 out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
1971
1972 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
1973 log.trace(getLogIDString() + ":serializeSelfManagedData(): No data : END");
1974 }
1975
1976 return;
1977 }
1978
1979 // let's create a temporary list with the handlers
1980 ArrayList<Handler> flatExecChain = flattenPhaseListToHandlers(executionChain, null);
1981
1982 //ArrayList selfManagedDataHolderList = serializeSelfManagedDataHelper(flatExecChain.iterator(), new ArrayList());
1983 ArrayList<SelfManagedDataHolder> selfManagedDataHolderList = serializeSelfManagedDataHelper(flatExecChain);
1984
1985 if (selfManagedDataHolderList.size() == 0) {
1986 out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
1987
1988 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
1989 log.trace(getLogIDString() + ":serializeSelfManagedData(): No data : END");
1990 }
1991
1992 return;
1993 }
1994
1995 out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
1996
1997 // SelfManagedData can be binary so won't be able to treat it as a
1998 // string - need to treat it as a byte []
1999
2000 // how many handlers actually
2001 // returned serialized SelfManagedData
2002 out.writeInt(selfManagedDataHolderList.size());
2003
2004 for (int i = 0; i < selfManagedDataHolderList.size(); i++) {
2005 out.writeObject(selfManagedDataHolderList.get(i));
2006 }
2007
2008 }
2009 catch (IOException e) {
2010 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2011 log.trace("MessageContext:serializeSelfManagedData(): Exception [" +
2012 e.getClass().getName() + "] description [" + e.getMessage() + "]", e);
2013 }
2014 }
2015
2016 }
2017
2018
2019 /**
2020 * This is the helper method to do the recursion for serializeSelfManagedData()
2021 *
2022 * @param handlers
2023 * @return ArrayList
2024 */
2025 private ArrayList<SelfManagedDataHolder> serializeSelfManagedDataHelper(ArrayList<Handler> handlers) {
2026 ArrayList<SelfManagedDataHolder> selfManagedDataHolderList = new ArrayList<SelfManagedDataHolder>();
2027 Iterator<Handler> it = handlers.iterator();
2028
2029 try {
2030 while (it.hasNext()) {
2031 Handler handler = (Handler) it.next();
2032
2033 //if (handler instanceof Phase)
2034 //{
2035 // selfManagedDataHolderList = serializeSelfManagedDataHelper(((Phase)handler).getHandlers().iterator(), selfManagedDataHolderList);
2036 //}
2037 //else if (SelfManagedDataManager.class.isAssignableFrom(handler.getClass()))
2038 if (SelfManagedDataManager.class.isAssignableFrom(handler.getClass())) {
2039 // only call the handler's serializeSelfManagedData if it implements SelfManagedDataManager
2040
2041 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2042 log.trace(
2043 "MessageContext:serializeSelfManagedDataHelper(): calling handler [" +
2044 handler.getClass().getName() + "] name [" +
2045 handler.getName() + "] serializeSelfManagedData method");
2046 }
2047
2048 ByteArrayOutputStream baos_fromHandler =
2049 ((SelfManagedDataManager) handler).serializeSelfManagedData(this);
2050
2051 if (baos_fromHandler != null) {
2052 baos_fromHandler.close();
2053
2054 try {
2055 SelfManagedDataHolder selfManagedDataHolder = new SelfManagedDataHolder(
2056 handler.getClass().getName(), handler.getName(),
2057 baos_fromHandler.toByteArray());
2058 selfManagedDataHolderList.add(selfManagedDataHolder);
2059 selfManagedDataHandlerCount++;
2060 }
2061 catch (Exception exc) {
2062 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2063 log.trace("MessageContext:serializeSelfManagedData(): exception [" +
2064 exc.getClass().getName() + "][" + exc.getMessage() +
2065 "] in setting up SelfManagedDataHolder object for [" +
2066 handler.getClass().getName() + " / " + handler.getName() + "] ",
2067 exc);
2068 }
2069 }
2070 }
2071 }
2072 }
2073
2074 return selfManagedDataHolderList;
2075 }
2076 catch (Exception ex) {
2077 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2078 log.trace("MessageContext:serializeSelfManagedData(): exception [" +
2079 ex.getClass().getName() + "][" + ex.getMessage() + "]", ex);
2080 }
2081 return null;
2082 }
2083
2084 }
2085
2086 /**
2087 * During deserialization, the executionChain will be
2088 * re-constituted before the SelfManagedData is restored.
2089 * This means the handler instances are already available.
2090 * This method lets us find the handler instance from the
2091 * executionChain so we can call each one's
2092 * deserializeSelfManagedData method.
2093 *
2094 * @param it The iterator from the executionChain object
2095 * @param classname The class name
2096 * @param qNameAsString The QName in string form
2097 * @return SelfManagedDataManager handler
2098 */
2099 private SelfManagedDataManager deserialize_getHandlerFromExecutionChain(Iterator<Handler> it,
2100 String classname,
2101 String qNameAsString) {
2102 SelfManagedDataManager handler_toreturn = null;
2103
2104 try {
2105 while ((it.hasNext()) && (handler_toreturn == null)) {
2106 Handler handler = (Handler) it.next();
2107
2108 if (handler instanceof Phase) {
2109 handler_toreturn = deserialize_getHandlerFromExecutionChain(
2110 ((Phase) handler).getHandlers().iterator(), classname, qNameAsString);
2111 } else if ((handler.getClass().getName().equals(classname))
2112 && (handler.getName().equals(qNameAsString))) {
2113 handler_toreturn = (SelfManagedDataManager) handler;
2114 }
2115 }
2116 return handler_toreturn;
2117 }
2118 catch (ClassCastException e) {
2119 // Doesn't seem likely to happen, but just in case...
2120 // A handler classname in the executionChain matched up with our parameter
2121 // classname, but the existing class in the executionChain is a different
2122 // implementation than the one we saved during serializeSelfManagedData.
2123 // NOTE: the exception gets absorbed!
2124
2125 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2126 log.trace(
2127 "MessageContext:deserialize_getHandlerFromExecutionChain(): ClassCastException thrown: " +
2128 e.getMessage(), e);
2129 }
2130 return null;
2131 }
2132 }
2133
2134
2135 /*
2136 * We don't need to create new instances of the handlers
2137 * since the executionChain is rebuilt after readExternal().
2138 * We just have to find them in the executionChain and
2139 * call each handler's deserializeSelfManagedData method.
2140 */
2141 private void deserializeSelfManagedData() throws IOException {
2142 try {
2143 for (int i = 0;
2144 (selfManagedDataListHolder != null) && (i < selfManagedDataListHolder.size()); i++)
2145 {
2146 SelfManagedDataHolder selfManagedDataHolder =
2147 (SelfManagedDataHolder) selfManagedDataListHolder.get(i);
2148
2149 String classname = selfManagedDataHolder.getClassname();
2150 String qNameAsString = selfManagedDataHolder.getId();
2151
2152 SelfManagedDataManager handler = deserialize_getHandlerFromExecutionChain(
2153 executionChain.iterator(), classname, qNameAsString);
2154
2155 if (handler == null) {
2156 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2157 log.trace(getLogIDString() + ":deserializeSelfManagedData(): [" +
2158 classname +
2159 "] was not found in the executionChain associated with the message context.");
2160 }
2161
2162 throw new IOException("The class [" + classname +
2163 "] was not found in the executionChain associated with the message context.");
2164 }
2165
2166 ByteArrayInputStream handlerData =
2167 new ByteArrayInputStream(selfManagedDataHolder.getData());
2168
2169 // the handler implementing SelfManagedDataManager is responsible for repopulating
2170 // the SelfManagedData in the MessageContext (this)
2171
2172 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2173 log.trace(getLogIDString() +
2174 ":deserializeSelfManagedData(): calling handler [" + classname + "] [" +
2175 qNameAsString + "] deserializeSelfManagedData method");
2176 }
2177
2178 handler.deserializeSelfManagedData(handlerData, this);
2179 handler.restoreTransientData(this);
2180 }
2181 }
2182 catch (IOException ioe) {
2183 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2184 log.trace(getLogIDString() + ":deserializeSelfManagedData(): IOException thrown: " +
2185 ioe.getMessage(), ioe);
2186 }
2187 throw ioe;
2188 }
2189
2190 }
2191
2192 /* ===============================================================
2193 * Externalizable support
2194 * ===============================================================
2195 */
2196
2197
2198 /**
2199 * Save the contents of this MessageContext instance.
2200 * <p/>
2201 * NOTE: Transient fields and static fields are not saved.
2202 * Also, objects that represent "static" data are
2203 * not saved, except for enough information to be
2204 * able to find matching objects when the message
2205 * context is re-constituted.
2206 *
2207 * @param out The stream to write the object contents to
2208 * @throws IOException
2209 */
2210 public void writeExternal(ObjectOutput o) throws IOException {
2211 SafeObjectOutputStream out = SafeObjectOutputStream.install(o);
2212 String logCorrelationIDString = getLogIDString();
2213
2214 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2215 log.trace(logCorrelationIDString + ":writeExternal(): writing to output stream");
2216 }
2217
2218 //---------------------------------------------------------
2219 // in order to handle future changes to the message
2220 // context definition, be sure to maintain the
2221 // object level identifiers
2222 //---------------------------------------------------------
2223 // serialization version ID
2224 out.writeLong(serialVersionUID);
2225
2226 // revision ID
2227 out.writeInt(revisionID);
2228
2229 //---------------------------------------------------------
2230 // various simple fields
2231 //---------------------------------------------------------
2232
2233 // the type of execution flow for the message context
2234 out.writeInt(FLOW);
2235
2236 // various flags
2237 out.writeBoolean(processingFault);
2238 out.writeBoolean(paused);
2239 out.writeBoolean(outputWritten);
2240 out.writeBoolean(newThreadRequired);
2241 out.writeBoolean(isSOAP11);
2242 out.writeBoolean(doingREST);
2243 out.writeBoolean(doingMTOM);
2244 out.writeBoolean(doingSwA);
2245 out.writeBoolean(responseWritten);
2246 out.writeBoolean(serverSide);
2247
2248 out.writeLong(getLastTouchedTime());
2249 out.writeObject(getLogCorrelationID());
2250
2251 //-----------------------------------------------------------------------
2252 // Create and initialize the OMOutputFormat for Message Externalization
2253 //-----------------------------------------------------------------------
2254
2255 OMOutputFormat outputFormat= new OMOutputFormat();
2256 outputFormat.setSOAP11(isSOAP11);
2257 boolean persistOptimized = getPersistOptimized();
2258 if (persistOptimized) {
2259 outputFormat.setDoOptimize(true);
2260 }
2261 String charSetEnc = (String) getProperty(MessageContext.CHARACTER_SET_ENCODING);
2262 if (charSetEnc == null) {
2263 OperationContext opContext = getOperationContext();
2264 if (opContext != null) {
2265 charSetEnc =
2266 (String) opContext.getProperty(MessageContext.CHARACTER_SET_ENCODING);
2267 }
2268 }
2269 if (charSetEnc == null) {
2270 charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
2271 }
2272 outputFormat.setCharSetEncoding(charSetEnc);
2273
2274 // ----------------------------------------------------------
2275 // Externalize the Message
2276 // ----------------------------------------------------------
2277 MessageExternalizeUtils.writeExternal(out, this, logCorrelationIDString, outputFormat);
2278
2279 // ---------------------------------------------------------
2280 // ArrayList executionChain
2281 // handler and phase related data
2282 //---------------------------------------------------------
2283 // The strategy is to save some metadata about each
2284 // member of the list and the order of the list.
2285 // Then when the message context is re-constituted,
2286 // try to match up with phases and handlers on the
2287 // engine.
2288 //
2289 // Non-null list:
2290 // UTF - description string
2291 // boolean - active flag
2292 // int - current handler index
2293 // int - current phase index
2294 // int - expected number of entries in the list
2295 // objects - MetaDataEntry object per list entry
2296 // last entry will be empty MetaDataEntry
2297 // with MetaDataEntry.LAST_ENTRY marker
2298 // int - adjusted number of entries in the list
2299 // includes the last empty entry
2300 //
2301 // Empty list:
2302 // UTF - description string
2303 // boolean - empty flag
2304 //---------------------------------------------------------
2305 out.writeUTF("executionChain");
2306 if (executionChain != null && executionChain.size() > 0) {
2307 // start writing data to the output stream
2308 out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
2309 out.writeInt(currentHandlerIndex);
2310 out.writeInt(currentPhaseIndex);
2311 out.writeInt(executionChain.size());
2312
2313 // put the metadata on each member of the list into a buffer
2314
2315 // match the current index with the actual saved list
2316 int nextIndex = 0;
2317
2318 Iterator<Handler> i = executionChain.iterator();
2319
2320 while (i.hasNext()) {
2321 Object obj = i.next();
2322 String objClass = obj.getClass().getName();
2323 // start the meta data entry for this object
2324 MetaDataEntry mdEntry = new MetaDataEntry();
2325 mdEntry.setClassName(objClass);
2326
2327 // get the correct object-specific name
2328 String qnameAsString;
2329
2330 if (obj instanceof Phase) {
2331 Phase phaseObj = (Phase) obj;
2332 qnameAsString = phaseObj.getName();
2333
2334 // add the list of handlers to the meta data
2335 setupPhaseList(phaseObj, mdEntry);
2336 } else if (obj instanceof Handler) {
2337 Handler handlerObj = (Handler) obj;
2338 qnameAsString = handlerObj.getName();
2339 } else {
2340 // TODO: will there be any other kinds of objects in the execution Chain?
2341 qnameAsString = "NULL";
2342 }
2343
2344 mdEntry.setQName(qnameAsString);
2345
2346 // update the index for the entry in the chain
2347
2348 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2349 log.trace(logCorrelationIDString +
2350 ":writeExternal(): ***BEFORE OBJ WRITE*** executionChain entry class [" +
2351 objClass + "] qname [" + qnameAsString + "]");
2352 }
2353
2354 out.writeObject(mdEntry);
2355
2356 // update the index so that the index
2357 // now indicates the next entry that
2358 // will be attempted
2359 nextIndex++;
2360
2361 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2362 log.trace(logCorrelationIDString +
2363 ":writeExternal(): ***AFTER OBJ WRITE*** executionChain entry class [" +
2364 objClass + "] qname [" + qnameAsString + "]");
2365 }
2366
2367 } // end while entries in execution chain
2368
2369 // done with the entries in the execution chain
2370 // add the end-of-list marker
2371 MetaDataEntry lastEntry = new MetaDataEntry();
2372 lastEntry.setClassName(MetaDataEntry.END_OF_LIST);
2373
2374 out.writeObject(lastEntry);
2375 nextIndex++;
2376
2377 // nextIndex also gives us the number of entries
2378 // that were actually saved as opposed to the
2379 // number of entries in the executionChain
2380 out.writeInt(nextIndex);
2381
2382 } else {
2383 // general case: handle "null" or "empty"
2384 out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
2385
2386 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2387 log.trace(logCorrelationIDString + ":writeExternal(): executionChain is NULL");
2388 }
2389 }
2390
2391 //---------------------------------------------------------
2392 // LinkedList executedPhases
2393 //---------------------------------------------------------
2394 // The strategy is to save some metadata about each
2395 // member of the list and the order of the list.
2396 // Then when the message context is re-constituted,
2397 // try to match up with phases and handlers on the
2398 // engine.
2399 //
2400 // Non-null list:
2401 // UTF - description string
2402 // boolean - active flag
2403 // int - expected number of entries in the list
2404 // objects - MetaDataEntry object per list entry
2405 // last entry will be empty MetaDataEntry
2406 // with MetaDataEntry.LAST_ENTRY marker
2407 // int - adjusted number of entries in the list
2408 // includes the last empty entry
2409 //
2410 // Empty list:
2411 // UTF - description string
2412 // boolean - empty flag
2413 //---------------------------------------------------------
2414 out.writeUTF("executedPhases");
2415 if (executedPhases != null && executedPhases.size() > 0) {
2416
2417 // start writing data to the output stream
2418 out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
2419 out.writeInt(executedPhases.size());
2420
2421 // put the metadata on each member of the list into a buffer
2422
2423 int execNextIndex = 0;
2424
2425 Iterator<Handler> iterator = executedPhases.iterator();
2426
2427 while (iterator.hasNext()) {
2428 Object obj = iterator.next();
2429 String objClass = obj.getClass().getName();
2430 // start the meta data entry for this object
2431 MetaDataEntry mdEntry = new MetaDataEntry();
2432 mdEntry.setClassName(objClass);
2433
2434 // get the correct object-specific name
2435 String qnameAsString;
2436
2437 if (obj instanceof Phase) {
2438 Phase inPhaseObj = (Phase) obj;
2439 qnameAsString = inPhaseObj.getName();
2440
2441 // add the list of handlers to the meta data
2442 setupPhaseList(inPhaseObj, mdEntry);
2443 } else if (obj instanceof Handler) {
2444 Handler inHandlerObj = (Handler) obj;
2445 qnameAsString = inHandlerObj.getName();
2446 } else {
2447 // TODO: will there be any other kinds of objects in the list
2448 qnameAsString = "NULL";
2449 }
2450
2451 mdEntry.setQName(qnameAsString);
2452
2453 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2454 log.trace(logCorrelationIDString +
2455 ":writeExternal(): ***BEFORE Executed List OBJ WRITE*** executedPhases entry class [" +
2456 objClass + "] qname [" + qnameAsString + "]");
2457 }
2458
2459 out.writeObject(mdEntry);
2460
2461 // update the index so that the index
2462 // now indicates the next entry that
2463 // will be attempted
2464 execNextIndex++;
2465
2466 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2467 log.trace(logCorrelationIDString + ":writeExternal(): " +
2468 "***AFTER Executed List OBJ WRITE*** " +
2469 "executedPhases entry class [" + objClass + "] " +
2470 "qname [" + qnameAsString + "]");
2471 }
2472 } // end while entries in execution chain
2473
2474 // done with the entries in the execution chain
2475 // add the end-of-list marker
2476 MetaDataEntry lastEntry = new MetaDataEntry();
2477 lastEntry.setClassName(MetaDataEntry.END_OF_LIST);
2478
2479 out.writeObject(lastEntry);
2480 execNextIndex++;
2481
2482 // execNextIndex also gives us the number of entries
2483 // that were actually saved as opposed to the
2484 // number of entries in the executedPhases
2485 out.writeInt(execNextIndex);
2486
2487 } else {
2488 // general case: handle "null" or "empty"
2489 out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
2490
2491 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2492 log.trace(
2493 logCorrelationIDString + ":writeExternal(): executedPhases is NULL");
2494 }
2495 }
2496
2497 //---------------------------------------------------------
2498 // options
2499 //---------------------------------------------------------
2500 // before saving the Options, make sure there is a message ID
2501 String tmpID = getMessageID();
2502 if (tmpID == null) {
2503 // get an id to use when restoring this object
2504 tmpID = UUIDGenerator.getUUID();
2505 setMessageID(tmpID);
2506 }
2507
2508 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2509 log.trace(logCorrelationIDString + ":writeExternal(): message ID [" + tmpID + "]");
2510 }
2511
2512 out.writeUTF("options");
2513 out.writeObject(options);
2514
2515 //---------------------------------------------------------
2516 // operation
2517 //---------------------------------------------------------
2518 // axis operation
2519 //---------------------------------------------------------
2520 out.writeUTF("axisOperation");
2521 metaAxisOperation = null;
2522 if (axisOperation != null) {
2523 // TODO: may need to include the meta data for the axis service that is
2524 // the parent of the axis operation
2525 // make sure the axis operation has a name associated with it
2526 QName aoTmpQName = axisOperation.getName();
2527
2528 if (aoTmpQName == null) {
2529 aoTmpQName = new QName(ExternalizeConstants.EMPTY_MARKER);
2530 axisOperation.setName(aoTmpQName);
2531 }
2532
2533 metaAxisOperation = new MetaDataEntry(axisOperation.getClass().getName(),
2534 axisOperation.getName().toString());
2535 }
2536 out.writeObject(metaAxisOperation);
2537
2538 //---------------------------------------------------------
2539 // operation context
2540 //---------------------------------------------------------
2541 // The OperationContext has pointers to MessageContext objects.
2542 // In order to avoid having multiple copies of the object graph
2543 // being saved at different points in the serialization,
2544 // it is important to isolate this message context object.
2545 out.writeUTF("operationContext");
2546 if (operationContext != null) {
2547 operationContext.isolateMessageContext(this);
2548 }
2549
2550 out.writeObject(operationContext);
2551
2552
2553 //---------------------------------------------------------
2554 // service
2555 //---------------------------------------------------------
2556 // axis service
2557 //-------------------------
2558 // this is expected to be the parent of the axis operation object
2559 out.writeUTF("axisService");
2560 metaAxisService = null;
2561 if (axisService != null) {
2562 metaAxisService = new MetaDataEntry(axisService.getClass().getName(),
2563 axisService.getName());
2564 }
2565 out.writeObject(metaAxisService);
2566
2567 //-------------------------
2568 // serviceContextID string
2569 //-------------------------
2570 out.writeObject(serviceContextID);
2571
2572 //-------------------------
2573 // serviceContext
2574 //-------------------------
2575 // is this the same as the parent of the OperationContext?
2576 boolean isParent = false;
2577 out.writeUTF("serviceContext");
2578
2579 if (operationContext != null) {
2580 ServiceContext opctxParent = operationContext.getServiceContext();
2581
2582 if (serviceContext != null) {
2583 if (serviceContext.equals(opctxParent)) {
2584 // the ServiceContext is the parent of the OperationContext
2585 isParent = true;
2586 }
2587 }
2588 }
2589
2590 if (serviceContext == null) {
2591 out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
2592 } else {
2593 out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
2594 out.writeBoolean(isParent);
2595
2596 // only write out the object if it is not the parent
2597 if (!isParent) {
2598 out.writeObject(serviceContext);
2599 }
2600 }
2601
2602 //---------------------------------------------------------
2603 // axisServiceGroup
2604 //---------------------------------------------------------
2605 out.writeUTF("axisServiceGroup");
2606 metaAxisServiceGroup = null;
2607 if (axisServiceGroup != null) {
2608 metaAxisServiceGroup = new MetaDataEntry(axisServiceGroup.getClass().getName(),
2609 axisServiceGroup.getServiceGroupName());
2610 }
2611 out.writeObject(metaAxisServiceGroup);
2612
2613 //-----------------------------
2614 // serviceGroupContextId string
2615 //-----------------------------
2616 out.writeObject(serviceGroupContextId);
2617
2618 //-------------------------
2619 // serviceGroupContext
2620 //-------------------------
2621 // is this the same as the parent of the ServiceContext?
2622 isParent = false;
2623 out.writeUTF("serviceGroupContext");
2624
2625 if (serviceContext != null) {
2626 ServiceGroupContext srvgrpctxParent = (ServiceGroupContext) serviceContext.getParent();
2627
2628 if (serviceGroupContext != null) {
2629 if (serviceGroupContext.equals(srvgrpctxParent)) {
2630 // the ServiceGroupContext is the parent of the ServiceContext
2631 isParent = true;
2632 }
2633 }
2634 }
2635
2636 if (serviceGroupContext == null) {
2637 out.writeBoolean(ExternalizeConstants.EMPTY_OBJECT);
2638 } else {
2639 out.writeBoolean(ExternalizeConstants.ACTIVE_OBJECT);
2640 out.writeBoolean(isParent);
2641
2642 // only write out the object if it is not the parent
2643 if (!isParent) {
2644 out.writeObject(serviceGroupContext);
2645 }
2646 }
2647
2648 //---------------------------------------------------------
2649 // axis message
2650 //---------------------------------------------------------
2651 out.writeUTF("axisMessage");
2652 metaAxisMessage = null;
2653 if (axisMessage != null) {
2654 // This AxisMessage is expected to belong to the AxisOperation
2655 // that has already been recorded for this MessageContext.
2656 // If an AxisMessage associated with this Messagecontext is
2657 // associated with a different AxisOperation, then more
2658 // meta information would need to be saved
2659
2660 // make sure the axis message has a name associated with it
2661 String amTmpName = axisMessage.getName();
2662
2663 if (amTmpName == null) {
2664 amTmpName = ExternalizeConstants.EMPTY_MARKER;
2665 axisMessage.setName(amTmpName);
2666 }
2667
2668 // get the element name if there is one
2669 QName amTmpElementQName = axisMessage.getElementQName();
2670 String amTmpElemQNameString = null;
2671
2672 if (amTmpElementQName != null) {
2673 amTmpElemQNameString = amTmpElementQName.toString();
2674 }
2675
2676 metaAxisMessage = new MetaDataEntry(axisMessage.getClass().getName(),
2677 axisMessage.getName(), amTmpElemQNameString);
2678
2679 }
2680 out.writeObject(metaAxisMessage);
2681
2682 //---------------------------------------------------------
2683 // configuration context
2684 //---------------------------------------------------------
2685
2686 // NOTE: Currently, there does not seem to be any
2687 // runtime data important to this message context
2688 // in the configuration context.
2689 // if so, then need to save that runtime data and reconcile
2690 // it with the configuration context on the system when
2691 // this message context object is restored
2692
2693 //---------------------------------------------------------
2694 // session context
2695 //---------------------------------------------------------
2696 out.writeObject(sessionContext);
2697
2698 //---------------------------------------------------------
2699 // transport
2700 //---------------------------------------------------------
2701
2702 //------------------------------
2703 // incomingTransportName string
2704 //------------------------------
2705 out.writeObject(incomingTransportName);
2706
2707 // TransportInDescription transportIn
2708 metaTransportIn = null;
2709 if (transportIn != null) {
2710 metaTransportIn = new MetaDataEntry(null, transportIn.getName());
2711 }
2712 out.writeObject(metaTransportIn);
2713
2714 // TransportOutDescription transportOut
2715 metaTransportOut = null;
2716 if (transportOut != null) {
2717 metaTransportOut = new MetaDataEntry(null, transportOut.getName());
2718 }
2719 out.writeObject(metaTransportOut);
2720
2721
2722 //---------------------------------------------------------
2723 // properties
2724 //---------------------------------------------------------
2725 // Write out the local properties on the MessageContext
2726 // Don't write out the properties from other hierarchical layers.
2727 // (i.e. don't use getProperties())
2728 out.writeUTF("properties"); // write marker
2729 out.writeMap(properties);
2730
2731 //---------------------------------------------------------
2732 // special data
2733 //---------------------------------------------------------
2734 out.writeUTF("selfManagedData");
2735 serializeSelfManagedData(out);
2736
2737 //---------------------------------------------------------
2738 // done
2739 //---------------------------------------------------------
2740
2741 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2742 log.trace(logCorrelationIDString +
2743 ":writeExternal(): completed writing to output stream for " +
2744 logCorrelationIDString);
2745 }
2746
2747 }
2748
2749 /**
2750 * @return true if the data should be persisted as optimized attachments
2751 */
2752 private boolean getPersistOptimized() {
2753 boolean persistOptimized = false;
2754 if (attachments != null && attachments.getContentIDList().size() > 1) {
2755 persistOptimized = true;
2756 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
2757 log.trace(getLogIDString()
2758 + ":getPersistOptimized(): attachments present; persist optimized");
2759 }
2760 if (!persistOptimized) {
2761 Object property = getProperty(Configuration.ENABLE_MTOM);
2762 if (property != null && JavaUtils.isTrueExplicitly(property)) {
2763 persistOptimized = true;
2764 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
2765 log.trace(getLogIDString()
2766 + ":getPersistOptimized(): ENBABLE_MTOM is set; persist optimized");
2767 }
2768 }
2769 if (!persistOptimized) {
2770 Object property = getProperty(Configuration.ENABLE_SWA);
2771 if (property != null && JavaUtils.isTrueExplicitly(property)) {
2772 persistOptimized = true;
2773 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
2774 log.trace(getLogIDString()
2775 + ":getPersistOptimized(): ENBABLE_SWA is set; persist optimized");
2776 }
2777 }
2778 if (!persistOptimized && LoggingControl.debugLoggingAllowed && log.isTraceEnabled())
2779 log.trace(getLogIDString()
2780 + ":getPersistOptimized(): No attachments or attachment settings; persist non-optimized");
2781 return persistOptimized;
2782 }
2783
2784
2785 /**
2786 * Restore the contents of the MessageContext that was
2787 * previously saved.
2788 * <p/>
2789 * NOTE: The field data must read back in the same order and type
2790 * as it was written. Some data will need to be validated when
2791 * resurrected.
2792 *
2793 * @param in The stream to read the object contents from
2794 * @throws IOException
2795 * @throws ClassNotFoundException
2796 */
2797 public void readExternal(ObjectInput inObject) throws IOException, ClassNotFoundException {
2798 SafeObjectInputStream in = SafeObjectInputStream.install(inObject);
2799 // set the flag to indicate that the message context is being
2800 // reconstituted and will need to have certain object references
2801 // to be reconciled with the current engine setup
2802 needsToBeReconciled = true;
2803
2804 // trace point
2805 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2806 log.trace(myClassName + ":readExternal(): BEGIN bytes available in stream [" +
2807 in.available() + "] ");
2808 }
2809
2810 //---------------------------------------------------------
2811 // object level identifiers
2812 //---------------------------------------------------------
2813
2814 // serialization version ID
2815 long suid = in.readLong();
2816
2817 // revision ID
2818 int revID = in.readInt();
2819
2820 // make sure the object data is in a version we can handle
2821 if (suid != serialVersionUID) {
2822 throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_SUID);
2823 }
2824
2825 // make sure the object data is in a revision level we can handle
2826 if (revID != REVISION_2) {
2827 throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_REVID);
2828 }
2829
2830 //---------------------------------------------------------
2831 // various simple fields
2832 //---------------------------------------------------------
2833
2834 // the type of execution flow for the message context
2835 FLOW = in.readInt();
2836
2837 // various flags
2838 processingFault = in.readBoolean();
2839 paused = in.readBoolean();
2840 outputWritten = in.readBoolean();
2841 newThreadRequired = in.readBoolean();
2842 isSOAP11 = in.readBoolean();
2843 doingREST = in.readBoolean();
2844 doingMTOM = in.readBoolean();
2845 doingSwA = in.readBoolean();
2846 responseWritten = in.readBoolean();
2847 serverSide = in.readBoolean();
2848
2849 long time = in.readLong();
2850 setLastTouchedTime(time);
2851 logCorrelationID = (String) in.readObject();
2852
2853 // trace point
2854 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2855 logCorrelationIDString = "[MessageContext: logID=" + getLogCorrelationID() + "]";
2856 log.trace(myClassName + ":readExternal(): reading the input stream for " +
2857 getLogIDString());
2858 }
2859
2860 //---------------------------------------------------------
2861 // Message
2862 // Read the message and attachments
2863 //---------------------------------------------------------
2864 envelope = MessageExternalizeUtils.readExternal(in, this, getLogIDString());
2865
2866 //---------------------------------------------------------
2867 // ArrayList executionChain
2868 // handler and phase related data
2869 //---------------------------------------------------------
2870 // Restore the metadata about each member of the list
2871 // and the order of the list.
2872 // This metadata will be used to match up with phases
2873 // and handlers on the engine.
2874 //
2875 // Non-null list:
2876 // UTF - description string
2877 // boolean - active flag
2878 // int - current handler index
2879 // int - current phase index
2880 // int - expected number of entries in the list
2881 // not including the last entry marker
2882 // objects - MetaDataEntry object per list entry
2883 // last entry will be empty MetaDataEntry
2884 // with MetaDataEntry.LAST_ENTRY marker
2885 // int - adjusted number of entries in the list
2886 // includes the last empty entry
2887 //
2888 // Empty list:
2889 // UTF - description string
2890 // boolean - empty flag
2891 //---------------------------------------------------------
2892
2893 // the local chain is not enabled until the
2894 // list has been reconstituted
2895 executionChain = null;
2896 currentHandlerIndex = -1;
2897 currentPhaseIndex = 0;
2898 metaExecutionChain = null;
2899
2900 String marker = in.readUTF();
2901 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2902 log.trace(getLogIDString() +
2903 ": readExternal(): About to read executionChain, marker is: " + marker);
2904 }
2905 boolean gotChain = in.readBoolean();
2906
2907 if (gotChain == ExternalizeConstants.ACTIVE_OBJECT) {
2908 metaHandlerIndex = in.readInt();
2909 metaPhaseIndex = in.readInt();
2910
2911 int expectedNumberEntries = in.readInt();
2912
2913 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2914 log.trace(getLogIDString() +
2915 ":readExternal(): execution chain: expected number of entries [" +
2916 expectedNumberEntries + "]");
2917 }
2918
2919 // setup the list
2920 metaExecutionChain = new ArrayList<MetaDataEntry>();
2921
2922 // process the objects
2923 boolean keepGoing = true;
2924 int count = 0;
2925
2926 while (keepGoing) {
2927 // stop when we get to the end-of-list marker
2928
2929 // get the object
2930 Object tmpObj = in.readObject();
2931
2932 count++;
2933
2934 MetaDataEntry mdObj = (MetaDataEntry) tmpObj;
2935
2936 // get the class name, then add it to the list
2937 String tmpClassNameStr;
2938 String tmpQNameAsStr;
2939
2940 if (mdObj != null) {
2941 tmpClassNameStr = mdObj.getClassName();
2942
2943 if (tmpClassNameStr.equalsIgnoreCase(MetaDataEntry.END_OF_LIST)) {
2944 // this is the last entry
2945 keepGoing = false;
2946 } else {
2947 // add the entry to the meta data list
2948 metaExecutionChain.add(mdObj);
2949
2950 tmpQNameAsStr = mdObj.getQNameAsString();
2951
2952 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2953 String tmpHasList = mdObj.isListEmpty() ? "no children" : "has children";
2954
2955 if (log.isTraceEnabled()) {
2956 log.trace(getLogIDString() +
2957 ":readExternal(): meta data class [" + tmpClassNameStr +
2958 "] qname [" + tmpQNameAsStr + "] index [" + count + "] [" +
2959 tmpHasList + "]");
2960 }
2961 }
2962 }
2963 } else {
2964 // some error occurred
2965 keepGoing = false;
2966 }
2967
2968 } // end while keep going
2969
2970 int adjustedNumberEntries = in.readInt();
2971
2972 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2973 log.trace(getLogIDString() +
2974 ":readExternal(): adjusted number of entries ExecutionChain [" +
2975 adjustedNumberEntries + "] ");
2976 }
2977 }
2978
2979 if ((metaExecutionChain == null) || (metaExecutionChain.isEmpty())) {
2980 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
2981 log.trace(getLogIDString() +
2982 ":readExternal(): meta data for Execution Chain is NULL");
2983 }
2984 }
2985
2986 //---------------------------------------------------------
2987 // LinkedList executedPhases
2988 //
2989 // Note that in previous versions of Axis2, this was
2990 // represented by two lists: "inboundExecutedPhases", "outboundExecutedPhases",
2991 // however since the message context itself represents a flow
2992 // direction, one of these lists was always null. This was changed
2993 // around 2007-06-08 revision r545615. For backward compatability
2994 // with streams saved in previous versions of Axis2, we need
2995 // to be able to process both the old style and new style.
2996 //---------------------------------------------------------
2997 // Restore the metadata about each member of the list
2998 // and the order of the list.
2999 // This metadata will be used to match up with phases
3000 // and handlers on the engine.
3001 //
3002 // Non-null list:
3003 // UTF - description string
3004 // boolean - active flag
3005 // int - expected number of entries in the list
3006 // not including the last entry marker
3007 // objects - MetaDataEntry object per list entry
3008 // last entry will be empty MetaDataEntry
3009 // with MetaDataEntry.LAST_ENTRY marker
3010 // int - adjusted number of entries in the list
3011 // includes the last empty entry
3012 //
3013 // Empty list:
3014 // UTF - description string
3015 // boolean - empty flag
3016 //---------------------------------------------------------
3017
3018 // the local chain is not enabled until the
3019 // list has been reconstituted
3020 executedPhases = null;
3021 metaExecuted = null;
3022
3023 marker = in.readUTF();
3024 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3025 log.trace(getLogIDString() +
3026 ": readExternal(): About to read executedPhases, marker is: " + marker);
3027 }
3028
3029 // Previous versions of Axis2 saved two phases in the stream, although one should
3030 // always have been null. The two phases and their associated markers are, in this order:
3031 // "inboundExecutedPhases", "outboundExecutedPhases".
3032 boolean gotInExecList = in.readBoolean();
3033 boolean oldStyleExecutedPhases = false;
3034 if (marker.equals("inboundExecutedPhases")) {
3035 oldStyleExecutedPhases = true;
3036 }
3037
3038 if (oldStyleExecutedPhases && (gotInExecList == ExternalizeConstants.EMPTY_OBJECT)) {
3039 // There are an inboundExecutedPhases and an outboundExecutedPhases and this one
3040 // is empty, so skip over it and read the next one
3041 marker = in.readUTF();
3042 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3043 log.trace(getLogIDString() +
3044 ": readExternal(): Skipping over oldStyle empty inboundExecutedPhases");
3045 log.trace(getLogIDString() +
3046 ": readExternal(): About to read executedPhases, marker is: " + marker);
3047 }
3048 gotInExecList = in.readBoolean();
3049 }
3050
3051 /*
3052 * At this point, the stream should point to either "executedPhases" if this is the
3053 * new style of serialization. If it is the oldStyle, it should point to whichever
3054 * of "inbound" or "outbound" executed phases contains an active object, since only one
3055 * should
3056 */
3057 if (gotInExecList == ExternalizeConstants.ACTIVE_OBJECT) {
3058 int expectedNumberInExecList = in.readInt();
3059
3060 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3061 log.trace(getLogIDString() +
3062 ":readExternal(): executed phases: expected number of entries [" +
3063 expectedNumberInExecList + "]");
3064 }
3065
3066 // setup the list
3067 metaExecuted = new LinkedList<MetaDataEntry>();
3068
3069 // process the objects
3070 boolean keepGoing = true;
3071 int count = 0;
3072
3073 while (keepGoing) {
3074 // stop when we get to the end-of-list marker
3075
3076 // get the object
3077 Object tmpObj = in.readObject();
3078
3079 count++;
3080
3081 MetaDataEntry mdObj = (MetaDataEntry) tmpObj;
3082
3083 // get the class name, then add it to the list
3084 String tmpClassNameStr;
3085 String tmpQNameAsStr;
3086 String tmpHasList = "no list";
3087
3088 if (mdObj != null) {
3089 tmpClassNameStr = mdObj.getClassName();
3090
3091 if (tmpClassNameStr.equalsIgnoreCase(MetaDataEntry.END_OF_LIST)) {
3092 // this is the last entry
3093 keepGoing = false;
3094 } else {
3095 // add the entry to the meta data list
3096 metaExecuted.add(mdObj);
3097
3098 tmpQNameAsStr = mdObj.getQNameAsString();
3099
3100 if (!mdObj.isListEmpty()) {
3101 tmpHasList = "has list";
3102 }
3103
3104 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3105 log.trace(getLogIDString() +
3106 ":readExternal(): meta data class [" + tmpClassNameStr +
3107 "] qname [" + tmpQNameAsStr + "] index [" + count + "] [" +
3108 tmpHasList + "]");
3109 }
3110 }
3111 } else {
3112 // some error occurred
3113 keepGoing = false;
3114 }
3115
3116 } // end while keep going
3117
3118 int adjustedNumberInExecList = in.readInt();
3119
3120 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3121 log.trace(getLogIDString() +
3122 ":readExternal(): adjusted number of entries executedPhases [" +
3123 adjustedNumberInExecList + "] ");
3124 }
3125 }
3126
3127 if ((metaExecuted == null) || (metaExecuted.isEmpty())) {
3128 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3129 log.trace(getLogIDString() +
3130 ":readExternal(): meta data for executedPhases list is NULL");
3131 }
3132 }
3133
3134 marker = in.readUTF(); // Read marker
3135 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3136 log.trace(getLogIDString() +
3137 ": readExternal(): After reading executedPhases, marker is: " + marker);
3138 }
3139
3140 // If this is an oldStyle that contained both an inbound and outbound executed phases,
3141 // and the outbound phases wasn't read above, then we need to skip over it
3142 if (marker.equals("outboundExecutedPhases")) {
3143 Boolean gotOutExecList = in.readBoolean();
3144 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3145 log.trace(getLogIDString() +
3146 ": readExternal(): Skipping over outboundExecutedPhases, marker is: " + marker +
3147 ", is list an active object: " + gotOutExecList);
3148 }
3149 if (gotOutExecList != ExternalizeConstants.EMPTY_OBJECT) {
3150 throw new IOException("Both inboundExecutedPhases and outboundExecutedPhases had active objects");
3151 }
3152
3153 marker = in.readUTF();
3154 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3155 log.trace(getLogIDString() +
3156 ": readExternal(): After skipping ooutboundExecutePhases, marker is: " + marker);
3157 }
3158 }
3159
3160 //---------------------------------------------------------
3161 // options
3162 //---------------------------------------------------------
3163
3164 options = (Options) in.readObject();
3165
3166 if (options != null) {
3167 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3168 log.trace(getLogIDString() + ":readExternal(): restored Options [" +
3169 options.getLogCorrelationIDString() + "]");
3170 }
3171 }
3172
3173 //---------------------------------------------------------
3174 // operation
3175 //---------------------------------------------------------
3176
3177 // axisOperation is not usable until the meta data has been reconciled
3178 axisOperation = null;
3179 marker = in.readUTF(); // Read Marker
3180 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3181 log.trace(getLogIDString() +
3182 ": readExternal(): About to read axisOperation, marker is: " + marker);
3183 }
3184 metaAxisOperation = (MetaDataEntry) in.readObject();
3185
3186 // operation context is not usable until it has been activated
3187 // NOTE: expect this to be the parent
3188 marker = in.readUTF(); // Read marker
3189 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3190 log.trace(getLogIDString() +
3191 ": readExternal(): About to read operationContext, marker is: " + marker);
3192 }
3193 operationContext = (OperationContext) in.readObject();
3194
3195 if (operationContext != null) {
3196 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3197 log.trace(getLogIDString() + ":readExternal(): restored OperationContext [" +
3198 operationContext.getLogCorrelationIDString() + "]");
3199 }
3200 }
3201
3202 //---------------------------------------------------------
3203 // service
3204 //---------------------------------------------------------
3205
3206 // axisService is not usable until the meta data has been reconciled
3207 axisService = null;
3208 marker = in.readUTF(); // Read marker
3209 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3210 log.trace(getLogIDString() +
3211 ": readExternal(): About to read axisService, marker is: " + marker);
3212 }
3213 metaAxisService = (MetaDataEntry) in.readObject();
3214
3215 //-------------------------
3216 // serviceContextID string
3217 //-------------------------
3218 serviceContextID = (String) in.readObject();
3219
3220 //-------------------------
3221 // serviceContext
3222 //-------------------------
3223 marker = in.readUTF(); // Read marker
3224 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3225 log.trace(getLogIDString() +
3226 ": readExternal(): About to read serviceContext, marker is: " + marker);
3227 }
3228
3229 boolean servCtxActive = in.readBoolean();
3230
3231 if (servCtxActive == ExternalizeConstants.EMPTY_OBJECT) {
3232 // empty object
3233
3234 serviceContext = null;
3235 } else {
3236 // active object
3237
3238 boolean isParent = in.readBoolean();
3239
3240 // there's an object to read in if it is not the parent of the operation context
3241 if (!isParent) {
3242 serviceContext = (ServiceContext) in.readObject();
3243 } else {
3244 // the service context is the parent of the operation context
3245 // so get it from the operation context during activate
3246 serviceContext = null;
3247 }
3248 }
3249
3250 //---------------------------------------------------------
3251 // serviceGroup
3252 //---------------------------------------------------------
3253
3254 // axisServiceGroup is not usable until the meta data has been reconciled
3255 axisServiceGroup = null;
3256 marker = in.readUTF(); // Read marker
3257 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3258 log.trace(getLogIDString() +
3259 ": readExternal(): About to read AxisServiceGroup, marker is: " + marker);
3260 }
3261 metaAxisServiceGroup = (MetaDataEntry) in.readObject();
3262
3263 //-----------------------------
3264 // serviceGroupContextId string
3265 //-----------------------------
3266 serviceGroupContextId = (String) in.readObject();
3267
3268 //-----------------------------
3269 // serviceGroupContext
3270 //-----------------------------
3271 marker = in.readUTF();
3272 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3273 log.trace(getLogIDString() +
3274 ": readExternal(): About to read ServiceGroupContext, marker is: " + marker);
3275 }
3276
3277 boolean servGrpCtxActive = in.readBoolean();
3278
3279 if (servGrpCtxActive == ExternalizeConstants.EMPTY_OBJECT) {
3280 // empty object
3281
3282 serviceGroupContext = null;
3283 } else {
3284 // active object
3285
3286 boolean isParentSGC = in.readBoolean();
3287
3288 // there's an object to read in if it is not the parent of the service group context
3289 if (!isParentSGC) {
3290 serviceGroupContext = (ServiceGroupContext) in.readObject();
3291 } else {
3292 // the service group context is the parent of the service context
3293 // so get it from the service context during activate
3294 serviceGroupContext = null;
3295 }
3296 }
3297
3298 //---------------------------------------------------------
3299 // axis message
3300 //---------------------------------------------------------
3301
3302 // axisMessage is not usable until the meta data has been reconciled
3303 axisMessage = null;
3304 marker = in.readUTF(); // Read marker
3305 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3306 log.trace(getLogIDString() +
3307 ": readExternal(): About to read AxisMessage, marker is: " + marker);
3308 }
3309 metaAxisMessage = (MetaDataEntry) in.readObject();
3310 reconcileAxisMessage = (metaAxisMessage != null);
3311
3312
3313 //---------------------------------------------------------
3314 // configuration context
3315 //---------------------------------------------------------
3316
3317 // TODO: check to see if there is any runtime data important to this
3318 // message context in the configuration context
3319 // if so, then need to restore the saved runtime data and reconcile
3320 // it with the configuration context on the system when
3321 // this message context object is restored
3322
3323 //---------------------------------------------------------
3324 // session context
3325 //---------------------------------------------------------
3326 sessionContext = (SessionContext) in.readObject();
3327
3328 //---------------------------------------------------------
3329 // transport
3330 //---------------------------------------------------------
3331
3332 //------------------------------
3333 // incomingTransportName string
3334 //------------------------------
3335 incomingTransportName = (String) in.readObject();
3336
3337 // TransportInDescription transportIn
3338 // is not usable until the meta data has been reconciled
3339 transportIn = null;
3340 metaTransportIn = (MetaDataEntry) in.readObject();
3341
3342 // TransportOutDescription transportOut
3343 // is not usable until the meta data has been reconciled
3344 transportOut = null;
3345 metaTransportOut = (MetaDataEntry) in.readObject();
3346
3347 //---------------------------------------------------------
3348 // properties
3349 //---------------------------------------------------------
3350 // read local properties
3351 marker = in.readUTF(); // Read marker
3352 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3353 log.trace(getLogIDString() +
3354 ": readExternal(): About to read properties, marker is: " + marker);
3355 }
3356 properties = in.readMap(new HashMapUpdateLockable());
3357
3358
3359 //---------------------------------------------------------
3360 // special data
3361 //---------------------------------------------------------
3362 marker = in.readUTF(); // Read marker
3363 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3364 log.trace(getLogIDString() +
3365 ": readExternal(): About to read SpecialData, marker is: " + marker);
3366 }
3367
3368 boolean gotSelfManagedData = in.readBoolean();
3369
3370 if (gotSelfManagedData == ExternalizeConstants.ACTIVE_OBJECT) {
3371 selfManagedDataHandlerCount = in.readInt();
3372
3373 if (selfManagedDataListHolder == null) {
3374 selfManagedDataListHolder = new ArrayList<SelfManagedDataHolder>();
3375 } else {
3376 selfManagedDataListHolder.clear();
3377 }
3378
3379 for (int i = 0; i < selfManagedDataHandlerCount; i++) {
3380 selfManagedDataListHolder.add((SelfManagedDataHolder) in.readObject());
3381 }
3382 }
3383
3384 //---------------------------------------------------------
3385 // done
3386 //---------------------------------------------------------
3387
3388 // trace point
3389 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3390 log.trace(getLogIDString() +
3391 ":readExternal(): message context object created for " +
3392 getLogIDString());
3393 }
3394 }
3395
3396
3397 /**
3398 * This method checks to see if additional work needs to be
3399 * done in order to complete the object reconstitution.
3400 * Some parts of the object restored from the readExternal()
3401 * cannot be completed until we have a configurationContext
3402 * from the active engine. The configurationContext is used
3403 * to help this object to plug back into the engine's
3404 * configuration and deployment objects.
3405 *
3406 * @param cc The configuration context object representing the active configuration
3407 */
3408 public void activate(ConfigurationContext cc) {
3409 // see if there's any work to do
3410 if (!needsToBeReconciled) {
3411 // return quick
3412 return;
3413 }
3414
3415 // use the supplied configuration context
3416 setConfigurationContext(cc);
3417
3418 // get the axis configuration
3419 AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();
3420
3421 // We previously saved metaAxisService; restore it
3422 if (metaAxisService != null) {
3423 this.setAxisService(ActivateUtils.findService(axisConfig,
3424 metaAxisService.getClassName(),
3425 metaAxisService.getQNameAsString()));
3426 }
3427
3428 // We previously saved metaAxisServiceGroup; restore it
3429 if (metaAxisServiceGroup != null) {
3430 this.setAxisServiceGroup(
3431 ActivateUtils.findServiceGroup(axisConfig,
3432 metaAxisServiceGroup.getClassName(),
3433 metaAxisServiceGroup.getQNameAsString()));
3434 }
3435
3436 // We previously saved metaAxisOperation; restore it
3437 if (metaAxisOperation != null) {
3438 AxisService serv = axisService;
3439
3440 if (serv != null) {
3441 // TODO: check for the empty name
3442 this.setAxisOperation(ActivateUtils.findOperation(serv,
3443 metaAxisOperation.getClassName(),
3444 metaAxisOperation.getQName()));
3445 } else {
3446 this.setAxisOperation(ActivateUtils.findOperation(axisConfig,
3447 metaAxisOperation.getClassName(),
3448 metaAxisOperation.getQName()));
3449 }
3450 }
3451
3452 // We previously saved metaAxisMessage; restore it
3453 if (metaAxisMessage != null) {
3454 AxisOperation op = axisOperation;
3455
3456 if (op != null) {
3457 // TODO: check for the empty name
3458 this.setAxisMessage(ActivateUtils.findMessage(op,
3459 metaAxisMessage.getQNameAsString(),
3460 metaAxisMessage.getExtraName()));
3461 }
3462 }
3463
3464 //---------------------------------------------------------------------
3465 // operation context
3466 //---------------------------------------------------------------------
3467 // this will do a full hierarchy, so do it first
3468 // then we can re-use its objects
3469
3470 if (operationContext != null) {
3471 operationContext.activate(cc);
3472
3473 // this will be set as the parent of the message context
3474 // after the other context objects have been activated
3475 }
3476
3477 //---------------------------------------------------------------------
3478 // service context
3479 //---------------------------------------------------------------------
3480
3481 if (serviceContext == null) {
3482 // get the parent serviceContext of the operationContext
3483 if (operationContext != null) {
3484 serviceContext = operationContext.getServiceContext();
3485 }
3486 }
3487
3488 // if we have a service context, make sure it is usable
3489 if (serviceContext != null) {
3490 // for some reason, the service context might be set differently from
3491 // the operation context parent
3492 serviceContext.activate(cc);
3493 }
3494
3495 //---------------------------------------------------------------------
3496 // service group context
3497 //---------------------------------------------------------------------
3498
3499 if (serviceGroupContext == null) {
3500 // get the parent serviceGroupContext of the serviceContext
3501 if (serviceContext != null) {
3502 serviceGroupContext = (ServiceGroupContext) serviceContext.getParent();
3503 }
3504 }
3505
3506 // if we have a service group context, make sure it is usable
3507 if (serviceGroupContext != null) {
3508 // for some reason, the service group context might be set differently from
3509 // the service context parent
3510 serviceGroupContext.activate(cc);
3511 }
3512
3513 //---------------------------------------------------------------------
3514 // other context-related reconciliation
3515 //---------------------------------------------------------------------
3516
3517 this.setParent(operationContext);
3518
3519 //---------------------------------------------------------------------
3520 // options
3521 //---------------------------------------------------------------------
3522 if (options != null) {
3523 options.activate(cc);
3524 }
3525
3526 String tmpID = getMessageID();
3527 String logCorrelationIDString = getLogIDString();
3528
3529 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3530 log.trace(logCorrelationIDString + ":activate(): message ID [" + tmpID + "] for " +
3531 logCorrelationIDString);
3532 }
3533
3534 //---------------------------------------------------------------------
3535 // transports
3536 //---------------------------------------------------------------------
3537
3538 // We previously saved metaTransportIn; restore it
3539 if (metaTransportIn != null) {
3540 QName qin = metaTransportIn.getQName();
3541 TransportInDescription tmpIn = null;
3542 try {
3543 tmpIn = axisConfig.getTransportIn(qin.getLocalPart());
3544 }
3545 catch (Exception exin) {
3546 // if a fault is thrown, log it and continue
3547 log.trace(logCorrelationIDString +
3548 "activate(): exception caught when getting the TransportInDescription [" +
3549 qin.toString() + "] from the AxisConfiguration [" +
3550 exin.getClass().getName() + " : " + exin.getMessage() + "]");
3551 }
3552
3553 if (tmpIn != null) {
3554 transportIn = tmpIn;
3555 } else {
3556 transportIn = null;
3557 }
3558 } else {
3559 transportIn = null;
3560 }
3561
3562 // We previously saved metaTransportOut; restore it
3563 if (metaTransportOut != null) {
3564 // TODO : Check if this should really be a QName?
3565 QName qout = metaTransportOut.getQName();
3566 TransportOutDescription tmpOut = null;
3567 try {
3568 tmpOut = axisConfig.getTransportOut(qout.getLocalPart());
3569 }
3570 catch (Exception exout) {
3571 // if a fault is thrown, log it and continue
3572 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3573 log.trace(logCorrelationIDString +
3574 "activate(): exception caught when getting the TransportOutDescription [" +
3575 qout.toString() + "] from the AxisConfiguration [" +
3576 exout.getClass().getName() + " : " + exout.getMessage() + "]");
3577 }
3578 }
3579
3580 if (tmpOut != null) {
3581 transportOut = tmpOut;
3582 } else {
3583 transportOut = null;
3584 }
3585 } else {
3586 transportOut = null;
3587 }
3588
3589 //-------------------------------------------------------
3590 // reconcile the execution chain
3591 //-------------------------------------------------------
3592 if (metaExecutionChain != null) {
3593 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3594 log.trace(
3595 logCorrelationIDString + ":activate(): reconciling the execution chain...");
3596 }
3597
3598 currentHandlerIndex = metaHandlerIndex;
3599 currentPhaseIndex = metaPhaseIndex;
3600
3601 executionChain = restoreHandlerList(metaExecutionChain);
3602
3603 try {
3604 deserializeSelfManagedData();
3605 }
3606 catch (Exception ex) {
3607 // log the exception
3608 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3609 log.trace(logCorrelationIDString +
3610 ":activate(): *** WARNING *** deserializing the self managed data encountered Exception [" +
3611 ex.getClass().getName() + " : " + ex.getMessage() + "]", ex);
3612 }
3613 }
3614 }
3615
3616 //-------------------------------------------------------
3617 // reconcile the lists for the executed phases
3618 //-------------------------------------------------------
3619 if (metaExecuted != null) {
3620 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3621 log.trace(logCorrelationIDString +
3622 ":activate(): reconciling the executed chain...");
3623 }
3624
3625 if (!(executedPhasesReset)) {
3626 executedPhases =
3627 restoreExecutedList(executedPhases, metaExecuted);
3628 }
3629 }
3630
3631 if (executedPhases == null) {
3632 executedPhases = new LinkedList<Handler>();
3633 }
3634
3635
3636 //-------------------------------------------------------
3637 // finish up remaining links
3638 //-------------------------------------------------------
3639 if (operationContext != null) {
3640 operationContext.restoreMessageContext(this);
3641 }
3642
3643 //-------------------------------------------------------
3644 // done, reset the flag
3645 //-------------------------------------------------------
3646 needsToBeReconciled = false;
3647
3648 }
3649
3650
3651 /**
3652 * This method checks to see if additional work needs to be
3653 * done in order to complete the object reconstitution.
3654 * Some parts of the object restored from the readExternal()
3655 * cannot be completed until we have an object that gives us
3656 * a view of the active object graph from the active engine.
3657 * <p/>
3658 * NOTE: when activating an object, you only need to call
3659 * one of the activate methods (activate() or activateWithOperationContext())
3660 * but not both.
3661 *
3662 * @param operationCtx The operation context object that is a member of the active object graph
3663 */
3664 public void activateWithOperationContext(OperationContext operationCtx) {
3665 // see if there's any work to do
3666 if (!(needsToBeReconciled)) {
3667 // return quick
3668 return;
3669 }
3670
3671 String logCorrelationIDString = getLogIDString();
3672 // trace point
3673 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3674 log.trace(logCorrelationIDString + ":activateWithOperationContext(): BEGIN");
3675 }
3676
3677 if (operationCtx == null) {
3678 // won't be able to finish
3679 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3680 log.trace(logCorrelationIDString +
3681 ":activateWithOperationContext(): *** WARNING *** No active OperationContext object is available.");
3682 }
3683 return;
3684 }
3685
3686 //---------------------------------------------------------------------
3687 // locate the objects in the object graph
3688 //---------------------------------------------------------------------
3689 ConfigurationContext configCtx = operationCtx.getConfigurationContext();
3690
3691 if (configCtx == null) {
3692 // won't be able to finish
3693 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3694 log.trace(logCorrelationIDString +
3695 ":activateWithOperationContext(): *** WARNING *** No active ConfigurationContext object is available.");
3696 }
3697 return;
3698 }
3699
3700 AxisConfiguration axisCfg = configCtx.getAxisConfiguration();
3701
3702 AxisOperation axisOp = operationCtx.getAxisOperation();
3703 ServiceContext serviceCtx = operationCtx.getServiceContext();
3704
3705 ServiceGroupContext serviceGroupCtx = null;
3706 AxisService axisSrv = null;
3707 AxisServiceGroup axisSG = null;
3708
3709 if (serviceCtx != null) {
3710 serviceGroupCtx = serviceCtx.getServiceGroupContext();
3711 axisSrv = serviceCtx.getAxisService();
3712 }
3713
3714 if (serviceGroupCtx != null) {
3715 axisSG = serviceGroupCtx.getDescription();
3716 }
3717
3718 //---------------------------------------------------------------------
3719 // link to the objects in the object graph
3720 //---------------------------------------------------------------------
3721
3722 setConfigurationContext(configCtx);
3723
3724 setAxisOperation(axisOp);
3725 setAxisService(axisSrv);
3726 setAxisServiceGroup(axisSG);
3727
3728 setServiceGroupContext(serviceGroupCtx);
3729 setServiceContext(serviceCtx);
3730 setOperationContext(operationCtx);
3731
3732 //---------------------------------------------------------------------
3733 // reconcile the remaining objects
3734 //---------------------------------------------------------------------
3735
3736 // We previously saved metaAxisMessage; restore it
3737 if (metaAxisMessage != null) {
3738 if (axisOp != null) {
3739 // TODO: check for the empty name
3740 this.setAxisMessage(ActivateUtils.findMessage(axisOp,
3741 metaAxisMessage.getQNameAsString(),
3742 metaAxisMessage.getExtraName()));
3743 }
3744 }
3745
3746 //---------------------------------------------------------------------
3747 // options
3748 //---------------------------------------------------------------------
3749 if (options != null) {
3750 options.activate(configCtx);
3751 }
3752
3753 String tmpID = getMessageID();
3754
3755 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3756 log.trace(logCorrelationIDString + ":activateWithOperationContext(): message ID [" +
3757 tmpID + "]");
3758 }
3759
3760 //---------------------------------------------------------------------
3761 // transports
3762 //---------------------------------------------------------------------
3763
3764 // We previously saved metaTransportIn; restore it
3765 if (metaTransportIn != null) {
3766 QName qin = metaTransportIn.getQName();
3767 TransportInDescription tmpIn = null;
3768 try {
3769 tmpIn = axisCfg.getTransportIn(qin.getLocalPart());
3770 }
3771 catch (Exception exin) {
3772 // if a fault is thrown, log it and continue
3773 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3774 log.trace(logCorrelationIDString +
3775 "activateWithOperationContext(): exception caught when getting the TransportInDescription [" +
3776 qin.toString() + "] from the AxisConfiguration [" +
3777 exin.getClass().getName() + " : " + exin.getMessage() + "]");
3778 }
3779
3780 }
3781
3782 if (tmpIn != null) {
3783 transportIn = tmpIn;
3784 } else {
3785 transportIn = null;
3786 }
3787 } else {
3788 transportIn = null;
3789 }
3790
3791 // We previously saved metaTransportOut; restore it
3792 if (metaTransportOut != null) {
3793 QName qout = metaTransportOut.getQName();
3794 TransportOutDescription tmpOut = null;
3795 try {
3796 tmpOut = axisCfg.getTransportOut(qout.getLocalPart());
3797 }
3798 catch (Exception exout) {
3799 // if a fault is thrown, log it and continue
3800 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3801 log.trace(logCorrelationIDString +
3802 "activateWithOperationContext(): exception caught when getting the TransportOutDescription [" +
3803 qout.toString() + "] from the AxisConfiguration [" +
3804 exout.getClass().getName() + " : " + exout.getMessage() + "]");
3805 }
3806 }
3807
3808 if (tmpOut != null) {
3809 transportOut = tmpOut;
3810 } else {
3811 transportOut = null;
3812 }
3813 } else {
3814 transportOut = null;
3815 }
3816
3817 //-------------------------------------------------------
3818 // reconcile the execution chain
3819 //-------------------------------------------------------
3820 if (metaExecutionChain != null) {
3821 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3822 log.trace(logCorrelationIDString +
3823 ":activateWithOperationContext(): reconciling the execution chain...");
3824 }
3825
3826 currentHandlerIndex = metaHandlerIndex;
3827 currentPhaseIndex = metaPhaseIndex;
3828
3829 executionChain = restoreHandlerList(metaExecutionChain);
3830
3831 try {
3832 deserializeSelfManagedData();
3833 }
3834 catch (Exception ex) {
3835 // log the exception
3836 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3837 log.trace(logCorrelationIDString +
3838 ":activateWithOperationContext(): *** WARNING *** deserializing the self managed data encountered Exception [" +
3839 ex.getClass().getName() + " : " + ex.getMessage() + "]", ex);
3840 }
3841 }
3842 }
3843
3844 //-------------------------------------------------------
3845 // reconcile the lists for the executed phases
3846 //-------------------------------------------------------
3847 if (metaExecuted != null) {
3848 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3849 log.trace(logCorrelationIDString +
3850 ":activateWithOperationContext(): reconciling the executed chain...");
3851 }
3852
3853 if (!(executedPhasesReset)) {
3854 executedPhases =
3855 restoreExecutedList(executedPhases, metaExecuted);
3856 }
3857 }
3858
3859 if (executedPhases == null) {
3860 executedPhases = new LinkedList<Handler>();
3861 }
3862
3863 //-------------------------------------------------------
3864 // done, reset the flag
3865 //-------------------------------------------------------
3866 needsToBeReconciled = false;
3867
3868 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
3869 log.trace(logCorrelationIDString + ":activateWithOperationContext(): END");
3870 }
3871 }
3872
3873
3874 /**
3875 * @param metaDataEntries ArrayList of MetaDataEntry objects
3876 * @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.
3877 */
3878 private ArrayList<Handler> restoreHandlerList(ArrayList<MetaDataEntry> metaDataEntries) {
3879 AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();
3880
3881 List<Handler> existingHandlers = new ArrayList<Handler>();
3882
3883 // TODO: I'm using clone for the ArrayList returned from axisConfig object.
3884 // Does it do a deep clone of the Handlers held there? Does it matter?
3885 switch (FLOW) {
3886 case IN_FLOW:
3887 existingHandlers.addAll(axisConfig.getInFlowPhases());
3888 break;
3889
3890 case OUT_FLOW:
3891 existingHandlers.addAll(axisConfig.getOutFlowPhases());
3892 break;
3893
3894 case IN_FAULT_FLOW:
3895 existingHandlers.addAll(axisConfig.getInFaultFlowPhases());
3896 break;
3897
3898 case OUT_FAULT_FLOW:
3899 existingHandlers.addAll(axisConfig.getOutFaultFlowPhases());
3900 break;
3901 }
3902
3903 existingHandlers = flattenHandlerList(existingHandlers, null);
3904
3905 ArrayList<Handler> handlerListToReturn = new ArrayList<Handler>();
3906
3907 for (int i = 0; i < metaDataEntries.size(); i++) {
3908 Handler handler = (Handler) ActivateUtils
3909 .findHandler(existingHandlers, (MetaDataEntry) metaDataEntries.get(i));
3910
3911 if (handler != null) {
3912 handlerListToReturn.add(handler);
3913 }
3914 }
3915
3916 return handlerListToReturn;
3917 }
3918
3919
3920 /**
3921 * Using meta data for phases/handlers, create a linked list of actual
3922 * phase/handler objects. The created list is composed of the objects
3923 * from the base list at the top of the created list followed by the
3924 * restored objects.
3925 *
3926 * @param base Linked list of phase/handler objects
3927 * @param metaDataEntries Linked list of MetaDataEntry objects
3928 * @return LinkedList of objects or NULL if none available
3929 */
3930 private LinkedList<Handler> restoreExecutedList(LinkedList<Handler> base, LinkedList<MetaDataEntry> metaDataEntries) {
3931 if (metaDataEntries == null) {
3932 return base;
3933 }
3934
3935 // get a list of existing handler/phase objects for the restored objects
3936
3937 ArrayList<MetaDataEntry> tmpMetaDataList = new ArrayList<MetaDataEntry>(metaDataEntries);
3938
3939 ArrayList<Handler> existingList = restoreHandlerList(tmpMetaDataList);
3940
3941 if ((existingList == null) || (existingList.isEmpty())) {
3942 return base;
3943 }
3944
3945 // set up a list to return
3946
3947 LinkedList<Handler> returnedList = new LinkedList<Handler>();
3948
3949 if (base != null) {
3950 returnedList.addAll(base);
3951 }
3952
3953 returnedList.addAll(existingList);
3954
3955 return returnedList;
3956 }
3957
3958
3959 /**
3960 * Process the list of handlers from the Phase object
3961 * into the appropriate meta data.
3962 *
3963 * @param phase The Phase object containing a list of handlers
3964 * @param mdPhase The meta data object associated with the specified Phase object
3965 */
3966 private void setupPhaseList(Phase phase, MetaDataEntry mdPhase) {
3967 // get the list from the phase object
3968 List<Handler> handlers = phase.getHandlers();
3969
3970 if (handlers.isEmpty()) {
3971 // done, make sure there is no list in the given meta data
3972 mdPhase.removeList();
3973 return;
3974 }
3975
3976 // get the metadata on each member of the list
3977
3978 int listSize = handlers.size();
3979
3980 if (listSize > 0) {
3981
3982 Iterator<Handler> i = handlers.iterator();
3983
3984 while (i.hasNext()) {
3985 Object obj = i.next();
3986 String objClass = obj.getClass().getName();
3987
3988 // start the meta data entry for this object
3989 MetaDataEntry mdEntry = new MetaDataEntry();
3990 mdEntry.setClassName(objClass);
3991
3992 // get the correct object-specific name
3993 String qnameAsString;
3994
3995 if (obj instanceof Phase) {
3996 // nested condition, the phase object contains another phase!
3997 Phase phaseObj = (Phase) obj;
3998 qnameAsString = phaseObj.getName();
3999
4000 // add the list of handlers to the meta data
4001 setupPhaseList(phaseObj, mdEntry);
4002 } else if (obj instanceof Handler) {
4003 Handler handlerObj = (Handler) obj;
4004 qnameAsString = handlerObj.getName();
4005 } else {
4006 // TODO: will there be any other kinds of objects
4007 // in the list?
4008 qnameAsString = "NULL";
4009 }
4010
4011 mdEntry.setQName(qnameAsString);
4012
4013 // done with setting up the meta data for the list entry
4014 // so add it to the parent
4015 mdPhase.addToList(mdEntry);
4016
4017 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
4018 log.trace(getLogIDString() + ":setupPhaseList(): list entry class [" +
4019 objClass + "] qname [" + qnameAsString + "]");
4020 }
4021
4022 } // end while entries in list
4023 } else {
4024 // a list with no entries
4025 // done, make sure there is no list in the given meta data
4026 mdPhase.removeList();
4027 }
4028 }
4029
4030
4031 /**
4032 * Return a Read-Only copy of this message context
4033 * that has been extracted from the object
4034 * hierachy. In other words, the message context
4035 * copy does not have links to the object graph.
4036 * <p/>
4037 * NOTE: The copy shares certain objects with the original.
4038 * The intent is to use the copy to read values but not
4039 * modify them, especially since the copy is not part
4040 * of the normal *Context and Axis* object graph.
4041 *
4042 * @return A copy of the message context that is not in the object graph
4043 */
4044 public MessageContext extractCopyMessageContext() {
4045 MessageContext copy = new MessageContext();
4046 String logCorrelationIDString = getLogIDString();
4047 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
4048 log.trace(logCorrelationIDString + ":extractCopyMessageContext(): based on " +
4049 logCorrelationIDString + " into copy " + copy.getLogIDString());
4050 }
4051
4052 //---------------------------------------------------------
4053 // various simple fields
4054 //---------------------------------------------------------
4055
4056 copy.setFLOW(FLOW);
4057
4058 copy.setProcessingFault(processingFault);
4059 copy.setPaused(paused);
4060 copy.setOutputWritten(outputWritten);
4061 copy.setNewThreadRequired(newThreadRequired);
4062 copy.setDoingREST(doingREST);
4063 copy.setDoingMTOM(doingMTOM);
4064 copy.setDoingSwA(doingSwA);
4065 copy.setResponseWritten(responseWritten);
4066 copy.setServerSide(serverSide);
4067
4068 copy.setLastTouchedTime(getLastTouchedTime());
4069
4070 //---------------------------------------------------------
4071 // message
4072 //---------------------------------------------------------
4073 try {
4074 copy.setEnvelope(envelope);
4075 }
4076 catch (Exception ex) {
4077 if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
4078 log.trace(logCorrelationIDString +
4079 ":extractCopyMessageContext(): Exception caught when setting the copy with the envelope",
4080 ex);
4081 }
4082 }
4083
4084 copy.setAttachmentMap(attachments);
4085
4086 copy.setIsSOAP11Explicit(isSOAP11);
4087
4088 //---------------------------------------------------------
4089 // ArrayList executionChain
4090 // handler and phase related data
4091 //---------------------------------------------------------
4092 copy.setExecutionChain(executionChain);
4093
4094 // the setting of the execution chain is actually a reset
4095 // so copy the indices after putting in the execution chain
4096 copy.setCurrentHandlerIndex(currentHandlerIndex);
4097 copy.setCurrentPhaseIndex(currentPhaseIndex);
4098
4099 //---------------------------------------------------------
4100 // LinkedList executedPhases
4101 //---------------------------------------------------------
4102 copy.setExecutedPhasesExplicit(executedPhases);
4103
4104 //---------------------------------------------------------
4105 // options
4106 //---------------------------------------------------------
4107 copy.setOptionsExplicit(options);
4108
4109 //---------------------------------------------------------
4110 // axis operation
4111 //---------------------------------------------------------
4112 copy.setAxisOperation(null);
4113
4114 //---------------------------------------------------------
4115 // operation context
4116 //---------------------------------------------------------
4117 copy.setOperationContext(null);
4118
4119 //---------------------------------------------------------
4120 // axis service
4121 //---------------------------------------------------------
4122 copy.setAxisService(null);
4123
4124 //-------------------------
4125 // serviceContextID string
4126 //-------------------------
4127 copy.setServiceContextID(serviceContextID);
4128
4129 //-------------------------
4130 // serviceContext
4131 //-------------------------
4132 copy.setServiceContext(null);
4133
4134 //---------------------------------------------------------
4135 // serviceGroup
4136 //---------------------------------------------------------
4137 copy.setServiceGroupContext(null);
4138
4139 //-----------------------------
4140 // serviceGroupContextId string
4141 //-----------------------------
4142 copy.setServiceGroupContextId(serviceGroupContextId);
4143
4144 //---------------------------------------------------------
4145 // axis message
4146 //---------------------------------------------------------
4147 copy.setAxisMessage(axisMessage);
4148
4149 //---------------------------------------------------------
4150 // configuration context
4151 //---------------------------------------------------------
4152 copy.setConfigurationContext(configurationContext);
4153
4154 //---------------------------------------------------------
4155 // session context
4156 //---------------------------------------------------------
4157 copy.setSessionContext(sessionContext);
4158
4159 //---------------------------------------------------------
4160 // transport
4161 //---------------------------------------------------------
4162
4163 //------------------------------
4164 // incomingTransportName string
4165 //------------------------------
4166 copy.setIncomingTransportName(incomingTransportName);
4167
4168 copy.setTransportIn(transportIn);
4169 copy.setTransportOut(transportOut);
4170
4171 //---------------------------------------------------------
4172 // properties
4173 //---------------------------------------------------------
4174 // Only set the local properties (i.e. don't use getProperties())
4175 copy.setProperties(properties);
4176
4177 //---------------------------------------------------------
4178 // special data
4179 //---------------------------------------------------------
4180
4181 copy.setSelfManagedDataMapExplicit(selfManagedDataMap);
4182
4183 //---------------------------------------------------------
4184 // done
4185 //---------------------------------------------------------
4186
4187 return copy;
4188 }
4189
4190 //------------------------------------------------------------------------
4191 // additional setter methods needed to copy the message context object
4192 //------------------------------------------------------------------------
4193
4194 public void setIsSOAP11Explicit(boolean t) {
4195 isSOAP11 = t;
4196 }
4197
4198 public void setExecutedPhasesExplicit(LinkedList<Handler> inb) {
4199 executedPhases = inb;
4200 }
4201
4202 public void setSelfManagedDataMapExplicit(LinkedHashMap<String, Object> map) {
4203 selfManagedDataMap = map;
4204 }
4205
4206 public void setOptionsExplicit(Options op) {
4207 this.options = op;
4208 }
4209
4210
4211 /**
4212 * Trace a warning message, if needed, indicating that this
4213 * object needs to be activated before accessing certain fields.
4214 *
4215 * @param methodname The method where the warning occurs
4216 */
4217 private void checkActivateWarning(String methodname) {
4218 if (needsToBeReconciled) {
4219 if (LoggingControl.debugLoggingAllowed && log.isWarnEnabled()) {
4220 log.warn(getLogIDString() + ":" + methodname + "(): ****WARNING**** " + myClassName +
4221 ".activate(configurationContext) needs to be invoked.");
4222 }
4223 }
4224 }
4225
4226 public ConfigurationContext getRootContext() {
4227 return configurationContext;
4228 }
4229
4230 public boolean isFault() {
4231 try {
4232 return getEnvelope().hasFault();
4233 } catch (Exception e) {
4234 // TODO: What should we be doing here? No envelope certainly seems bad....
4235 return false;
4236 }
4237 }
4238
4239
4240 /**
4241 * Obtain the Exception which caused the processing chain to halt.
4242 * @return null, or an Exception.
4243 */
4244 public Exception getFailureReason() {
4245 return failureReason;
4246 }
4247
4248 /**
4249 * Set the failure reason. Only AxisEngine should ever do this.
4250 *
4251 * @param failureReason an Exception which caused processing to halt.
4252 */
4253 public void setFailureReason(Exception failureReason) {
4254 this.failureReason = failureReason;
4255 }
4256 }