[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r7517 - in trunk/gnue-common: src/datasources src/datasources/dri
From: |
johannes |
Subject: |
[gnue] r7517 - in trunk/gnue-common: src/datasources src/datasources/drivers/Base src/datasources/drivers/DBSIG2 src/datasources/drivers/appserver/appserver src/datasources/drivers/interbase/Schema/Creation src/datasources/drivers/sapdb/Schema/Creation unittest |
Date: |
Wed, 4 May 2005 07:55:49 -0500 (CDT) |
Author: johannes
Date: 2005-05-04 07:55:46 -0500 (Wed, 04 May 2005)
New Revision: 7517
Modified:
trunk/gnue-common/src/datasources/GConnections.py
trunk/gnue-common/src/datasources/GLoginHandler.py
trunk/gnue-common/src/datasources/drivers/Base/Connection.py
trunk/gnue-common/src/datasources/drivers/DBSIG2/Connection.py
trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Creation/Creation.py
trunk/gnue-common/src/datasources/drivers/sapdb/Schema/Creation/Creation.py
trunk/gnue-common/unittest/datasource.py
Log:
Improved concept of GLoginHandler to support better login dialogs
Modified: trunk/gnue-common/src/datasources/GConnections.py
===================================================================
--- trunk/gnue-common/src/datasources/GConnections.py 2005-05-04 07:11:00 UTC
(rev 7516)
+++ trunk/gnue-common/src/datasources/GConnections.py 2005-05-04 12:55:46 UTC
(rev 7517)
@@ -1,6 +1,9 @@
+# GNU Enterprise Common Library - Connection Manager
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-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
@@ -16,26 +19,16 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2005 Free Software Foundation
-#
-# FILE:
-# GConnections.py
-#
-# DESCRIPTION:
+# $Id$
"""
Class that loads connection definition files and maintains
database connections.
"""
-#
+
# NOTES:
#
-# If you pass GConnections an "eventHandler" instance,
-# it will generate a Connections:Connect(name, base)
-# when a new connection is created.
-#
-# HISTORY:
-#
-# $Id$
+# If you pass GConnections an "eventHandler" instance, it will generate a
+# Connections:Connect(name, base) when a new connection is created.
from ConfigParser import *
from ConfigParser import RawConfigParser # is not in __all__
@@ -90,8 +83,6 @@
self._authenticatedUsers = {}
self._eventHandler=eventhandler
- gDebug (2, 'Conn File: "%s"' % location)
-
if len(location):
fileHandle = openResource(location)
@@ -342,80 +333,92 @@
checkFields = connection.getLoginFields ()
authenticator = None
- haveAllInformation = True
- for rf, dummy1, dummy2 in checkFields:
- if not (loginData.has_key (rf) and loginData [rf] is not None):
- haveAllInformation = 0
+ haveAllInformation = True
+ needFieldConversion = False
+
+ for item in checkFields:
+ if len (item) == 3:
+ needFieldConversion = True
+ fieldname = item [0]
+ elif len (item) == 6:
+ fieldname = item [1]
+ else:
+ raise InvalidLoginFieldsError, checkFields
+
+ if not (fieldname in loginData and loginData [fieldname] is not None):
+ haveAllInformation = False
break
if haveAllInformation:
-# try:
-# self._authenticatedUsers[base] = loginData['_username']
-# except KeyError:
-# self._authenticatedUsers[base] = None
-
if authenticator:
connection.connect (authenticator.login (loginData))
else:
connection.connect (loginData)
else:
+ if needFieldConversion:
+ fields = []
+ for (name, label, password) in checkFields:
+ fields.append ((label, name, password and 'password' or 'string',
+ None, None, []))
+
+ checkFields = fields
+ needFieldConversion = False
+
+ descr = self.getConnectionParameter (connection_base, 'comment', '')
+ text = u_('Login required for %(newline)s"%(description)s"') \
+ % {'newline': len (descr) and '\n' or '',
+ 'description': descr or connection_base}
+
+ title = u_("GNU Enterprise: Login to %s") % connection_base
+ header = [(text, None, 'label', None, None, []),
+ ('', None, 'label', None, None, [])]
+
attempts = 4
gDebug (7, 'Getting new data connection to %s' % connection_name)
errortext = None
+
while attempts:
-
try:
+ fields = header + checkFields
# Ask the UI to prompt for our login data
- loginData.update(self._loginHandler.getLogin(
- [connection_base,
- self.getConnectionParameter(connection_base,'comment',''),
- checkFields], errortext))
+ result = self._loginHandler.askLogin (title, fields, loginData,
+ errortext)
+ loginData.update (result)
# Ask the data object to connect to the database
if authenticator:
- connection.connect(authenticator.login(loginData))
+ connection.connect (authenticator.login (loginData))
else:
- connection.connect(loginData)
+ connection.connect (loginData)
# We're done!
attempts = 0
- self._loginHandler.destroyLoginDialog()
except Exceptions.LoginError:
- # Oops, they must have entered an invalid user/password.
- # Those silly users.
- # user: Hey! Who are you calling silly?!!!
- # Ok, then "those address@hidden users"
- attempts = attempts - 1
- errortext = errors.getException () [2]
- self._loginHandler.destroyLoginDialog ()
+ attempts -= 1
+ errortext = errors.getException () [2]
if not attempts:
# Four times is plenty...
- tmsg = u_("Unable to log in after 4 attempts.\n\nError: %s") \
- % errortext
- raise Exceptions.LoginError, tmsg
+ raise Exceptions.LoginError, \
+ u_("Unable to log in after 4 attempts.\n\nError: %s") \
+ % errortext
- except GLoginHandler.UserCanceledLogin:
- # Guess they changed their minds. Treat as a login error.
- self._loginHandler.destroyLoginDialog()
- tmsg = u_("User canceled the login request.")
- raise Exceptions.LoginError, tmsg
-
# Add to authenticated user list
try:
- self._authenticatedUsers[connection] = loginData['_username']
+ self._authenticatedUsers [connection] = loginData ['_username']
+
except KeyError:
- self._authenticatedUsers[connection] = None
+ self._authenticatedUsers [connection] = None
if self._eventHandler:
- self._eventHandler.dispatchEvent('Connections:Connect',
- name=connection_name, base=connection_base)
+ self._eventHandler.dispatchEvent ('Connections:Connect',
+ name = connection_name, base = connection_base)
# Done
connection.__connected = True
Modified: trunk/gnue-common/src/datasources/GLoginHandler.py
===================================================================
--- trunk/gnue-common/src/datasources/GLoginHandler.py 2005-05-04 07:11:00 UTC
(rev 7516)
+++ trunk/gnue-common/src/datasources/GLoginHandler.py 2005-05-04 12:55:46 UTC
(rev 7517)
@@ -1,14 +1,17 @@
+# GNU Enterprise Common Library - Connections - Base Login Handler
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-2005 Free Software Foundation
#
-# 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
+# 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
+# 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
@@ -16,79 +19,247 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2005 Free Software Foundation
-#
-# FILE:
-# GConnections.py
-#
-# DESCRIPTION:
-# Class that handles prompting user for login information
-# (design to be subclassed by the UI portion).
-#
-# NOTES:
-#
+# $Id$
+import getpass
-#
-# If user stops the login process (cancel button?), raise this exception
-#
-class UserCanceledLogin(Exception):
- pass
+from gnue.common.apps import errors
+# =============================================================================
+# Exceptions
+# =============================================================================
+class UserCanceledLogin (errors.UserError):
+ def __init__ (self):
+ msg = u_("User canceled the login request.")
+ errors.UserError.__init__ (self, msg)
+
+
+
+# =============================================================================
+# Base class for all login handler
+# =============================================================================
+
class LoginHandler:
# The client app can set any default values for the needed parameters.
defaults = {}
- #
- # getLogin is passed an list consisting of:
- # Connection Name
- # Connection Comments/Description
- # List of Fields to Input:
- # Attribute Name, Label/Description, Is Password?
- #
- # It should return a dictionary of {Attribute Name: Inputted Value}
- #
- def getLogin(self, requiredFields, errortext=None):
+ # ---------------------------------------------------------------------------
+ # Get login information (depreciated)
+ # ---------------------------------------------------------------------------
+
+ def getLogin (self, requiredFields, errortext = None):
+ """
+ DEPRECIATED: get information for the given fields and return a dictionary
+
+ @param requiredFields: sequence of [connection name, description, sequence
+ of fields (name, label, is password)]
+ @param errortext: message of the last error occured
+
+ @raises UserCanceledLogin: if the user canceled the login request
+ """
pass
+ # ---------------------------------------------------------------------------
# Called when the app no longer needs the login handler
- def destroyLoginDialog(self):
+ # ---------------------------------------------------------------------------
+
+ def destroyLoginDialog (self):
pass
-#
-# This is a basic solution to getting a login
-#
-try:
- import getpass
-except:
- getpass = None
+ # ---------------------------------------------------------------------------
+ # Ask for all fields given by the field definitions
+ # ---------------------------------------------------------------------------
-class BasicLoginHandler(LoginHandler):
+ def askLogin (self, title, fielddefs, defaultData, lastError = None):
+ """
+ Ask for login information as specified by the given field definitions using
+ the given default data.
- defaults = {'_username': None, '_password': None}
+ @param title: title for the login dialog
+ @param fielddefs: sequence of field definitions for InputDialogs
+ @param defaultData: dictionary with default values
+ @param lastError: last error message or None
- def getLogin(self, loginData, error):
+ @raises UserCanceledLogin: if the user canceled the login request
+
+ @return: dictionary of all keys/values the user has entered.
+ """
+
+ fields = []
+ for (label, name, ftype, default, master, elements) in fielddefs:
+ default = defaultData.get (name, default)
+ fields.append ((label, name, ftype, default, master, elements))
+
+ if lastError:
+ errorField = (lastError, None, 'warning', None, None, [])
+ added = False
+ for (ix, field) in enumerate (fields):
+ if not field [2] in ['label', 'warning', 'image']:
+ fields.insert (ix, errorField)
+ added = True
+ break
+
+ if not added:
+ fields.append (errorField)
+
+ result = self._askLogin (title, fields)
+ if result is None:
+ raise UserCanceledLogin
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Do the dirty work for askLogin
+ # ---------------------------------------------------------------------------
+
+ def _askLogin (self, title, fields):
+ """
+ Descendants override this method to do all the dirty work for askLogin ().
+ This class converts the given field definition sequence into an old style
+ format as required by getLogin () and finally calls getLogin. This process
+ will fade out as soon as getLogin is obsolete.
+ """
+
+ # flatten the blown-up sequence till all support the new style definitions
+ data = []
+ labels = []
+ error = None
+
+ for (label, name, ftype, default, master, elements) in fields:
+ if ftype in ['image']:
+ continue
+
+ elif ftype == 'label':
+ labels.append (label)
+
+ elif ftype == 'warning':
+ error = label
+
+ else:
+ data.append ((name, label, ftype == 'password'))
+
try:
- print "*"*60
- if len(loginData[1]):
- print 'Attempting to log into "%s" (%s):' % (loginData[1],
loginData[0])
- else:
- print 'Attempting to log into %s:' % (loginData[0])
+ name = len (labels) and labels [0] or ''
+ desc = len (labels) > 1 and labels [1] or ''
+ return self.getLogin ([name, desc, data], error)
+
+ finally:
+ self.destroyLoginDialog ()
+
+
+# =============================================================================
+# Class implementing a basic login handler using raw_input and getpass
+# =============================================================================
+
+class BasicLoginHandler (LoginHandler):
+ """
+ Class implementing a basic login handler using raw_input () and getpass ()
+ as input methods.
+ """
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, useDefaults = False, silent = False):
+ """
+ @param useDefaults: if True, does not ask for a field if it has a default
+ other than None, but uses that default directly
+ @param silent: if True, no output occurs and it implicitly sets useDefaults
+ to True.
+ """
+
+ self.__silent = silent
+ self.__useDefaults = silent and True or useDefaults
+
+
+ # ---------------------------------------------------------------------------
+ # Ask for all fields requestd
+ # ---------------------------------------------------------------------------
+
+ def _askLogin (self, title, fields):
+
+ result = {}
+
+ if not self.__silent:
+ print "*" * 60
+ print title
print
- val = {}
- for prompt in loginData[2]:
- if not (self.defaults.has_key(prompt[0]) and
self.defaults.get(prompt[0],None)):
- if prompt[2] and getpass:
- val[prompt[0]] = getpass.getpass(" %s: " % prompt[1])
+
+ try:
+ for (label, name, ftype, default, master, elements) in fields:
+ if ftype in ['label', 'warning']:
+ if not self.__silent:
+ print " %s" % label
+
+ elif ftype in ['string', 'password']:
+ if self.__useDefaults and default is not None:
+ result [name] = default
else:
- val[prompt[0]] = raw_input(" %s: " % prompt[1])
- print
- print "*"*60
- return val
+ if ftype == 'password':
+ value = getpass.getpass (" %s: " % label)
+ else:
+ # raw_input print's it's argument to stderr, so we have to print
+ # the label manually here since stderr might be redirected
+ print " %s:" % label,
+ value = raw_input ()
+
+ result [name] = [value, default][value is None]
+
+ elif ftype in ['dropdown']:
+ # TODO: sort all fields according to master-detail dependencies and
+ # then validate the input values using the 'allowedValues' dicts
+ if self.__useDefaults and default is not None:
+ result [name] = default
+ else:
+ print " %s:" % label,
+ result [name] = raw_input ()
+
except KeyboardInterrupt:
raise UserCanceledLogin
+
+ return result
+
+
+# =============================================================================
+# Class implementing a 'silent' login handler
+# =============================================================================
+
+class SilentLoginHandler (LoginHandler):
+
+ # ---------------------------------------------------------------------------
+ # Create a new instance
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, **keywords):
+ """
+ Provides all given keywords as login data.
+ @param keywords: all keys and values given by this dictionary are available
+ as 'login data' and will be returned if requested by askLogin ()
+ """
+
+ self.__loginData = keywords
+
+
+ # ---------------------------------------------------------------------------
+ # Ask for the given fields
+ # ---------------------------------------------------------------------------
+
+ def _askLogin (self, title, fields):
+
+ result = {}
+ for (label, name, ftype, default, master, elements) in fields:
+ if not ftype in ['label', 'warning', 'image']:
+ value = self.__loginData.get (name, default)
+ if value is None:
+ value = default
+
+ result [name] = value
+
+ return result
Modified: trunk/gnue-common/src/datasources/drivers/Base/Connection.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/Base/Connection.py
2005-05-04 07:11:00 UTC (rev 7516)
+++ trunk/gnue-common/src/datasources/drivers/Base/Connection.py
2005-05-04 12:55:46 UTC (rev 7517)
@@ -83,14 +83,21 @@
Return information about the necessary login parameters for the L{connect}
method.
- The return value is a list of tuples in the form (fieldname, label, hide).
- The first element of the tuple is the field name passed as a dictionary key
- to the connect method later. The second element is a label to display to
- the user. If the third element is True, the input for this field should be
- hidden on the screen.
+ The return value is a list of tuples in the form (label, fieldname,
+ fieldtype, defaultvalue, masterfield, [(label, value-dict), ...]).
+ The first element of the tuple is the label to display to the user. The
+ second element of the tuple is the field name passed as a dictionary key to
+ the connect method later. The third element is the fieldtype (label,
+ string, password, dropdown, image) and 'defaultvalue' gives a default value
+ for the field. The 'masterfield' and element-sequence are used for
+ dropdowns, where 'masterfield' specifies a fielddefinition (a tuple like
+ this one) defining a master value. The element-sequence holds a list of
+ tuples (label, value-dictionary) describing the allowed values (per
+ master-field if any).
- A typical return value would be [("username", "User name:", False),
- ("password", "Password:", True)].
+ A typical return value would be:
+ [(_('User Name'), '_username', 'string', None, None, []),
+ (_('Password'), '_password', 'password', None, None, [])]
"""
gEnter (8)
Modified: trunk/gnue-common/src/datasources/drivers/DBSIG2/Connection.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/DBSIG2/Connection.py
2005-05-04 07:11:00 UTC (rev 7516)
+++ trunk/gnue-common/src/datasources/drivers/DBSIG2/Connection.py
2005-05-04 12:55:46 UTC (rev 7517)
@@ -406,7 +406,8 @@
# ---------------------------------------------------------------------------
def _getLoginFields (self):
- return [('_username', _('User Name'), 0), ('_password', _('Password'), 1)]
+ return [(_('User Name'), '_username', 'string', None, None, []),
+ (_('Password'), '_password', 'password', None, None, [])]
# ---------------------------------------------------------------------------
Modified:
trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
2005-05-04 07:11:00 UTC (rev 7516)
+++ trunk/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
2005-05-04 12:55:46 UTC (rev 7517)
@@ -87,6 +87,9 @@
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]
@@ -107,7 +110,9 @@
found = False
vDict = item [3][masterkey]
for record in vDict:
- if record [field] == value:
+ # 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
@@ -128,18 +133,48 @@
dbauth = self.parameters.get ('authentication', 'False')
if dbauth.lower () in ['true', 'yes', 'y']:
- result.extend ([['_username', _('User Name'), 0],
- ['_password', _('Password'), 1]])
+ 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]:
- result.append ([filterId, filterLabel + ':', False])
- break
+ 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
# ---------------------------------------------------------------------------
Modified:
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Creation/Creation.py
===================================================================
---
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Creation/Creation.py
2005-05-04 07:11:00 UTC (rev 7516)
+++
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Creation/Creation.py
2005-05-04 12:55:46 UTC (rev 7517)
@@ -52,10 +52,17 @@
host = self.connection.parameters.get ('host', None)
gsecbin = self.connection.parameters.get ('gsecbin', 'gsec')
- res = {'_password': ''}
+ loginHandler = BasicLoginHandler ()
+ fields = [(u_("Password"), '_password', 'password', None, None, [])]
+ title = u_("Logon for SYSDBA into Security Database")
+
+ error = None
+ res = {'_password': ''}
while not res ['_password']:
- res = BasicLoginHandler ().getLogin (['as SYSDBA', 'Security Database',
- [['_password', 'Password', True]]], '')
+ res = loginHandler.askLogin (title, fields, {}, error)
+ if not res ['_password']:
+ error = u_("Please specify a password")
+
syspw = res ['_password']
if host:
Modified:
trunk/gnue-common/src/datasources/drivers/sapdb/Schema/Creation/Creation.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/sapdb/Schema/Creation/Creation.py
2005-05-04 07:11:00 UTC (rev 7516)
+++ trunk/gnue-common/src/datasources/drivers/sapdb/Schema/Creation/Creation.py
2005-05-04 12:55:46 UTC (rev 7517)
@@ -59,9 +59,10 @@
username = self.connection.parameters.get ('username', 'gnue')
password = self.connection.parameters.get ('password', 'gnue')
- res = BasicLoginHandler ().getLogin (['OS User', host, \
- [['_username', u_('User Name'), False],
- ['_password', u_('Password'), True]]], '')
+ title = u_("OS User for host %s") % host
+ fields = [(u_("User Name"), '_username', 'string', None, None, []),
+ (u_("Password"), '_password', 'password', None, None, [])]
+ res = BasicLoginHandler ().askLogin (title, fields, {})
try:
session = sapdb.dbm.DBM (host, '', '',
Modified: trunk/gnue-common/unittest/datasource.py
===================================================================
--- trunk/gnue-common/unittest/datasource.py 2005-05-04 07:11:00 UTC (rev
7516)
+++ trunk/gnue-common/unittest/datasource.py 2005-05-04 12:55:46 UTC (rev
7517)
@@ -55,29 +55,12 @@
+ _('\n Location: "%s"') % connections_file
- loginhandler = geasLoginHandler ()
-# if self.OPTIONS ["username"]:
-# loginhandler.setLoginData (self.OPTIONS ["username"],
-# self.OPTIONS ["password"])
- loginhandler.setLoginData ('jan',None)
- connections.setLoginHandler (loginhandler)
+ connections.setLoginHandler ( \
+ GLoginHandler.SilentLoginHandler (_username = 'jan', _password = None))
+
return connections
-# =============================================================================
-# Login Handler
-# =============================================================================
-class geasLoginHandler (GLoginHandler.LoginHandler):
- def setLoginData (self,username,password):
- self._username = username
- self._password = password
-
- def getLogin (self, *arguments):
- if hasattr (self, "_username"):
- return {"_username": self._username, "_password": self._password}
- return {"_username": "gnue", "_password": None}
-
-
####################################################################
#
# Basic Datasourcetestcase
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7517 - in trunk/gnue-common: src/datasources src/datasources/drivers/Base src/datasources/drivers/DBSIG2 src/datasources/drivers/appserver/appserver src/datasources/drivers/interbase/Schema/Creation src/datasources/drivers/sapdb/Schema/Creation unittest,
johannes <=