KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ziclix > python > sql > zxJDBC


1 /*
2  * Jython Database Specification API 2.0
3  *
4  * $Id: zxJDBC.java,v 1.14 2005/02/23 04:26:18 bzimmer Exp $
5  *
6  * Copyright (c) 2001 brian zimmer <bzimmer@ziclix.com>
7  *
8  */

9 package com.ziclix.python.sql;
10
11 import org.python.core.ClassDictInit;
12 import org.python.core.Options;
13 import org.python.core.Py;
14 import org.python.core.PyBuiltinFunctionSet;
15 import org.python.core.PyClass;
16 import org.python.core.PyDictionary;
17 import org.python.core.PyException;
18 import org.python.core.PyInteger;
19 import org.python.core.PyObject;
20 import org.python.core.PyString;
21 import org.python.core.PyStringMap;
22
23 import java.lang.reflect.Field JavaDoc;
24 import java.sql.SQLException JavaDoc;
25 import java.text.MessageFormat JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.MissingResourceException JavaDoc;
29 import java.util.Properties JavaDoc;
30 import java.util.ResourceBundle JavaDoc;
31
32 /**
33  * Creates database connections.
34  * <p/>
35  * <pre>
36  * from com.ziclix.python.sql import zxJDBC
37  * db = zxJDBC.connect("jdbc:mysql://localhost:3306/MySql", None, None, "org.gjt.mm.mysql.Driver")
38  * </pre>
39  *
40  * @author brian zimmer
41  * @author last revised by $Author: bzimmer $
42  * @version $Revision: 1.14 $
43  */

