KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > MessageContext


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis ;
18
19 import org.apache.axis.attachments.Attachments;
20 import org.apache.axis.client.AxisClient;
21 import org.apache.axis.components.logger.LogFactory;
22 import org.apache.axis.description.OperationDesc;
23 import org.apache.axis.description.ServiceDesc;
24 import org.apache.axis.encoding.TypeMapping;
25 import org.apache.axis.encoding.TypeMappingRegistry;
26 import org.apache.axis.constants.Style;
27 import org.apache.axis.constants.Use;
28 import org.apache.axis.handlers.soap.SOAPService;
29 import org.apache.axis.schema.SchemaVersion;
30 import org.apache.axis.session.Session;
31 import org.apache.axis.soap.SOAPConstants;
32 import org.apache.axis.utils.JavaUtils;
33 import org.apache.axis.utils.LockableHashtable;
34 import org.apache.axis.utils.Messages;
35 import org.apache.commons.logging.Log;
36
37 import javax.xml.namespace.QName JavaDoc;
38 import javax.xml.rpc.Call JavaDoc;
39 import javax.xml.rpc.handler.soap.SOAPMessageContext JavaDoc;
40 import java.io.File JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.Hashtable JavaDoc;
43
44 // fixme: fields are declared throughout this class, some at the top, and some
45
// near to where they are used. We should move all field declarations into a
46
// single block - it makes it easier to see what is decalred in this class and
47
// what is inherited. It also makes it easier to find them.
48
/**
49  * A MessageContext is the Axis implementation of the javax
50  * SOAPMessageContext class, and is core to message processing
51  * in handlers and other parts of the system.
52  *
53  * This class also contains constants for accessing some
54  * well-known properties. Using a hierarchical namespace is
55  * strongly suggested in order to lower the chance for
56  * conflicts.
57  *
58  * (These constants should be viewed as an explicit list of well
59  * known and widely used context keys, there's nothing wrong
60  * with directly using the key strings. This is the reason for
61  * the hierarchical constant namespace.
62  *
63  * Actually I think we might just list the keys in the docs and
64  * provide no such constants since they create yet another
65  * namespace, but we'd have no compile-time checks then.
66  *
67  * Whaddya think? - todo by Jacek)
68  *
69  *
70  * @author Doug Davis (dug@us.ibm.com)
71  * @author Jacek Kopecky (jacek@idoox.com)
72  */

