/[gnue]/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
ViewVC logotype

Diff of /gnue-common/src/datasources/drivers/appserver/appserver/Connection.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by jcater, Fri Oct 10 01:21:12 2003 UTC revision 1.2 by jcater, Tue Nov 25 17:01:32 2003 UTC
# Line 0  Line 1 
1    #
2    # This file is part of GNU Enterprise.
3    #
4    # GNU Enterprise is free software; you can redistribute it
5    # and/or modify it under the terms of the GNU General Public
6    # License as published by the Free Software Foundation; either
7    # version 2, or (at your option) any later version.
8    #
9    # GNU Enterprise is distributed in the hope that it will be
10    # useful, but WITHOUT ANY WARRANTY; without even the implied
11    # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12    # PURPOSE. See the GNU General Public License for more details.
13    #
14    # You should have received a copy of the GNU General Public
15    # License along with program; see the file COPYING. If not,
16    # write to the Free Software Foundation, Inc., 59 Temple Place
17    # - Suite 330, Boston, MA 02111-1307, USA.
18    #
19    # Copyright 2000-2003 Free Software Foundation
20    #
21    # FILE:
22    # appserver/Connection.py
23    #
24    # DESCRIPTION:
25    # Implementation of dbdriver for use with GNUe Application Server.
26    #
27    # NOTES:
28    #
29    # HISTORY:
30    #
31    
32    VERSION="0.0.1"
33    
34    __all__ = ['Connection']
35    
36    from gnue.common.datasources import GDataObjects, GConditions
37    from gnue.common.datasources.drivers.Base import Connection as BaseConnection
38    from gnue.common.apps import GDebug
39    from gnue.common.rpc import GComm
40    
41    from DataObject import *
42    
43    import string
44    import types
45    import md5
46    import sys
47    import mx.DateTime, mx.DateTime.ISO
48    
49    from DataObject import DataObject
50    from gnue.common.datasources.drivers.appserver.Schema.Discovery.Introspection import Introspection
51    
52    
53    # TODO: move all non standart Connection functions (request, ...) into a subobject native
54    #       to prevent namespace conflicts
55    
56    class Connection(BaseConnection):
57    
58      _DatabaseError = GComm.Error
59      defaultBehavior = Introspection
60      supportedDataObjects = {
61        'object': DataObject
62      }
63    
64      # We only need the basics -- username and password -- to log in
65      def getLoginFields(self):
66        return [['_username', 'User Name',0],['_password', 'Password',1]]
67    
68    
69      def connect(self, connectData):
70        user = connectData['_username']
71        passwd = connectData['_password']
72    
73        params = { 'host': connectData['host'],
74                   'port': connectData['port'],
75                   'transport': connectData['transport']}
76    
77        self._server = GComm.attach(connectData['rpctype'],params)
78    
79        GDebug.printMesg(3,"Setup the link to the session manager")
80        self._sm = self._server.request("Session")
81    
82        if connectData.has_key('encoding'):
83          GDebug.printMesg(1,"Appserver's dbdriver doesn't 'encoding' parameter, as the transport"+\
84                           " encoding has to be 'utf-8'.")
85    
86        #GDebug.printMesg(3,"Get the status of the session manager")
87        #GDebug.printMesg(3,"Status: "+sessionManager.Status())
88    
89        try:
90          GDebug.printMesg(3,"Open Session ...")
91          GDebug.printMesg(1,"Logging into appserver as user '%s'" % (user))
92          self._sess_id = self._sm.open({'user':user,'password':passwd})
93    
94        except Exception, msg:
95          tmsg = _("Error loging into appserver: %s") % msg
96          raise GDataObjects.ConnectionError, tmsg
97    
98        if self._sess_id == 0:
99          tmsg = _("Error loging into appserver")
100          raise GDataObjects.ConnectionError, tmsg
101    
102        self._updateCursor = Appserver_UpdateCursor(self)
103    
104      def cursor(self):
105        return self._updateCursor
106    
107      def request(self,table,filter,sort,fieldlist,unicodeMode=0):
108        listid = self._sm.request(self._sess_id,table,filter,sort,fieldlist)
109        return Appserver_ListCursor(self,listid,table,fieldlist,unicodeMode)
110    
111      def call(self,classname,obj_id_list,methodname,parameters):
112        self._sm.call(self._sess_id,classname,obj_id_list,methodname,parameters)
113    
114      def commit(self,classname):
115        self._updateCursor.execute(classname)
116        self._sm.commit(self._sess_id)
117    
118      def rollback(self,classname):
119        self._updateCursor.revert(classname)
120        self._sm.rollback(self._sess_id)
121    
122      def close(self,commit):
123        self._sm.close(self._sess_id,commit)
124    
125      # Return a sequence number from sequence 'name'
126      # def getSequence(self, name):
127      # !!! has to be emulated !!!
128      # return self.__singleQuery("select nextval('%s')" % name)
129    
130      # Run the SQL statement 'statement'
131      #def sql(self, statement):
132      # !!! has to be emulated !!!
133      #  cursor = self.__connection.cursor()
134      #  try:
135      #    cursor.execute(statement)
136      #    cursor.close()
137      #  except:
138      #    cursor.close()
139      #    raise
140    
141    
142    
143    class Appserver_ListCursor:
144      def __init__(self,dataCon,listid,classname,fieldlist,unicodeMode=0):
145        self._dataCon=dataCon
146        self._listid=listid
147        self._fieldlist=fieldlist
148        self._stackpos=0
149        self._unicodeMode=unicodeMode
150        self._fieldtypes = self._dataCon._sm.load (self._dataCon._sess_id,
151                                                   classname, [''], self._fieldlist)
152        self._fieldtypes = self._fieldtypes [0]
153    
154      # convert a value retrieved from RPC to the correct native Python type
155      def __rpc_to_native (self, value, type):
156    
157        # Empty strings indicate None
158        if value == '':
159          return None
160    
161        # String: convert to unicode or local encoding
162        elif type [:7] == 'string(':
163          value = unicode (value, 'utf-8')
164          if self._unicodeMode:
165            return value
166          else:
167            return value.encode (gConfig ('textEncoding'))
168    
169        # Date: convert to mx.DateTime object
170        elif type == 'date':
171          return mx.DateTime.ISO.ParseDate (value)
172    
173        # Time: convert to mx.DateTime object
174        elif type == 'time':
175          return mx.DateTime.ISO.ParseTime (value)
176    
177        # DateTime: convert to mx.DateTime object
178        elif type == 'datetime':
179          return mx.DateTime.ISO.ParseDateTime (value)
180    
181        # All others (id, number, boolean, reference): no need to convert
182        else:
183          return value
184    
185      def fetch(self,count=5):
186        if self._stackpos == -1:
187          return []
188        
189        result = self._dataCon._sm.fetch(self._dataCon._sess_id,
190                                         self._listid,self._stackpos,count)
191        if len(result)<count:
192          self._stackpos=-1
193          
194        else:
195          self._stackpos=self._stackpos+len(result)
196    
197        list = []
198        for i in result:
199          dict = {}
200          j = 0
201          for fieldName in self._fieldlist:
202            dict [fieldName] = self.__rpc_to_native (i [j+1], self._fieldtypes [j])
203            j += 1
204            
205          dict["gnue_id"]=i[0]
206          list.append(dict)      
207        return list
208    
209      def count(self):
210        if not hasattr(self,"_count"):
211          self._count = self._dataCon._sm.count(self._dataCon._sess_id,self._listid)
212    
213        return self._count
214    
215      def close(self):
216        pass
217        # TODO: Implement List Close command
218    
219    class Appserver_UpdateCursor:
220      def __init__(self,dataCon,unicodeMode=0):
221        self._dataCon=dataCon
222        self._deleteList={}
223        self._updateList={}
224        self._updateKeyList={}
225        self._unicodeMode=unicodeMode
226    
227      def delete(self,classname,id):
228        if not self._deleteList.has_key(classname):
229           self._deleteList[classname]=[]
230          
231        self._deleteList[classname].append(id)
232    
233      def update(self, classname, id, fieldDict):
234        if not self._updateList.has_key(classname):
235           self._updateList[classname]=[]
236           self._updateKeyList[classname]=[]
237    
238        self._updateList[classname].append(fieldDict)
239        self._updateKeyList[classname].append(id)
240    
241      # convert a native Python type into something transportable by RPC
242      def __native_to_rpc (self, s):
243        if type (s) == types.StringType:
244          if self._unicodeMode:
245            msg = 'WARNING: non-unicode passed to the dbdriver (%s)' % value
246            GDebug.printMesg (0, msg)
247          s = unicode (s, gConfig ('textEncoding'))
248        if type (s) == types.UnicodeType:
249          s = s.encode ('utf-8')
250        elif type (s) == mx.DateTime.DateTimeType:
251          s = s.date + ' ' + s.time
252        elif s is None:
253          s = ''
254        return s
255    
256      def execute (self, classname):
257        if self._deleteList.has_key (classname):
258          self._dataCon._sm.delete (self._dataCon._sess_id, classname,
259                                    self._deleteList [classname])
260          del self._deleteList [classname]
261    
262        if self._updateList.has_key (classname):
263          while len (self._updateList [classname]):
264            id = self._updateKeyList[classname].pop()
265            dict = self._updateList[classname].pop()
266            # TODO: merge calls with similar updated fields (=dict.values())
267            data = [self.__native_to_rpc (x) for x in dict.values ()]
268            new_ids = self._dataCon._sm.store (self._dataCon._sess_id, classname,
269                                               [id], dict.keys(), [data])
270            dict ["gnue_id"] = new_ids [0]
271          del self._updateList [classname]
272          del self._updateKeyList [classname]
273    
274      def revert (self, classname):
275        if self._deleteList.has_key (classname):
276          del self._deleteList [classname]
277        if self._updateList.has_key (classname):
278          del self._updateList [classname]
279          del self._updateKeyList [classname]

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26