source: TI04-geosplat/trunk/cgi/splatui @ 1210

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI04-geosplat/trunk/cgi/splatui@1210
Revision 1210, 16.0 KB checked in by astephen, 14 years ago (diff)

Updated lots of stuff to get zsi working with version 2.0 or lower.

  • Property svn:executable set to *
Line 
1#!<YOUR_PYTHON_HERE>
2#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
3#   This software may be distributed under the terms of the
4#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5
6"""
7splatui
8=======
9
10Holds the GSCGIClient class the users interact with if they
11are calling the package web service via a CGI interface through a
12web browser. Typically this script will be called "splatui".
13
14"""
15
16# Import standard library modules
17import cgi, random, time, re
18
19# Import SOAP library
20from ZSI.client import Binding
21from ZSI.version import Version as zsiv
22zsiv=float("%s.%s" % zsiv[:2])
23       
24# Import package modules
25from pygsc import *
26
27# Set up cgi error reporting to screen if DEBUG is on
28if DEBUG==1:
29    import cgitb
30    cgitb.enable()
31 
32
33class GSCGIClient:
34    """
35    The controlling class for interacting with the package via the web.
36    """
37   
38    def __init__(self):
39        """
40        Initiates the instance setting up the appropriate
41        internal objects and calls to the relevant classes depending
42        on the configuration and arguments provided.
43        """
44        self.username="undefined"
45        self.password="undefined"
46        self.secureToken="undefined"
47        self.userRoles=[]
48        self.loginStatus="out"
49        self.loginMessage=""
50        self.sessionObject={}
51       
52        self.displayer=DisplayManager()
53
54        # Parse the arguments
55        try:
56            self._parseArgs()
57        except:
58            if DEBUG==1:
59                raise
60            else:
61                CGIErrorHandler("Error parsing arguments: "+str(sys.exc_type), noheader=0)
62
63        # Destroy any arguments not intended to pass any further
64        try:
65            self._destroyUnnecessaryArgs()
66        except:
67            if DEBUG==1:
68                raise
69            else:
70                CGIErrorHandler("Error destroying arguments: "+str(sys.exc_type), noheader=0)
71
72        # If switched on check security       
73        if RESTRICTED_DATA==1:
74            try:
75                self._checkSecurity()
76            except:
77                if DEBUG==1:
78                    raise
79                else:
80                    CGIErrorHandler("Security error: "+str(sys.exc_type), noheader=0)
81        else:
82            self.secureToken="undefined"             
83           
84        # Call the dx Web Service with the arguments provided       
85        try:
86            self._callGSWebService(self.args)
87        except SystemExit:
88            pass
89        except:
90            if DEBUG==1:
91                raise
92            else:
93                CGIErrorHandler("Error calling Web Service: "+str(sys.exc_type), noheader=0)       
94
95        try:   
96            self.displayer._displayHTMLFooter()
97        except:
98            if DEBUG==1:
99                raise
100            else:
101                CGIErrorHandler("Error generating HTML footer: "+str(sys.exc_type), noheader=0)
102       
103       
104    def _parseArgs(self):
105        """
106        Parses the arguments sent, if any, ready for sending to the
107        web service.
108        """
109        # Get arguments
110        self.args={}                           
111        args=cgi.FieldStorage()
112       
113        # Get upload file link
114        if args.has_key("uploadedFile"):
115            self.tempFileLink=args["uploadedFile"].file
116            self.args["fileName"]=args["uploadedFile"].filename
117
118        # Populate the argument dictionary
119        for key in args.keys():
120            if key=="uploadedFile": continue
121            self.args[key]=args.getvalue(key)
122                   
123        if self.args.has_key("sessionID") and self.args["sessionID"]=="undefined":
124            self.args["sessionID"]="undefined"     
125         
126        # Check for secure items, destroy if necessary and assign as instance variables   
127        if self.args.has_key("yousirnaim"):
128            self.username=self.args["yousirnaim"]
129            self.args["username"]=self.username
130            del self.args["yousirnaim"]
131           
132        if self.args.has_key("parcewerd"):
133            self.password=self.args["parcewerd"]
134            del self.args["parcewerd"] 
135               
136        if self.args.has_key("secureToken"):
137            self.secureToken=self.args["secureToken"]
138            del self.args["secureToken"]   
139       
140        if not self.args.has_key("username"):
141            self.args["username"]="undefined"
142                                   
143
144    def _destroyUnnecessaryArgs(self):
145        """
146        Destroy the arguments that should not be passed to the main dx Web Service.
147        """
148        if self.args.has_key("password"):
149            del self.args["password"]   
150       
151       
152    def _checkSecurity(self):
153        """
154        If security is switched on with RESTRICTED_DATA=1 then this will
155        call the local implementation of the security.
156        """
157        secChecker=SecurityViaCGI(self.username, self.password, self.secureToken)
158       
159        # Deal with logout
160        ############# NOTE - doesn't destroy session server side (yet)
161        if self.args.has_key("logout") and self.args["logout"]=="Logout":
162            secChecker.logout()
163            secCheck="You have been logged out."
164        else:
165            secCheck=secChecker.validate()         
166           
167        if type(secCheck)==type(""):
168            # Returned string means error in log in or logged out
169            self.loginMessage=secCheck
170        else:
171            self.loginStatus="in"
172            self.loginMessage=""
173            (self.secureToken, self.username, self.userRoles)=secCheck   
174
175               
176    def _callGSWebService(self, args):
177        """
178        According to the arguments given this binds to an appropriate
179        Web Service and calls it with the relevant arguments.
180        """
181        # Just print the login page if not logged in and login required
182        if RESTRICTED_DATA==1 and self.loginStatus=="out":
183            self.displayer._displayHTTPHeader()
184            self.displayer._displayHTMLHeader()
185            self.displayer._displayIntroduction()           
186            self.displayer._displayLoginBar(self.username, self.loginStatus, self.loginMessage)
187            return     
188       
189        #print "Content-Type: text/html\n\n"
190
191        if CALL_METHOD.upper()=="WS":
192            self.server=WSCaller()
193        elif CALL_METHOD.upper()=="LOCAL":
194            serverLocation=LOCAL_SERVER_PACKAGE
195            sys.path.append(serverLocation)
196            #print sys.path
197            self.server=LocalCaller()
198
199        # Get session ID
200        optionCategories=None
201        newSess=self._getSession()
202               
203        # Perform actions as requested by user
204        if self.args.has_key("action"):
205            actionReturn=self._performActions()
206            if actionReturn=="Display footer then complete":
207                return
208       
209        # Clear request if required
210        if self.args.has_key("clearRequest") or self.args.has_key("newRequest"):
211            if self.args.has_key("clearRequest"):
212                del self.args["clearRequest"]
213            else:
214                del self.args["newRequest"]
215            self.sessionID, self.secureToken=self.server.callServerMethod("newRequest",
216                                                  [self.sessionID, self.secureToken])
217                                       
218        if not self.args.has_key("targetPage") and newSess==1:     
219            if keyPatternMatch(self.args, "fileURIList")==0:
220                self.args["targetPage"]="FileURIPage"
221                return self._generateTargetPage()
222            elif keyPatternMatch(self.args, "fileVariable")==0:
223                self.args["targetPage"]="VariableSelectionPage"
224                fileURIs=self.args["fileURIList"].split()
225                (optionCategories, options, optionStrings, secureToken)= \
226                                 self.server.callServerMethod("provideFileURIs",
227                                     [self.sessionID, self.secureToken, fileURIs])     
228            else:
229                pass                                       
230       
231        elif (keyPatternMatch(self.args, "fileVariable")==0 and keyPatternMatch(self.args, "graphicalOutputType")==0) and \
232             (keyPatternMatch(self.args, "plotType")==0 and keyPatternMatch(self.args, "confirm")==0): 
233                if not self.args.has_key("fileURIList"):
234                    # Pressed proceed without selecting
235                    pass
236                else:
237                    self.args["targetPage"]="VariableSelectionPage"
238                    fileURIs=self.args["fileURIList"].split()
239                    resp=self.server.callServerMethod("provideFileURIs",
240                                     [self.sessionID, self.secureToken, fileURIs])
241               
242                    if zsiv>=2.0:
243                        resp=resp[0]
244                    (optionCategories, options, optionStrings, secureToken)=apply(self._cleanOptsTuple, resp)
245                               
246        # Make sure instance and args sessionID are the same
247        self.args["sessionID"]=self.sessionID
248       
249        # Ensure args contains secureToken object
250        if not self.args.has_key("secureToken"):
251            self.args["secureToken"]=self.secureToken
252
253        # Create outputs if needed...
254        if self.args.has_key("action") and self.args["action"]=="createOutput":
255            self._doOutputCreation()
256        else:       
257            # Get the options (and make selections if appropriate)
258            if optionCategories==None:
259                (optionCategories, options, optionStrings, secureToken)=self._getLatestOptions()                   
260            # Analyse the request
261            self._respondToOptionCategories(optionCategories, options, optionStrings)   
262   
263       
264    def _getSession(self):
265        """
266        Checks if a session is already underway and starts one if not.
267        """           
268        # If no session then start a session and get a sessionID
269        if not self.args.has_key("sessionID") or self.args["sessionID"] in ("undefined", None, "None"):
270            # Start session if not known about
271            resp=self.server.callServerMethod("startSession", [self.username, self.password, self.secureToken])
272            #print resp
273            if zsiv>=2.0:
274                resp=resp[0]
275            self.sessionID, self.secureToken=resp
276            return 1
277        else:
278            self.sessionID=self.args["sessionID"]
279            return 0
280
281
282    def _generateTargetPage(self):
283        """
284        Generates output page based on targetPage specified in arguments.
285        """
286        if self.args["targetPage"]=="FileURIPage":
287                self.displayer._displayHTTPHeader()
288                self.displayer._displayHTMLHeader()
289                self.displayer._displayIntroduction()
290                self.displayer._displayMainTableHeader(self.sessionID)
291                self.displayer._displayFileURIInput()
292                self.displayer._displayMainTableFooter()
293               
294                   
295           
296    def _checkIfComplete(self):
297        """
298        Checks if complete, returns 1 (yes) or 0 (no).
299        """
300        isCompleteStatus=0       
301        if self.args.has_key("isComplete"):     
302            resp=self.server.callServerMethod("isComplete",                                            [self.sessionID, self.secureToken]) 
303            if zsiv>=2.0:
304                resp=resp[0]           
305            isCompleteStatus, self.secureToken=resp
306   
307        return isCompleteStatus
308       
309       
310    def _performActions(self):
311        """
312        If "action" argument received then do the appropriate action.
313        """     
314        if 1:  # Move all back <-- one tab and delete this line
315            action=self.args["action"]
316            if action=="viewRequestSummary":
317                summary=self.server.callServerMethod("summariseRequest", [self.sessionID, self.secureToken])[0]
318                self.displayer._displayHTTPHeader()
319                self.displayer._displayHTMLHeader()
320                self.displayer._displayRequestSummaryTable(summary)
321                self.displayer._displayReturnLine(self.sessionID)
322                return "Display footer then complete"
323               
324            elif action=="saveRequest":
325                dataSubsetSpecifier, self.secureToken=self.server.callServerMethod("getDataSubsetSpecifier",
326                                                           [self.sessionID, self.secureToken])
327                self.displayer._displayHTTPHeader()
328                self.displayer._displayHTMLHeader()             
329                self.displayer._displaySaveRequestOptions(dataSubsetSpecifier, self.sessionID)
330                self.displayer._displayReturnLine(self.sessionID)
331                return "Display footer then complete"
332               
333            elif action=="uploadRequest":
334                self.displayer._displayHTTPHeader()
335                self.displayer._displayHTMLHeader()
336                self.displayer._displayUploadRequestOptions(self.sessionID)
337                self.displayer._displayReturnLine(self.sessionID)               
338                return "Display footer then complete"           
339               
340            elif action=="parseUploadedFile":
341                xmlFileString=self.tempFileLink.read()     
342                status, self.secureToken=self.server.callServerMethod("uploadRequest",
343                                              [self.sessionID, xmlFileString, self.secureToken])
344       
345         
346    def _getLatestOptions(self):
347        """
348        If target page provided then get the options for that page,
349        otherwise get whatever options are presented by the dx and
350        send latest selections to update request.
351        """
352        if self.args.has_key("targetPage"):
353            tp=self.args["targetPage"]
354            def tp2catMap(item):
355                return item[0].lower()+item[1:-4]           
356            optionCategory=tp2catMap(tp)
357            resp=self.server.callServerMethod("getOptions",                            [self.sessionID, self.secureToken, optionCategory])
358            if zsiv>=2.0:
359                resp=resp[0]
360            (optionCategories, options, optionStrings, secureToken)=resp
361        else: 
362            resp=self.server.callServerMethod("selectOptions", [self.sessionID,                 self._packArgsAsList(self.args)])
363            if zsiv>=2.0:
364                resp=resp[0]
365            (optionCategories, options, optionStrings, secureToken)=resp       
366        return self._cleanOptsTuple(optionCategories, options, optionStrings, secureToken)
367
368
369    def _cleanOptsTuple(self, a,b,c,d):
370        return (a[0],b[0],c[0],d[0])
371
372    def _respondToOptionCategories(self, optionCategories, options, optionStrings):
373        """
374        Work out what the option category is and respond by displaying
375        the appropriate user interface.
376        """     
377        # Analyse the option categories now
378        if optionCategories in ("No category", [], None):
379            optcat=None
380        else:
381            optcat=optionCategories[0].split("_")[0]
382       
383        #print optcat,[i.split("_")[0] for i in optionCategories]
384        # Can display simple form for these categories 
385        if optcat=="fileVariable":
386            self.displayer._displayHTTPHeader()
387            self.displayer._displayHTMLHeader()
388            self.displayer._displayMainTableHeader(self.sessionID)                 
389            self.displayer._displayVariableSelections(options, optionStrings)
390            self.displayer._displayMainTableFooter()   
391       
392        elif optcat=="graphicalOutputType":
393            self.displayer._displayHTTPHeader()
394            self.displayer._displayHTMLHeader()
395            self.displayer._displayMainTableHeader(self.sessionID)                 
396            self.displayer._displayGraphicalOutputTypeSelections(optionCategories, options, optionStrings)
397            self.displayer._displayMainTableFooter()   
398
399        elif optcat=="animationAxis":
400            self.displayer._displayHTTPHeader()
401            self.displayer._displayHTMLHeader()
402            self.displayer._displayMainTableHeader(self.sessionID)                 
403            self.displayer._displayAnimationAxisOptions(optionCategories, options, optionStrings)
404            self.displayer._displayMainTableFooter()   
405               
406        elif optionCategories!=None and "plotType" in [i.split("_")[0] for i in optionCategories]:
407            self.displayer._displayHTTPHeader()
408            self.displayer._displayHTMLHeader()
409            self.displayer._displayMainTableHeader(self.sessionID)                 
410            self.displayer._displayPlotConfigurations(optionCategories, options, optionStrings)
411            self.displayer._displayMainTableFooter()
412           
413        # If there are no option categories then the request is likely to be complete
414        elif optcat==None or optcat==[]:
415
416            # Display confirmation page if needed
417            if CONFIRMATION_PAGE==1 and not self.args.has_key("confirm"):
418                self.displayer._displayHTTPHeader()
419                self.displayer._displayHTMLHeader()
420                #(summaryString, self.secureToken)
421                resp=self.server.callServerMethod("summariseRequest",
422                                                          [self.sessionID, self.secureToken])
423                if zsiv>=2.0:
424                    resp=resp[0]
425                summaryString, self.secureToken=resp
426                summaryString=summaryString[0]
427                self.displayer._displayMainTableHeader(self.sessionID)   
428                self.displayer._displayConfirmationSection(summaryString)
429
430
431    def _doOutputCreation(self):
432        """
433        Generate output and appropriate web page.
434        """
435        if self.args.has_key("action") and self.args["action"]=="createOutput":             
436                self.displayer._displayHTTPHeader()
437                self.displayer._displayHTMLHeader()             
438                self.displayer._displayProcessingWaiter()   
439                #outputFilePath, self.secureToken
440                resp=self.server.callServerMethod("createOutput", [self.sessionID, self.secureToken])
441                if zsiv>=2.0:
442                    resp=resp[0]
443                outputFilePath, self.secureToken=resp
444                outputFilePath=outputFilePath[0]
445                self.displayer._displayOutputFile(outputFilePath)               
446
447
448    def _packArgsAsList(self, args):
449        """
450        In order to work with ZSI SOAP library need to pack up arguments as a list
451        of [keyword, value] pairs rather than a dictionary.
452        """
453        newList=[]
454        for key, value in args.items():
455            newList.append([key, value])
456        return newList
457       
458       
459    def _validateRequest(self):
460        """
461        Calls the validation Web Service to check that the current selection is
462        within the available options. This will be needed as users can write their
463        own XML files and upload them.
464        """
465        pass
466       
467
468if __name__=="__main__":
469
470    GSCGIClient()       
Note: See TracBrowser for help on using the repository browser.