73 public class MessageContext implements SOAPMessageContext JavaDoc {
74     /** The <code>Log</code> used for logging all messages. */
75     protected static Log log =
76             LogFactory.getLog(MessageContext.class.getName());
77
78     /**
79      * The request message. If we're on the client, this is the outgoing
80      * message heading to the server. If we're on the server, this is the
81      * incoming message we've received from the client.
82      */

83     private Message requestMessage;
84
85     /**
86      * The response message. If we're on the server, this is the outgoing
87      * message heading back to the client. If we're on the client, this is the
88      * incoming message we've received from the server.
89      */

90     private Message responseMessage;
91
92     /**
93      * That unique key/name that the next router/dispatch handler should use
94      * to determine what to do next.
95      */

96     private String JavaDoc targetService;
97
98     /**
99      * The name of the Transport which this message was received on (or is
100      * headed to, for the client).
101      */

102     private String JavaDoc transportName;
103
104     /**
105      * The default <code>ClassLoader</code> that this service should use.
106      */

107     private ClassLoader JavaDoc classLoader;
108
109     /**
110      * The AxisEngine which this context is involved with.
111      */

112     private AxisEngine axisEngine;
113
114     /**
115      * A Session associated with this request.
116      */

117     private Session session;
118
119     /**
120      * Should we track session state, or not?
121      * default is not.
122      * Could potentially refactor this so that
123      * maintainSession iff session != null...
124      */

125     private boolean maintainSession = false;
126
127     // fixme: ambiguity here due to lac of docs - havePassedPivot vs
128
// request/response, vs sending/processing & recieving/responding
129
// I may have just missed the key bit of text
130
/**
131      * Are we doing request stuff, or response stuff? True if processing
132      * response (I think).
133      */

134     private boolean havePassedPivot = false;
135
136     /**
137      * Maximum amount of time to wait on a request, in milliseconds.
138      */

139     private int timeout = Constants.DEFAULT_MESSAGE_TIMEOUT;
140
141     /**
142      * An indication of whether we require "high fidelity" recording of
143      * deserialized messages for this interaction. Defaults to true for
144      * now, and can be set to false, usually at service-dispatch time.
145      */

146     private boolean highFidelity = true;
147
148     /**
149      * Storage for an arbitrary bag of properties associated with this
150      * MessageContext.
151      */

152     private LockableHashtable bag = new LockableHashtable();
153
154     /*
155      * These variables are logically part of the bag, but are separated
156      * because they are used often and the Hashtable is more expensive.
157      *
158      * fixme: this may be fixed by moving to a plain Map impl like HashMap.
159      * Alternatively, we could hide all this magic behind a custom Map impl -
160      * is synchronization on the map needed? these properties aren't
161      * synchronized so I'm guessing not.
162      */

163     private String JavaDoc username = null;
164     private String JavaDoc password = null;
165     private String JavaDoc encodingStyle = Use.ENCODED.getEncoding();
166     private boolean useSOAPAction = false;
167     private String JavaDoc SOAPActionURI = null;
168
169     /**
170      * SOAP Actor roles.
171      */

172     private String JavaDoc[] roles;
173
174     /** Our SOAP namespaces and such. */
175     private SOAPConstants soapConstants = Constants.DEFAULT_SOAP_VERSION;
176
177     /** Schema version information - defaults to 2001. */
178     private SchemaVersion schemaVersion = SchemaVersion.SCHEMA_2001;
179
180     /** Our current operation. */
181     private OperationDesc currentOperation = null;
182
183     /**
184      * The current operation.
185      *
186      * @return the current operation; may be <code>null</code>
187      */

188     public OperationDesc getOperation()
189     {
190         return currentOperation;
191     }
192
193     /**
194      * Set the current operation.
195      *
196      * @param operation the <code>Operation</code> this context is executing
197      */

198     public void setOperation(OperationDesc operation)
199     {
200         currentOperation = operation;
201     }
202
203     /**
204      * Returns a list of operation descriptors that could may
205      * possibly match a body containing an element of the given QName.
206      * For non-DOCUMENT, the list of operation descriptors that match
207      * the name is returned. For DOCUMENT, all the operations that have
208      * qname as a parameter are returned
209      *
210      * @param qname of the first element in the body
211      * @return list of operation descriptions
212      * @throws AxisFault if the operation names could not be looked up
213      */

214     public OperationDesc [] getPossibleOperationsByQName(QName JavaDoc qname) throws AxisFault
215     {
216         if (currentOperation != null) {
217             return new OperationDesc [] { currentOperation };
218         }
219
220         OperationDesc [] possibleOperations = null;
221
222         if (serviceHandler == null) {
223             try {
224                 if (log.isDebugEnabled()) {
225                     log.debug(Messages.getMessage("dispatching00",
226                                                    qname.getNamespaceURI()));
227                 }
228
229                 // Try looking this QName up in our mapping table...
230
setService(axisEngine.getConfig().
231                            getServiceByNamespaceURI(qname.getNamespaceURI()));
232             } catch (ConfigurationException e) {
233                 // Didn't find one...
234
}
235
236         }
237
238         if (serviceHandler != null) {
239             ServiceDesc desc = serviceHandler.getInitializedServiceDesc(this);
240
241             if (desc != null) {
242                 if (desc.getStyle() != Style.DOCUMENT) {
243                     possibleOperations = desc.getOperationsByQName(qname);
244                 } else {
245                     // DOCUMENT Style
246
// Get all of the operations that have qname as
247
// a possible parameter QName
248
ArrayList JavaDoc allOperations = desc.getOperations();
249                     ArrayList JavaDoc foundOperations = new ArrayList JavaDoc();
250                     for (int i=0; i < allOperations.size(); i++ ) {
251                         OperationDesc tryOp =
252                             (OperationDesc) allOperations.get(i);
253                         if (tryOp.getParamByQName(qname) != null) {
254                             foundOperations.add(tryOp);
255                         }
256                     }
257                     if (foundOperations.size() > 0) {
258                         possibleOperations = (OperationDesc[])
259                             JavaUtils.convert(foundOperations,
260                                               OperationDesc[].class);
261                     }
262                 }
263             }
264         }
265         return possibleOperations;
266     }
267
268     /**
269      * get the first possible operation that could match a
270      * body containing an element of the given QName. Sets the currentOperation
271      * field in the process; if that field is already set then its value
272      * is returned instead
273      * @param qname name of the message body
274      * @return an operation or null
275      * @throws AxisFault
276      */

277     public OperationDesc getOperationByQName(QName JavaDoc qname) throws AxisFault
278     {
279         if (currentOperation == null) {
280             OperationDesc [] possibleOperations = getPossibleOperationsByQName(qname);
281             if (possibleOperations != null && possibleOperations.length > 0) {
282                 currentOperation = possibleOperations[0];
283             }
284         }
285
286         return currentOperation;
287     }
288
289     /**
290      * Get the active message context.
291      *
292      * @return the current active message context
293      */

294     public static MessageContext getCurrentContext() {
295        return AxisEngine.getCurrentMessageContext();
296     }
297
298     /**
299      * Temporary directory to store attachments.
300      */

301     protected static String JavaDoc systemTempDir= null;
302     /**
303      * set the temp dir
304      * TODO: move this piece of code out of this class and into a utilities
305      * class.
306      */

307     static {
308         try {
309             //get the temp dir from the engine
310
systemTempDir=AxisProperties.getProperty(AxisEngine.ENV_ATTACHMENT_DIR);
311         } catch(Throwable JavaDoc t) {
312             systemTempDir= null;
313         }
314
315         if(systemTempDir== null) {
316             try {
317                 //or create and delete a file in the temp dir to make
318
//sure we have write access to it.
319
File JavaDoc tf= File.createTempFile("Axis", ".tmp");
320                 File JavaDoc dir= tf.getParentFile();
321                 if (tf.exists()) {
322                     tf.delete();
323                 }
324                 if (dir != null) {
325                   systemTempDir= dir.getCanonicalPath();
326                 }
327             } catch(Throwable JavaDoc t) {
328                 log.debug("Unable to find a temp dir with write access");
329                 systemTempDir= null;
330             }
331         }
332     }
333
334     /**
335      * Create a message context.
336      * @param engine the controlling axis engine. Null is actually accepted here,
337      * though passing a null engine in is strongly discouraged as many of the methods
338      * assume that it is in fact defined.
339      */

340     public MessageContext(AxisEngine engine) {
341         this.axisEngine = engine;
342
343         if(null != engine){
344             java.util.Hashtable JavaDoc opts= engine.getOptions();
345             String JavaDoc attachmentsdir= null;
346             if(null!=opts) {
347                 attachmentsdir= (String JavaDoc) opts.get(AxisEngine.PROP_ATTACHMENT_DIR);
348             }
349             if(null == attachmentsdir) {
350                 attachmentsdir= systemTempDir;
351             }
352             if(attachmentsdir != null){
353                 setProperty(ATTACHMENTS_DIR, attachmentsdir);
354             }
355
356             // If SOAP 1.2 has been specified as the default for the engine,
357
// switch the constants over.
358
String JavaDoc defaultSOAPVersion = (String JavaDoc)engine.getOption(
359                                                  AxisEngine.PROP_SOAP_VERSION);
360             if (defaultSOAPVersion != null && "1.2".equals(defaultSOAPVersion)) {
361                 setSOAPConstants(SOAPConstants.SOAP12_CONSTANTS);
362             }
363
364             String JavaDoc singleSOAPVersion = (String JavaDoc)engine.getOption(
365                                         AxisEngine.PROP_SOAP_ALLOWED_VERSION);
366             if (singleSOAPVersion != null) {
367                 if ("1.2".equals(singleSOAPVersion)) {
368                     setProperty(Constants.MC_SINGLE_SOAP_VERSION,
369                                 SOAPConstants.SOAP12_CONSTANTS);
370                 } else if ("1.1".equals(singleSOAPVersion)) {
371                     setProperty(Constants.MC_SINGLE_SOAP_VERSION,
372                                 SOAPConstants.SOAP11_CONSTANTS);
373                 }
374             }
375         }
376     }
377
378     /**
379      * during finalization, the dispose() method is called.
380      * @see #dispose()
381      */

382     protected void finalize() {
383         dispose();
384     }
385
386     /**
387      * Mappings of QNames to serializers/deserializers (and therfore
388      * to Java types).
389      */

390     private TypeMappingRegistry mappingRegistry = null;
391
392     /**
393      * Replace the engine's type mapping registry with a local one. This will
394      * have no effect on any type mappings obtained before this call.
395      *
396      * @param reg the new <code>TypeMappingRegistry</code>
397      */

398     public void setTypeMappingRegistry(TypeMappingRegistry reg) {
399         mappingRegistry = reg;
400     }
401
402     /**
403      * Get the currently in-scope type mapping registry.
404      *
405      * By default, will return a reference to the AxisEngine's TMR until
406      * someone sets our local one (usually as a result of setting the
407      * serviceHandler).
408      *
409      * @return the type mapping registry to use for this request.
410      */

411     public TypeMappingRegistry getTypeMappingRegistry() {
412         if (mappingRegistry == null) {
413             return axisEngine.getTypeMappingRegistry();
414         }
415
416         return mappingRegistry;
417     }
418
419     /**
420      * Return the type mapping currently in scope for our encoding style.
421      *
422      * @return the type mapping
423      */

424     public TypeMapping getTypeMapping()
425     {
426         return (TypeMapping)getTypeMappingRegistry().
427                 getTypeMapping(encodingStyle);
428     }
429
430     /**
431      * The name of the transport for this context.
432      *
433      * @return the transport name
434      */

435     public String JavaDoc getTransportName()
436     {
437         return transportName;
438     }
439
440     // fixme: the transport names should be a type-safe e-num, or the range
441
// of legal values should be specified in the documentation and validated
442
// in the method (raising IllegalArgumentException)
443
/**
444      * Set the transport name for this context.
445      *
446      * @param transportName the name of the transport
447      */

448     public void setTransportName(String JavaDoc transportName)
449     {
450         this.transportName = transportName;
451     }
452
453     /**
454      * Get the <code>SOAPConstants</code> used by this message context.
455      *
456      * @return the soap constants
457      */

458     public SOAPConstants getSOAPConstants() {
459         return soapConstants;
460     }
461
462     /**
463      * Set the <code>SOAPConstants</code> used by this message context.
464      * This may also affect the encoding style.
465      *
466      * @param soapConstants the new soap constants to use
467      */

468     public void setSOAPConstants(SOAPConstants soapConstants) {
469         // when changing SOAP versions, remember to keep the encodingURI
470
// in synch.
471
if (this.soapConstants.getEncodingURI().equals(encodingStyle)) {
472             encodingStyle = soapConstants.getEncodingURI();
473         }
474
475         this.soapConstants = soapConstants;
476     }
477
478     /**
479      * Get the XML schema version information.
480      *
481      * @return the <code>SchemaVersion</code> in use
482      */

483     public SchemaVersion getSchemaVersion() {
484         return schemaVersion;
485     }
486
487     /**
488      * Set the XML schema version this message context will use.
489      *
490      * @param schemaVersion the new <code>SchemaVersion</code>
491      */

492     public void setSchemaVersion(SchemaVersion schemaVersion) {
493         this.schemaVersion = schemaVersion;
494     }
495
496     /**
497      * Get the current session.
498      *
499      * @return the <code>Session</code> this message context is within
500      */

501     public Session getSession()
502     {
503         return session;
504     }
505
506     /**
507      * Set the current session.
508      *
509      * @param session the new <code>Session</code>
510      */

511     public void setSession(Session session)
512     {
513         this.session = session;
514     }
515
516     /**
517      * Indicates if the opration is encoded.
518      *
519      * @return <code>true</code> if it is encoded, <code>false</code> otherwise
520      */

521     public boolean isEncoded() {
522         return (getOperationUse() == Use.ENCODED);
523         //return soapConstants.getEncodingURI().equals(encodingStyle);
524
}
525
526     /**
527      * Set whether we are maintaining session state.
528      *
529      * @param yesno flag to set to <code>true</code> to maintain sessions
530      */

531     public void setMaintainSession (boolean yesno) {
532         maintainSession = yesno;
533     }
534
535     /**
536      * Discover if we are maintaining session state.
537      *
538      * @return <code>true</code> if we are maintaining state, <code>false</code>
539      * otherwise
540      */

541     public boolean getMaintainSession () {
542         return maintainSession;
543     }
544
545     /**
546      * Get the request message.
547      *
548      * @return the request message (may be null).
549      */

550     public Message getRequestMessage() {
551         return requestMessage ;
552     }
553
554     /**
555      * Set the request message, and make sure that message is associated
556      * with this MessageContext.
557      *
558      * @param reqMsg the new request Message.
559      */

560     public void setRequestMessage(Message reqMsg) {
561         requestMessage = reqMsg ;
562         if (requestMessage != null) {
563             requestMessage.setMessageContext(this);
564         }
565     }
566
567     /**
568      * Get the response message.
569      *
570      * @return the response message (may be null).
571      */

572     public Message getResponseMessage() { return responseMessage ; }
573
574     /**
575      * Set the response message, and make sure that message is associated
576      * with this MessageContext.
577      *
578      * @param respMsg the new response Message.
579      */

580     public void setResponseMessage(Message respMsg) {
581         responseMessage = respMsg;
582         if (responseMessage != null) {
583             responseMessage.setMessageContext(this);
584
585             //if we have received attachments of a particular type
586
// than that should be the default type to send.
587
Message reqMsg = getRequestMessage();
588             if (null != reqMsg) {
589                 Attachments reqAttch = reqMsg.getAttachmentsImpl();
590                 Attachments respAttch = respMsg.getAttachmentsImpl();
591                 if (null != reqAttch && null != respAttch) {
592                     if (respAttch.getSendType() == Attachments.SEND_TYPE_NOTSET)
593                         //only if not explicity set.
594
respAttch.setSendType(reqAttch.getSendType());
595                 }
596             }
597         }
598     }
599
600     /**
601      * Return the current (i.e. request before the pivot, response after)
602      * message.
603      *
604      * @return the current <code>Message</code>
605      */

606     public Message getCurrentMessage()
607     {
608         return (havePassedPivot ? responseMessage : requestMessage);
609     }
610
611     /**
612      * Gets the SOAPMessage from this message context.
613      *
614      * @return the <code>SOAPMessage</code>, <code>null</code> if no request
615      * <code>SOAPMessage</code> is present in this
616      * <code>SOAPMessageContext</code>
617      */

618     public javax.xml.soap.SOAPMessage JavaDoc getMessage() {
619         return getCurrentMessage();
620     }
621
622     /**
623      * Set the current message. This will set the request before the pivot,
624      * and the response afterwards, as guaged by the passedPivod property.
625      *
626      * @param curMsg the <code>Message</code> to assign
627      */

628     public void setCurrentMessage(Message curMsg)
629     {
630         curMsg.setMessageContext(this);
631
632         if (havePassedPivot) {
633             responseMessage = curMsg;
634         } else {
635             requestMessage = curMsg;
636         }
637     }
638
639     /**
640      * Sets the SOAPMessage for this message context.
641      * This is equivalent to casting <code>message</code> to
642      * <code>Message</code> and then passing it on to
643      * <code>setCurrentMessage()</code>.
644      *
645      * @param message the <code>SOAPMessage</code> this context is for
646      */

647     public void setMessage(javax.xml.soap.SOAPMessage JavaDoc message) {
648         setCurrentMessage((Message)message);
649     }
650
651     /**
652      * Determine when we've passed the pivot.
653      *
654      * @return <code>true</code> if we have, <code>false</code> otherwise
655      */

656     public boolean getPastPivot()
657     {
658         return havePassedPivot;
659     }
660
661     // fixme: is there any legitimate case where we could pass the pivot and
662
// then go back again? Is there documentation about the life-cycle of a
663
// MessageContext, and in particular the re-use of instances that would be
664
// relevant?
665
/**
666      * Indicate when we've passed the pivot.
667      *
668      * @param pastPivot true if we are past the pivot point, false otherwise
669      */

670     public void setPastPivot(boolean pastPivot)
671     {
672         havePassedPivot = pastPivot;
673     }
674
675     /**
676      * Set timeout in our MessageContext.
677      *
678      * @param value the maximum amount of time, in milliseconds
679      */

680     public void setTimeout (int value) {
681         timeout = value;
682     }
683
684     /**
685      * Get timeout from our MessageContext.
686      *
687      * @return value the maximum amount of time, in milliseconds
688      */

689     public int getTimeout () {
690         return timeout;
691     }
692
693     /**
694      * Get the classloader, implicitly binding to the thread context
695      * classloader if an override has not been supplied.
696      *
697      * @return the class loader
698      */

699     public ClassLoader JavaDoc getClassLoader() {
700         if ( classLoader == null ) {
701             classLoader = Thread.currentThread().getContextClassLoader();
702         }
703         return( classLoader );
704     }
705
706     /**
707      * Set a new classloader. Setting to null will result in getClassLoader()
708      * binding back to the thread context class loader.
709      *
710      * @param cl the new <code>ClassLoader</code> or <code>null</code>
711      */

712     public void setClassLoader(ClassLoader JavaDoc cl ) {
713         classLoader = cl ;
714     }
715
716     /**
717      * Get the name of the targed service for this message.
718      *
719      * @return the target service
720      */

721     public String JavaDoc getTargetService() {
722         return targetService;
723     }
724
725     /**
726      * Get the axis engine. This will be <code>null</code> if the message was
727      * created outside an engine
728      *
729      * @return the current axis engine
730      */

731     public AxisEngine getAxisEngine()
732     {
733         return axisEngine;
734     }
735
736     /**
737      * Set the target service for this message.
738      * <p>
739      * This looks up the named service in the registry, and has
740      * the side effect of setting our TypeMappingRegistry to the
741      * service's.
742      *
743      * @param tServ the name of the target service
744      * @throws AxisFault if anything goes wrong in resolving or setting the
745      * service
746      */

747     public void setTargetService(String JavaDoc tServ) throws AxisFault {
748         log.debug("MessageContext: setTargetService(" + tServ+")");
749
750         if (tServ == null) {
751             setService(null);
752         }
753         else {
754             try {
755                 setService(getAxisEngine().getService(tServ));
756             } catch (AxisFault fault) {
757                 // If we're on the client, don't throw this fault...
758
if (!isClient()) {
759                     throw fault;
760                 }
761             }
762         }
763         targetService = tServ;
764     }
765
766     /** ServiceHandler is the handler that is the "service". This handler
767      * can (and probably will actually be a chain that contains the
768      * service specific request/response/pivot point handlers
769      */

770     private SOAPService serviceHandler ;
771
772     /**
773      * Get the <code>SOAPService</code> used to handle services in this
774      * context.
775      *
776      * @return the service handler
777      */

778     public SOAPService getService() {
779         return serviceHandler;
780     }
781
782     /**
783      * Set the <code>SOAPService</code> used to handle services in this
784      * context. This method configures a wide range of
785      * <code>MessageContext</code> properties to suit the handler.
786      *
787      * @param sh the new service handler
788      * @throws AxisFault if the service could not be set
789      */

790     public void setService(SOAPService sh) throws AxisFault
791     {
792         log.debug("MessageContext: setServiceHandler("+sh+")");
793         serviceHandler = sh;
794         if (sh != null) {
795             if(!sh.isRunning()) {
796                 throw new AxisFault(Messages.getMessage("disabled00"));
797             }
798             targetService = sh.getName();
799             SOAPService service = sh;
800             TypeMappingRegistry tmr = service.getTypeMappingRegistry();
801             setTypeMappingRegistry(tmr);
802
803             // styles are not "soap version aware" so compensate...
804
setEncodingStyle(service.getUse().getEncoding());
805
806             // This MessageContext should now defer properties it can't find
807
// to the Service's options.
808
bag.setParent(sh.getOptions());
809
810             // Note that we need (or don't need) high-fidelity SAX recording
811
// of deserialized messages according to the setting on the
812
// new service.
813
highFidelity = service.needsHighFidelityRecording();
814
815             service.getInitializedServiceDesc(this);
816         }
817     }
818
819     /**
820      * Let us know whether this is the client or the server.
821      *
822      * @return true if we are a client
823      */

824     public boolean isClient()
825     {
826         return (axisEngine instanceof AxisClient);
827     }
828
829     // fixme: public final statics tend to go in a block at the top of the
830
// class deffinition, not marooned in the middle
831
// fixme: chose public static final /or/ public final static
832
/** Contains an instance of Handler, which is the
833      * ServiceContext and the entrypoint of this service.
834      *
835      * (if it has been so configured - will our deployment
836      * tool do this by default? - todo by Jacek)
837      */

838     public static final String JavaDoc ENGINE_HANDLER = "engine.handler";
839
840     /** This String is the URL that the message came to.
841      */

842     public static final String JavaDoc TRANS_URL = "transport.url";
843
844     /** Has a quit been requested? Hackish... but useful... -- RobJ */
845     public static final String JavaDoc QUIT_REQUESTED = "quit.requested";
846
847     /** Place to store an AuthenticatedUser. */
848     public static final String JavaDoc AUTHUSER = "authenticatedUser";
849
850     /** If on the client - this is the Call object. */
851     public static final String JavaDoc CALL = "call_object" ;
852
853     /** Are we doing Msg vs RPC? - For Java Binding. */
854     public static final String JavaDoc IS_MSG = "isMsg" ;
855
856     /** The directory where in coming attachments are created. */
857     public static final String JavaDoc ATTACHMENTS_DIR = "attachments.directory" ;
858
859     /** A boolean param, to control whether we accept missing parameters
860      * as nulls or refuse to acknowledge them.
861      */

862     public final static String JavaDoc ACCEPTMISSINGPARAMS = "acceptMissingParams";
863
864     /** The value of the property is used by service WSDL generation (aka ?WSDL)
865      * For the service's interface namespace if not set TRANS_URL property is used.
866      */

867     public static final String JavaDoc WSDLGEN_INTFNAMESPACE = "axis.wsdlgen.intfnamespace";
868
869     /** The value of the property is used by service WSDL generation (aka ?WSDL).
870      * For the service's location if not set TRANS_URL property is used.
871      * (helps provide support through proxies.
872      */

873     public static final String JavaDoc WSDLGEN_SERV_LOC_URL = "axis.wsdlgen.serv.loc.url";
874
875     // fixme: should this be a type-safe e-num?
876
/** The value of the property is used by service WSDL generation (aka ?WSDL).
877      * Set this property to request a certain level of HTTP.
878      * The values MUST use org.apache.axis.transport.http.HTTPConstants.HEADER_PROTOCOL_10
879      * for HTTP 1.0
880      * The values MUST use org.apache.axis.transport.http.HTTPConstants.HEADER_PROTOCOL_11
881      * for HTTP 1.1
882      */

883     public static final String JavaDoc HTTP_TRANSPORT_VERSION = "axis.transport.version";
884
885     // fixme: is this the name of a security provider, or the name of a security
886
// provider class, or the actualy class of a security provider, or
887
// something else?
888
/**
889      * The security provider.
890      */

891     public static final String JavaDoc SECURITY_PROVIDER = "securityProvider";
892
893     /*
894      * IMPORTANT.
895      * If adding any new constants to this class. Make them final. The
896      * ones above are left non-final for compatibility reasons.
897      */

898
899     /**
900      * Get a <code>String</code> property by name.
901      *
902      * @param propName the name of the property to fetch
903      * @return the value of the named property
904      * @throws ClassCastException if the property named does not have a
905      * <code>String</code> value
906      */

907     public String JavaDoc getStrProp(String JavaDoc propName) {
908         return (String JavaDoc) getProperty(propName);
909     }
910
911     /**
912      * Tests to see if the named property is set in the 'bag', returning
913      * <code>false</code> if it is not present at all.
914      * This is equivalent to <code>isPropertyTrue(propName, false)</code>.
915      *
916      * @param propName the name of the property to check
917      * @return true or false, depending on the value of the property
918      */

919     public boolean isPropertyTrue(String JavaDoc propName) {
920         return isPropertyTrue(propName, false);
921     }
922
923     /**
924      * Test if a property is set to something we consider to be true in the
925      * 'bag'.
926      * <ul>
927      * <li>If not there then <code>defaultVal</code> is returned.</li>
928      * <li>If there, then...<ul>
929      * <li>if its a <code>Boolean</code>, we'll return booleanValue()</li>
930      * <li>if its an <code>Integer</code>, we'll return <code>false</code>
931      * if its <code>0</code> else <code>true</code></li>
932      * <li>if its a <code>String</code> we'll return <code>false</code> if its
933      * <code>"false"</code>" or <code>"0"</code> else <code>true</code></li>
934      * <li>All other types return <code>true</code></li>
935      * </ul></li>
936      * </ul>
937      *
938      * @param propName the name of the property to check
939      * @param defaultVal the default value
940      * @return true or false, depending on the value of the property
941      */

942     public boolean isPropertyTrue(String JavaDoc propName, boolean defaultVal) {
943         return JavaUtils.isTrue(getProperty(propName), defaultVal);
944     }
945
946     /**
947      * Allows you to set a named property to the passed in value.
948      * There are a few known properties (like username, password, etc)
949      * that are variables in Call. The rest of the properties are
950      * stored in a Hashtable. These common properties should be
951      * accessed via the accessors for speed/type safety, but they may
952      * still be obtained via this method. It's up to one of the
953      * Handlers (or the Axis engine itself) to go looking for
954      * one of them.
955      *
956      * @param name Name of the property
957      * @param value Value of the property
958      */

959     public void setProperty(String JavaDoc name, Object JavaDoc value) {
960         if (name == null || value == null) {
961             return;
962             // Is this right? Shouldn't we throw an exception like:
963
// throw new IllegalArgumentException(msg);
964
}
965         else if (name.equals(Call.USERNAME_PROPERTY)) {
966             if (!(value instanceof String JavaDoc)) {
967                 throw new IllegalArgumentException JavaDoc(
968                         Messages.getMessage("badProp00", new String JavaDoc[] {
969                         name, "java.lang.String", value.getClass().getName()}));
970             }
971             setUsername((String JavaDoc) value);
972         }
973         else if (name.equals(Call.PASSWORD_PROPERTY)) {
974             if (!(value instanceof String JavaDoc)) {
975                 throw new IllegalArgumentException JavaDoc(
976                         Messages.getMessage("badProp00", new String JavaDoc[] {
977                         name, "java.lang.String", value.getClass().getName()}));
978             }
979             setPassword((String JavaDoc) value);
980         }
981         else if (name.equals(Call.SESSION_MAINTAIN_PROPERTY)) {
982             if (!(value instanceof Boolean JavaDoc)) {
983                 throw new IllegalArgumentException JavaDoc(
984                         Messages.getMessage("badProp00", new String JavaDoc[]
985                         {name,
986                         "java.lang.Boolean",
987                         value.getClass().getName()}));
988             }
989             setMaintainSession(((Boolean JavaDoc) value).booleanValue());
990         }
991         else if (name.equals(Call.SOAPACTION_USE_PROPERTY)) {
992             if (!(value instanceof Boolean JavaDoc)) {
993                 throw new IllegalArgumentException JavaDoc(
994                         Messages.getMessage("badProp00", new String JavaDoc[]
995                         {name,
996                         "java.lang.Boolean",
997                         value.getClass().getName()}));
998             }
999             setUseSOAPAction(((Boolean JavaDoc) value).booleanValue());
1000        }
1001        else if (name.equals(Call.SOAPACTION_URI_PROPERTY)) {
1002            if (!(value instanceof String JavaDoc)) {
1003                throw new IllegalArgumentException JavaDoc(
1004                        Messages.getMessage("badProp00", new String JavaDoc[]
1005                        {name,
1006                        "java.lang.String",
1007                        value.getClass().getName()}));
1008            }
1009            setSOAPActionURI((String JavaDoc) value);
1010        }
1011        else if (name.equals(Call.ENCODINGSTYLE_URI_PROPERTY)) {
1012            if (!(value instanceof String JavaDoc)) {
1013                throw new IllegalArgumentException JavaDoc(
1014                        Messages.getMessage("badProp00", new String JavaDoc[]
1015                        {name,
1016                        "java.lang.String",
1017                        value.getClass().getName()}));
1018            }
1019            setEncodingStyle((String JavaDoc) value);
1020        }
1021        else {
1022            bag.put(name, value);
1023        }
1024    } // setProperty
1025

1026    /**
1027     * Returns true if the MessageContext contains a property with the specified name.
1028     * @param name Name of the property whose presense is to be tested
1029     * @return Returns true if the MessageContext contains the
1030          property; otherwise false
1031     */

1032    public boolean containsProperty(String JavaDoc name) {
1033        Object JavaDoc propertyValue = getProperty(name);
1034        return (propertyValue != null);
1035    }
1036
1037    /**
1038     * Returns an <code>Iterator</code> view of the names of the properties in
1039     * this <code>MessageContext</code>.
1040     *
1041     * @return an <code>Iterator</code> over all property names
1042     */

1043    public java.util.Iterator JavaDoc getPropertyNames() {
1044        // fixme: this is potentially unsafe for the caller - changing the
1045
// properties will kill the iterator. Consider iterating over a copy:
1046
// return new HashSet(bag.keySet()).iterator();
1047
return bag.keySet().iterator();
1048    }
1049
1050    /**
1051     * Returns an Iterator view of the names of the properties
1052     * in this MessageContext and any parents of the LockableHashtable
1053     * @return Iterator for the property names
1054     */

1055    public java.util.Iterator JavaDoc getAllPropertyNames() {
1056        return bag.getAllKeys().iterator();
1057    }
1058
1059    /**
1060     * Returns the value associated with the named property - or null if not
1061     * defined/set.
1062     *
1063     * @param name the property name
1064     * @return Object value of the property - or null
1065     */

1066    public Object JavaDoc getProperty(String JavaDoc name) {
1067        if (name != null) {
1068            if (name.equals(Call.USERNAME_PROPERTY)) {
1069                return getUsername();
1070            }
1071            else if (name.equals(Call.PASSWORD_PROPERTY)) {
1072                return getPassword();
1073            }
1074            else if (name.equals(Call.SESSION_MAINTAIN_PROPERTY)) {
1075                return getMaintainSession() ? Boolean.TRUE : Boolean.FALSE;
1076            }
1077            else if (name.equals(Call.OPERATION_STYLE_PROPERTY)) {
1078                return (getOperationStyle() == null) ? null : getOperationStyle().getName();
1079            }
1080            else if (name.equals(Call.SOAPACTION_USE_PROPERTY)) {
1081                return useSOAPAction() ? Boolean.TRUE : Boolean.FALSE;
1082            }
1083            else if (name.equals(Call.SOAPACTION_URI_PROPERTY)) {
1084                return getSOAPActionURI();
1085            }
1086            else if (name.equals(Call.ENCODINGSTYLE_URI_PROPERTY)) {
1087                return getEncodingStyle();
1088            }
1089            else if (bag == null) {
1090                return null;
1091            }
1092            else {
1093                return bag.get(name);
1094            }
1095        }
1096        else {
1097            return null;
1098        }
1099    }
1100
1101    // fixme: this makes no copy of parent, so later modifications to parent
1102
// can alter this context - is this intended? If so, it needs documenting.
1103
// If not, it needs fixing.
1104
/**
1105     * Set the Hashtable that contains the default values for our
1106     * properties.
1107     *
1108     * @param parent
1109     */

1110    public void setPropertyParent(Hashtable parent)
1111    {
1112        bag.setParent(parent);
1113    }
1114
1115    /**
1116     * Set the username.
1117     *
1118     * @param username the new user name
1119     */

1120    public void setUsername(String JavaDoc username) {
1121        this.username = username;
1122    } // setUsername
1123

1124    /**
1125     * Get the user name.
1126     *
1127     * @return the user name as a <code>String</code>
1128     */

1129    public String JavaDoc getUsername() {
1130        return username;
1131    } // getUsername
1132

1133    /**
1134     * Set the password.
1135     *
1136     * @param password a <code>String</code> containing the new password
1137     */

1138    public void setPassword(String JavaDoc password) {
1139        this.password = password;
1140    } // setPassword
1141

1142    /**
1143     * Get the password.
1144     *
1145     * @return the current password <code>String</code>
1146     */

1147    public String JavaDoc getPassword() {
1148        return password;
1149    } // getPassword
1150

1151    /**
1152     * Get the operation style. This is either the style of the current
1153     * operation or if that is not set, the style of the service handler, or
1154     * if that is not set, <code>Style.RPC</code>.
1155     *
1156     * @return the <code>Style</code> of this message
1157     */

1158    public Style getOperationStyle() {
1159        if (currentOperation != null) {
1160            return currentOperation.getStyle();
1161        }
1162
1163        if (serviceHandler != null) {
1164            return serviceHandler.getStyle();
1165        }
1166
1167        return Style.RPC;
1168    } // getOperationStyle
1169

1170    /**
1171     * Get the operation use.
1172     *
1173     * @return the operation <code>Use</code>
1174     */

1175    public Use getOperationUse() {
1176        if (currentOperation != null) {
1177            return currentOperation.getUse();
1178        }
1179
1180        if (serviceHandler != null) {
1181            return serviceHandler.getUse();
1182        }
1183
1184        return Use.ENCODED;
1185    } // getOperationUse
1186

1187    /**
1188     * Enable or dissable the use of soap action information. When enabled,
1189     * the message context will attempt to use the soap action URI
1190     * information during binding of soap messages to service methods. When
1191     * dissabled, it will make no such attempt.
1192     *
1193     * @param useSOAPAction <code>true</code> if soap action URI information
1194     * should be used, <code>false</code> otherwise
1195     */

1196    public void setUseSOAPAction(boolean useSOAPAction) {
1197        this.useSOAPAction = useSOAPAction;
1198    } // setUseSOAPAction
1199

1200    // fixme: this doesn't follow beany naming conventions - should be
1201
// isUseSOAPActions or getUseSOAPActions or something prettier
1202
/**
1203     * Indicates wether the soap action URI is being used or not.
1204     *
1205     * @return <code>true</code> if it is, <code>false</code> otherwise
1206     */

1207    public boolean useSOAPAction() {
1208        return useSOAPAction;
1209    } // useSOAPAction
1210

1211    // fixme: this throws IllegalArgumentException but never raises it -
1212
// perhaps in a sub-class?
1213
// fixme: IllegalArgumentException is unchecked. Best practice says you
1214
// should document unchecked exceptions, but not list them in throws
1215
/**
1216     * Set the soapAction URI.
1217     *
1218     * @param SOAPActionURI a <code>String</code> giving the new soap action
1219     * URI
1220     * @throws IllegalArgumentException if the URI is not liked
1221     */

1222    public void setSOAPActionURI(String JavaDoc SOAPActionURI)
1223            throws IllegalArgumentException JavaDoc {
1224        this.SOAPActionURI = SOAPActionURI;
1225    } // setSOAPActionURI
1226

1227    /**
1228     * Get the soapAction URI.
1229     *
1230     * @return the URI of this soap action
1231     */

1232    public String JavaDoc getSOAPActionURI() {
1233        return SOAPActionURI;
1234    } // getSOAPActionURI
1235

1236    /**
1237     * Sets the encoding style to the URI passed in.
1238     *
1239     * @param namespaceURI URI of the encoding to use.
1240     */

1241    public void setEncodingStyle(String JavaDoc namespaceURI) {
1242        if (namespaceURI == null) {
1243            namespaceURI = Constants.URI_LITERAL_ENC;
1244        }
1245        else if (Constants.isSOAP_ENC(namespaceURI)) {
1246            namespaceURI = soapConstants.getEncodingURI();
1247        }
1248
1249        encodingStyle = namespaceURI;
1250    } // setEncodingStype
1251

1252    /**
1253     * Returns the encoding style as a URI that should be used for the SOAP
1254     * message.
1255     *
1256     * @return String URI of the encoding style to use
1257     */

1258    public String JavaDoc getEncodingStyle() {
1259        return encodingStyle;
1260    } // getEncodingStyle
1261

1262    public void removeProperty(String JavaDoc propName)
1263    {
1264        if (bag != null) {
1265            bag.remove(propName);
1266        }
1267    }
1268
1269    /**
1270     * Return this context to a clean state.
1271     */

1272    public void reset()
1273    {
1274        if (bag != null) {
1275            bag.clear();
1276        }
1277        serviceHandler = null;
1278        havePassedPivot = false;
1279        currentOperation = null;
1280    }
1281
1282    /**
1283     * Read the high fidelity property.
1284     * <p>
1285     * Some behavior may be apropreate for high fidelity contexts that is not
1286     * relevant for low fidelity ones or vica-versa.
1287     *
1288     * @return <code>true</code> if the context is high fidelity,
1289     * <code>false</code> otherwise
1290     */

1291    public boolean isHighFidelity() {
1292        return highFidelity;
1293    }
1294
1295    /**
1296     * Set the high fidelity propert.
1297     * <p>
1298     * Users of the context may be changing what they do based upon this flag.
1299     *
1300     * @param highFidelity the new value of the highFidelity property
1301     */

1302    public void setHighFidelity(boolean highFidelity) {
1303        this.highFidelity = highFidelity;
1304    }
1305
1306    /**
1307     * Gets the SOAP actor roles associated with an execution of the
1308     * <code>HandlerChain</code> and its contained <code>Handler</code>
1309     * instances.
1310     * <p>
1311     * <i>Not (yet) implemented method in the SOAPMessageContext interface</i>.
1312     * <p>
1313     * <b>Note:</b> SOAP actor roles apply to the SOAP node and are managed
1314     * using <code>HandlerChain.setRoles()</code> and
1315     * <code>HandlerChain.getRoles()</code>. Handler instances in the
1316     * <code>HandlerChain</code> use this information about the SOAP actor roles
1317     * to process the SOAP header blocks. Note that the SOAP actor roles are
1318     * invariant during the processing of SOAP message through the
1319     * <code>HandlerChain</code>.
1320     *
1321     * @return an array of URIs for SOAP actor roles
1322     * @see javax.xml.rpc.handler.HandlerChain#setRoles(java.lang.String[]) HandlerChain.setRoles(java.lang.String[])
1323     * @see javax.xml.rpc.handler.HandlerChain#getRoles() HandlerChain.getRoles()
1324     */

1325    public String JavaDoc[] getRoles() {
1326        //TODO: Flesh this out.
1327
return roles;
1328    }
1329
1330    /**
1331     * Set the SOAP actor roles associated with an executioni of
1332     * <code>CodeHandlerChain</code> and its contained <code>Handler</code>
1333     * instances.
1334     *
1335     * @param roles an array of <code>String</code> instances, each representing
1336     * the URI for a SOAP actor role
1337     */

1338    public void setRoles( String JavaDoc[] roles) {
1339        this.roles = roles;
1340    }
1341
1342    /**
1343     * if a message (or subclass) has any disposal needs, this method
1344     * is where it goes. Subclasses *must* call super.dispose(), and
1345     * be prepared to be called from the finalizer as well as earlier
1346     */

1347    public synchronized void dispose() {
1348        log.debug("disposing of message context");
1349        if(requestMessage!=null) {
1350            requestMessage.dispose();
1351            requestMessage=null;
1352        }
1353        if(responseMessage!=null) {
1354            responseMessage.dispose();
1355            responseMessage=null;
1356        }
1357    }
1358}
1359
Popular Tags