commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r7622 - in trunk/gnue-common/src/datasources/drivers: . other


From: reinhard
Subject: [gnue] r7622 - in trunk/gnue-common/src/datasources/drivers: . other
Date: Mon, 20 Jun 2005 04:56:55 -0500 (CDT)

Author: reinhard
Date: 2005-06-20 04:56:54 -0500 (Mon, 20 Jun 2005)
New Revision: 7622

Added:
   trunk/gnue-common/src/datasources/drivers/other/
   trunk/gnue-common/src/datasources/drivers/other/appserver.py
Removed:
   trunk/gnue-common/src/datasources/drivers/appserver/
Log:
Moved appserver dbdriver into a single file, too.


Copied: trunk/gnue-common/src/datasources/drivers/other/appserver.py (from rev 
7619, trunk/gnue-common/src/datasources/drivers/appserver/appserver/__init__.py)
===================================================================
--- trunk/gnue-common/src/datasources/drivers/appserver/appserver/__init__.py   
2005-06-20 09:40:30 UTC (rev 7619)
+++ trunk/gnue-common/src/datasources/drivers/other/appserver.py        
2005-06-20 09:56:54 UTC (rev 7622)
@@ -0,0 +1,518 @@
+# GNU Enterprise Datasource Library - Driver for GNUe-AppServer
+#
+# Copyright 2000-2005 Free Software Foundation
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+"""
+Database driver plugin for GNU Enterprise Application Server backends.
+"""
+
+import sys
+
+from gnue.common.apps import errors, i18n
+from gnue.common.datasources import Exceptions, GSchema
+from gnue.common.datasources.drivers import Base
+from gnue.common.rpc import client
+
+
+# =============================================================================
+# Driver info
+# =============================================================================
+
+class DriverInfo:
+
+  name = "GNU Enterprise Application Server"
+
+  url = "http://www.gnuenterprise.org/tools/appserver/";
+
+  description = """
+GNUe AppServer is GNUe's middleware for database access.
+"""
+  isfree = True
+
+  doc = """
+Description
+-----------
+Python driver GNUe Application Server.
+
+Support
+-------
+POSIX Support: YES
+
+Win32 Support: YES
+
+Platforms Tested:
+
+  - Linux/Unix (Debian, RedHat, SuSe, etc)
+  - Windows NT/XP/2000
+
+Connection Properties
+---------------------
+* host       -- This is the hostname/ip address of the host running AppServer 
(required)
+* port       -- The port that AppServer is running on (required)
+* timeout    -- Command timeout in seconds (optional)
+* transport  -- Transport used for network connections (http, https) (required)
+* rpctype    -- RPC driver used for network communication (xmlrpc, soap, etc.)
+  See GNUe Common's RPC documentation for a list of all RPC types. (required)
+
+Examples
+--------
+  [appserver]
+  comment = Connection to the GNUe Application Server
+  provider = appserver
+  rpctype = xmlrpc
+  host = localhost
+  port = 8765
+  transport = http
+
+Notes
+-----
+1. GNUe AppServer works natively in utf-8, so encoding= is not a valid 
property.
+
+2. This driver is fully functional with no known serious problems.
+"""
+
+
+# =============================================================================
+# Schema handling for GNUe-AppServer
+# =============================================================================
+
+class Behavior (Base.Behavior):
+  """
+  Limitations:
+    - Appserver cannot reproduce indices
+  """
+
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, connection):
+
+    Base.Behavior.__init__ (self, connection)
+
+    _RELTYPE = {'type': 'object', 'name': u_('Business Object Class')}
+
+
+  # ---------------------------------------------------------------------------
+  # Read the connection's schema
+  # ---------------------------------------------------------------------------
+
+  def _readSchema_ (self, parent):
+    """
+    Read the connection's schema and build a GSchema object tree connected to
+    the given parent object (which is of type GSSchema).
+    """
+
+    tables = self.__readTables (parent)
+    self.__readFields (tables)
+    self.__addConstraints (tables)
+
+    # We read calculated fields after building the constraints, because this
+    # way a field having a reference type does not introduce a non-existing
+    # constraint.
+    self.__readCalculatedFields (tables)
+
+
+  # ---------------------------------------------------------------------------
+  # Read all classes
+  # ---------------------------------------------------------------------------
+
+  def __readTables (self, parent):
+
+    sm  = self.__connection._sm
+    sid = self.__connection._sess_id
+    lid = sm.request (sid, u"gnue_class", [], [u"gnue_module.gnue_name",
+                  u"gnue_name"], [u"gnue_module.gnue_name", u"gnue_name"])
+
+    result = {}
+    for (gid, module, name) in sm.fetch (sid, lid, 0, sm.count (sid, lid)):
+      fullname = "%s_%s" % (module, name)
+      master = parent.findChildOfType ('GSTables') or \
+                                     GSchema.GSTables (parent, **self._RELTYPE)
+      result [gid] = GSchema.GSTable (master, name = fullname, id = gid)
+
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Read all properties
+  # ---------------------------------------------------------------------------
+
+  def __readFields (self, tables):
+    
+    sm  = self.__connection._sm
+    sid = self.__connection._sess_id
+
+    sort  = [u"gnue_module", u"gnue_name"]
+    props = [u"gnue_module.gnue_name", u"gnue_class", u"gnue_name",
+             u"gnue_length", u"gnue_nullable", u"gnue_scale", u"gnue_type"]
+    lid = sm.request (sid, u"gnue_property", [], sort, props)
+
+    result = {}
+    for record in sm.fetch (sid, lid, 0, sm.count (sid, lid)):
+      (gid, module, cid, name, length, nullable, scale, ftype) = record
+
+      result [gid] = self.__createField (tables, gid, module, cid, name,
+                                         length, nullable, scale, ftype)
+
+
+  # ---------------------------------------------------------------------------
+  # Add all kind of constraints
+  # ---------------------------------------------------------------------------
+
+  def __addConstraints (self, tables):
+
+    for (gid, table) in tables.items ():
+      # Add the primary key constraint, as it is 'well known'
+      pk = GSchema.GSPrimaryKey (table, name = u"pk_%s" % table.name)
+      GSchema.GSPKField (pk, name = u"gnue_id")
+
+      # Iterate over all fields and create a foreign key constraint for
+      # reference type properties
+      for field in table.findChildrenOfType ('GSField', False, True):
+        if '_' in field.nativetype:
+          master = table.findChildOfType ('GSConstraints') or \
+                                                  GSchema.GSConstraints (table)
+          constraint = GSchema.GSForeignKey (master,
+              name = "fk_%s_%s" % (table.name, field.nativetype),
+              references = field.nativetype)
+
+          GSchema.GSFKField (constraint, name = field.name,
+                                         references = u"gnue_id")
+
+
+  # ---------------------------------------------------------------------------
+  # Read all calculated fields
+  # ---------------------------------------------------------------------------
+
+  def __readCalculatedFields (self, tables):
+    
+    sm  = self.__connection._sm
+    sid = self.__connection._sess_id
+
+    sort  = [u"gnue_module", u"gnue_class", u"gnue_name"]
+    props = [u"gnue_module.gnue_name", u"gnue_class", u"gnue_name",
+             u"gnue_length", u"gnue_nullable", u"gnue_scale", u"gnue_type"]
+    cond  = ['and', ['like',    ['field', u'gnue_name'], ['const', u'get%']],
+                    ['notnull', ['field', u'gnue_type']]]
+    lid = sm.request (sid, u"gnue_procedure", cond, sort, props)
+
+    result = {}
+    for record in sm.fetch (sid, lid, 0, sm.count (sid, lid)):
+      (gid, module, cid, name, length, nullable, scale, ftype) = record
+
+      result [gid] = self.__createField (tables, gid, module, cid, name [3:],
+                                         length, nullable, scale, ftype)
+
+
+  # ---------------------------------------------------------------------------
+  # Create a new GSField instance from the given arguments
+  # ---------------------------------------------------------------------------
+
+  def __createField (self, tables, gid, module, cid, name, length, nullable,
+                     scale, ftype):
+
+    table  = tables [cid]
+    master = table.findChildOfType ('GSFields') or GSchema.GSFields (table)
+
+    if '_' in ftype or ftype == 'id':
+      dtype  = 'string'
+      length = 32
+    else:
+      dtype = ftype
+
+    attrs = {'id'        : gid,
+             'name'      : "%s_%s" % (module, name),
+             'type'      : dtype,
+             'nativetype': ftype,
+             'nullable'  : nullable}
+    if length:
+      attrs ['length'] = length
+    if scale:
+      attrs ['precision'] = scale
+
+    return GSchema.GSField (master, **attrs)
+
+
+# =============================================================================
+# ResultSet class
+# =============================================================================
+
+class ResultSet (Base.ResultSet):
+  """
+  Handles a resultset (i.e. a list) in the GNUe-AppServer backend.
+  """
+
+  # ---------------------------------------------------------------------------
+  # Implementation of virtual methods
+  # ---------------------------------------------------------------------------
+
+  def _query_object_ (self, connection, table, fieldnames, condition, 
sortorder,
+                     distinct):
+    self.__sm = connection._sm
+    self.__session_id = connection._sess_id
+    self.__list_id = self.__sm.request (self.__session_id, table,
+                                        condition.prefixNotation (), sortorder,
+                                        fieldnames)
+    self.__fieldnames = fieldnames
+    self.__distinct   = distinct        # currently not honored
+
+  # ---------------------------------------------------------------------------
+
+  def _count_ (self):
+    return self.__sm.count (self.__session_id, self.__list_id)
+
+  # ---------------------------------------------------------------------------
+
+  def _fetch_ (self, cachesize):
+    position = 0
+    while True:
+      rows = self.__sm.fetch (self.__session_id, self.__list_id, position,
+                              cachesize)
+      for row in rows:
+        # row [0] is the gnue_id that wasn't requested
+        yield dict (zip (self.__fieldnames, row[1:]))
+      # if fetch returned less rows than we requested, we're at the end of data
+      if len (rows) < cachesize:
+        break
+      position += len (rows)
+
+
+# =============================================================================
+# GNUe-AppServer Connection class
+# =============================================================================
+
+class Connection (Base.Connection):
+  """
+  Connection class for GNUe-AppServer backends.
+  """
+
+  _resultSetClass   = ResultSet
+  _primarykeyFields = [u'gnue_id']
+  _behavior         = Behavior
+
+
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, connections, name, parameters):
+
+    Base.Connection.__init__ (self, connections, name, parameters)
+    self.__filters = None
+    self.__server  = None
+    self._sm       = None
+
+
+  # ---------------------------------------------------------------------------
+  # Create/return a connection to the appserver
+  # ---------------------------------------------------------------------------
+
+  def __getSessionManager (self):
+
+    if self.__server is None:
+      params = {'host'     : self.parameters.get ('host'),
+                'port'     : self.parameters.get ('port'),
+                'transport': self.parameters.get ('transport')}
+      rpcType = self.parameters.get ('rpctype')
+      self.__server = client.attach (rpcType, params)
+
+      if self.parameters.has_key ('timeout'):
+        self.__server.setTimeout (float (self.parameters ['timeout']))
+
+    if self._sm is None:
+      self._sm = self.__server.request ('Session')
+
+    return self._sm
+
+
+  # ---------------------------------------------------------------------------
+  # Update the given filter values
+  # ---------------------------------------------------------------------------
+
+  def __updateFilters (self, connectData):
+
+    if connectData.get ('_username') == 'foobar':
+      raise Exceptions.LoginError, "What a silly username ..."
+
+    for item in self.__filters:
+      (filterId, filterLabel) = item [0]
+
+      if connectData.has_key (filterId):
+        value = connectData [filterId]
+        (label, search, field) = item [1][0]
+
+        # if there are no filter values we've to skip replacement. Maybe the
+        # user just wants to add new filter values
+        if not len (item [3].keys ()):
+          continue
+
+        if item [2] is None:
+          masterkey = None
+        else:
+          masterkey = connectData [item [2]]
+
+        found = False
+        vDict = item [3][masterkey]
+        for record in vDict:
+          # The supplied value of a filter might could be the description or
+          # the gnue_id.
+          if record [field] == value or record ['gnue_id'] == value:
+            connectData [filterId] = record [u'gnue_id']
+            found = True
+            break
+
+        if not found:
+          raise Exceptions.LoginError, \
+              u_("'%(value)s' is not a valid filter-value for '%(filter)s'") \
+              % {'value': value,
+                 'filter': label}
+
+
+  # ---------------------------------------------------------------------------
+  # Implementations of virtual methods
+  # ---------------------------------------------------------------------------
+
+  def _getLoginFields (self):
+    result = []
+
+    dbauth = self.parameters.get ('authentication', 'False')
+    if dbauth.lower () in ['true', 'yes', 'y']:
+      result.extend ([(_('User Name'), '_username', 'string', None, None, []),
+                      (_('Password'), '_password', 'password', None, None, 
[])])
+
+    self.__getSessionManager ()
+    self.__filters = self._sm.getFilters (i18n.getuserlocale ())
+
+    for item in self.__filters:
+      (filterId, filterLabel) = item [0]
+      (master, allowed)  = item [2:4]
+
+      elements = []
+      cdefault = self.parameters.get (filterId)
+      default  = None
+
+      for (label, search, field) in item [1]:
+        data = {}
+        if master is not None:
+          for (mkey, values) in allowed.items ():
+            add = data.setdefault (mkey, {})
+            for vdict in values:
+              if vdict [field] == cdefault:
+                default = vdict ['gnue_id']
+              add [vdict ['gnue_id']] = vdict [field]
+
+        else:
+          for values in allowed.values ():
+            for vdict in values:
+              if vdict [field] == cdefault:
+                default = vdict ['gnue_id']
+              data [vdict ['gnue_id']] = vdict [field]
+
+        elements.append ((label, data))
+
+      # Make sure to have the proper default values (keys) set
+      if default is None and filterId in self.parameters:
+        del self.parameters [filterId]
+      elif default:
+        self.parameters [filterId] = default
+
+      fielddef = [filterLabel, filterId, 'dropdown', default, master, elements]
+      result.append (fielddef)
+
+    return result
+
+  # ---------------------------------------------------------------------------
+
+  def _connect (self, connectData):
+    self.__getSessionManager ()
+    self.__updateFilters (connectData)
+    try:
+      self._sess_id = self._sm.open (connectData)
+    except errors.RemoteError, e:
+      if e.getName () == 'AuthError':
+        raise Exceptions.LoginError, e.getMessage ()
+      else:
+        raise
+
+  # ---------------------------------------------------------------------------
+
+  def _initialize (self, table, fields):
+    id = self._sm.store (self._sess_id, table, [None], [], [[]]) [0]
+    return self.requery (table, {u'gnue_id': id}, fields)
+
+  # ---------------------------------------------------------------------------
+
+  def _insert (self, table, newfields, recno):
+    f = newfields.copy ()
+    id = f.pop (u'gnue_id')
+    self._sm.store (self._sess_id, table, [id], f.keys (), [f.values ()])
+
+  # ---------------------------------------------------------------------------
+
+  def _update (self, table, oldfields, newfields, recno):
+    f = newfields
+    id = oldfields [u'gnue_id']
+    self._sm.store (self._sess_id, table, [id], f.keys (), [f.values ()])
+
+  # ---------------------------------------------------------------------------
+
+  def _delete (self, table, oldfields, recno):
+    id = oldfields [u'gnue_id']
+    self._sm.delete (self._sess_id, table, [id])
+
+  # ---------------------------------------------------------------------------
+
+  def _requery (self, table, oldfields, fields):
+    id = oldfields [u'gnue_id']
+    rows = self._sm.load (self._sess_id, table, [id], fields)
+    if len (rows):
+      row = rows [0]
+      result = {}
+      for i in range (len (fields)):
+        result [fields [i]] = row [i]
+      return result
+    else:
+      return None
+
+  # ---------------------------------------------------------------------------
+
+  def _call (self, table, oldfields, methodname, parameters):
+    id = oldfields [u'gnue_id']
+    return self._sm.call (self._sess_id, table, [id], methodname,
+                          parameters) [0]
+
+  # ---------------------------------------------------------------------------
+
+  def _commit (self):
+    self._sm.commit (self._sess_id)
+
+  # ---------------------------------------------------------------------------
+
+  def _rollback (self):
+    self._sm.rollback (self._sess_id)
+
+  # ---------------------------------------------------------------------------
+
+  def _close (self):
+    if self._sm is not None:
+      self._sm.close (self._sess_id, False)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]