1#!/usr/bin/python
2#############################################################################
3# Software Testing Automation Framework (STAF)                              #
4# (C) Copyright IBM Corp. 2001, 2005                                        #
5#                                                                           #
6# This software is licensed under the Eclipse Public License (EPL) V1.0.    #
7#############################################################################
8
9import PYSTAF
10
11# Utility functions
12
13def STAFWrapData(message):
14    return ":%d:%s" % (len(message), message)
15
16# Allows you to access this function using either name
17wrapData = STAFWrapData
18
19# Privacy utility methods
20
21def STAFAddPrivacyDelimiters(data):
22    return "%s" % (PYSTAF.STAFAddPrivacyDelimiters(data))
23
24def STAFEscapePrivacyDelimiters(data):
25    return "%s" % (PYSTAF.STAFEscapePrivacyDelimiters(data))
26
27def STAFMaskPrivateData(data):
28    return "%s" % (PYSTAF.STAFMaskPrivateData(data))
29
30def STAFRemovePrivacyDelimiters(data, numLevels = 0):
31    return "%s" % (PYSTAF.STAFRemovePrivacyDelimiters(data, numLevels))
32
33# Allows you to access these functions using either name
34addPrivacyDelimiters = STAFAddPrivacyDelimiters
35escapePrivacyDelimiters = STAFEscapePrivacyDelimiters
36maskPrivateData = STAFMaskPrivateData
37removePrivacyDelimiters = STAFRemovePrivacyDelimiters
38
39# STAFException class
40
41class STAFException:
42
43    def __init__(self, rc = 0, result = ""):
44        self.rc = rc
45        self.result = result
46
47# STAFResult class
48
49class STAFResult:
50
51    Ok                          = 0
52    InvalidAPI                  = 1
53    UnknownService              = 2
54    InvalidHandle               = 3
55    HandleAlreadyExists         = 4
56    HandleDoesNotExist          = 5
57    UnknownError                = 6
58    InvalidRequestString        = 7
59    InvalidServiceResult        = 8
60    REXXError                   = 9
61    BaseOSError                 = 10
62    ProcessAlreadyComplete      = 11
63    ProcessNotComplete          = 12
64    VariableDoesNotExist        = 13
65    UnResolvableString          = 14
66    InvalidResolveString        = 15
67    NoPathToMachine             = 16
68    FileOpenError               = 17
69    FileReadError               = 18
70    FileWriteError              = 19
71    FileDeleteError             = 20
72    STAFNotRunning              = 21
73    CommunicationError          = 22
74    TrusteeDoesNotExist         = 23
75    InvalidTrustLevel           = 24
76    AccessDenied                = 25
77    STAFRegistrationError       = 26
78    ServiceConfigurationError   = 27
79    QueueFull                   = 28
80    NoQueueElement              = 29
81    NotifieeDoesNotExist        = 30
82    InvalidAPILevel             = 31
83    ServiceNotUnregisterable    = 32
84    ServiceNotAvailable         = 33
85    SemaphoreDoesNotExist       = 34
86    NotSemaphoreOwner           = 35
87    SemaphoreHasPendingRequests = 36
88    Timeout                     = 37
89    JavaError                   = 38
90    ConverterError              = 39
91    MoveError                   = 40
92    InvalidObject               = 41
93    InvalidParm                 = 42
94    RequestNumberNotFound       = 43
95    InvalidAsynchOption         = 44
96    RequestNotComplete          = 45
97    ProcessAuthenticationDenied = 46
98    InvalidValue                = 47
99    DoesNotExist                = 48
100    AlreadyExists               = 49
101    DirectoryNotEmpty           = 50
102    DirectoryCopyError          = 51
103    DiagnosticsNotEnabled       = 52
104    HandleAuthenticationDenied  = 53
105    HandleAlreadyAuthenticated  = 54
106    InvalidSTAFVersion          = 55
107    RequestCancelled            = 56
108    CreateThreadError           = 57
109    MaximumSizeExceeded         = 58
110    MaximumHandlesExceeded      = 59
111    NotRequester                = 60
112
113    def __init__(self, rc = 0, result = ""):
114        self.rc = rc
115        self.result = result
116        self.resultContext = None
117        self.resultObj = None
118
119    def __init__(self, rc, result, doUnmarshallResult):
120        self.rc = rc
121        self.result = result
122        if doUnmarshallResult:
123            self.resultContext = unmarshall(self.result)
124            self.resultObj = self.resultContext.getRootObject()
125        else:
126            self.resultContext = None
127            self.resultObj = None
128
129# STAFHandle class
130
131class STAFHandle:
132
133    # STAFHandle types
134
135    Standard = 0
136    Static   = 1
137
138    # Modes for submit call
139
140    Synchronous   = 0
141    FireAndForget = 1
142    Queue         = 2
143    Retain        = 3
144    QueueRetain   = 4
145
146    # Note: I would have liked to have used STAFHandle.Standard in place of "0"
147    #       in the methods below, but the class hasn't been defined yet.
148
149    def __init__(self, handleNameOrNumber, handleType = 0):
150
151        self.handleType = handleType
152        self.doUnmarshallResult = 1
153
154        if (handleType == STAFHandle.Standard):
155            if (type(handleNameOrNumber) != types.StringType):
156                raise TypeError, 'A string is required if using standard handle type'
157            rc, self.handle = PYSTAF.STAFRegister(handleNameOrNumber)
158            if (rc != 0):
159                raise STAFException(rc)
160        else:
161            if (type(handleNameOrNumber) != types.IntType):
162                raise TypeError, 'An integer is required if using static handle type'
163            self.handle = handleNameOrNumber
164
165    def submit(self, location, service, request, mode = Synchronous):
166        rc, result = PYSTAF.STAFSubmit(self.handle, mode, location, service, request)
167        return STAFResult(rc, result, self.doUnmarshallResult)
168
169    def unregister(self):
170        if (self.handleType == 0):
171            rc = PYSTAF.STAFUnregister(self.handle)
172            if (rc != 0):
173                raise STAFException(rc)
174            self.handle = 0
175
176        return 0
177
178    # Set a flag (0, 1) to indicate if the result should be auto-unmarshalled
179    def setDoUnmarshallResult(self, flag):
180        if flag:
181            self.doUnmarshallResult = 1
182        else:
183            self.doUnmarshallResult = 0
184
185    # Retrieve the auto-unmarshall result flag
186    def getDoUnmarshallResult(self):
187        return self.doUnmarshallResult
188
189
190# Marshalling constants and imports
191
192import types
193
194UNMARSHALLING_DEFAULTS  = 0
195IGNORE_INDIRECT_OBJECTS = 1
196
197MARSHALLED_DATA_MARKER = '@SDT/'
198NONE_MARKER            = '@SDT/$0:0:'
199SCALAR_MARKER          = '@SDT/$'
200SCALAR_STRING_MARKER   = '@SDT/$S'
201LIST_MARKER            = '@SDT/['
202MAP_MARKER             = '@SDT/{'
203MC_INSTANCE_MARKER     = '@SDT/%'
204CONTEXT_MARKER         = '@SDT/*'
205
206# Formatting constants and imports
207
208import os
209
210NONE_STRING            = '<None>'
211DISPLAY_NAME_KEY       = 'display-name'
212MAP_CLASS_MAP_KEY      = 'map-class-map'
213MAP_CLASS_NAME_KEY     = 'staf-map-class-name'
214ENTRY_SEPARATOR        = ''
215INDENT_DELTA           = 2
216# 80 spaces
217SPACES = ('                                         ' +
218          '                                         ')
219
220# STAFMapClassDefinitionClass
221
222class STAFMapClassDefinition:
223    # Constructors
224    def __init__(self, name = None, mapClassDef = None):
225        if (mapClassDef is None) and (name is None):
226            self.mapClassDef = { 'name': '', 'keys': [] }
227        elif (name is not None):
228            self.mapClassDef = { 'name': name, 'keys': [] }
229        else:
230            self.mapClassDef = mapClassDef
231
232    def createInstance(self):
233        return { 'staf-map-class-name' : self.mapClassDef['name'] }
234
235    def addKey(self, keyName, displayName = None):
236        theKey = { 'key': keyName }
237        if displayName is not None:
238            theKey['display-name'] = displayName
239        self.mapClassDef['keys'].append(theKey)
240
241    def setKeyProperty(self, keyName, property, value):
242        for key in self.mapClassDef['keys']:
243            if key['key'] == keyName:
244                key[property] = value
245
246    def keys(self):
247        return self.mapClassDef['keys']
248
249    def name(self):
250        return self.mapClassDef['name']
251
252    def getMapClassDefinitionObject(self):
253        return self.mapClassDef
254
255    def __str__(self):
256        return formatObject(self.mapClassDef)
257
258    def __repr__(self):
259        return formatObject(self.mapClassDef)
260
261# STAFMarshallingContext class
262
263class STAFMarshallingContext:
264
265    def isMarshalledData(self, someData):
266        return someData.startswith('@SDT/')
267
268    def __init__(self, obj = None, mapClassMap = None):
269        if mapClassMap is None:
270            self.mapClassMap = {}
271        else:
272            self.mapClassMap = mapClassMap
273        self.rootObject = obj
274
275    def setMapClassDefinition(self,  mapClassDef):
276        self.mapClassMap[mapClassDef.name()] = mapClassDef.getMapClassDefinitionObject()
277
278    def getMapClassDefinition(self, mapClassName):
279        return STAFMapClassDefinition(
280            mapClassDef = self.mapClassMap.get(mapClassName, None))
281
282    def hasMapClassDefinition(self, mapClassName):
283        return self.mapClassMap.has_key(mapClassName)
284
285    def getMapClassMap(self):
286        return self.mapClassMap
287
288    def mapClassDefinitionIterator(self):
289        return self.mapClassMap.keys()
290
291    def setRootObject(self, rootObject):
292        self.rootObject = rootObject
293
294    def getRootObject(self):
295        return self.rootObject
296
297    def getPrimaryObject(self):
298        if  len(self.mapClassMap.keys()) == 0:
299            return self.rootObject
300        else:
301            return self
302
303    def marshall(self):
304        return marshall(self, self)
305
306    def __str__(self):
307        return formatObject(self.rootObject, self)
308
309    # XXX: Change to show the key map class in addition?
310    def __repr__(self):
311        return formatObject(self.rootObject, self)
312
313# Function that tests if a string is marshalled data
314
315def isMarshalledData(someData):
316    return someData.startswith('@SDT/')
317
318# General marshalling function
319
320def marshall(object, context = None):
321    if object is None:
322        return NONE_MARKER
323
324    if type(object) == types.ListType:
325
326        # Build a list of strings and join them for performance reasons
327
328        listDataList = []
329
330        for item in object:
331            listDataList.append(marshall(item, context))
332
333        listData = ''.join(listDataList)
334
335        return "%s%s:%s:%s" % (LIST_MARKER, len(object), len(listData), listData)
336
337    if type(object) == types.DictType:
338
339        # If a staf-map-class-name key exists in the map, make sure that
340        # it's map class definition is provided in the marshalling context.
341        # If it's not, then treat the map as a plain map object.
342
343        isMapClass = 0
344        mapClassName = ''
345
346        if ((context is not None) and
347            (isinstance(context, STAFMarshallingContext)) and
348            (object.has_key('staf-map-class-name'))):
349
350            mapClassName = object['staf-map-class-name']
351
352            if context.hasMapClassDefinition(mapClassName):
353                isMapClass = 1
354
355        if isMapClass:
356
357            mapClass = context.getMapClassDefinition(mapClassName)
358
359            # Build a list of strings and join them for performance reasons
360
361            mapDataList = []
362            mapDataList.append(":%s:%s" % (len(mapClassName), mapClassName))
363
364            for key in mapClass.keys():
365
366                if object.has_key(key['key']):
367                    thisObj = object[key['key']]
368                else:
369                    thisObj = None
370
371                mapDataList.append(marshall(thisObj, context))
372
373            mapData = ''.join(mapDataList)
374
375            return "%s:%s:%s" % (MC_INSTANCE_MARKER, len(mapData), mapData)
376
377        else:
378
379            # Build a list of strings and join them for performance reasons
380
381            mapDataList = []
382
383            for key in object.keys():
384                mapDataList.append(
385                    ":%s:%s%s" % (len(str(key)), str(key),
386                                  marshall(object[key], context)))
387
388            mapData = ''.join(mapDataList)
389
390            return "%s:%s:%s" % (MAP_MARKER, len(mapData), mapData)
391
392    if isinstance(object, STAFMarshallingContext):
393
394        if len(object.mapClassMap.keys()) == 0:
395            return marshall(object.getRootObject(), context)
396        else:
397            contextMap = { 'map-class-map': object.mapClassMap }
398
399            # Note: We can't simply put the root object as a map key like
400            #       "root-object" and then marshall the whole map, as in
401            #       the unmarshalling routines, we need to be able to
402            #       unmarshall the root object in the context of the
403            #       map-class-map.
404
405            mcData = (marshall(contextMap, context) +
406                      marshall(object.getRootObject(), object))
407
408            return "%s:%s:%s" % (CONTEXT_MARKER, len(mcData), mcData)
409
410    # if object has method 'marshall':
411
412    return "%s:%s:%s" % (SCALAR_STRING_MARKER, len(str(object)), str(object))
413
414# General unmarshalling function (catches all exceptions)
415#   Unmarshalls the input data string and returns a marshalling context.
416#   If an exception occurs, it returns a marshalling context of the
417#   input data string
418
419def unmarshall(data, context = None, flags = UNMARSHALLING_DEFAULTS):
420
421    try:
422
423        if context is None:
424            context = STAFMarshallingContext()
425
426        if data.startswith(NONE_MARKER):
427            return STAFMarshallingContext()
428
429        elif data.startswith(SCALAR_MARKER):
430
431            # @SDT/$S:<string-length>:<String>
432
433            colonIndex = data.find(':', len(SCALAR_MARKER))
434
435            if colonIndex == -1:
436                return STAFMarshallingContext(data)
437
438            dataIndex = colonIndex + 1
439
440            colonIndex = data.find(':', dataIndex)
441
442            if colonIndex == -1:
443                return STAFMarshallingContext(data)
444
445            stringLength = int(data[dataIndex:colonIndex])
446
447            dataIndex = colonIndex + 1
448
449            if stringLength != (len(data) - dataIndex):
450                return STAFMarshallingContext(data)
451
452            theString = data[dataIndex:]
453
454            if (theString.startswith(MARSHALLED_DATA_MARKER) and
455                ((flags & IGNORE_INDIRECT_OBJECTS) !=
456                 IGNORE_INDIRECT_OBJECTS)):
457                return unmarshall(theString, context, flags)
458            else:
459                return STAFMarshallingContext(theString)
460
461        elif data.startswith(LIST_MARKER):
462
463            # @SDT/[<number-of-items>:<array-length>:<SDT-Any-1>...<SDT-Any-n>
464
465            # Get number-of-items in the list
466
467            colonIndex = data.find(':', len(LIST_MARKER))
468
469            if colonIndex == -1:
470                return STAFMarshallingContext(data)
471
472            numItems = int(data[len(LIST_MARKER):colonIndex])
473
474            # Get array-length
475
476            dataIndex = colonIndex + 1
477
478            colonIndex = data.find(':', dataIndex)
479
480            if colonIndex == -1:
481                return STAFMarshallingContext(data)
482
483            arrayLength = int(data[dataIndex:colonIndex])
484
485            dataIndex = colonIndex + 1
486
487            if arrayLength != (len(data) - dataIndex):
488                return STAFMarshallingContext(data)
489
490            # Create a list of the data
491
492            list = []
493
494            for i in range(numItems):
495
496                # Get the next item in the list and unmarshall it and add it
497                # to the list
498
499                colonIndex1 = data.find(':', dataIndex)
500
501                if colonIndex1 == -1:
502                    return STAFMarshallingContext(data)
503
504                colonIndex2 = data.find(':', colonIndex1 + 1)
505
506                if colonIndex2 == -1:
507                    return STAFMarshallingContext(data)
508
509                itemLength = int(data[colonIndex1 + 1:colonIndex2])
510
511                list.append(
512                    unmarshall(data[dataIndex:colonIndex2 + itemLength + 1],
513                               context, flags).getPrimaryObject())
514
515                dataIndex = colonIndex2 + itemLength + 1
516
517            return STAFMarshallingContext(list)
518
519        elif data.startswith(MAP_MARKER):
520
521            # @SDT/{:<map-length>::<key-1-length>:<key-1><SDT-Any>
522            #                     ...
523            #                     :<key-n-length>:<key-1><SDT-Any>
524
525            # Get map-length
526
527            colonIndex = data.find(':', len(MAP_MARKER))
528
529            if colonIndex == -1:
530                return STAFMarshallingContext(data)
531
532            dataIndex = colonIndex + 1
533
534            colonIndex = data.find(':', dataIndex)
535
536            if colonIndex == -1:
537                return STAFMarshallingContext(data)
538
539            mapLength = int(data[dataIndex:colonIndex])
540
541            dataIndex = colonIndex + 1
542
543            if mapLength != (len(data) - dataIndex):
544                return STAFMarshallingContext(data)
545
546            # Create the map (aka dictionary) of data
547
548            map = {}
549
550            while dataIndex < len(data):
551
552                # Get the key first
553
554                keyColonIndex1 = data.find(':', dataIndex)
555
556                if keyColonIndex1 == -1:
557                    return STAFMarshallingContext(data)
558
559                keyColonIndex2 = data.find(':', keyColonIndex1 + 1)
560
561                if keyColonIndex2 == -1:
562                    return STAFMarshallingContext(data)
563
564                keyLength = int(data[keyColonIndex1 + 1:keyColonIndex2])
565                key = data[keyColonIndex2 + 1:keyColonIndex2 + 1 + keyLength]
566
567                dataIndex = keyColonIndex2 + 1 + keyLength
568
569                # Now, get the object
570
571                colonIndex1 = data.find(':', dataIndex)
572
573                if colonIndex1 == -1:
574                    return STAFMarshallingContext(data)
575
576                colonIndex2 = data.find(':', colonIndex1 + 1)
577
578                if colonIndex2 == -1:
579                    return STAFMarshallingContext(data)
580
581                itemLength = int(data[colonIndex1 + 1:colonIndex2])
582
583                map[key] = unmarshall(
584                    data[dataIndex:colonIndex2 + itemLength + 1],
585                    context, flags).getPrimaryObject()
586
587                dataIndex = colonIndex2 + itemLength + 1
588
589            return STAFMarshallingContext(map)
590
591        elif data.startswith(MC_INSTANCE_MARKER):
592
593            # @SDT/%:<map-class-instance-length>::<map-class-name-length>:
594            #     <map-class-name><SDT-Any-value-1>...<SDT-Any-value-n>
595
596            # Get the map-class-instance-length
597
598            colonIndex = data.find(':', len(MC_INSTANCE_MARKER))
599
600            if colonIndex == -1:
601                return STAFMarshallingContext(data)
602
603            dataIndex = colonIndex + 1
604
605            colonIndex = data.find(':', dataIndex)
606
607            if colonIndex == -1:
608                return STAFMarshallingContext(data)
609
610            mapClassInstanceLength = int(data[dataIndex:colonIndex])
611
612            dataIndex = colonIndex + 1
613
614            if mapClassInstanceLength != (len(data) - dataIndex):
615                return STAFMarshallingContext(data)
616
617            # Get map-class-name-length
618
619            colonIndex = data.find(':', dataIndex)
620
621            if colonIndex == -1:
622                return STAFMarshallingContext(data)
623
624            dataIndex = colonIndex + 1
625
626            colonIndex = data.find(':', dataIndex)
627
628            if colonIndex == -1:
629                return STAFMarshallingContext(data)
630
631            mapClassNameLength = int(data[dataIndex:colonIndex])
632
633            # Get map-class-name
634
635            dataIndex = colonIndex + 1
636
637            mapClassName = data[dataIndex : dataIndex + mapClassNameLength]
638
639            dataIndex = dataIndex + mapClassNameLength
640
641            # Create a map and add the the staf-map-class-name key and value
642            # to the map
643
644            map = { 'staf-map-class-name': mapClassName }
645
646            # Unmarshall all of the actual keys and add to the map
647
648            mapClass = context.getMapClassDefinition(mapClassName)
649            keys = mapClass.keys()
650            keyIndex = 0
651
652            while dataIndex < len(data):
653                colonIndex = data.find(':', dataIndex)
654
655                if colonIndex == -1:
656                    return STAFMarshallingContext(data)
657
658                colonIndex2 = data.find(':', colonIndex + 1)
659
660                if colonIndex2 == -1:
661                    return STAFMarshallingContext(data)
662
663                itemLength = int(data[colonIndex + 1:colonIndex2])
664
665                map[keys[keyIndex]['key']] = unmarshall(
666                    data[dataIndex:colonIndex2 + itemLength + 1],
667                    context, flags).getPrimaryObject()
668
669                dataIndex = colonIndex2 + itemLength + 1
670                keyIndex = keyIndex + 1
671
672            return STAFMarshallingContext(map)
673
674        elif data.startswith(CONTEXT_MARKER):
675
676            # @SDT/*:<context-length>:
677            #       @SDT/{:<mapClassLength>:<mapClassData><rootObject>
678
679            # Get context-length
680
681            colonIndex = data.find(':', len(CONTEXT_MARKER))
682
683            if colonIndex == -1:
684                return STAFMarshallingContext(data)
685
686            contextIndex = data.find(':', colonIndex + 1)
687
688            if contextIndex == -1:
689                return STAFMarshallingContext(data)
690
691            contextLength = int(data[colonIndex + 1:contextIndex])
692
693            contextIndex = contextIndex + 1
694
695            if contextLength != (len(data) - contextIndex):
696                return STAFMarshallingContext(data)
697
698            # Get mapClassLength
699
700            colonIndex = data.find(':', contextIndex)
701
702            if colonIndex == -1:
703                return STAFMarshallingContext(data)
704
705            mapIndex = contextIndex
706            mapDataIndex = data.find(':', colonIndex + 1)
707
708            if mapDataIndex == -1:
709                return STAFMarshallingContext(data)
710
711            mapLength = int(data[colonIndex + 1:mapDataIndex])
712
713            mapDataIndex = mapDataIndex + 1
714
715            if mapLength > (len(data) - mapDataIndex):
716                return STAFMarshallingContext(data)
717
718            # Create a new marshalling context with the map classes
719            # and root object
720
721            contextMap = unmarshall(data[mapIndex:mapDataIndex + mapLength],
722                                    context, flags).getPrimaryObject()
723            mapClassMap = contextMap['map-class-map']
724            newContext = STAFMarshallingContext(None, mapClassMap)
725
726            colonIndex = data.find(':', mapDataIndex + mapLength)
727
728            if colonIndex == -1:
729                return STAFMarshallingContext(data)
730
731            rootObjIndex = mapDataIndex + mapLength
732            rootObjDataIndex = data.find(':', colonIndex + 1)
733
734            if rootObjDataIndex == -1:
735                return STAFMarshallingContext(data)
736
737            rootObjLength = int(data[colonIndex + 1:rootObjDataIndex])
738
739            rootObjDataIndex = rootObjDataIndex + 1
740
741            if rootObjLength > (len(data) - rootObjDataIndex):
742                return STAFMarshallingContext(data)
743
744            newContext.setRootObject(
745                unmarshall(data[rootObjIndex:rootObjDataIndex + rootObjLength],
746                           newContext, flags).getPrimaryObject())
747
748            return newContext
749
750        elif data.startswith(MARSHALLED_DATA_MARKER):
751
752            # Here, we don't know what the type is
753            return STAFMarshallingContext(data)
754
755    except:
756        # If any exception occurs unmarshalling the result, assume invalid
757        # marshalled data and return a new marshalling context of the input
758        # data string
759        return STAFMarshallingContext(data)
760
761    return STAFMarshallingContext(data)
762
763
764# Formatting function
765#
766# Notes:
767#   1) The indentLevel option is not meant to be used by a user calling
768#   the formatObject procedure, thus we don't document it exernally.
769#   It's meant to be used internally by the formatObject method when
770#   recursively calling itself.
771#   2) The flags option is not currently used (it's for future use)
772
773def formatObject(obj, context = None, indentLevel = 0, flags = 0):
774
775    # Build a list of strings to output and join them for performance reasons
776    output = []
777
778    if type(obj) == types.ListType:
779        list = obj
780        output.append('[')
781        indentLevel = indentLevel + 1
782
783        if len(list) > 0:
784            output.append(os.linesep)
785
786        # Format each object in the list
787
788        i = 0
789
790        for item in list:
791
792            indent = indentLevel * INDENT_DELTA
793            output.append(SPACES[: indent])
794
795            if (type(item) == types.ListType or
796                type(item) == types.DictType or
797                isinstance(item, STAFMarshallingContext)):
798                output.append(formatObject(item, context, indentLevel, flags))
799            elif item is None:
800                output.append(NONE_STRING)
801            else:
802                output.append(str(item))
803
804            if i < (len(list) - 1):
805                output.append(ENTRY_SEPARATOR)
806
807            output.append(os.linesep)
808
809        indentLevel = indentLevel - 1
810
811        if len(list) > 0:
812            indent = indentLevel * INDENT_DELTA
813            output.append(SPACES[: indent])
814
815        output.append(']')
816
817    elif type(obj) == types.DictType:
818        dict = obj
819        output.append('{')
820        indentLevel = indentLevel + 1
821
822        if len(dict) > 0:
823            output.append(os.linesep)
824
825        # Check if the map object has a map class key and if the context
826        # is valid and contains a map class definition for this map class.
827        # If not, treat as a plain map class.
828
829        if (dict.has_key(MAP_CLASS_NAME_KEY) and
830            (context is not None) and
831            isinstance(context, STAFMarshallingContext) and
832            context.hasMapClassDefinition(dict[MAP_CLASS_NAME_KEY])):
833
834            mapClass = context.getMapClassDefinition(dict[MAP_CLASS_NAME_KEY])
835
836            # Determine maximum key length
837
838            maxKeyLength = 0
839
840            for theKey in mapClass.keys():
841                theKeyString = theKey['key']
842
843                if theKey.has_key(DISPLAY_NAME_KEY):
844                    theKeyString = theKey[DISPLAY_NAME_KEY]
845                if len(theKeyString) > maxKeyLength:
846                    maxKeyLength = len(theKeyString)
847
848            # Now print each object in the map
849
850            i = 0
851
852            for theKey in mapClass.keys():
853                theKeyString = theKey['key']
854
855                if theKey.has_key(DISPLAY_NAME_KEY):
856                    theKeyString = theKey[DISPLAY_NAME_KEY]
857
858                indent = indentLevel * INDENT_DELTA
859                output.append('%s%s' % (SPACES[: indent], theKeyString))
860
861                indent = maxKeyLength - len(theKeyString)
862                output.append('%s: ' % (SPACES[: indent]))
863
864                if dict.has_key(theKey['key']):
865                    thisObj = dict[theKey['key']]
866                else:
867                    thisObj = None
868
869                if (type(thisObj) == types.ListType or
870                    type(thisObj) == types.DictType or
871                    isinstance(thisObj, STAFMarshallingContext)):
872                    output.append(formatObject(thisObj, context, indentLevel, flags))
873                elif thisObj is None:
874                    output.append(NONE_STRING)
875                else:
876                    output.append(str(thisObj))
877
878                if i < (len(dict) - 1):
879                    output.append(ENTRY_SEPARATOR)
880
881                output.append(os.linesep)
882                i = i + 1
883
884        else:
885            # Determine maximum key length
886
887            maxKeyLength = 0
888
889            for theKeyString in dict.keys():
890                if len(theKeyString) > maxKeyLength:
891                    maxKeyLength = len(theKeyString)
892
893            # Now print each object in the map
894
895            i = 0
896
897            for theKeyString in dict.keys():
898                indent = indentLevel * INDENT_DELTA
899                output.append('%s%s' % (SPACES[: indent], theKeyString))
900
901                indent = maxKeyLength - len(theKeyString)
902                output.append('%s: ' % (SPACES[: indent]))
903
904                thisObj = dict[theKeyString]
905
906                if (type(thisObj) == types.ListType or
907                    type(thisObj) == types.DictType or
908                    isinstance(thisObj, STAFMarshallingContext)):
909                    output.append(formatObject(thisObj, context, indentLevel, flags))
910                elif thisObj is None:
911                    output.append(NONE_STRING)
912                else:
913                    output.append(str(thisObj))
914
915                if i < (len(dict) - 1):
916                    output.append(ENTRY_SEPARATOR)
917
918                output.append(os.linesep)
919                i = i + 1
920
921        indentLevel = indentLevel - 1
922
923        if len(dict) > 0:
924            indent = indentLevel * INDENT_DELTA
925            output.append(SPACES[: indent])
926
927        output.append('}')
928
929    elif isinstance(obj, STAFMarshallingContext):
930        inputContext = obj
931        return formatObject(inputContext.getRootObject(), inputContext,
932                            indentLevel, flags)
933    elif obj is None:
934        return NONE_STRING
935    else:
936        return str(obj)
937
938    return ''.join(output)
939
940
941# Used if called as script
942
943if (__name__ == "__main__"):
944
945    import sys
946
947    if len(sys.argv) < 4:
948        print "Usage: %s location service request" % sys.argv[0]
949        sys.exit(1)
950
951    location = sys.argv[1]
952    service = sys.argv[2]
953    request = sys.argv[3]
954
955    for requestPart in sys.argv[4:]:
956        request = request + " " + requestPart
957
958    try:
959        handle = STAFHandle("STAF/Client/Python")
960    except STAFException, e:
961        print "Error registering with STAF, RC: %d" % e.rc
962        sys.exit(e.rc)
963
964    result = handle.submit(location, service, request)
965
966    resultMC = unmarshall(result.result)
967
968    if (result.rc != 0):
969        print "Error submitting request, RC: %d" % result.rc
970
971        if (len(result.result) != 0):
972            print "Additional info: %s" % resultMC
973
974    else:
975        print "Response"
976        print "--------"
977        print resultMC
978
979    rc = handle.unregister()
980
981    sys.exit(rc)
982