KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > sql > tools > XmlDump


1 package com.quadcap.sql.tools;
2
3 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.BufferedWriter JavaDoc;
42 import java.io.FileInputStream JavaDoc;
43 import java.io.FileOutputStream JavaDoc;
44 import java.io.IOException JavaDoc;
45 import java.io.InputStream JavaDoc;
46 import java.io.OutputStream JavaDoc;
47 import java.io.OutputStreamWriter JavaDoc;
48 import java.io.Reader JavaDoc;
49 import java.io.Writer JavaDoc;
50
51
52 import java.util.Iterator JavaDoc;
53 import java.util.List JavaDoc;
54 import java.util.HashMap JavaDoc;
55 import java.util.Map JavaDoc;
56
57
58 import java.util.ArrayList JavaDoc;
59 import java.util.Hashtable JavaDoc;
60 import java.util.Properties JavaDoc;
61 import java.util.Vector JavaDoc;
62
63 import java.sql.Blob JavaDoc;
64 import java.sql.Clob JavaDoc;
65 import java.sql.Connection JavaDoc;
66 import java.sql.DatabaseMetaData JavaDoc;
67 import java.sql.ResultSet JavaDoc;
68 import java.sql.ResultSetMetaData JavaDoc;
69 import java.sql.Statement JavaDoc;
70
71 import java.sql.SQLException JavaDoc;
72 import java.sql.Types JavaDoc;
73
74 import java.util.zip.GZIPOutputStream JavaDoc;
75
76 import com.quadcap.sql.Backup;
77
78 import com.quadcap.sql.types.Type;
79
80 import com.quadcap.util.Config;
81 import com.quadcap.util.Debug;
82
83 import com.quadcap.util.collections.DiGraph;
84
85 /**
86   * Dump an SQL database in an XML representation. The XML document
87   * has an outer tag of <code>&lt;database&gt;</code>. Each child element
88   * then contains one table row, where the tag name specifies the table name;
89   * each child element of this tag contains one column value where the
90   * tag name specifies the column name. Most object are represented in
91   * their standard Java <code>toString</code> style representation, except
92   * binary objects, which are dumped in hexadecimal. (Base-64 would probably
93   * be better...)
94   *
95   * @author Stan Bailes
96   */