44 public class zxJDBC extends PyObject implements ClassDictInit {
45
46     /**
47      * Field Error
48      */

49     public static PyObject Error = Py.None;
50
51     /**
52      * Field Warning
53      */

54     public static PyObject Warning = Py.None;
55
56     /**
57      * Field InterfaceError
58      */

59     public static PyObject InterfaceError = Py.None;
60
61     /**
62      * Field DatabaseError
63      */

64     public static PyObject DatabaseError = Py.None;
65
66     /**
67      * Field InternalError
68      */

69     public static PyObject InternalError = Py.None;
70
71     /**
72      * Field OperationalError
73      */

74     public static PyObject OperationalError = Py.None;
75
76     /**
77      * Field ProgrammingError
78      */

79     public static PyObject ProgrammingError = Py.None;
80
81     /**
82      * Field IntegrityError
83      */

84     public static PyObject IntegrityError = Py.None;
85
86     /**
87      * Field DataError
88      */

89     public static PyObject DataError = Py.None;
90
91     /**
92      * Field NotSupportedError
93      */

94     public static PyObject NotSupportedError = Py.None;
95
96     /**
97      * The ResourceBundle with error messages and doc strings
98      */

99     private static ResourceBundle JavaDoc resourceBundle = null;
100
101     /**
102      * Instance used to create date-like objects as per the API
103      */

104     public static DateFactory datefactory = new JavaDateFactory();
105
106     static {
107         try {
108             resourceBundle = ResourceBundle.getBundle("com.ziclix.python.sql.resource.zxJDBCMessages");
109         } catch (MissingResourceException JavaDoc e) {
110             throw new RuntimeException JavaDoc("missing zxjdbc resource bundle");
111         }
112     }
113
114     /**
115      * Initializes the module.
116      *
117      * @param dict
118      */

119     public static void classDictInit(PyObject dict) {
120
121         dict.__setitem__("apilevel", new PyString("2.0"));
122         dict.__setitem__("threadsafety", new PyInteger(1));
123         dict.__setitem__("paramstyle", new PyString("qmark"));
124         dict.__setitem__("__version__", Py.newString("$Revision: 1.14 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null));
125         dict.__setitem__("Date", new zxJDBCFunc("Date", 1, 3, 3, false, "construct a Date from year, month, day"));
126         dict.__setitem__("Time", new zxJDBCFunc("Time", 2, 3, 3, false, "construct a Date from hour, minute, second"));
127         dict.__setitem__("Timestamp", new zxJDBCFunc("Timestamp", 3, 6, 6, false, "construct a Timestamp from year, month, day, hour, minute, second"));
128         dict.__setitem__("DateFromTicks", new zxJDBCFunc("DateFromTicks", 4, 1, 1, false, "construct a Date from seconds since the epoch"));
129         dict.__setitem__("TimeFromTicks", new zxJDBCFunc("TimeFromTicks", 5, 1, 1, false, "construct a Time from seconds since the epoch"));
130         dict.__setitem__("TimestampFromTicks", new zxJDBCFunc("TimestampFromTicks", 6, 1, 1, false, "construct a Timestamp from seconds since the epoch"));
131         dict.__setitem__("Binary", new zxJDBCFunc("Binary", 7, 1, 1, false, "construct an object capable of holding binary data"));
132         zxJDBC._addSqlTypes(dict);
133         zxJDBC._addConnectors(dict);
134         zxJDBC._buildExceptions(dict);
135
136         // hide from python
137
dict.__setitem__("initModule", null);
138         dict.__setitem__("toString", null);
139         dict.__setitem__("getPyClass", null);
140         dict.__setitem__("classDictInit", null);
141         dict.__setitem__("_addSqlTypes", null);
142         dict.__setitem__("_addConnectors", null);
143         dict.__setitem__("_buildExceptions", null);
144         dict.__setitem__("_empty__init__", null);
145         dict.__setitem__("buildClass", null);
146         dict.__setitem__("createExceptionMessage", null);
147         dict.__setitem__("resourceBundle", null);
148         dict.__setitem__("getString", null);
149         dict.__setitem__("makeException", null);
150     }
151
152     /**
153      * Field __class__
154      */

155     public static PyClass __class__;
156
157     /**
158      * Method getPyClass
159      *
160      * @return PyClass
161      */

162     protected PyClass getPyClass() {
163         return __class__;
164     }
165
166     /**
167      * Add the types from java.sql.Types
168      *
169      * @param dict
170      * @throws PyException
171      */

172     protected static void _addSqlTypes(PyObject dict) throws PyException {
173
174         PyDictionary sqltype = new PyDictionary();
175
176         dict.__setitem__("sqltype", sqltype);
177
178         try {
179             Class JavaDoc c = Class.forName("java.sql.Types");
180             Field JavaDoc[] fields = c.getFields();
181
182             for (int i = 0; i < fields.length; i++) {
183                 Field JavaDoc f = fields[i];
184                 PyString name = Py.newString(f.getName());
185                 PyObject value = new DBApiType(f.getInt(c));
186
187                 dict.__setitem__(name, value);
188                 sqltype.__setitem__(value, name);
189             }
190
191             c = Class.forName("java.sql.ResultSet");
192             fields = c.getFields();
193
194             for (int i = 0; i < fields.length; i++) {
195                 Field JavaDoc f = fields[i];
196                 PyString name = Py.newString(f.getName());
197                 PyObject value = Py.newInteger(f.getInt(c));
198
199                 dict.__setitem__(name, value);
200             }
201         } catch (Throwable JavaDoc t) {
202             throw makeException(t);
203         }
204
205         dict.__setitem__("ROWID", dict.__getitem__(Py.newString("OTHER")));
206         dict.__setitem__("NUMBER", dict.__getitem__(Py.newString("NUMERIC")));
207         dict.__setitem__("STRING", dict.__getitem__(Py.newString("VARCHAR")));
208         dict.__setitem__("DATETIME", dict.__getitem__(Py.newString("TIMESTAMP")));
209
210         return;
211     }
212
213     /**
214      * Add all the possible connectors
215      *
216      * @param dict
217      * @throws PyException
218      */

219     protected static void _addConnectors(PyObject dict) throws PyException {
220
221         PyObject connector = Py.None;
222         Properties JavaDoc props = new Properties JavaDoc();
223
224         props.put("connect", "com.ziclix.python.sql.connect.Connect");
225         props.put("lookup", "com.ziclix.python.sql.connect.Lookup");
226         props.put("connectx", "com.ziclix.python.sql.connect.Connectx");
227
228         java.util.Enumeration JavaDoc names = props.propertyNames();
229
230         while (names.hasMoreElements()) {
231             String JavaDoc name = ((String JavaDoc) names.nextElement()).trim();
232             String JavaDoc className = props.getProperty(name).trim();
233
234             try {
235                 connector = (PyObject) Class.forName(className).newInstance();
236                 dict.__setitem__(name, connector);
237                 Py.writeComment("zxJDBC", "loaded connector [" + className + "] as [" + name + "]");
238             } catch (Throwable JavaDoc t) {
239                 Py.writeComment("zxJDBC", "failed to load connector [" + name + "] using class [" + className + "]");
240             }
241         }
242
243         return;
244     }
245
246     /**
247      * Create the exception classes and get their descriptions from the resource bundle.
248      *
249      * @param dict
250      */

251     protected static void _buildExceptions(PyObject dict) {
252
253         Error = buildClass("Error", Py.StandardError, "_empty__init__");
254         Warning = buildClass("Warning", Py.StandardError, "_empty__init__");
255         InterfaceError = buildClass("InterfaceError", Error, "_empty__init__");
256         DatabaseError = buildClass("DatabaseError", Error, "_empty__init__");
257         InternalError = buildClass("InternalError", DatabaseError, "_empty__init__");
258         OperationalError = buildClass("OperationalError", DatabaseError, "_empty__init__");
259         ProgrammingError = buildClass("ProgrammingError", DatabaseError, "_empty__init__");
260         IntegrityError = buildClass("IntegrityError", DatabaseError, "_empty__init__");
261         DataError = buildClass("DataError", DatabaseError, "_empty__init__");
262         NotSupportedError = buildClass("NotSupportedError", DatabaseError, "_empty__init__");
263     }
264
265     public static PyObject _empty__init__(PyObject[] arg, String JavaDoc[] kws) {
266         PyObject dict = new PyStringMap();
267         dict.__setitem__("__module__", new PyString("zxJDBC"));
268         return dict;
269     }
270
271     /**
272      * Return the string associated with the key for the default resource bundle. It
273      * first checks for 'key.N' where N starts at 0 and increments by one. If any indexed
274      * key is found, the results of all the indexed values are concatenated with the line
275      * separator. If no indexed key is found, it defaults to checking the bundle by the
276      * key value alone.
277      *
278      * @param key
279      * @return String
280      */

281     public static String JavaDoc getString(String JavaDoc key) {
282         int i = 0;
283         List JavaDoc lines = null;
284         String JavaDoc resource = null;
285         while (true) {
286             try {
287                 resource = resourceBundle.getString(key + "." + (i++));
288                 if (lines == null) {
289                     lines = new ArrayList JavaDoc();
290                 }
291                 lines.add(resource);
292             } catch (MissingResourceException JavaDoc e) {
293                 break;
294             }
295         }
296         if ((lines == null) || (lines.size() == 0)) {
297             try {
298                 resource = resourceBundle.getString(key);
299             } catch (MissingResourceException JavaDoc e) {
300                 return key;
301             }
302         } else {
303             String JavaDoc sep = System.getProperty("line.separator");
304             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
305             for (i = 0; i < lines.size() - 1; i++) {
306                 sb.append(lines.get(i)).append(sep);
307             }
308             sb.append(lines.get(lines.size() - 1));
309             resource = sb.toString();
310         }
311         return resource;
312     }
313
314     /**
315      * Return a formatted string. The key is used to get the format and the values
316      * are passed, along with the format, to a MessageFormat who formats it appropriately.
317      *
318      * @param key
319      * @param values
320      * @return String
321      */

322     public static String JavaDoc getString(String JavaDoc key, Object JavaDoc[] values) {
323         String JavaDoc format = getString(key);
324         return MessageFormat.format(format, values);
325     }
326
327     /**
328      * Return a newly instantiated PyException of the type Error.
329      *
330      * @param msg
331      * @return PyException
332      */

333     public static PyException makeException(String JavaDoc msg) {
334         return makeException(Error, msg);
335     }
336
337     /**
338      * Return a newly instantiated PyException of the given type.
339      *
340      * @param type
341      * @param msg
342      * @return PyException
343      */

344     public static PyException makeException(PyObject type, String JavaDoc msg) {
345         return Py.makeException(type, Py.newString((msg == null) ? "" : msg));
346     }
347
348     /**
349      * Return a newly instantiated PyException of the type Error.
350      *
351      * @param throwable
352      * @return PyException
353      */

354     public static PyException makeException(Throwable JavaDoc throwable) {
355         return makeException(Error, throwable);
356     }
357
358     /**
359      * Return a newly instantiated PyException of the given type.
360      *
361      * @param type
362      * @param t
363      * @return PyException
364      */

365     public static PyException makeException(PyObject type, Throwable JavaDoc t) {
366
367         if (Options.showJavaExceptions) {
368             java.io.CharArrayWriter JavaDoc buf = new java.io.CharArrayWriter JavaDoc();
369             java.io.PrintWriter JavaDoc writer = new java.io.PrintWriter JavaDoc(buf);
370             writer.println("Java Traceback:");
371             if (t instanceof PyException) {
372                 ((PyException) t).super__printStackTrace(writer);
373             } else {
374                 t.printStackTrace(writer);
375             }
376             Py.stderr.print(buf.toString());
377         }
378
379         if (t instanceof PyException) {
380             return (PyException) t;
381         } else if (t instanceof SQLException JavaDoc) {
382             SQLException JavaDoc sqlException = (SQLException JavaDoc) t;
383             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
384             do {
385                 buffer.append(sqlException.getMessage());
386                 buffer.append(" [SQLCode: " + sqlException.getErrorCode() + "]");
387                 if (sqlException.getSQLState() != null) {
388                     buffer.append(", [SQLState: " + sqlException.getSQLState() + "]");
389                 }
390                 sqlException = sqlException.getNextException();
391                 if (sqlException != null) {
392                     buffer.append(System.getProperty("line.separator"));
393                 }
394             } while (sqlException != null);
395
396             return makeException(type, buffer.toString());
397         } else {
398             return makeException(type, t.getMessage());
399         }
400     }
401
402     /**
403      * Method buildClass
404      *
405      * @param classname
406      * @param superclass
407      * @param classCodeName
408      * @return PyObject
409      */

410     protected static PyObject buildClass(String JavaDoc classname, PyObject superclass, String JavaDoc classCodeName) {
411         PyObject[] parents = (superclass == null) ? Py.EmptyObjects : new PyObject[]{superclass};
412         PyString doc = Py.newString(getString(classname));
413         PyObject cls = Py.makeClass(classname, parents, Py.newJavaCode(zxJDBC.class, classCodeName), doc);
414         return cls;
415     }
416 }
417
418 class zxJDBCFunc extends PyBuiltinFunctionSet {
419
420     zxJDBCFunc(String JavaDoc name, int index, int minargs, int maxargs, boolean func, String JavaDoc doc) {
421         super(name, index, minargs, maxargs, func, doc);
422     }
423
424     public PyObject __call__(PyObject arg) {
425         long ticks;
426         switch (index) {
427             case 4:
428                 ticks = ((Number JavaDoc) arg.__tojava__(Number JavaDoc.class)).longValue();
429                 return zxJDBC.datefactory.DateFromTicks(ticks);
430             case 5:
431                 ticks = ((Number JavaDoc) arg.__tojava__(Number JavaDoc.class)).longValue();
432                 return zxJDBC.datefactory.TimeFromTicks(ticks);
433             case 6:
434                 ticks = ((Number JavaDoc) arg.__tojava__(Number JavaDoc.class)).longValue();
435                 return zxJDBC.datefactory.TimestampFromTicks(ticks);
436             case 7:
437                 return arg;
438             default :
439                 throw argCountError(1);
440         }
441     }
442
443     public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) {
444         switch (index) {
445             case 1:
446                 int year = ((Number JavaDoc) arga.__tojava__(Number JavaDoc.class)).intValue();
447                 int month = ((Number JavaDoc) argb.__tojava__(Number JavaDoc.class)).intValue();
448                 int day = ((Number JavaDoc) argc.__tojava__(Number JavaDoc.class)).intValue();
449                 return zxJDBC.datefactory.Date(year, month, day);
450             case 2:
451                 int hour = ((Number JavaDoc) arga.__tojava__(Number JavaDoc.class)).intValue();
452                 int minute = ((Number JavaDoc) argb.__tojava__(Number JavaDoc.class)).intValue();
453                 int second = ((Number JavaDoc) argc.__tojava__(Number JavaDoc.class)).intValue();
454                 return zxJDBC.datefactory.Time(hour, minute, second);
455             default :
456                 throw argCountError(3);
457         }
458     }
459
460     public PyObject fancyCall(PyObject[] args) {
461         switch (index) {
462             case 3:
463                 int year = ((Number JavaDoc) args[0].__tojava__(Number JavaDoc.class)).intValue();
464                 int month = ((Number JavaDoc) args[1].__tojava__(Number JavaDoc.class)).intValue();
465                 int day = ((Number JavaDoc) args[2].__tojava__(Number JavaDoc.class)).intValue();
466                 int hour = ((Number JavaDoc) args[3].__tojava__(Number JavaDoc.class)).intValue();
467                 int minute = ((Number JavaDoc) args[4].__tojava__(Number JavaDoc.class)).intValue();
468                 int second = ((Number JavaDoc) args[5].__tojava__(Number JavaDoc.class)).intValue();
469                 return zxJDBC.datefactory.Timestamp(year, month, day, hour, minute, second);
470             default :
471                 throw argCountError(args.length);
472         }
473     }
474 }
475
476
Popular Tags