[Top][All Lists]
[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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7622 - in trunk/gnue-common/src/datasources/drivers: . other,
reinhard <=