97
98 public class XmlDump implements Backup {
99     Connection JavaDoc conn;
100     int indentLevel = 0;
101     String JavaDoc lineSep;
102     boolean wasBegin = false;
103     boolean wasEnd = false;
104
105     /**
106      * No-argument constructor. The object so constructed needs a
107      * <code>Connection</code> in order to do anything useful.
108      */

109     public XmlDump() {
110     lineSep = System.getProperty("line.separator");
111     }
112
113     /**
114      * Construct an XmlDump object bound to the specified connection.
115      *
116      * @param conn the database connection
117      */

118     public XmlDump(Connection JavaDoc conn) {
119     this.conn = conn;
120     lineSep = System.getProperty("line.separator");
121     }
122
123     /**
124      * Construct an XmlDump object bound to the specified connection,
125      * and with a specified initial indent level.
126      *
127      * @param conn the database connection
128      * @param indentLevel the initial indent level (in units -- currently
129      * indent units are simple spaces
130      */

131     public XmlDump(Connection JavaDoc conn, int indentLevel) {
132     this.indentLevel = indentLevel;
133     this.conn = conn;
134     lineSep = System.getProperty("line.separator");
135     }
136
137     /**
138      * Set the dumper's database connection
139      *
140      * @param conn the new database connection
141      */

142     public void setConnection(Connection JavaDoc conn) {
143     this.conn = conn;
144     }
145
146     /**
147      * Get the dumper's database connection
148      *
149      * @return the current database connection
150      */

151     public Connection JavaDoc getConnection() {
152     return conn;
153     }
154
155     final void beginTag(Writer JavaDoc w, String JavaDoc tag) throws IOException JavaDoc {
156     if (wasBegin) w.write(lineSep);
157     for (int i = 0; i < indentLevel; i++) w.write(' ');
158     indentLevel++;
159     w.write('<');
160     w.write(tag);
161     w.write('>');
162     wasBegin = true;
163     wasEnd = false;
164     }
165
166     final void endTag(Writer JavaDoc w, String JavaDoc tag) throws IOException JavaDoc {
167     indentLevel--;
168     if (wasEnd) {
169         for (int i = 0; i < indentLevel; i++) w.write(' ');
170     }
171     w.write('<');
172     w.write('/');
173     w.write(tag);
174     w.write('>');
175     w.write(lineSep);
176     wasBegin = false;
177     wasEnd = true;
178     }
179
180     static final String JavaDoc charsLt = "&lt;";
181     static final String JavaDoc charsGt = "&gt;";
182     static final String JavaDoc charsAmp = "&amp;";
183
184     final void writeString(Writer JavaDoc w, String JavaDoc str) throws IOException JavaDoc {
185     for (int i = 0; i < str.length(); i++) {
186         char c = str.charAt(i);
187         switch (c) {
188         case '<':
189         w.write(charsLt);
190         break;
191         case '>':
192         w.write(charsGt);
193         break;
194         case '&':
195         w.write(charsAmp);
196         break;
197         default:
198         w.write(c);
199         }
200     }
201     wasBegin = false;
202     wasEnd = false;
203     }
204
205     static final char[] hexBytes = {
206     '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
207     };
208
209     final void writeBinaryStream(Writer JavaDoc w, InputStream JavaDoc is) throws IOException JavaDoc {
210         int c;
211         while ((c = is.read()) >= 0) {
212             w.write(hexBytes[(c >> 4) & 0xf]);
213             w.write(hexBytes[c & 0xf]);
214         }
215     }
216
217     final void writeCharacterStream(Writer JavaDoc w, Reader JavaDoc r) throws IOException JavaDoc {
218         int ci;
219         while ((ci = r.read()) >= 0) {
220             char c = (char)ci;
221         switch (c) {
222         case '<':
223         w.write(charsLt);
224         break;
225         case '>':
226         w.write(charsGt);
227         break;
228         case '&':
229         w.write(charsAmp);
230         break;
231         default:
232         w.write(c);
233         }
234         }
235     }
236
237     final void writeBinary(Writer JavaDoc w, Object JavaDoc obj)
238     throws IOException JavaDoc
239     {
240     if (obj instanceof Boolean JavaDoc) {
241         w.write((((Boolean JavaDoc)obj).booleanValue()) ? '1' : '0');
242     } else {
243         byte[] buf = (byte[])obj;
244         for (int i = 0; i < buf.length; i++) {
245         byte c = buf[i];
246         w.write(hexBytes[(c >> 4) & 0xf]);
247         w.write(hexBytes[c & 0xf]);
248         }
249     }
250     }
251
252     final void writeValue(Writer JavaDoc w, Object JavaDoc obj, int jdbcType)
253     throws SQLException JavaDoc, IOException JavaDoc
254     {
255     switch (jdbcType) {
256     case Types.BIT:
257     case Types.TINYINT:
258     case Types.SMALLINT:
259     case Types.INTEGER:
260     case Types.BIGINT:
261     case Types.FLOAT:
262     case Types.REAL:
263     case Types.DOUBLE:
264     case Types.NUMERIC:
265     case Types.DECIMAL:
266     case Types.CHAR:
267     case Types.VARCHAR:
268     case Types.LONGVARCHAR:
269     case Types.DATE:
270     case Types.TIME:
271     case Types.TIMESTAMP:
272     case Types.OTHER:
273             writeString(w, obj.toString());
274             break;
275 //- //#ifdef JDK11
276
//- case Type.CLOB:
277
//#else
278
case Types.CLOB:
279         writeCharacterStream(w, ((Clob JavaDoc)obj).getCharacterStream());
280         //#endif
281
break;
282 //- //#ifdef JDK11
283
//- case Type.BLOB:
284
//#else
285
case Types.BLOB:
286         //#endif
287
writeBinaryStream(w, ((Blob JavaDoc)obj).getBinaryStream());
288         break;
289     case Types.BINARY:
290     case Types.VARBINARY:
291     case Types.LONGVARBINARY:
292         writeBinary(w, obj);
293         break;
294     case Types.NULL:
295         //#ifndef JDK11
296
case Types.JAVA_OBJECT:
297     case Types.DISTINCT:
298     case Types.STRUCT:
299     case Types.ARRAY:
300     case Types.REF:
301         //#endif
302
throw new IOException JavaDoc("Not supported, jdbc type: " + jdbcType +
303                 ", object = " + obj.getClass().getName() + ": " + obj);
304     }
305     }
306
307     List JavaDoc parseViewDef(String JavaDoc s) {
308         List JavaDoc ret = new ArrayList JavaDoc();
309         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
310         int idx = s.indexOf(" AS ");
311         if (idx >= 0) {
312             s = s.substring(idx+4);
313         }
314         boolean l = false;
315         for (int i = 0; i < s.length(); i++) {
316             char c = s.charAt(i);
317             boolean d = Character.isLetterOrDigit(c) || c == '.';
318             if (d ^ l) {
319                 if (sb.length() > 0) {
320                     ret.add(sb.toString());
321                     sb.setLength(0);
322                 }
323             }
324             if (d) {
325                 sb.append(c);
326             }
327             l = d;
328         }
329         if (sb.length() > 0) ret.add(sb.toString());
330         return ret;
331     }
332
333     void dumpViewDefinitions(Writer JavaDoc w) throws SQLException JavaDoc, IOException JavaDoc {
334     DatabaseMetaData JavaDoc dbMeta = (DatabaseMetaData JavaDoc)conn.getMetaData();
335     ResultSet JavaDoc rs = (ResultSet JavaDoc)dbMeta.getTables(null, "%", "%", null);
336         Map JavaDoc map = new HashMap JavaDoc();
337         DiGraph graph = new DiGraph();
338     try {
339         while (rs.next()) {
340                 String JavaDoc type = rs.getString(4);
341                 if (type.toLowerCase().indexOf("view") >= 0) {
342                     String JavaDoc schema = rs.getString(2);
343                     String JavaDoc table = rs.getString(3);
344                     if (schema != null && schema.length() > 0) {
345                         table = schema + "." + table;
346                     }
347                     String JavaDoc view = rs.getString(5);
348                     if (view != null) {
349                         Iterator JavaDoc it = parseViewDef(view).iterator();
350                         while (it.hasNext()) {
351                             String JavaDoc base = it.next().toString();
352                             graph.addArc(base, table);
353                             //graph.addArc(table, base);
354
}
355                         map.put(table, view);
356                     }
357                 }
358             }
359             Iterator JavaDoc iter = graph.levelize(true);
360             while (iter.hasNext()) {
361                 String JavaDoc s = iter.next().toString();
362                 Object JavaDoc x = map.get(s);
363                 if (x != null) {
364                     beginTag(w, "ddl");
365                     writeString(w, "CREATE " + x.toString());
366                     endTag(w, "ddl");
367                 }
368             }
369         } finally {
370         rs.close();
371     }
372     }
373
374     void dumpIndexDefinitions(Writer JavaDoc w, String JavaDoc tableName)
375         throws SQLException JavaDoc, IOException JavaDoc
376     {
377     String JavaDoc schemaP = null;
378     String JavaDoc tableP = tableName;
379     int idx = tableName.indexOf('.');
380     if (idx > 0) {
381         schemaP = tableName.substring(0, idx);
382         tableP = tableName.substring(idx+1);
383     }
384     DatabaseMetaData JavaDoc dbMeta = (DatabaseMetaData JavaDoc)conn.getMetaData();
385     ResultSet JavaDoc rs = (ResultSet JavaDoc)dbMeta.getIndexInfo(null, schemaP, tableP, false, true);
386         try {
387             StringBuffer JavaDoc columns = new StringBuffer JavaDoc();
388             boolean unique = false;
389             String JavaDoc table = null;
390             String JavaDoc index = null;
391             while (rs.next()) {
392                 if (rs.getObject(5) != null) {
393                     String JavaDoc sch = rs.getString(2);
394                     String JavaDoc tab = rs.getString(3);
395                     if (sch != null && sch.length() > 0) {
396                         tab = sch + "." + tab;
397                     }
398                     if (index != null && !index.equals(rs.getString(6))) {
399                         beginTag(w, "ddl");
400                         writeString(w, "CREATE " + (unique ? "UNIQUE " : "") +
401                                     " INDEX " + index + " ON " +
402                                     table + "(" + columns + ")");
403                         endTag(w, "ddl");
404                         columns.setLength(0);
405                     }
406                     String JavaDoc column = rs.getString(9);
407                     unique = !rs.getBoolean(4);
408                     index = rs.getString(6);
409                     table = tab;
410                     if (columns.length() > 0) columns.append(", ");
411                     columns.append(column);
412                 }
413             }
414             if (index != null) {
415                 beginTag(w, "ddl");
416                 writeString(w, "CREATE " + (unique ? "UNIQUE " : "") +
417                             " INDEX " + index + " ON " +
418                             table + "(" + columns + ")");
419                 endTag(w, "ddl");
420             }
421         } finally {
422         rs.close();
423     }
424     }
425     
426     
427     final Iterator JavaDoc orderTables() throws SQLException JavaDoc {
428         ArrayList JavaDoc t = new ArrayList JavaDoc();
429     DatabaseMetaData JavaDoc dbMeta = (DatabaseMetaData JavaDoc)conn.getMetaData();
430     ResultSet JavaDoc rs = (ResultSet JavaDoc)dbMeta.getTables(null, "%", "%", null);
431     try {
432         while (rs.next()) {
433                 String JavaDoc type = rs.getString(4);
434                 if (type.toLowerCase().indexOf("table") >= 0) {
435                     String JavaDoc schema = rs.getString(2);
436                     String JavaDoc table = rs.getString(3);
437                     if (schema != null && schema.length() > 0) {
438                         table = schema + "." + table;
439                     }
440                     t.add(table);
441                 }
442         }
443     } finally {
444         rs.close();
445     }
446         return t.iterator();
447     }
448     
449     class DbType {
450     int type;
451     String JavaDoc prefix;
452     String JavaDoc suffix;
453     String JavaDoc createParams;
454     DbType(int type, String JavaDoc prefix, String JavaDoc suffix, String JavaDoc createParams) {
455         this.type = type;
456         this.prefix = prefix == null ? "" : prefix;
457         this.suffix = suffix == null ? "" : suffix;
458         this.createParams = createParams == null ? "" : createParams;
459     }
460
461     String JavaDoc getTypePrefix() { return prefix; }
462     String JavaDoc getTypeSuffix() { return suffix; }
463
464     String JavaDoc getCreateParams(ResultSet JavaDoc rs) throws SQLException JavaDoc {
465         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("");
466         String JavaDoc cp = createParams;
467         while (cp.length() > 0) {
468         String JavaDoc param = cp;
469         int idx = cp.indexOf(',');
470         if (idx > 0) {
471             param = cp.substring(0, idx).trim();
472             cp = cp.substring(idx+1).trim();
473         } else {
474             cp = "";
475         }
476         if (param.equalsIgnoreCase("length") ||
477             param.equalsIgnoreCase("precision")) {
478             if (sb.length() == 0) {
479             sb.append('(');
480             } else {
481             sb.append(',');
482             }
483             sb.append(rs.getString(7));
484         } else if (param.equalsIgnoreCase("scale")) {
485             if (sb.length() == 0) {
486             sb.append('(');
487             } else {
488             sb.append(',');
489             }
490             sb.append(rs.getString(9));
491         }
492         }
493         if (sb.length() > 0) {
494         sb.append(')');
495         }
496         return sb.toString();
497     }
498     };
499
500     Hashtable JavaDoc types = null;
501
502     Hashtable JavaDoc getTypes() throws SQLException JavaDoc {
503     if (types == null) {
504         types = new Hashtable JavaDoc();
505         DatabaseMetaData JavaDoc dbMeta = (DatabaseMetaData JavaDoc)conn.getMetaData();
506         ResultSet JavaDoc rs = (ResultSet JavaDoc)dbMeta.getTypeInfo();
507         while (rs.next()) {
508         int type = rs.getInt(2);
509         String JavaDoc prefix = rs.getString(4);
510         String JavaDoc suffix = rs.getString(5);
511         String JavaDoc createParams = rs.getString(6);
512         DbType t = new DbType(type, prefix, suffix, createParams);
513         types.put(new Integer JavaDoc(type), t);
514         }
515     }
516     return types;
517     }
518
519     DbType getType(int type) throws SQLException JavaDoc {
520         DbType t = null;
521     getTypes();
522     t = (DbType)types.get(new Integer JavaDoc(type));
523         if (t == null) {
524             throw new RuntimeException JavaDoc("no type: " + type);
525         }
526         return t;
527     }
528
529     /**
530      * Dump the SQL foreign key constraints for the specified table
531      */

532     public void dumpTableForeignKeys(Writer JavaDoc w, String JavaDoc tableName)
533     throws SQLException JavaDoc, IOException JavaDoc
534     {
535     String JavaDoc schema = null;
536     String JavaDoc table = tableName;
537     int idx = tableName.indexOf('.');
538     if (idx > 0) {
539         schema = tableName.substring(0, idx);
540         table = tableName.substring(idx+1);
541     }
542     DatabaseMetaData JavaDoc dbMeta = (DatabaseMetaData JavaDoc)conn.getMetaData();
543     ResultSet JavaDoc rs = (ResultSet JavaDoc)dbMeta.getImportedKeys(null, schema, table);
544     String JavaDoc cname = "";
545     Vector JavaDoc pkeys = null;
546     String JavaDoc pkTable = null;
547     StringBuffer JavaDoc sb = new StringBuffer JavaDoc("");
548     while (rs.next()) {
549         String JavaDoc constraintName = rs.getString(12);
550         if (!constraintName.equals(cname)) {
551         if (cname.length() > 0) {
552             sb.append(") references ");
553             sb.append(pkTable);
554             sb.append("(");
555             for (int i = 0; i < pkeys.size(); i++) {
556             if (i > 0) sb.append(", ");
557             sb.append(pkeys.elementAt(i).toString());
558             }
559             sb.append(")\n");
560             beginTag(w, "ddl");
561             writeString(w, sb.toString());
562             endTag(w, "ddl");
563         }
564         String JavaDoc pkSchema = rs.getString(2);
565         if (pkSchema != null && pkSchema.length() > 0) {
566             pkTable = pkSchema + "." + rs.getString(3);
567         } else {
568             pkTable = rs.getString(3);
569         }
570         cname = constraintName;
571         sb.setLength(0);
572         sb.append("\nalter table ");
573         sb.append(tableName);
574         sb.append(" add constraint ");
575         sb.append(cname);
576         sb.append(" foreign key(");
577         pkeys = new Vector JavaDoc();
578         } else {
579         sb.append(", ");
580         }
581         sb.append(rs.getString(8));
582         pkeys.addElement(rs.getString(4));
583     }
584     if (cname.length() > 0) {
585         sb.append(") references ");
586         sb.append(pkTable);
587         sb.append("(");
588         for (int i = 0; i < pkeys.size(); i++) {
589         if (i > 0) sb.append(", ");
590         sb.append(pkeys.elementAt(i).toString());
591         }
592         sb.append(")");
593         beginTag(w, "ddl");
594         writeString(w, sb.toString());
595         endTag(w, "ddl");
596     }
597     }
598
599     /**
600      * Dump the SQL table definition for the specified table
601      */

602     public void dumpTableDefinition(Writer JavaDoc w, String JavaDoc tableName)
603     throws SQLException JavaDoc, IOException JavaDoc
604     {
605     Hashtable JavaDoc constraints = new Hashtable JavaDoc();
606     String JavaDoc schema = null;
607     String JavaDoc table = tableName;
608     int idx = tableName.indexOf('.');
609     if (idx > 0) {
610         schema = tableName.substring(0, idx);
611         table = tableName.substring(idx+1);
612     }
613     DatabaseMetaData JavaDoc dbMeta = (DatabaseMetaData JavaDoc)conn.getMetaData();
614     ResultSet JavaDoc rs = (ResultSet JavaDoc)dbMeta.getColumns(null, schema, table, "%");
615
616         ResultSet JavaDoc rs2 =
617             conn.createStatement().executeQuery("select * from " + tableName);
618         ResultSetMetaData JavaDoc rsMeta = rs2.getMetaData();
619         
620     StringBuffer JavaDoc sb = new StringBuffer JavaDoc("\ncreate table ");
621     sb.append(tableName);
622     sb.append('(');
623     boolean first = true;
624     while (rs.next()) {
625         sb.append("\n\t");
626         if (!first) sb.append(", ");
627         first = false;
628         int type = rs.getInt(5);
629         DbType t = getType(type);
630         sb.append(rs.getString(4)); // column name
631
sb.append(' ');
632         sb.append(rs.getString(6)); // type name
633
sb.append(t.getCreateParams(rs));
634         if (rs.getInt(11) == ResultSetMetaData.columnNoNulls) {
635         sb.append(" NOT NULL");
636         }
637         String JavaDoc dflt = rs.getString(13);
638         if (dflt != null) {
639         sb.append(" DEFAULT ");
640         sb.append(t.getTypePrefix());
641         sb.append(dflt);
642         sb.append(t.getTypeSuffix());
643         }
644             if (rsMeta.isAutoIncrement(rs.getInt(17))) {
645                 sb.append(" WITH IDENTITY");
646             }
647     }
648     rs.close();
649         rs2.close();
650
651     rs = (ResultSet JavaDoc)dbMeta.getPrimaryKeys(null, schema, table);
652     first = true;
653     while (rs.next()) {
654         if (first) {
655         constraints.put(rs.getString(6), "");
656         sb.append("\n\t, constraint ");
657         sb.append(rs.getString(6)); // constraint name
658
sb.append(" primary key (");
659         first = false;
660         } else {
661         sb.append(", ");
662         }
663         sb.append(rs.getString(4)); // column name
664
}
665     if (!first) sb.append(')');
666     rs.close();
667
668     String JavaDoc iname = "";
669     rs = (ResultSet JavaDoc)dbMeta.getIndexInfo(null, schema, table, true, false);
670     first = true;
671     while (rs.next()) {
672         String JavaDoc indexName = rs.getString(6);
673         if (constraints.get(indexName) != null) continue;
674             if (rs.getObject(5) != null) continue;
675         if (indexName.equals(iname)) {
676         sb.append(", ");
677         } else {
678         if (iname.length() > 0) {
679             sb.append(")");
680         }
681         sb.append("\n\t, constraint ");
682         sb.append(indexName);
683         sb.append(" unique(");
684         iname = indexName;
685         }
686         sb.append(rs.getString(9)); // column name
687
}
688     if (iname.length() > 0) {
689         sb.append(')');
690     }
691     rs.close();
692
693     sb.append(")\n");
694     beginTag(w, "ddl");
695     writeString(w, sb.toString());
696     endTag(w, "ddl");
697     }
698
699     /**
700      * Dump the rows of the specified table to the output stream in XML
701      * format. Each row is dumped as an XML element with the tag name
702      * equal to the table name. Each non-null column is dumped as a
703      * sub-element with the tag name equal to the column name.
704      *
705      * @param w the output stream
706      * @param tableName the name of the database table to dump.
707      *
708      * @exception IOException may be thrown
709      * @exception SQLException may be thrown
710      */

711     public void dumpTable(Writer JavaDoc w, String JavaDoc tableName)
712     throws IOException JavaDoc, SQLException JavaDoc
713     {
714     tableName = tableName.toUpperCase();
715     Statement JavaDoc s = (Statement JavaDoc)conn.createStatement();
716     try {
717         ResultSet JavaDoc rs = (ResultSet JavaDoc)s.executeQuery("select * from " + tableName);
718         try {
719         ResultSetMetaData JavaDoc rm = (ResultSetMetaData JavaDoc)rs.getMetaData();
720         int cols = rm.getColumnCount();
721         while (rs.next()) {
722             beginTag(w, tableName);
723             for (int i = 1; i <= cols; i++) {
724             Object JavaDoc obj = rs.getObject(i);
725             if (!rs.wasNull()) {
726                 beginTag(w, rm.getColumnName(i));
727                             try {
728                                 writeValue(w, obj, rm.getColumnType(i));
729                             } catch (IOException JavaDoc e) {
730                                 Debug.println("Table: " + tableName +
731                                               ", column = " + i + ": " +
732                                               rm.getColumnName(i));
733                                 throw e;
734                             }
735                 endTag(w, rm.getColumnName(i));
736             }
737             }
738             endTag(w, tableName);
739         }
740         } finally {
741         rs.close();
742         }
743     } finally {
744         s.close();
745     }
746     }
747
748     /**
749      * Dump all of the tables in the database which is referenced by the
750      * current connection object to the specified output stream. This
751      * routine writes a well-formed XML document, with a document element
752      * named <code>&lt;database&gt;</code>. Sub-elements correspond to
753      * indidivual table rows.<p>
754      *
755      * This routine first constructs a graph of the foreign table reference
756      * constraints, and attempts to output base tables before dependant
757      * tables, so that the resulting file can be imported without causing
758      * foreign key integrity violations.<p>
759      *
760      * @param w the output stream
761      *
762      * @exception IOException may be thrown
763      * @exception SQLException may be thrown
764      */

765     public void dumpTables(Writer JavaDoc w)
766     throws IOException JavaDoc, SQLException JavaDoc
767     {
768     w.write("<?xml version=\"1.0\"?>\n");
769     beginTag(w, "database");
770     Iterator JavaDoc iter = orderTables();
771     while (iter.hasNext()) {
772         String JavaDoc table = iter.next().toString();
773         dumpTableDefinition(w, table);
774     }
775         dumpViewDefinitions(w);
776
777     iter = orderTables();
778     beginTag(w, "dml");
779     while (iter.hasNext()) {
780         String JavaDoc table = iter.next().toString();
781         dumpTable(w, table);
782     }
783     endTag(w, "dml");
784
785         iter = orderTables();
786         while (iter.hasNext()) {
787             String JavaDoc table = iter.next().toString();
788             dumpIndexDefinitions(w, table);
789         }
790
791     iter = orderTables();
792     while (iter.hasNext()) {
793         String JavaDoc table = iter.next().toString();
794         dumpTableForeignKeys(w, table);
795     }
796     endTag(w, "database");
797     }
798
799     /**
800      * A convenience function that sets the current connection and dumps
801      * the database in one go.
802      *
803      * @param conn the database connection
804      * @param w the output stream
805      *
806      * @exception IOException may be thrown
807      * @exception SQLException may be thrown
808      */

809     public void backup(java.sql.Connection JavaDoc conn, Writer JavaDoc w)
810     throws IOException JavaDoc, SQLException JavaDoc
811     {
812     this.conn = (Connection JavaDoc)conn;
813     dumpTables(w);
814     }
815
816     /**
817      * Establish a database connection based on the settings of system
818      * properties.
819      *
820      * <p>The following system properties are used to establish the
821      * database connection:
822      * <table border=1>
823      * <tr><th align=left>jdbc.driver</th>
824      * <td>The name of the JDBC driver class (default
825      * <code>com.quadcap.jdbc.JdbcDriver</code>)</td></tr>
826      * <tr><th align=left>jdbc.url</th>
827      * <td>The JDBC URL used to establish the database connection.
828      * </td></tr>
829      * <tr><th align=left>jdbc.props</th>
830      * <td>The name of a properties file used to establish the connection.
831      * If this property is specified, <code>jdbc.user</code> and
832      * <code>jdbc.password</code> aren't used.
833      * If this property has the value <code>"system"</code>, then
834      * the system properties are passed to the
835      * <code>DriverManager.getConnection()</code> method.
836      * </td></tr>
837      * <tr><th align=left>jdbc.user</th>
838      * <td>The user name used to establish the
839      * database connection. If neither <code>jdbc.props</code>
840      * nor <code>jdbc.user</code> is specified, the
841      * <code>DriverManager.getConnection(String url)</code>
842      * method is used to establish the connection.</td></tr>
843      * <tr><th align=left>jdbc.password</th>
844      * <td>The password used to establish the
845      * database connection.</td></tr>
846      * </table>
847      * </p>
848      *
849      * @exception Exception may be thrown if there's a problem connecting
850      * to the database.
851      */

852     public static Connection JavaDoc makeConnection() throws Exception JavaDoc {
853         Config.reset();
854     String JavaDoc driver = Config.getProperty("jdbc.driver",
855                        "com.quadcap.jdbc.JdbcDriver");
856     String JavaDoc url = Config.getProperty("jdbc.url");
857     String JavaDoc user = Config.getProperty("jdbc.user");
858     String JavaDoc pass = Config.getProperty("jdbc.password");
859     String JavaDoc propsfile = Config.getProperty("jdbc.props");
860     Connection JavaDoc xconn = null;
861     Class.forName(driver);
862     if (propsfile != null) {
863         Properties JavaDoc props;
864         if (propsfile.equals("system")) {
865         props = System.getProperties();
866         } else {
867         props = new Properties JavaDoc();
868         FileInputStream JavaDoc pfile = new FileInputStream JavaDoc(propsfile);
869         props.load(pfile);
870         }
871         xconn =
872                 (Connection JavaDoc)java.sql.DriverManager.getConnection(url, props);
873     } else if (user != null) {
874         xconn =
875                 (Connection JavaDoc)java.sql.DriverManager.getConnection(url, user,
876                                                                  pass);
877     } else {
878         xconn = (Connection JavaDoc)java.sql.DriverManager.getConnection(url);
879     }
880     return xconn;
881     }
882
883     /**
884      * A main program which allows this function to be run as a command-line
885      * application for doing an off-line dump. The name of the output file is
886      * specified as the argument. If the name of the output file
887      * ends with <code>".gz"</code>, the output is compressed using the
888      * <code>gzip</code> compression mechanism.
889      *
890      * @see makeConnection for a description of the System properties used
891      * to establish the database connection.
892      * @param args <code>com.quadcap.sql.tools.XmlDump</code>
893      * <i>output file</i>
894      */

895     public static void main(String JavaDoc[] args) {
896     try {
897         Connection JavaDoc xconn = makeConnection();
898             try {
899                 XmlDump dump = new XmlDump(xconn);
900                 String JavaDoc outfile = args[0];
901                 if (outfile.endsWith(".xml")) {
902                     FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(outfile);
903                     OutputStreamWriter JavaDoc ow = new OutputStreamWriter JavaDoc(fos);
904                     BufferedWriter JavaDoc bw = new BufferedWriter JavaDoc(ow);
905                     dump.dumpTables(bw);
906                     bw.close();
907                 } else if (outfile.endsWith(".xml.gz")) {
908                     FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(outfile);
909                     GZIPOutputStream JavaDoc gos = new GZIPOutputStream JavaDoc(fos);
910                     OutputStreamWriter JavaDoc ow = new OutputStreamWriter JavaDoc(gos);
911                     BufferedWriter JavaDoc bw = new BufferedWriter JavaDoc(ow);
912                     dump.dumpTables(bw);
913                     bw.flush();
914                     bw.close();
915                 } else {
916                     throw new Exception JavaDoc("Unrecognized output type for file: " +
917                                         outfile);
918                 }
919             } finally {
920                 xconn.close();
921             }
922     } catch (Exception JavaDoc e) {
923         com.quadcap.util.Debug.print(e);
924     }
925     }
926 }
927
Popular Tags