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

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

Latest working version with install method.
Can accept more than one file but doesn't combine variables yet.

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