source: TI02-CSML/trunk/services/3rdParty/pywps-1.0.0/pywps/Wps/execute.py @ 2194

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/services/3rdParty/pywps-1.0.0/pywps/Wps/execute.py@2194
Revision 2194, 37.1 KB checked in by lawrence, 13 years ago (diff)

Adding various specs and 3rd party code of interest for the CSML
services development.

Line 
1"""
2This module generates XML file with Execute response of WPS and executes the process
3"""
4# Author:       Jachym Cepicky
5#               http://les-ejk.cz
6# Lince:
7#
8# Web Processing Service implementation
9# Copyright (C) 2006 Jachym Cepicky
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24
25from ogc import execute
26from xml.dom.minidom import Document
27from xml.dom.minidom import parse
28import grass
29import wpsexceptions
30import append
31
32from threading import Thread
33import tempfile, shutil, os, urllib,time,sys,re
34
35class Status(Thread):
36    """
37    Make thread for watching at process.status array
38    """
39    def __init__ (self,document=None, filename=None,interval=1,process=None):
40      Thread.__init__(self)
41
42      self.document = document # xml document
43      self.filename = filename # name of input file
44      self.interval = interval # interval for checking
45      self.process = process   # process
46
47    def run(self):
48        """
49        Run this in thread
50        """
51        oldmessage = None
52        oldpercent = 0
53
54        while 1:
55            try:
56                # get new message from the process
57                newmessage,newpercent=self.process.status
58
59                # no reason for continuing
60                if self.process.stopChecking:
61                    break
62            except AttributeError,e:
63                newmessage=""
64                newpercent=0
65            except ValueError,e :
66                pass
67
68            # generate the xml
69            if oldmessage != newmessage or\
70                newpercent != oldpercent:
71
72                status = self.document.getElementsByTagName('Status')[0].firstChild
73                self.document.getElementsByTagName('Status')[0].removeChild(status)
74                status = self.document.getElementsByTagName('Status')[0]
75                node = self.document.createElement("ProcessStarted")
76                messnode = self.document.createTextNode(newmessage)
77                node.setAttribute("message",newmessage)
78                node.setAttribute("percentCompleted",str(newpercent))
79                node.appendChild(messnode)
80                status.appendChild(node)
81
82                file = open(self.filename,"w")
83                file.write(self.document.toprettyxml())
84                file.close()
85
86                oldmessage = newmessage
87                oldpercent = newpercent
88
89            # wait about a second
90            time.sleep(self.interval)
91
92class Execute:
93    """
94    This class includes functions for perforing the Execute operation and
95    returning the resulting XML or file or value
96
97    NOTE: If you are here, you should allready have created some writeable
98    teporary directory and chdir in it.
99    """
100
101    def __init__(self, serverSettings, grassSettings, process, formvalues,):
102        """
103        Initialization of the Execute request
104
105        Inputs:
106            serverSettings  -   file from  etc/settings.py or similar
107                                structure
108            grassSettings   -   file from /etc/grass.py or similar
109                                structure
110            process         -   file with process, with settings and
111                                "execute" function
112            formvalues      -   input comma separated string in form
113                                "arg1,value1,arg2,value2,arg3,value3,..."
114        """
115
116        self.settings = serverSettings  # etc/settings.py
117        self.grassSettings = grassSettings  # etc/grass.py
118        self.WPS = execute.WPS()        # ogc/execute.py
119        self.ex = self.WPS.e['response'] # just shorcut
120        self.process = process          # processes/...
121        self.Append = append.Append()   # functions for siple appending
122                                        # attributes and nodes
123        self.wpsExceptions = wpsexceptions.WPSExceptions() # function for
124                                        # printing execptions
125        self.dirsToRemove = []          # here appear temporary
126                                        # directories, which should be
127                                        # removed e.g.
128                                        # [/tmp/tmpgrassSOMETHING,
129                                        # /var/grassdata/spear/tmpmapset]
130        self.formvalues = formvalues   # comma separated string
131        self.timestamp = "%d-%d-%d-%d-%d-%d" % (time.localtime()[0:6])
132
133                                    # the output XML file name - needed, if
134                                    # statusSupported == true
135        self.executeresponseXmlName = "executeresponse-%s.xml" % (self.timestamp)
136        self.statusLocation = None  # URL to executeresponseXmlName file
137        self.statusSupported = None   # Default -> everything will be printed
138                                    # to STDOUT and what more, no fork is
139                                    # needed
140 
141        self.document = Document()
142        self.status = "ProcessAccepted" # default: everything is all right
143        self.statusMessage = None
144        self.errorCode = 0
145        self.pid = os.getpid()
146
147        #
148        # storing the data in self.process.Inputs[input]['value']
149        #
150        if not 'datainputs' in self.formvalues.keys():
151            print "Content-type: text/xml\n"
152            print self.wpsExceptions.make_exception("MissingParameterValue","DataInputs")
153            self.document = None
154            return
155        else:
156            if not self.checkInputs(formvalues=self.formvalues):
157                return
158
159        #
160        # Status Support
161        #
162        try:
163            # if store && status are supported and set to "true"
164            # fork the process
165            if self.process.statusSupported == "true" and \
166               self.process.storeSupported.lower() == "true" and \
167               self.formvalues['status'].lower() == "true" and \
168               self.formvalues['store'].lower() == "true":
169
170                # fork process
171                # It's way harder than it should be to have a CGI script
172                # do something asynchronously in Apache. The root of the
173                # problem is that it's not enough to fork a child, you
174                # have to close stdin, stdout, and stderr. Only you can't
175                # really close them, you have to reassign them.
176                try: 
177                    self.statusLocation = self.settings.ServerSettings['outputUrl']+"/"+self.executeresponseXmlName
178                    self.pid = os.fork() 
179                    if self.pid:
180                        self.make_response_xml()
181                        file = open(
182                                os.path.join(self.settings.ServerSettings['outputPath'],self.executeresponseXmlName),"w")
183                        file.write(self.document.toprettyxml())
184                        file.close()
185                        return
186                    else:
187                        # Reassign stdin, stdout, stderr for child
188                        # so Apache will ignore it
189                        # time.sleep(2)
190                        self.status = "ProcessStarted"
191                        si = open('/dev/null', 'r')
192                        so = open('/dev/null', 'a+')
193                        se = open('/dev/null', 'a+', 0)
194                        os.dup2(si.fileno(), sys.stdin.fileno())
195                        os.dup2(so.fileno(), sys.stdout.fileno())
196                        os.dup2(se.fileno(), sys.stderr.fileno())
197
198                        # make document
199                        self.make_response_xml()
200
201                        # begin checking
202                        self.process.stopChecking = False
203
204                        # define thread
205                        status = Status(document=self.document, 
206                                    filename=os.path.join(
207                                        self.settings.ServerSettings['outputPath'],
208                                        self.executeresponseXmlName),
209                                    interval=1,
210                                    process=self.process)
211                        # take care on self.process.status
212                        status.start()
213
214                except OSError, e: 
215                    print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
216                    sys.exit(1)
217        except KeyError,e :
218            print >>sys.stderr, "Execute.execute failed with KeyError : (%s)" % (e) 
219        except AttributeError,e :
220            pass
221            print >>sys.stderr, "Execute.execute failed with AttributeError: %s" % (e) 
222
223        #
224        # Return just XML response -> statusSupported == "true"
225        # or execute the process and return the XML after that
226        #
227        self.execute()
228        return 
229
230    def execute(self):
231        """
232        1) Creates the temporary directory
233        2) If needed, downloads the data
234        3) Calls the process
235        4) Returns the XML or the resulting file/value
236        5) Cleans the temporary directory
237
238        Reason for having this all in separate function is the possible
239        fork of the process.
240        """
241       
242        #
243        # create the tempdir
244        #
245        self.tempdir = self.mktempdir()
246        if not self.tempdir:
247            return
248        else:
249            self.dirsToRemove.append(self.tempdir)
250       
251        #
252        # make GRASS MAPSET.
253        # NOTE: Current dir should be somewhere in /tmp/tmpgrassSOMETHING
254        # which is LOCATION_NAME to us
255        #
256        # Set
257        #     *self.process.grassEnv
258        # variables
259        grassEnv = grass.GRASS(self.grassSettings)
260        try:
261            self.mapset = grassEnv.mkmapset(self.process.grassLocation)
262            self.dirsToRemove.append(os.path.join(self.process.grassLocation,self.mapset))
263            self.process.grassenv=grassEnv.grassenv
264        except AttributeError:
265            self.mapset = grassEnv.mkmapset()
266 
267        #
268        # downloading the data
269        #
270        for procInput in self.process.Inputs:
271            # only Complex Input Data will try to download
272            if "ComplexValueReference" in procInput.keys() or \
273               "ComplexValue" in procInput.keys(): 
274
275
276                valtype = 'ComplexValueReference'
277                if "ComplexValue" in procInput.keys():
278                    valtype = "ComplexValue"
279
280                # download
281                newFileName = \
282                    self.get_data(data=self.formvalues['datainputs'][procInput['Identifier']],
283                                  output=procInput['Identifier'],
284                                  type=valtype)
285                if not newFileName:
286                    self.cleanTempDir()
287                    return
288                else:
289                    procInput['value'] = newFileName # replace the
290                    self.process.DataInputs[procInput['Identifier']] = procInput['value']
291        #######
292        # MAKE
293        if sys.stdout == sys.__stdout__:
294            sys.stdout = sys.__stderr__
295        # None == Everything OK. String == Problem
296        try:
297            error = self.process.execute()
298            if sys.stdout == sys.__stderr__:
299                sys.stdout = sys.__stdout__
300
301            if error:
302                self.errorCode = 1
303                raise StandardError, error
304
305            else:
306                self.status = "ProcessSucceeded"
307            self.process.stopChecking = True
308            # just to be shure, go back to grass mapset
309            os.system("""g.mapset mapset=%s >/dev/null 2>&1""" %\
310                    (grassEnv.grassenv['MAPSET']))
311
312        except Exception,e:
313            sys.stderr.write("PyWPS ERROR: %s in self.process.execute()\n" % (e))
314            if sys.stdout == sys.__stderr__:
315                sys.stdout = sys.__stdout__
316            self.status = "ProcessFailed"
317            self.statusMessage = e
318            self.make_response_xml()
319            # just to be shure, go back to grass mapset
320            os.system("""g.mapset mapset=%s >/dev/null 2>&1""" %\
321                    (grassEnv.grassenv['MAPSET']))
322            self.cleanTempDir()
323            return
324
325        # is there stored map?
326        outputMap = False
327        for procOutput in self.process.Outputs:
328            try:
329                if type(procOutput['value']) == type(None) or \
330                    procOutput['value'] == []:
331                     try:
332                        procOutput['value'] = self.process.DataOutputs[procOutput['Identifier']]
333                     except:
334                         raise KeyError, "Output value not set"
335            except KeyError,e:
336                    procOutput['value'] = e
337               
338            if 'ComplexValueReference' in procOutput.keys():
339                    outputMap = True
340
341        # for each process output
342        for procOutput in self.process.Outputs:
343            # store support requested?
344            if 'store' in self.formvalues.keys() and\
345                self.formvalues['store'].lower() == "true": 
346                # store support setted in the conf. file
347                if 'ComplexValueReference' in procOutput.keys():
348
349                        try:
350                            # move output files to prepared directory
351                            try:
352                                (name,appendix) = procOutput['value'].split(".")
353                            except ValueError:
354                                name = procOutput['value']
355                                appendix="out"
356                            procOutput['filename'] =  name+"-"+self.timestamp+"."+appendix
357                            procOutput['filePath'] = os.path.join(
358                                    self.settings.ServerSettings['outputPath'], 
359                                    procOutput['filename']) 
360                            shutil.move(procOutput['value'], 
361                                    procOutput['filePath'])
362                            # replace the output value: file.tif ->
363                            # http://server/file.tif
364                            procOutput['value'] = os.path.join(
365                                    self.settings.ServerSettings['outputUrl'],
366                                    procOutput['filename'])
367
368                        except IOError, what:
369                            print "Content-type: text/xml\n"
370                            print self.wpsExceptions.make_exception(
371                                    "ServerError","IOError: %s" % what)
372                            self.document = None
373                            self.cleanTempDir()
374                            return
375
376            else:
377                # content type
378                try:
379                    outtype = None
380                    if procOutput.has_key("ComplexValue"):
381                        outtype="ComplexValue"
382                    elif procOutput.has_key("ComplexValueReference"):
383                        outtype="ComplexValueReference"
384                    elif procOutput.has_key("LiteralValue"):
385                        outtype="LiteralValue"
386                    elif procOutput.has_key("BoundingBoxValue"):
387                        outtype="BoundingBoxValue"
388
389                    if outtype:
390                        conttype = procOutput[outtype]['Formats'][0]
391                    else:
392                        raise KeyError
393                except KeyError:
394                    conttype = "text/plain"
395
396                self.data_response(procOutput,conttype=conttype)
397                self.document = None
398                self.cleanTempDir()
399                # only first output
400                return
401
402        self.make_response_xml()
403        # clean temp Dir
404        self.cleanTempDir()
405        return
406       
407    def data_response(self,output,where="stdout",conttype="text/plain"):
408        """ This function sends outputValue to STDOUT -> to the browser
409
410        outputType - one of "ComplexOutput", "LiteralOutput",
411        outputValue - name of the file/variable
412        conttype    - Content-type, default text/plain
413        """
414
415        # return to stdout
416        if where=="stdout":
417            print "Content-type: %s\n" % (conttype)
418
419            if "ComplexValue" in output.keys() or \
420               "ComplexValueReference" in output.keys():
421                outputh = open(output['value'],"r")
422                for line in outputh:
423                    print line,
424                outputh.close()
425
426            elif "LiteralValue" in output.keys():
427                print output['value'],
428
429            elif "BoundingBoxValue" in output.keys():
430                if output['value'][0] >  output['value'][2]:
431                    output['value'][0],  output['value'][1], output['value'][2],  output['value'][3] =\
432                            output['value'][2],  output['value'][3], output['value'][0],  output['value'][1] 
433                print output['value'][0],output['value'][1],output['value'][2],output['value'][3],
434
435            self.document = None
436            return
437
438        # return as text variable
439        else:
440            if conttype=="text/plain":
441                outputh = open(output['value'],"r")
442                str=""
443                for line in outputh.readlines():
444                    str += line
445                outputh.close()
446                # if file[0].find("xml") > -1:
447                #     file = file[1:]
448                return str
449            elif conttype=="text/xml":
450                out= parse(output['value'])
451                return out.firstChild
452
453    def make_response_xml(self):
454        """
455        This function generates responding XML file.
456        """
457
458        #
459        # cleaning the document
460        #
461        self.document = Document()
462
463        #
464        # Create the root node in XML document
465        #
466        self.Execute = self.document.createElementNS(self.WPS.namespaces['ows'],"ExecuteResponse")
467        self.Execute.setAttribute("xmlns",self.WPS.namespaces['wps'])
468        self.Execute.setAttribute("xmlns:ows",self.WPS.namespaces['ows'])
469        self.Execute.setAttribute("xmlns:xlink",self.WPS.namespaces['xlink'])
470        self.Execute.setAttribute("xmlns:xsi",self.WPS.namespaces['xsi'])
471        self.Execute.setAttribute("xsi:schemaLocation",self.WPS.namespaces['wps']+' '+self.WPS.schemalocation['wps'])
472        if self.statusLocation:
473            self.Execute.setAttribute("statusLocation",self.statusLocation)
474        self.document.appendChild(self.Execute)
475
476       
477
478
479        # attributes
480        try:
481            for attribute in self.ex['attributes'].keys():
482                if attribute == "statusLocation":
483                    continue
484                self.Append.Attribute(
485                        document=self.document,
486                        attributeName = attribute,
487                        Node = self.Execute,
488                        Attributes = self.ex['attributes'],
489                        Values = self.settings.WPS
490                        )
491        except AttributeError, what:
492            pass
493       
494        # For each element separate function
495        for element in self.ex['order']:
496            if element == 'Identifier':
497                identifier = self.document.createElement(
498                        self.ex['elements']['Identifier']['ns']+"Identifier")
499                identifier.appendChild(
500                        self.document.createTextNode(self.process.Identifier))
501                self.Execute.appendChild(identifier)
502            elif element == 'Status':
503                self.statusNode(self.Execute)
504            elif element == "DataInputs":
505                # this structure is ommited
506                pass
507            elif element == "OutputDefinitions":
508                # this structure is ommited
509                pass
510            elif element == "ProcessOutputs":
511                if self.status == "ProcessSucceeded":
512                    self.process_outputsNode(self.Execute)
513        return
514
515    def statusNode(self,parent):
516        """
517        Status XML Node
518
519        Inputs:
520            parent   -  parent XML node
521        """
522        Status = self.ex['elements']['Status']
523        statusNode = self.document.createElement("%s%s" % \
524                (Status['ns'],"Status"))
525
526        if self.statusMessage:
527            message = self.statusMessage
528        else:
529            message = ''
530
531        node = self.document.createElement("%s%s" % \
532                (Status['elements'][self.status]['ns'],self.status))
533        if self.status == "ProcessStarted":
534            node.setAttribute("%s%s" % \
535                    (Status['elements'][self.status]['attributes']['message']['ns'],"message"),
536                    message )
537        elif self.status.lower() == "processfailed":
538            # Exceptions, ProcessFailed
539            # NOTE: Should be separate function
540               
541            report = self.document.createElement("ows:ExceptionReport")
542            report.setAttribute("verion","1.0")
543            node.appendChild(report)
544
545            # code: known errors do have code  1, unkown 0
546            exception = self.document.createElement("ows:Exception")
547            exception.setAttribute("exceptionCode", str(self.errorCode))
548            report.appendChild(exception)
549
550            text = self.document.createElement("ows:ExceptionText")
551            text.appendChild(self.document.createTextNode(str(message)))
552            exception.appendChild(text)
553
554        statusNode.appendChild(node)
555        parent.appendChild(statusNode)
556        return
557
558    def process_outputsNode(self,parent):
559        """
560        ProcessOutputs XML Node
561        """
562        outputOws = self.ex['elements']['ProcessOutputs']['elements']['Output']
563
564        processOutputs = self.document.createElement("ProcessOutputs")
565        parent.appendChild(processOutputs)
566
567        # for each element in output structure
568        for outputProc in self.process.Outputs:
569            outputNode = self.document.createElement("Output") 
570            processOutputs.appendChild(outputNode)
571
572            # for each node in input ogc's conf. structure
573            for element in outputOws['order']:
574                if element == "ValueFormChoice":
575
576                    #
577                    # ComplexValueReference
578                    if "ComplexValueReference" in outputProc.keys():
579                        ComplexValueRef = self.document.createElement("ComplexValueReference")
580                        outputNode.appendChild(ComplexValueRef)
581                        for attribute in outputOws['elements']['ValueFormChoice']['elements']['ComplexValueReference']['attributes']:
582                            if attribute == "format":
583                                ComplexValueRef.setAttribute("format",outputProc['ComplexValueReference']['Formats'][0])
584                            elif attribute == "reference":
585                                ComplexValueRef.setAttribute(
586                                        "ows:reference",outputProc['value'])
587                            else:
588                                    self.Append.Attribute(
589                                        document=self.document,
590                                        attributeName = attribute,
591                                        Node = ComplexValueRef,
592                                        Attributes =\
593                                        outputOws['elements']['ValueFormChoice']['elements']['ComplexValueReference']['attributes'],
594                                        Values = outputProc
595                                        )
596                    #
597                    # ComplexValue
598                    elif "ComplexValue" in outputProc.keys():
599                        ComplexValue = self.document.createElement("ComplexValue")
600                        outputNode.appendChild(ComplexValue)
601                        format = outputProc['ComplexValue']['Formats'][0] 
602                        for attribute in outputOws['elements']['ValueFormChoice']['elements']['ComplexValue']['attributes']:
603
604                            if attribute == "format":
605                                ComplexValue.setAttribute("format",format)
606                        for elm in outputOws['elements']['ValueFormChoice']['elements']['ComplexValue']['elements']:
607                            if elm == "Value":
608                                node = self.document.createElement("Value")
609
610                                # if format of this element is text/xml or
611                                # similar, append xml, append text/plain
612                                # otherwise
613                                if format == "text/xml":
614                                    out =  self.data_response(
615                                            outputProc,where="file",
616                                            conttype="text/xml")
617                                else:
618                                    out = self.document.createTextNode(
619                                    self.data_response(outputProc,where="file")
620                                    #"XML or Binary result should be here"
621                                            )
622                                node.appendChild(out)
623                                ComplexValue.appendChild(node)
624
625                    #
626                    # LiteralValue
627                    # LiteralData is depredecated
628                    elif "LiteralData" in outputProc.keys() or\
629                         "LiteralValue" in outputProc.keys():
630                        LiteralValue = self.document.createElement("LiteralValue")
631                        outputNode.appendChild(LiteralValue)
632                        #LiteralValue.setAttribute("value",
633                        #str(outputProc['value']))
634                        LiteralValue.appendChild(
635                                self.document.createTextNode(str(outputProc['value'])))
636
637                    #
638                    # BoundBox
639                    elif "BoundingBoxValue" in outputProc.keys():
640                        bboxNode = self.document.createElement("%s%s" %\
641                                (outputOws['elements']['ValueFormChoice']['elements']['BoundingBoxValue']['ns'],"BoundingBoxValue"))
642                        outputNode.appendChild(bboxNode)
643
644                        lower = self.document.createElement("%s%s" % \
645                                (outputOws['elements']['ValueFormChoice']['elements']['BoundingBoxValue']['elements']['LowerCorner']['ns'],"LowerCorner"))
646
647                        upper = self.document.createElement("%s%s" % \
648                                (outputOws['elements']['ValueFormChoice']['elements']['BoundingBoxValue']['elements']['UpperCorner']['ns'],"UpperCorner"))
649
650                        try:
651                            if outputProc['value'][0] >  outputProc['value'][2]:
652                                outputProc['value'][0],  outputProc['value'][1], outputProc['value'][2],  outputProc['value'][3] =\
653                                        outputProc['value'][2],  outputProc['value'][3], outputProc['value'][0],  outputProc['value'][1] 
654                            lower.appendChild(self.document.createTextNode(
655                                "%s %s" %
656                                (str(outputProc['value'][0]).strip(),str(outputProc['value'][1]).strip())))
657                            upper.appendChild(self.document.createTextNode(
658                                "%s %s" %
659                                (str(outputProc['value'][2]).strip(),str(outputProc['value'][3]).strip())))
660
661                        except IndexError,e:
662                            lower = upper = "%s: not enough output values for bounding box"
663                        bboxNode.appendChild(lower)
664                        bboxNode.appendChild(upper)
665
666
667                        pass
668                else: # try to append 'standard' node
669                    self.Append.Node(
670                        document=self.document, 
671                        childNode=element, 
672                        parentNode=outputNode,
673                        Elements=outputOws['elements'],
674                        Values=outputProc
675                        )
676        return
677
678    def get_data(self,
679                 data=None,
680                 postFile=None,
681                 maxSize=5242880,
682                 output="input.file",
683                 type="ComplexValue"):
684        """
685        Tryes to download the data from net and check's, if they are in
686        appropriate format.
687
688        data - URI, from which the file should be downloaded, or e.g. GML
689                string
690        postFile - file name which arriwed trough the POST method
691        """
692        try:
693            maxSize = self.settings.ServerSettings['maxSize']
694        except KeyError:
695            pass
696
697        # check, if the file with this name already exist.
698        # if so, try to find "filename.fileN" name, where N
699        # standes for integer bumber
700        inputNumber = 1
701        while inputNumber:
702            if os.path.isfile(output):
703                output = "%s-%d" %(output,inputNumber)
704                inputNumber +=1
705            else:
706                break
707
708
709        if type=="ComplexValueReference":
710            if data:
711                inputUrl = urllib.urlopen(data)
712               
713                try:
714                    fout=open(output,'wb')
715                except IOError, what:
716                    print "Content-type: text/xml\n"
717                    print self.wpsExceptions.make_exception(
718                        "ServerError","IOError: %s" % what)
719                    self.document = None
720                    return
721
722                # ok, get the file!
723                size = 0
724                while 1:
725                    # reading after 100kB
726                    size += 100000
727                    chunk = inputUrl.read(100000)
728
729                    # something is wrong
730                    if re.search("not found",chunk,re.IGNORECASE):
731                        print "Content-type: text/xml\n"
732                        print self.wpsExceptions.make_exception(
733                                "InvalidParameterValue",
734                                "server says: %s not found" % (data))
735                        self.document = None
736                        return
737
738                    # everything is here, break
739                    if not chunk: 
740                        break
741                    fout.write (chunk)
742
743                    # TOO BIG! STOP THIS
744                    if size > maxSize: 
745                        print "Content-type: text/xml\n"
746                        print self.wpsExceptions.make_exception("FileSizeExceeded")
747                        self.document = None
748                        return
749                fout.close()
750        elif type=="ComplexValue":
751            try:
752                fout=open(output,'w')
753                fout.write(data)
754                fout.close()
755            except IOError, what:
756                print "Content-type: text/xml\n"
757                print self.wpsExceptions.make_exception(
758                    "ServerError","IOError: %s" % what)
759                self.document = None
760                return
761
762        if not os.path.isfile(output):
763            print "Content-type: text/xml\n"
764            print self.wpsExceptions.make_exception("InvalidParameterValue","DataInputs")
765            self.document = None
766            return
767        else:
768            return output
769
770    def cleanTempDir(self,directory=None):
771        """
772        Cleans temporary directory - removes the complet tree.
773        if directory not set, it will go thru self.dirsToRemove variable
774        """
775        if directory:
776            if os.path.isdir(directory):
777                shutil.rmtree(directory)
778            else:
779                raise TypeError
780            return 
781        else:
782            for dir in self.dirsToRemove:
783                shutil.rmtree(dir)
784   
785    def mktempdir(self,directory=None):
786        """
787        Creates temporary directory and  chdir to it
788
789        returns name of the temp directory, if OK
790        nothing if failed
791
792        inputs:
793            directory   -   if set, the tmpgrassSOMETHING dir will be created in this directory
794                            if not set, will try to look to settitings.ServerSettings['tempPath']
795                            if not set, will try to create in default directory (/tmp)
796        """
797        # create our temp directory where the admin wants to
798        # in /tmp else
799        try:
800            if directory:
801                    tempdir = tempfile.mkdtemp(prefix="tmpgrass",dir=directory)
802            else:
803                try:
804                    tempdir = tempfile.mkdtemp(prefix="tmpgrass",dir=self.settings.ServerSettings['tempPath'])
805                except KeyError:
806                    tempdir = tempfile.mkdtemp()
807        except (IOError,OSError), what:
808            print "Content-type: text/xml\n"
809            print self.wpsExceptions.make_exception(
810                    "ServerError","IOError, OSError: tempdir not created - %s" % what)
811            self.document = None
812            return
813        #########
814        # everything will be done in our temp directory
815        os.chdir(tempdir)
816        return (tempdir)
817
818    def checkInputs(self,formvalues=None):
819        """
820        Check the process input values sended in the 'formvalues' string.
821        The string represents comma separated values: key1,value1,key2,value2
822
823        If everything looks good, new DataInputs structure is returned.
824        """
825       
826        # new variable for each process for easy access of input values
827        #     *self.process.DataInputs
828        #     *self.process.DataOutputs
829        self.process.DataInputs = {}
830        self.process.DataOutputs = {}
831
832        if not formvalues:
833            return
834        #
835        # All the parameters are here?
836        #
837        for input in self.process.Inputs:
838            try:
839                if not formvalues['datainputs'][input['Identifier']]:
840                        raise KeyError
841            except (KeyError),e :
842                if not input.has_key('value') or input['value'] == None:
843                    print "Content-type: text/xml\n"
844                    print self.wpsExceptions.make_exception( \
845                            "MissingParameterValue",input['Identifier'])
846                    self.document = None
847                    return
848        #
849        # Type and value checking
850        #   
851        for input in self.process.Inputs:
852           
853            # it can happen, that dataType is not set but default value is
854            # -> get the dataType from default value
855
856            if (input.has_key('value') and not input.has_key('dataType')):
857                input['dataType'] = type(input['value'])
858                   
859            # set "value"
860            if formvalues['datainputs'].has_key(input['Identifier']):
861
862                input['value'] = formvalues['datainputs'][input['Identifier']]
863
864                if self._checkType(input,formvalues['datainputs'][input['Identifier']]):
865                    print "Content-type: text/xml\n"
866                    print self.wpsExceptions.make_exception(
867                            "InvalidParameterValue","%s: %s" % \
868                                    (str(input['Identifier']), 
869                                    str(formvalues['datainputs'][input['Identifier']])))
870                    self.document = None
871                    return
872
873                if input.has_key('LiteralValue') and \
874                    len(input['value']) == 1:
875                        input['value'] = input['value'][0]
876                elif input.has_key("BoundingBoxValue"):
877                    if input['value'][0] > input['value'][2]:
878                        input['value'][0], input['value'][2] = input['value'][2],input['value'][0]
879                        input['value'][1], input['value'][3] = input['value'][3],input['value'][1]
880
881            # setting input values to one structure - pointer to input['value']
882            self.process.DataInputs[input['Identifier']] = input['value']
883
884        return True
885
886    #
887    # Type and value checking
888    #   
889    def _checkType(self,input=None,values=None):
890        """This function checkes type and value of input values"""
891         
892        if not type(values) == type([]):
893            values = [values]
894
895        for value in values:
896            try:
897                if input['dataType'] == type(0.0):
898                    value = float(value)
899                elif input['dataType'] == type(1):
900                    value =  int(value)
901                elif input['dataType'] == type(''):
902                    value = str(value)
903            except (KeyError),e:
904                pass
905            except TypeError,e:
906                return True
907
908            # list of allowed literal values in
909            if input.has_key("LiteralValue"):
910                isin = False
911                if not input['LiteralValue'].has_key('values') or\
912                        "*" in input['LiteralValue']['values']:
913                    isin = True
914                else:
915                    if value in input['LiteralValue']['values']:
916                        isin = True
917                if not isin:
918                    return True
919
920            return
Note: See TracBrowser for help on using the repository browser.