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