Changeset 4504 for MILK


Ignore:
Timestamp:
27/11/08 15:20:35 (11 years ago)
Author:
cbyrom
Message:

Improve handling of errors by adding a method to unpack these in a consistent manner.
Add method to tidy inputs - to avoid unpickleable data being stored in session (which cannot be done). Currently this only deals with FieldStorage? objects.
Add global variable to store eXist client connections to the different provider IDs - to allow re-use of these across the web-app.

Location:
MILK/trunk/milk_server/milk_server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • MILK/trunk/milk_server/milk_server/config/milkMiddleware.py

    r4491 r4504  
    6868                                       raiseException = True, newLineChar="<br/>") 
    6969 
     70        # initialise collection to store re-usable connections to the eXist DB 
     71        self.globals.eXistDBCons = {} 
     72         
    7073        # Security Related 
    7174 
  • MILK/trunk/milk_server/milk_server/controllers/atom_editor/editatom.py

    r4494 r4504  
    55 @author: C Byrom, Tessella Sep 2008 
    66''' 
    7 import logging, traceback, sys 
     7import logging, traceback, sys, cgi 
    88from paste.request import parse_querystring 
    99from xml.parsers.expat import ExpatError 
     
    1919from ndgUtils import ndgObject 
    2020from ndgUtils.models.Atom import Atom, Person, Link, Category 
     21from ndgUtils.eXistConnector import eXistConnector 
    2122from ndgUtils.lib.atomvalidator import ValidationError 
    2223import ndgUtils.models.existdbclient as edc 
     
    5051 
    5152 
     53    def __unpackErrors(self, e): 
     54        ''' 
     55        Add exception errors to the common error structures - for use 
     56        in templates 
     57        @param e: Exception to add 
     58        ''' 
     59        errorMessage = e.message 
     60        if g.debugAtomEditor: 
     61            errorMessage = traceback.format_exc() 
     62 
     63        c.xml = escapeSpecialCharacters('Unexpected error loading page [%s]' \ 
     64                                        %str(errorMessage)) 
     65        c.doc='' 
     66         
     67        # unpack errors, if possible - NB, the c.errors value is used by the template 
     68        # function, displayErrors, which is used by most of the editor templates 
     69        if hasattr(e, 'unpack_errors'): 
     70            c.errors.update(e.unpack_errors()) 
     71        else: 
     72            c.errors['Unexpected error'] = [c.xml] 
     73 
     74        # tidy up errors - escaping any xml tags, if necessary 
     75        for key, errors in c.errors.items(): 
     76            newErrors = [] 
     77            for error in errors: 
     78                newErrors.append(escapeSpecialCharacters(error)) 
     79            c.errors[key] = newErrors 
     80 
     81 
    5282    def __handleError(self, e, template='error'): 
    5383        ''' 
     
    5989        containing the variable, c.xml to display properly  
    6090        ''' 
    61         errorMessage = e.message 
    62         if g.debugAtomEditor: 
    63             errorMessage = traceback.format_exc()#print_exception(*sys.exc_info()) 
    64  
    65         c.xml = 'Unexpected error loading page [%s]' %str(errorMessage) 
    66         c.doc='' 
     91        self.__unpackErrors(e) 
    6792        logging.error(c.xml) 
    68          
    6993        response.status_code = 400 
    7094        return render("genshi", template) 
     
    7498        ''' 
    7599        Upload a CSML or granulite file and store it in the session variable 
     100        NB, if the uri is specified, we're already dealing with an atom  
     101        (which this refers to) - so the file is not a granulite - since  
     102        this is used to create the atom 
    76103        ''' 
    77104        logging.info("Uploading file...") 
    78         file = request.POST.get('upload_CSML') 
    79         isGranulite = False 
    80         if file is None: 
    81             # check for granulite 
     105        if uri: 
     106            file = request.POST.get('upload_CSML') 
     107        else: 
    82108            file = request.POST.get('upload_granulite') 
    83             isGranulite = True 
    84              
    85         if file == '': 
    86             errorMessage = "Error: could not load file - please try again" 
    87             logging.error(errorMessage) 
    88             c.errors = {'Load error' : errorMessage} 
    89             return hc.index(hc()) 
    90  
    91         logging.debug("- file name: '%s'" %file.name) 
    92         # Prepare the basic data model 
     109 
    93110        c.errors = {} 
    94111        try: 
    95             # NB, if loading a granulite, this will create the displayed atom 
    96             if uri != None: 
    97                 self.prepareDataModel(uri) 
     112            if file == '': 
     113                errorMessage = "Error: could not load file - please try again" 
     114                logging.error(errorMessage) 
     115                raise IOError(errorMessage) 
    98116            else: 
    99                 self.__setup() 
    100                 c.atom = Atom() 
    101         except SystemError, e: 
    102             return self.__handleError(e) 
    103  
    104         # now process the input file and add any extra required data 
    105         try: 
    106             if isGranulite: 
    107                 self.__processGranuliteFile(file.value) 
    108             else: 
    109                 self.__processCSMLFile(file) 
     117                logging.debug("- file name: '%s'" %file.name) 
     118 
     119                # Prepare the basic data model 
     120                # NB, if loading a granulite, this will create the displayed atom 
     121                if uri: 
     122                    self.prepareDataModel(uri) 
     123                else: 
     124                    self.__setup() 
     125                    c.atom = Atom() 
     126 
     127                # now process the input file and add any extra required data 
     128                if uri: 
     129                    self.__processCSMLFile(file) 
     130                else: 
     131                    self.__processGranuliteFile(file.value) 
     132 
     133                # save new data 
     134                self.saveAtomToExist(c.atom) 
     135                             
     136                # now do redirection - NB, this ensures that current atom contents are 
     137                # reloaded and displayed 
     138                logging.info("File data loaded and extracted to atom") 
    110139        except Exception, e: 
    111             return self.__handleError(e, template='atom_editor/atom_granulator') 
    112  
    113         # save new data 
    114         self.saveAtomToExist(c.atom) 
    115                      
    116         # now do redirection - NB, this ensures that current atom contents are 
    117         # reloaded and displayed 
    118         logging.info("File data loaded and extracted to atom") 
    119         h.redirect_to(controller = 'atom_editor/editatom', action='edit', \ 
    120                         uri = c.atom.ndgURI) 
     140            c.errors['WARNING'] = ['Error loading data: the displayed data will not be saved - please fix problem and retry'] 
     141            self.__unpackErrors(e) 
     142 
     143        if uri and c.atom: 
     144            return self.edit(c.atom.ndgURI) 
     145        elif uri: 
     146            # something has gone wrong here... 
     147            return render("genshi", 'error') 
     148        else: 
     149            return self.createGranule() 
    121150 
    122151 
     
    128157        ''' 
    129158        logging.info("Extracting CSML data") 
    130         c.atom.addCSMLData(file) 
     159        csmlDoc = c.atom.addCSMLData(file.filename, file.value) 
    131160        logging.info("Finished extracting CSML data") 
     161         
     162        logging.info("Adding CSML file to eXist") 
     163        eXist = self.__getExistClient(c.atom.ME.providerID) 
     164        eXist.createOrUpdateEXistFile(csmlDoc.toPrettyXML(), \ 
     165                                      eXistConnector.NDG_A_COLLECTION_PATH + \ 
     166                                      c.atom.ME.providerID + '/', \ 
     167                                      file.filename) 
     168        logging.info("CSML file added to eXist") 
     169 
    132170     
    133171 
     
    151189         
    152190        logging.info("Finished processing granulite data") 
     191 
     192 
     193    def __getTidyInputs(self): 
     194        ''' 
     195        The inputs can be used generically to specify atom attributes - however 
     196        some inputs should not be set against the Atom object since they use slots 
     197        so cannot be pickled - which means saving the atom in the session with fail. 
     198        This method clears out any unwanted inputs 
     199        ''' 
     200        logging.debug("Getting pickleable input data") 
     201        inputs = request.params 
     202        tidyInputs = {} 
     203        for key, val in inputs.items(): 
     204            if not isinstance(val, cgi.FieldStorage): 
     205                tidyInputs[key] = val 
     206        logging.debug("Pickleable data extracted") 
     207        return tidyInputs 
    153208 
    154209     
     
    196251        logging.info("Validating input") 
    197252        try: 
    198         #    validator = AtomFormSchema() 
    199         #    validator.to_python(inputs) 
    200253            g.validator.setAtom(c.atom) 
    201254            g.validator.validateAtom() 
    202             #c.atom.validate() 
    203255            logging.info("- input valid") 
    204256        except ValidationError, e: 
     
    244296        # NB, passing in the inputs will overwrite any original values with the 
    245297        # user input ones 
    246         inputs = request.params 
     298        inputs = self.__getTidyInputs() 
     299         
    247300        c.atom = Atom(xmlString=str(x), ndgObject = self.ndgObject, **dict(inputs)) 
    248301         
     
    530583        ''' 
    531584        logging.info("Saving changes to eXist") 
    532         self.eXist = self.__getExistClient(atom.ME.providerID) 
    533         createdAtom = self.eXist.createAtomInExist(atom) 
     585        eXist = self.__getExistClient(atom.ME.providerID) 
     586        createdAtom = eXist.createAtomInExist(atom) 
    534587        logging.info("Changes successfully saved to eXist") 
    535588        return createdAtom 
    536589 
     590 
    537591    def __getExistClient(self, providerID): 
    538592        ''' 
    539593        Use the config data to set up and return an eXist client 
    540594        ''' 
    541         logging.info("Setting up eXist client") 
     595        logging.info("Setting up eXist client to provider, '%s'" %providerID) 
     596        # firstly check if there is a current connection available 
     597        eXistClient = g.eXistDBCons.get(providerID) 
     598        if eXistClient: 
     599            logging.info("- found existing client to provider - returning this") 
     600            return eXistClient 
     601         
    542602        # lookup the eXist DB to use according to the provider ID for the  
    543603        # data - NB, this is specified in the ndgDiscovery.config file 
     
    546606        eXistClient = edc.eXistDBClient(eXistDBHostname = existHost, \ 
    547607                                       configFile = configFile) 
     608         
     609        # add the client to the global variables for re-use 
     610        g.eXistDBCons[providerID] = eXistClient 
    548611        logging.info("Returning eXist client") 
    549612        return eXistClient 
     613 
    550614     
    551615    def create(self, saveData = None, **inputs): 
     
    565629                atomTypeID = inputs.get('atomTypeID').split('--')[1] 
    566630                inputs['atomTypeID'] = atomTypeID 
    567      
     631    
    568632                # activity deployments should have subtype deployment specified automatically 
    569633                if atomTypeID == g.vtd.ACTIVITY_DEPLOYMENT_TERM: 
Note: See TracChangeset for help on using the changeset viewer.