Module configParser |
[hide private]
[frames] | no frames]

## Source Code for Module configParser

      1
      2  import os, sys, dynamic, time, glob
      3  from utils import getFirstData, elementType
      4  from bootstrap import BSParser, BootstrapDocument
      5  from c3errors import FileDoesNotExistException, ConfigFileException, PermissionException, ObjectDoesNotExistException
      6  from types import MethodType
      7  from permissionHandler import PermissionHandler
      8
      9 -class C3Object(object):
     10      id = ""
     11      name = ""
     12      objectType = ""
     13      parent = None
     14      paths = {}
     15      subConfigs = {}
     16      objects = {}
     17      configStore = None
     18      settings = {}
     19      defaults = {}
     20      functionLogger = None
     21      permissionHandlers = {}
     22
     23      unresolvedObjects = {}
     24
     25      # temp storage
     26      _includeConfigStores = []
     27      _objectRefs = []
     28
     29
     30 -    def _getDomFromFile(self, session, fileName):
     31          """Read in an XML file from disk to get the configuration for this object."""
     32          # We need to be able to read in configurations from disk
     33
     34          if not os.path.exists(fileName):
     35              raise(FileDoesNotExistException(fileName))
     36
     37          f = file(fileName)
     38          doc = BootstrapDocument(f)
     39
     40          # Look on self for instantiated parser, otherwise use bootstrap
     41          p = self.get_path(session, 'parser')
     42          if (p <> None):
     43              # Not sure if this ever occurs...
     44              record = p.process_document(session, doc)
     45          else:
     46              record = BSParser.process_document(session,doc)
     47          dom = record.get_dom()
     48          return dom
     49
     50
     51 -    def _handleConfigNode(self, session, node):
     52          pass
     53
     54      # Return parsed value (eg Int, Bool, String etc)
     55      # Or raise an error
     56 -    def _verifyOption(self, type, value):
     57          return value
     58 -    def _verifySetting(self, type, value):
     59          return self._verifyOption(type, value)
     60 -    def _verifyDefault(self, type, value):
     61          return self._verifyOption(type, value)
     62
     63
     64 -    def _parseIncludes(self, session, path):
     65          dom = self._getDomFromFile(session, path)
     66          for child2 in dom.childNodes[0].childNodes:
     67              if child2.nodeType == elementType:
     68                  if child2.localName == "subConfigs":
     69                      self._recurseSubConfigs(session, child2)
     70                  elif (child2.localName == "objects"):
     71                      # record object ref to instantiate
     72                      for obj in child2.childNodes:
     73                          if (obj.nodeType == elementType and obj.localName == "path"):
     74                              type = obj.getAttributeNS(None,'type')
     75                              id = obj.getAttributeNS(None,'ref')
     76                              self._objectRefs.append((id, type))
     77
     78 -    def _recurseSubConfigs(self, session, child):
     79          for mod in child.childNodes:
     80              if mod.nodeType == elementType and mod.localName == "subConfig":
     81                  id = mod.getAttributeNS(None,'id')
     82                  self.subConfigs[id] = mod
     83
     84                  # Cache indexes and maps
     85                  type = mod.getAttributeNS(None,'type')
     86                  if type == 'index':
     87                      self.indexConfigs[id] = mod
     88                  elif type == 'protocolMap':
     89                      self.protocolMapConfigs[id] = mod
     90                  elif type == 'database':
     91                      self.databaseConfigs[id] = mod
     92                  elif type == '':
     93                      raise ConfigFileException("Object must have a type attribute: %s" % id)
     94
     95              elif mod.nodeType == elementType and mod.localName == "path":
     96                  if (mod.hasAttribute('type') and mod.getAttributeNS(None,'type') == 'includeConfigs'):
     97                      # Import into our space
     98                      if (mod.hasAttribute('ref')):
     99                          # <path type="includeConfigs" ref="configStore"/>
    100                          self._includeConfigStores.append(mod.getAttributeNS(None,'ref'))
    101                      else:
    102                          # <path type="includeConfigs">path/to/some/file.xml</path>
    103                          path = getFirstData(mod)
    104                          if  not os.path.isabs(path):
    105                              path = os.path.join(self.get_path(None, 'defaultPath'), path)
    106                          if os.path.isdir(path):
    107                              # include all configs in it at our space
    108                              files = glob.glob("%s/*.xml" % path)
    109                              for f in files:
    110                                  self._parseIncludes(session, f)
    111                          else:
    112                              self._parseIncludes(session, path)
    113                  else:
    114                      path = getFirstData(mod)
    115                      if  not os.path.isabs(path):
    116                          path = os.path.join(self.get_path(session, 'defaultPath'), path)
    117                      dom = self._getDomFromFile(session, path)
    118                      id = mod.getAttributeNS(None,'id')
    119                      self.subConfigs[id] = dom.childNodes[0]
    120                      ot = mod.getAttributeNS(None,'type')
    121                      if ot == 'database':
    122                          self.databaseConfigs[id] = dom.childNodes[0]
    123
    124 -    def __init__(self, session, topNode, parentObject=None):
    125          """The constructor for all Cheshire3 objects take the same arguments:
    126          session:  A Session object
    127          topNode:  The <config> or <subConfig> domNode for the configuration
    128          parent:   The object that provides the scope for this object.
    129          """
    130
    131
    132          self.docstring = ""
    133          self.parent = parentObject
    134          self.subConfigs = {}
    135          self.paths = {}
    136          self.objects = {}
    137          self.settings = {}
    138          self.defaults = {}
    139          self.permissionHandlers = {}
    140          self.unresolvedObjects = {}
    141          self.functionLogger = None
    142          self._objectRefs = []
    143          self._includeConfigStores = []
    144          pathObjects = {}
    145
    146          try:
    147              if (topNode.hasAttribute('id')):
    148                  self.id = topNode.getAttributeNS(None,'id')
    149          except:
    150              if (topNode.hasAttributeNS(None, 'id')):
    151                  self.id = topNode.getAttributeNS(None, 'id')
    152
    153          for child in topNode.childNodes:
    154              if child.nodeType == elementType:
    155                  if child.localName == "name":
    156                      self.name = getFirstData(child)
    157                  elif (child.localName == "objectType"):
    158                      self.objectType = getFirstData(child)
    159                  elif (child.localName == "paths"):
    160                      # Configure self with paths
    161                      for child2 in child.childNodes:
    162                          if child2.nodeType == elementType:
    163                              type = child2.getAttributeNS(None, 'type')
    164                              if child2.localName == "path":
    165                                  value = getFirstData(child2)
    166                                  self.paths[type] = value
    167                              elif child2.localName == "object":
    168                                  value = child2.getAttributeNS(None,'ref')
    169                                  pathObjects[type] = value
    170                  elif (child.localName == "imports"):
    171                      # Do this now so we can reference
    172                      for mod in child.childNodes:
    173                          if mod.nodeType == elementType and mod.localName == "module":
    174                              name, objects, withname = ('', [], None)
    175                              for n in mod.childNodes:
    176                                  if (n.nodeType == elementType):
    177                                      if (n.localName == 'name'):
    178                                          name = getFirstData(n)
    179                                      elif (n.localName == 'object'):
    180                                          objects.append(getFirstData(n))
    181                                      elif (n.localName == 'withName'):
    182                                          withname = getFirstData(n)
    183                              if (name):
    184                                  dynamic.globalImport(name, objects, withname)
    185                              else:
    186                                  raise(ConfigFileException('No name given for module to import in configFile for %s' % (self.id)))
    187
    188                  elif (child.localName == "subConfigs"):
    189                      # Pointers to dom nodes for config ids
    190                      self._recurseSubConfigs(session, child)
    191
    192                  elif (child.localName == "objects"):
    193                      for obj in child.childNodes:
    194                          if (obj.nodeType == elementType and obj.localName == "path"):
    195                              type = obj.getAttributeNS(None,'type')
    196                              id = obj.getAttributeNS(None,'ref')
    197                              self._objectRefs.append((id, type))
    198                  elif (child.localName == "options"):
    199                      # See configInfo in ZeeRex
    200                      for child2 in child.childNodes:
    201                          if (child2.nodeType == elementType):
    202                              type = child2.getAttributeNS(None,'type')
    203                              if (child2.localName == "setting"):
    204                                  dc = getFirstData(child2)
    205                                  if (dc):
    206                                      value = self._verifySetting(type, dc)
    207                                      self.settings[type] = value
    208                              elif (child2.localName == "default"):
    209                                  dc = getFirstData(child2)
    210                                  if (dc):
    211                                      value = self._verifyDefault(type, dc)
    212                                      self.defaults[type] = value
    213                  elif (child.localName == "actions"):
    214                      # permission rqmts
    215                      for child2 in child.childNodes:
    216                          if child2.nodeType == elementType:
    217                              p = PermissionHandler(child2, self)
    218                              self.permissionHandlers[p.actionIdentifier] = p
    219                  elif (child.localName == "docs"):
    220                      # Add per configuration documentation to docs stack.
    221                      self.docstring = getFirstData(child)
    222                  else:
    223                      self._handleConfigNode(session, child)
    224
    225          if (self.paths.has_key("pythonPath")):
    226              sys.path.append(self.paths['pythonPath'][1])
    227
    228          for p in self.permissionHandlers.keys():
    229              if p[0:5] == 'c3fn:':
    230                  self.auth_function(p[5:])
    231
    232          # Built, maybe set function logging
    233          log = self.get_setting(session, 'log')
    234          if (log):
    235              logList = log.strip().split()
    236              for l in logList:
    237                  self.log_function(l)
    238              del self.settings['log']
    239
    240          # Dynamically Instantiate objects. This is mindbending :}
    241          # Mindbending2: JIT building!
    242          if self.parent:
    243              self.parent.objects[self.id] = self
    244          for o in (self._objectRefs):
    245              # Instantiate
    246              obj = self.get_object(session, o[0])
    247
    248          # Add default Object types to paths
    249          for t in pathObjects.keys():
    250              self.unresolvedObjects[t] = pathObjects[t]
    251
    252          # Now check for configStore objects
    253          for csid in self._includeConfigStores:
    254              confStore = self.get_object(session, csid)
    255              if confStore != None:
    256                  for rec in confStore:
    257                      # do something with config
    258                      node = rec.get_dom()
    259                      node= node.childNodes[0]
    260                      nid = node.getAttributeNS(None, 'id')
    261                      self.subConfigs[nid] = node
    262                      ntype = node.getAttributeNS(None, 'type')
    263                      if ntype == 'index':
    264                          self.indexConfigs[nid] = node
    265                      elif ntype == 'protocolMap':
    266                          self.protocolMapConfigs[nid] = node
    267                      elif ntype == 'database':
    268                          self.databaseConfigs[nid] = node
    269                      elif ntype == '':
    270                          raise ConfigFileException("Object must have a type attribute: %s  -- in configStore %s" % (nid, csid))
    271
    272
    273 -    def get_setting(self, session, id, default=None):
    274          """Return the value for a setting on this object."""
    275          return self.settings.get(id, default)
    276
    277 -    def get_default(self, session, id, default=None):
    278          """Return the default value for an option on this object"""
    279          return self.defaults.get(id, default)
    280
    281 -    def get_object(self, session, id):
    282          """Return an object with the given id within this object's scope, or search upwards for it."""
    283          if (self.objects.has_key(id)):
    284              return self.objects[id]
    285          else:
    286              config = self.get_config(session, id)
    287              if config:
    288                  try:
    289                      obj = dynamic.makeObjectFromDom(session, config, self)
    290                  except ConfigFileException:
    291                      # Push back up
    292                      raise
    293                  return obj
    294              elif (self.parent <> None):
    295                  return self.parent.get_object(session, id)
    296              else:
    297                  raise ObjectDoesNotExistException(id)
    298
    299 -    def get_config(self, session, id):
    300          """Return a configuration for the given object."""
    301          if (self.subConfigs.has_key(id)):
    302              return self.subConfigs[id]
    303          #elif (self.parent <> None):
    304          #    return self.parent.get_config(session, id)
    305          else:
    306              return None
    307
    308 -    def get_path(self, session, id, default=None):
    309          """Return the named path"""
    310          if (self.paths.has_key(id)):
    311              path = self.paths[id]
    312              # Special handling for defaultPath :/
    313              if (id == "defaultPath" and not os.path.isabs(path)):
    314                  p1 = self.parent.get_path(session, id, default)
    315                  path = os.path.join(p1, path)
    316              return path
    317          elif (self.unresolvedObjects.has_key(id)):
    318              o = self.get_object(session, self.unresolvedObjects[id])
    319              self.paths[id] = o
    320              del self.unresolvedObjects[id]
    321              return o
    322          elif (self.parent <> None):
    323              return self.parent.get_path(session, id, default)
    324          else:
    325              return default
    326
    327 -    def log_function(self, name):
    328          """ Set a named function to log invocations."""
    329          if (name == "__all__"):
    330              names = dir(self)
    331          else:
    332              names = [name]
    333          for name in names:
    334              if (hasattr(self, name) and callable(getattr(self,name)) and name[0] <> '_'):
    335                  func = getattr(self, name)
    336                  setattr(self, "__postlog_%s" % (name), getattr(self, name))
    337                  code = """def mylogfn(self, *args, **kw):\n  if (hasattr(self,'__postlog_get_path')):\n    fn = self.__postlog_get_path\n  else:\n    fn = self.get_path\n  fl = fn(None, 'functionLogger');\n  if (fl):\n    fl.log(self, '%s', *args, **kw);\n  return self.__postlog_%s(*args, **kw);""" % (name, name)
    338                  exec code
    339                  setattr(self, name, MethodType(locals()['mylogfn'], self, self.__class__))
    340
    341 -    def unlog_function(self, name):
    342          """Remove the logging from a named function."""
    343          if (name == "__all__"):
    344              names = dir(self)
    345          else:
    346              names = [name]
    347          for name in names:
    348              if (hasattr(self, name) and callable(getattr(self,name)) and name[0] <> '_' and hasattr(self, '__postlog_%s' % name)):
    349                  setattr(self, name, getattr(self, '__postlog_%s' % name))
    350                  delattr(self, '__postlog_%s' % name)
    351
    352 -    def auth_function(self, name):
    353          """Add an authorisation layer on top of a named function."""
    354          if (hasattr(self, name) and callable(getattr(self,name)) and name[0] <> '_'):
    355              func = getattr(self, name)
    356              setattr(self, "__postauth_%s" % (name), func)
    357              code = """
    358  def myauthfn(self, session, *args, **kw):
    359      p = self.permissionHandlers['c3fn:%s']
    360      if (p):
    361          if not session or not session.user:
    362              raise PermissionException('Authenticated user required to call %s')
    363          if not p.hasPermission(session, session,user):
    364              raise PermissionException('Permission required to call %s')
    365      return self.__postauth_%s(*args, **kw);
    366  """ % (name, name, name, name)
    367              exec code
    368              setattr(self, name, MethodType(locals()['myauthfn'], self, self.__class__))
    369
    370
    371 -    def unauth_function(self, name):
    372          """Remove the authorisation requirement from the named function."""
    373          if (name == "__all__"):
    374              names = dir(self)
    375          else:
    376              names = [name]
    377          for name in names:
    378              if (hasattr(self, name) and callable(getattr(self,name)) and name[0] <> '_' and hasattr(self, '__postauth_%s' % name)):
    379                  setattr(self, name, getattr(self, '__postauth_%s' % name))
    380                  delattr(self, '__postauth_%s' % name)

381