Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/enableit/db/darrt/SchemaExporter.java


1   // Package declaration
2   package org.enableit.db.darrt ;
3   
4   // Java imports
5   import java.io.File ;
6   import java.io.FileOutputStream ;
7   import java.sql.Connection ;
8   import java.sql.DatabaseMetaData ;
9   import java.sql.ResultSet ;
10  import java.text.SimpleDateFormat ;
11  import java.util.ArrayList ;
12  import java.util.Arrays ;
13  import java.util.Date ;
14  import java.util.Iterator ;
15  import java.util.List ;
16  import java.util.StringTokenizer ;
17  import java.util.TreeMap ;
18  
19  // XML imports (inc in J2EE)
20  import javax.xml.parsers.DocumentBuilder;
21  import javax.xml.parsers.DocumentBuilderFactory;
22  import javax.xml.parsers.FactoryConfigurationError;
23  import javax.xml.parsers.ParserConfigurationException;
24  
25  import org.w3c.dom.Document;
26  import org.w3c.dom.Element;
27  import org.w3c.dom.Node;
28  import org.w3c.dom.NodeList;
29  
30  // Log4J imports
31  import org.apache.log4j.Category;
32  
33  import org.enableit.db.ConnectionFactory ;
34  import org.enableit.db.DataSourceProxy ; 
35  import org.enableit.db.DBException ;
36  import org.enableit.db.DBUtils ;
37  import org.enableit.db.SqlType ;
38  import org.enableit.db.darrt.schema.ProviderExt ;
39  
40  /**
41   * Export database schemas as XML.
42   *
43   * Note on ASA interpretation of DatabaseMetaData object:
44   * SchemaConstants.SCHEMA = users and groups
45   */
46  public class SchemaExporter extends AbstractSchemaHandler {
47  /*
48   * Constructors
49   */
50    /**
51     * Default Constructor
52     */
53    public SchemaExporter() {
54          formatter = new SimpleDateFormat() ; 
55      }
56  
57      /**
58       * The name of the schema to be exported.
59       * <p>
60       * If no schema is specified all will be exported.
61       */
62      public void setTargetSchema(String targetSchema) {
63      logger.info("METHOD_ENTRY: setTargetSchema: " + targetSchema);
64      
65          this.targetSchema = targetSchema ;
66  
67      logger.info("METHOD_EXIT: setTargetSchema");
68      }
69  
70      /**  
71       * Set the table types to export.
72       */
73      public void setTableTypes(String tableTypes) { 
74          StringTokenizer st = new StringTokenizer(tableTypes, ",");
75          String[] tableTypesArray = new String[st.countTokens()] ; 
76          int i = 0 ; 
77          while (st.hasMoreTokens()) {
78              tableTypesArray[i++] = st.nextToken().trim();
79          }
80          setTableTypes(tableTypesArray); 
81      } 
82  
83      /**
84       * An array of table types to be exported.
85       * <p>
86       * Table types include such things as 'TABLE' and 'VIEW', 
87       * though the exact list depends
88       * on the database vendor.
89       * <p>
90       * If no table types are specified all will be exported.
91       */
92      public void setTableTypes(String[] tableTypes) {
93  
94          if (tableTypes==null) {
95              this.tableTypes = null ;
96          } else { 
97              /* 
98               * The objective here is to set the local array to the 
99               * parameter array but to exclude VIEW
100              */
101             this.tableTypes = new String[tableTypes.length-1] ; 
102             logger.debug("No. of table types =" + tableTypes.length);
103 
104             int j = 0 ; 
105             try {
106                 for (int i=0 ; i<tableTypes.length ; i++) {
107                     if (!SchemaConstants.VIEW.equalsIgnoreCase(tableTypes[i])) {
108                         this.tableTypes[j++] = tableTypes[i] ;                 
109                     }
110                 }
111             } catch (ArrayIndexOutOfBoundsException e) {
112                 this.tableTypes = tableTypes ;
113             }
114             logger.info("tableTypes=" + Arrays.asList(this.tableTypes));
115         } 
116 
117         logger.info("METHOD_EXIT: setTableTypes");        
118     }
119 
120     /**
121      * Export the schema identified by the provided connection parameters.
122      */
123     public Document export(String driver, String url, 
124             String userid, String password)
125             throws DBException {
126     logger.info("METHOD_ENTRY: export: " + driver + "," 
127         + url + "," + userid + "," + password) ; 
128 
129         Document doc = null ;
130         try {
131             // Set the provider to avoid NPE in output
132             provider = new ProviderExt() ; 
133             provider.setConnectionProperties(driver, url, userid, password) ;
134             Connection conn = ConnectionFactory.getConnection(driver,
135                     url, userid, password);
136             if (conn == null) {
137                 throw new DBException("Null connection when connecting " 
138                         + "to database") ;
139             }
140 
141             doc = export(conn) ;
142             conn.close() ;
143             conn = null ;
144         } catch (DBException e) {
145             throw e ;
146         } catch (Exception e) {
147             logger.error(e.getMessage()) ; 
148             throw new DBException(e.getClass().getName() + ":" 
149                     + e.getMessage(), e) ;
150         }
151 
152         return doc ;
153     }
154 
155     /**
156      * Export the schema identified by the provided connection parameters.
157      */
158     public Document export(String dataSourceName)
159         throws DBException
160     {
161     logger.info("METHOD_ENTRY: export: dataSourceName=" + dataSourceName) ; 
162         Document doc = null ;
163         try {
164             // Set the provider to avoid NPE in output
165             provider = new ProviderExt() ; 
166             Connection conn = DataSourceProxy.getConnection(dataSourceName) ; 
167             if (conn==null) {
168                 throw new DBException("Null connection when connecting to database") ;
169             }
170 
171             doc = export(conn) ;
172             conn.close() ;
173             conn = null ;
174 
175         } catch (DBException e) {
176             throw e ;
177         } catch (Exception e) {
178             logger.error(e.getMessage(), e); 
179             throw new DBException(e.getClass().getName() + ":" + e.getMessage()) ;
180         }
181 
182         return doc ;
183     }
184 
185     /**
186      * Export the schema at the database already connected to.
187      */
188     private Document export(Connection conn)
189         throws DBException {
190         Document doc = null ;
191         // Construct an xml doc
192         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
193         try {
194             DocumentBuilder docBuilder = factory.newDocumentBuilder();
195             doc = docBuilder.newDocument() ;
196         } catch (ParserConfigurationException e) {
197             logger.error(e.getMessage());
198             throw new DBException(e.getMessage()) ;
199         }
200 
201         // get schema items to place in doc
202         try {
203             Element databaseTag = doc.createElement(SchemaConstants.ROOT_ELEMENT) ;
204             DatabaseMetaData dmd = conn.getMetaData() ;
205 
206             /*
207              * General database provider information
208              */
209             Element providerTag = doc.createElement(SchemaConstants.PROVIDER) ;
210             Element productNameTag = doc.createElement(SchemaConstants.NAME) ;
211             productNameTag.appendChild(doc.createTextNode(dmd.getDatabaseProductName()));
212             providerTag.appendChild(productNameTag) ;
213 
214             Element productVsnTag = doc.createElement(SchemaConstants.VSN) ;
215             productVsnTag.appendChild(doc.createTextNode(dmd.getDatabaseProductVersion())) ;
216             providerTag.appendChild(productVsnTag) ;
217 
218             Element productUrlTag = doc.createElement(SchemaConstants.URL_STRING) ;
219             productUrlTag.appendChild(doc.createTextNode(dmd.getURL())) ;
220             providerTag.appendChild(productUrlTag) ;
221 
222             Element usernameTag = doc.createElement(SchemaConstants.USERNAME) ;
223             usernameTag.appendChild(doc.createTextNode(dmd.getUserName())) ;
224             providerTag.appendChild(usernameTag) ;
225 
226             Element passwordTag = doc.createElement(SchemaConstants.PASSWORD) ;
227             passwordTag.appendChild(doc.createTextNode(provider.getPassword())) ;
228             providerTag.appendChild(passwordTag) ;
229 
230             // Database driver info
231             Element driverTag = doc.createElement(SchemaConstants.DRIVER) ;
232             Element driverNameTag = doc.createElement(SchemaConstants.NAME) ;
233             driverNameTag.appendChild(doc.createTextNode(dmd.getDriverName())) ;
234             driverTag.appendChild(driverNameTag) ;
235             Element driverVsnTag = doc.createElement(SchemaConstants.VSN) ;
236             driverVsnTag.appendChild(doc.createTextNode(dmd.getDriverVersion())) ;
237             driverTag.appendChild(driverVsnTag) ;
238             Element driverClassNameTag = doc.createElement(SchemaConstants.CLASS_NAME) ;
239             driverClassNameTag.appendChild(doc.createTextNode(
240                     provider.getDriver()==null
241                     ? ""
242                     : provider.getDriver().getClassName())) ;
243             driverTag.appendChild(driverClassNameTag) ;
244             providerTag.appendChild(driverTag) ;
245             
246             Element creationDateTag = doc.createElement(SchemaConstants.CREATION_DATE) ;
247             creationDateTag.appendChild(doc.createTextNode(formatter.format(new Date()))) ;
248             providerTag.appendChild(creationDateTag) ;
249             
250             databaseTag.appendChild(providerTag);
251 
252             /*
253              * Database metadata information (not sure if this is useful yet)
254              */
255             Element metadataTag = doc.createElement(SchemaConstants.METADATA) ;
256             Element catalogsTag = doc.createElement(SchemaConstants.CATALOGS) ;
257             ResultSet catalogs = dmd.getCatalogs() ;
258             while (catalogs.next()) {
259                 //logger.debug("TABLE TYPE: " + tableTypes.getString("TABLE_TYPE"));
260                 Element catalogNameTag = doc.createElement(SchemaConstants.NAME) ;
261                 catalogNameTag.appendChild(doc.createTextNode(catalogs.getString("TABLE_CAT").trim()));
262                 catalogsTag.appendChild(catalogNameTag);
263             }
264             catalogs.close() ;
265             metadataTag.appendChild(catalogsTag) ;
266 
267             Element tableTypesTag = doc.createElement(SchemaConstants.TABLE_TYPES) ;
268             ResultSet tableTypes = dmd.getTableTypes() ;
269             while (tableTypes.next()) {
270                 //logger.debug("TABLE TYPE: " + tableTypes.getString("TABLE_TYPE"));
271                 Element tableTypeNameTag = doc.createElement(SchemaConstants.NAME) ;
272                 tableTypeNameTag.appendChild(doc.createTextNode(tableTypes.getString("TABLE_TYPE").trim()));
273                 tableTypesTag.appendChild(tableTypeNameTag);
274             }
275             metadataTag.appendChild(tableTypesTag) ;
276 
277             Element catalogTermTag = doc.createElement(SchemaConstants.CATALOG_TERM) ;
278             catalogTermTag.appendChild(doc.createTextNode(dmd.getCatalogTerm()));
279             metadataTag.appendChild(catalogTermTag) ;
280 
281             Element schemaTermTag = doc.createElement(SchemaConstants.SCHEMA_TERM) ;
282             schemaTermTag.appendChild(doc.createTextNode(dmd.getSchemaTerm()));
283             metadataTag.appendChild(schemaTermTag) ;
284 
285             if (getDebug()) {
286                 databaseTag.appendChild(metadataTag) ;              
287             }
288 
289             /*
290              * Get the schema data (including the table data)
291              */
292 
293             ResultSet schemas = dmd.getSchemas() ;
294             ArrayList schList = (ArrayList)DBUtils.convertResultToList(schemas) ;
295 
296             for (Iterator i=schList.iterator() ; i.hasNext() ;) {
297                 Element schemaTag = doc.createElement(SchemaConstants.SCHEMA) ;
298                 TreeMap row = (TreeMap)i.next() ;
299                 String schemaName = (String)row.get("TABLE_SCHEM") ;
300         logger.debug("Found schema named: " + schemaName);
301 
302                 // If no target schema was specified, or if this is the one specified - export it
303                 if (targetSchema==null || schemaName.equalsIgnoreCase(targetSchema)) {
304           logger.debug("Exporting schema named: " + schemaName);
305                     Element schemaNameTag = doc.createElement(SchemaConstants.NAME) ;
306                     schemaNameTag.appendChild(doc.createTextNode(schemaName));
307                     schemaTag.appendChild(schemaNameTag) ;
308 
309                     if (this.tableTypes.length>0) {
310                         addTables(dmd, doc, schemaName, schemaTag, this.tableTypes) ;
311                     }
312                     String[] viewType = new String[1] ; 
313                     viewType[0] = "VIEW" ; // TODO is this constant for all dbms?
314                     viewExporter.setProvider(provider) ; 
315                     addTables(dmd, doc, schemaName, schemaTag, viewType) ;
316                     databaseTag.appendChild(schemaTag) ;
317                 } else { 
318           logger.debug("Ignoring schema named: " + schemaName);
319         } 
320             }
321             doc.appendChild(databaseTag);
322         } catch (Exception e) {
323             // Things to catch : array out of bounds from no column results found
324             logger.debug(e.getClass().getName() + ":" + e.getMessage()) ;
325             logger.debug(e) ;
326             //if (e.getMessage()==null || e.getMessage().length()==0) {
327                 e.printStackTrace(System.err) ;
328             //}
329         }
330         return doc ;
331     }
332 
333     /**
334      * Extract table metadata adding appropriate tags.
335      */
336     private void addTables(DatabaseMetaData dmd, Document doc, String schemaName,
337             Element schemaTag, String[] tableTypes)
338             throws SchemaHandlingException {
339         logger.info("METHOD_ENTRY: addTables");
340         
341         try {
342 
343             ResultSet tables = dmd.getTables(null, schemaName, getTablePattern(), tableTypes) ;
344             while (tables.next()) {
345                 String tableName = tables.getString("TABLE_NAME") ;
346                 String tableType = tables.getString("TABLE_TYPE") ;
347                 /*
348                  * The table portion
349                  */
350                 Element tableTag = null ;
351                 if (SchemaConstants.VIEW.equalsIgnoreCase(tableType)) {
352                     tableTag = doc.createElement(SchemaConstants.VIEW) ;
353                 } else {
354                     tableTag = doc.createElement(SchemaConstants.TABLE) ;
355                 }
356                 Element nameTag = doc.createElement(SchemaConstants.NAME) ;
357                 nameTag.appendChild(doc.createTextNode(tableName));
358                 tableTag.appendChild(nameTag) ;
359 
360                 Element typeTag = doc.createElement(SchemaConstants.TYPE) ;
361                 typeTag.appendChild(doc.createTextNode(tableType));
362                 tableTag.appendChild(typeTag) ;
363 
364                 // Capture Primary Key Name
365                 ResultSet pk = dmd.getPrimaryKeys(catalog, schemaName, tableName) ;
366                 ArrayList pkList = (ArrayList)DBUtils.convertResultToList(pk) ;
367                 pk.close() ;
368                 if (pkList.size()==0) {
369                     logger.warn("No primary key was found for " + tableName) ;
370                     //throw new DBException(msg) ;
371                 } else {
372                     TreeMap pkCol = (TreeMap)pkList.get(0);
373                     logger.debug(pkList.toString()) ;
374                 }
375 
376                 // All columns' data
377                 ResultSet columns = dmd.getColumns(catalog, schemaName, tableName, null) ;
378                 ArrayList colList = (ArrayList)DBUtils.convertResultToList(columns) ;
379                 columns.close() ;
380                 ResultSet pKeys = dmd.getExportedKeys(catalog, schemaName, tableName) ;
381                 ArrayList pKeyList = new ArrayList() ; 
382                 while (pKeys.next()) {
383                     pKeyList.add(pKeys.getString("PKCOLUMN_NAME")) ;                 
384                 }
385                 pKeys.close() ;                
386                 //pks.add(((TreeMap)colList.get(0)).get("COLUMN_NAME")) ;
387 
388                 // All foreign keys' data
389                 ResultSet fKeys = dmd.getImportedKeys(catalog, schemaName, tableName) ;
390                 ArrayList fKeyList = (ArrayList)DBUtils.convertResultToList(fKeys) ;
391                 //logger.debug("FKs found=" + fKeyList);
392                 fKeys.close() ;
393 
394                 // For each list element (represents a table column) ...
395                 Element columnTag = null ;
396                 for (Iterator i=colList.iterator() ; i.hasNext() ;) {
397                     TreeMap tableCol = (TreeMap)i.next() ;
398                     // ... for each column construct column element
399                     columnTag = doc.createElement(COLUMN) ;
400 
401                     // get column name & description
402                     String colName = (String)tableCol.get("COLUMN_NAME") ;
403                     Element colDescTag = doc.createElement(SchemaConstants.DESCRIPTION) ;
404                     colDescTag.appendChild(doc.createTextNode((String)tableCol.get("REMARKS"))) ;
405                     Element columnNameTag = doc.createElement(SchemaConstants.COL_NAME) ;
406                     columnNameTag.appendChild(doc.createTextNode(colName));
407                     columnTag.appendChild(colDescTag) ;
408                     columnTag.appendChild(columnNameTag) ;
409 
410                     // get column datatype
411                     // defined as short in JDBC doco, Oracle returns BigDecimal, Sybase an Integer
412                     Number typeObj = (Number)tableCol.get("DATA_TYPE") ;
413                     int type = (typeObj==null ? Integer.MIN_VALUE : typeObj.intValue());
414                     Number scaleObj = (Number)tableCol.get("COLUMN_SIZE") ;
415                     int scale = (scaleObj==null ? Integer.MIN_VALUE : scaleObj.intValue());
416                     Number precisionObj = (Number)tableCol.get("DECIMAL_DIGITS") ;
417                     int precision = (precisionObj==null ? Integer.MIN_VALUE : precisionObj.intValue());
418                     String colType = new SqlType(type, scale, precision).toString() ;
419                     Element columnTypeTag = doc.createElement(COL_TYPE) ;
420                     columnTypeTag.appendChild(doc.createTextNode(colType)) ;
421                     columnTag.appendChild(columnTypeTag) ;
422 
423                     // get column null / not null
424                     // assume the worst (includes don't know case)
425                     boolean isNullable = false ;
426                     logger.debug("Nullable: " + tableCol.get("IS_NULLABLE").toString()) ;
427                     if (((String)tableCol.get("IS_NULLABLE")).equals("YES")) {
428                         isNullable = true ;
429                     }
430                     Element nullableTag = doc.createElement(NULLABLE) ;
431                     nullableTag.appendChild(doc.createTextNode(String.valueOf(isNullable))) ;
432                     columnTag.appendChild(nullableTag) ;
433 
434                     // determine if column is primary key
435                     if (pKeyList.contains(colName)) {
436                         Element pkTag = doc.createElement(SchemaConstants.PK) ;
437                         pkTag.appendChild(doc.createTextNode("true")) ;
438                         columnTag.appendChild(pkTag) ;
439                     }
440 
441                     // determine if column is a foreign key
442                     for (Iterator j=fKeyList.iterator() ; j.hasNext() ;) {
443                         TreeMap key = (TreeMap)j.next() ;
444                         String fKeyName = (String)key.get("FKCOLUMN_NAME") ;
445                         if (fKeyName!=null && fKeyName.equals(colName)) {
446                             logger.debug("Found foreign key for column: " + fKeyName);
447                             Element fkTag = doc.createElement(FK) ;
448                             Element fkTableTag = doc.createElement(FK_TABLE) ;
449                             fkTableTag.appendChild(doc.createTextNode(
450                                     (String)key.get("PKTABLE_NAME"))) ;
451                             fkTag.appendChild(fkTableTag) ;
452 
453                             // foreign key data col (the actual foreign key)
454                             Element fkDataColTag = doc.createElement(FK_DATA_COLUMN) ;
455                             String pkName = (String)key.get("PKCOLUMN_NAME") ;
456                             Element fkDataColDescTag = doc.createElement(SchemaConstants.DESCRIPTION) ;
457                             fkDataColDescTag.appendChild(doc.createTextNode((String)key.get("REMARKS"))) ;
458                             fkDataColTag.appendChild(fkDataColDescTag) ;
459                             Element fkDataColNameTag = doc.createElement(SchemaConstants.FK_DATA_COL_NAME) ;
460                             fkDataColNameTag.appendChild(doc.createTextNode(pkName)) ;
461 
462                             // fk display column
463                             Element fkDisplayColTag = doc.createElement(FK_DISPLAY_COLUMN) ;
464                             Element fkDisplayColNameTag = doc.createElement(SchemaConstants.FK_DISPLAY_COL_NAME) ;
465                             fkDisplayColNameTag.appendChild(doc.createTextNode(pkName)) ;
466                             fkDataColTag.appendChild(fkDataColNameTag) ;
467                             Element fkDisplayColDescTag = doc.createElement(SchemaConstants.DESCRIPTION) ;
468                             fkDisplayColDescTag.appendChild(doc.createTextNode((String)key.get("REMARKS"))) ;
469                             fkDisplayColTag.appendChild(fkDisplayColDescTag) ;
470                             fkDisplayColTag.appendChild(fkDisplayColNameTag) ;
471                             fkTag.appendChild(fkDataColTag) ;
472                             fkTag.appendChild(fkDisplayColTag) ;
473 
474                             columnTag.appendChild(fkTag) ;
475                         }
476                     }
477 
478                     tableTag.appendChild(columnTag) ;
479                 }
480 
481                 if (SchemaConstants.VIEW.equalsIgnoreCase(tableType)) {
482                     // For views find, their definition
483                     Element definitionTag = doc.createElement(SchemaConstants.DEFINITION) ;
484                     String definition = viewExporter.export(dmd.getConnection(), tableName) ; 
485                     logger.debug("definition=" + definition);
486                     definitionTag.appendChild(doc.createTextNode(definition)) ;
487                     tableTag.appendChild(definitionTag) ;
488                 } else { 
489 
490                     // Get Index info - 1st null indicates drop catalog from criteria
491                     ResultSet indexes = dmd.getIndexInfo(null, schemaName, 
492                             tableName, uniqueIndexOnly, approxIndexStats) ; 
493                     int indexCount = 0 ; 
494                     String lastIndexName = null ;
495                     Element indexTag = null ; 
496                     while (indexes.next()) {
497                         
498                         switch (indexes.getInt("TYPE")) {
499                         case DatabaseMetaData.tableIndexStatistic :
500                             // do nothing     
501                           break ; 
502                         default : 
503                             String indexName = indexes.getString("INDEX_NAME") ; 
504                             if (lastIndexName==null || !indexName.equals(lastIndexName)) {
505                                 // Create new index 
506                                 if (indexTag!=null && lastIndexName!=null) { 
507                                     tableTag.appendChild(indexTag) ;
508                                 } 
509                                 indexCount++ ; 
510                                 indexTag = doc.createElement(SchemaConstants.INDEX) ;
511                                 
512                                 Element indexNameTag = doc.createElement(SchemaConstants.NAME) ;
513                                 indexNameTag.appendChild(
514                                         doc.createTextNode(String.valueOf(indexName))) ;
515                                 indexTag.appendChild(indexNameTag) ;
516 
517                                 Element indexTypeTag = doc.createElement(SchemaConstants.TYPE) ;
518                                 indexTypeTag.appendChild(
519                                         doc.createTextNode(String.valueOf(indexes.getInt("TYPE")))) ;
520                                 indexTag.appendChild(indexTypeTag) ;
521 
522                                 Element indexUniqueTag = doc.createElement(SchemaConstants.INDEX_UNIQUE) ;
523                                 // This is horrible - the jdk1.3.1 javadoc says the column should be called 'NON-UNIQUE'
524                                 String unique = "UNKNOWN" ; 
525                                 if (provider!=null && provider.getDriver() != null 
526                                         && provider.getDriver().getName() != null) { 
527                                     if (provider.getDriver().getName().indexOf("sybase")>0) {
528                                         unique = (indexes.getBoolean("TABLE_NAME") ? "UNIQUE" : "NON-UNIQUE") ;                                     
529                                     } else if (provider.getDriver().getName().indexOf("microsoft")>0) {
530                                         // ?? 
531                                     } else if (provider.getDriver().getName().indexOf("oracle")>0) {
532                                         unique = (indexes.getBoolean("TABLE_NAME") ? "UNIQUE" : "NON-UNIQUE") ; 
533                                     } 
534                                 } 
535                                 indexUniqueTag.appendChild(doc.createTextNode(unique)) ;
536                                 indexTag.appendChild(indexUniqueTag) ;
537                             } 
538 
539                             // Add index column details
540                             Element colNameTag = doc.createElement(SchemaConstants.COL_NAME) ;
541                             colNameTag.appendChild(
542                                     doc.createTextNode(indexes.getString("COLUMN_NAME"))) ;
543                             indexTag.appendChild(colNameTag) ;                        
544                             
545                             lastIndexName = indexName ;
546                         } 
547                     }
548 
549                     if (indexTag!=null) { 
550                         tableTag.appendChild(indexTag) ;
551                     } 
552                     indexCount++ ; 
553 
554                     logger.warn("Index count for table " + tableName + "=" + indexCount);
555                     indexes.close() ; 
556                     
557 
558                 }
559 
560                 schemaTag.appendChild(tableTag);
561             } // end while have tables
562         } catch (Exception e) {
563             logger.error("Error whilst trying to process schema named: " + schemaName) ;
564             e.printStackTrace() ;
565             throw new SchemaHandlingException(e.getMessage()) ;
566         }
567         logger.info("METHOD_EXIT: addTables");
568     }
569 
570 /*
571  * Methods
572  */
573     /**
574      *
575      *
576      * @param args
577      * args[0] - tableName to turn into XML representation
578      */
579     public static void main(String[] args)
580     {
581         try {
582             SchemaExporter transformer = new SchemaExporter() ;
583             transformer.export(args[0], args[1], args[2], args[3]) ;
584 
585         } catch (Exception e) {
586             System.out.println("Failed: " + e.getMessage()) ;
587         }
588     }
589 
590     /**
591      * Returns the directory name classes should be stored in based on the
592      * Java package name received
593      */
594     private String getPackageDir(String javaPackage)
595     {
596         StringBuffer dir = new StringBuffer() ;
597         StringTokenizer st = new StringTokenizer(javaPackage, ".");
598         while (st.hasMoreTokens()) {
599             dir.append(st.nextToken()) ;
600             dir.append("/") ;
601         }
602 
603         // remove final '/' and return
604         return dir.substring(0, dir.length()-1) ;
605     }
606 
607 /*
608  * Properties
609  */
610     private String catalog ;
611     private String targetDir ;
612     private String targetSchema ;
613     private String[] tableTypes ;
614 
615     private boolean uniqueIndexOnly = false ; 
616     private boolean approxIndexStats = false ; 
617 
618     private ProviderExt provider ; 
619     private ViewExporter viewExporter = new ViewExporter() ; 
620     private SimpleDateFormat formatter ; 
621 
622 /*
623  * Constant Properties
624  */
625 
626 
627 
628 /*
629  * Application specifics
630  *//*
631     public static final String JAVA_PACKAGE_DIR = "package-dir" ;
632     public static final String JAVA_PACKAGE_SchemaConstants.NAME = "package-name" ;
633     public static final String JAVA_PACKAGE_VALUE = "org.thestephensons.webservices" ;
634 */
635 /*
636  * Document Tags
637  */
638     //public static final String APP = "app" ;
639     //public static final String JAVA = "java" ;
640     public static final String SCHEMAS = "schemas" ;
641     public static final String COLUMN = "column" ;
642     public static final String COL_NAME = "col-name" ;
643     public static final String COL_TYPE = "col-type" ;
644     public static final String NULLABLE = "null" ;
645     public static final String PK = "primary-key" ;
646     public static final String FK = "foreign-key" ;
647     public static final String FK_TABLE = "fk-table-name" ;
648     public static final String FK_DATA_COLUMN = "data-column" ;
649     public static final String FK_DATA_COL_NAME = "col-name" ;
650     public static final String FK_DISPLAY_COLUMN = "display-column" ;
651     public static final String FK_DISPLAY_COL_NAME = "col-name" ;
652 
653     /**
654      * Define a static Category instance for logging.
655      */
656     private static Category logger = Category.getInstance(SchemaExporter.class);
657 
658 }
659