Coverage Report - org.kuali.core.db.torque.KualiTorqueSchemaDumpTask
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiTorqueSchemaDumpTask
0%
0/331
0%
0/124
2.644
 
 1  
 package org.kuali.core.db.torque;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.FileOutputStream;
 5  
 import java.io.PrintWriter;
 6  
 import java.io.Writer;
 7  
 import java.sql.Connection;
 8  
 import java.sql.DatabaseMetaData;
 9  
 import java.sql.ResultSet;
 10  
 import java.sql.SQLException;
 11  
 import java.sql.Types;
 12  
 import java.util.ArrayList;
 13  
 import java.util.HashMap;
 14  
 import java.util.List;
 15  
 import java.util.Map;
 16  
 
 17  
 import org.apache.commons.io.FilenameUtils;
 18  
 import org.apache.commons.io.IOUtils;
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.apache.tools.ant.BuildException;
 21  
 import org.apache.tools.ant.Project;
 22  
 import org.apache.torque.engine.database.model.TypeMap;
 23  
 import org.apache.torque.engine.platform.Platform;
 24  
 import org.apache.torque.engine.platform.PlatformFactory;
 25  
 import org.apache.xerces.dom.DocumentImpl;
 26  
 import org.apache.xerces.dom.DocumentTypeImpl;
 27  
 import org.apache.xml.serialize.Method;
 28  
 import org.apache.xml.serialize.OutputFormat;
 29  
 import org.apache.xml.serialize.XMLSerializer;
 30  
 import org.kuali.core.db.torque.pojo.ForeignKey;
 31  
 import org.kuali.core.db.torque.pojo.Column;
 32  
 import org.kuali.core.db.torque.pojo.Reference;
 33  
 import org.kuali.core.db.torque.pojo.Index;
 34  
 
 35  
 import static org.kuali.db.JDBCUtils.*;
 36  
 import org.w3c.dom.Element;
 37  
 
 38  0
 public class KualiTorqueSchemaDumpTask extends DumpTask {
 39  
 
 40  0
         boolean processTables = true;
 41  0
         boolean processViews = true;
 42  0
         boolean processSequences = true;
 43  
 
 44  
         /**
 45  
          * The file XML will be written to
 46  
          */
 47  
         File schemaXMLFile;
 48  
 
 49  
         /**
 50  
          * DOM document produced.
 51  
          */
 52  
         DocumentImpl doc;
 53  
 
 54  
         /**
 55  
          * The document root element.
 56  
          */
 57  
         Element databaseNode;
 58  
 
 59  
         /**
 60  
          * Map of columns that have primary keys.
 61  
          */
 62  
         Map<String, String> primaryKeys;
 63  
 
 64  
         protected void showConfiguration() {
 65  0
                 super.showConfiguration();
 66  0
                 log("Exporting to: " + schemaXMLFile.getAbsolutePath());
 67  0
         }
 68  
 
 69  
         protected String getSystemId() {
 70  0
                 if (antCompatibilityMode) {
 71  0
                         return "database.dtd";
 72  
                 } else {
 73  0
                         return ImpexDTDResolver.DTD_LOCATION;
 74  
                 }
 75  
         }
 76  
 
 77  
         protected DocumentImpl getDocumentImpl() {
 78  0
                 DocumentTypeImpl docType = new DocumentTypeImpl(null, "database", null, getSystemId());
 79  0
                 DocumentImpl doc = new DocumentImpl(docType);
 80  0
                 doc.appendChild(doc.createComment(" " + getComment() + " "));
 81  0
                 return doc;
 82  
         }
 83  
 
 84  
         /**
 85  
          * Execute the task
 86  
          */
 87  
         public void execute() throws BuildException {
 88  
                 try {
 89  0
                         log("--------------------------------------");
 90  0
                         log("Impex - Schema Export");
 91  0
                         log("--------------------------------------");
 92  0
                         log("Loading platform for " + getTargetDatabase());
 93  0
                         Platform platform = PlatformFactory.getPlatformFor(targetDatabase);
 94  0
                         updateConfiguration(platform);
 95  0
                         showConfiguration();
 96  0
                         doc = getDocumentImpl();
 97  0
                         generateXML(platform);
 98  0
                         serialize();
 99  0
                 } catch (Exception e) {
 100  0
                         throw new BuildException(e);
 101  0
                 }
 102  0
                 log("Impex - Schema Export finished");
 103  0
         }
 104  
 
 105  
         protected void serialize() throws BuildException {
 106  0
                 Writer out = null;
 107  
                 try {
 108  0
                         File file = new File(FilenameUtils.getFullPath(getSchemaXMLFile().getCanonicalPath()));
 109  0
                         File parentDirectory = file.getParentFile();
 110  0
                         boolean mkdirs = parentDirectory.mkdirs();
 111  0
                         if (!mkdirs) {
 112  0
                                 throw new BuildException("Unable to create " + parentDirectory.getAbsolutePath());
 113  
                         }
 114  0
                         out = new PrintWriter(new FileOutputStream(getSchemaXMLFile()));
 115  0
                         OutputFormat format = new OutputFormat(Method.XML, getEncoding(), true);
 116  0
                         XMLSerializer xmlSerializer = new XMLSerializer(out, format);
 117  0
                         xmlSerializer.serialize(doc);
 118  0
                 } catch (Exception e) {
 119  0
                         throw new BuildException("Error serializing", e);
 120  
                 } finally {
 121  0
                         IOUtils.closeQuietly(out);
 122  0
                 }
 123  0
         }
 124  
 
 125  
         protected Map<String, String> getPrimaryKeys(Platform platform, DatabaseMetaData dbMetaData, String curTable)
 126  
                         throws SQLException {
 127  0
                 List<String> primKeys = platform.getPrimaryKeys(dbMetaData, schema, curTable);
 128  
 
 129  
                 // Set the primary keys.
 130  0
                 Map<String, String> primaryKeys = new HashMap<String, String>();
 131  0
                 for (int k = 0; k < primKeys.size(); k++) {
 132  0
                         String curPrimaryKey = (String) primKeys.get(k);
 133  0
                         primaryKeys.put(curPrimaryKey, curPrimaryKey);
 134  
                 }
 135  0
                 return primaryKeys;
 136  
         }
 137  
 
 138  
         protected Element getColumnElement(Column col, String curTable) {
 139  0
                 String name = col.getName();
 140  0
                 Integer type = col.getSqlType();
 141  0
                 int size = col.getSize();
 142  0
                 int scale = col.getDecimalDigits();
 143  
 
 144  0
                 Integer nullType = col.getNullType();
 145  0
                 String defValue = col.getDefValue();
 146  
 
 147  0
                 Element column = doc.createElement("column");
 148  0
                 column.setAttribute("name", name);
 149  
 
 150  0
                 column.setAttribute("type", TypeMap.getTorqueType(type).getName());
 151  
 
 152  0
                 if (size > 0
 153  
                                 && (type.intValue() == Types.CHAR || type.intValue() == Types.VARCHAR
 154  
                                                 || type.intValue() == Types.LONGVARCHAR || type.intValue() == Types.DECIMAL || type.intValue() == Types.NUMERIC)) {
 155  0
                         column.setAttribute("size", String.valueOf(size));
 156  
                 }
 157  
 
 158  0
                 if (scale > 0 && (type.intValue() == Types.DECIMAL || type.intValue() == Types.NUMERIC)) {
 159  0
                         column.setAttribute("scale", String.valueOf(scale));
 160  
                 }
 161  
 
 162  0
                 if (primaryKeys.containsKey(name)) {
 163  0
                         column.setAttribute("primaryKey", "true");
 164  
                         // JHK: protect MySQL from excessively long column in the PK
 165  
                         // System.out.println( curTable + "." + name + " / " + size );
 166  0
                         if (column.getAttribute("size") != null && size > 765) {
 167  0
                                 log("updating column " + curTable + "." + name + " length from " + size + " to 255");
 168  0
                                 column.setAttribute("size", "255");
 169  
                         }
 170  
                 } else {
 171  0
                         if (nullType.intValue() == DatabaseMetaData.columnNoNulls) {
 172  0
                                 column.setAttribute("required", "true");
 173  
                         }
 174  
                 }
 175  
 
 176  0
                 if (StringUtils.isNotBlank(defValue)) {
 177  0
                         defValue = getDefaultValue(defValue);
 178  0
                         column.setAttribute("default", defValue);
 179  
                 }
 180  0
                 return column;
 181  
         }
 182  
 
 183  
         protected String getDefaultValue(String defValue) {
 184  0
                 if (StringUtils.isBlank(defValue)) {
 185  0
                         return null;
 186  
                 }
 187  0
                 defValue = defValue.trim();
 188  
                 // trim out parens & quotes out of def value.
 189  
                 // makes sense for MSSQL. not sure about others.
 190  0
                 if (defValue.startsWith("(") && defValue.endsWith(")")) {
 191  0
                         defValue = defValue.substring(1, defValue.length() - 1);
 192  
                 }
 193  
 
 194  0
                 if (defValue.startsWith("'") && defValue.endsWith("'")) {
 195  0
                         defValue = defValue.substring(1, defValue.length() - 1);
 196  
                 }
 197  0
                 if (defValue.equals("NULL")) {
 198  0
                         defValue = "";
 199  
                 }
 200  0
                 return defValue;
 201  
         }
 202  
 
 203  
         protected void processColumns(DatabaseMetaData dbMetaData, String curTable, Element table) throws SQLException {
 204  0
                 List<Column> columns = getColumns(dbMetaData, curTable);
 205  0
                 for (Column column : columns) {
 206  0
                         Element columnElement = getColumnElement(column, curTable);
 207  0
                         table.appendChild(columnElement);
 208  0
                 }
 209  0
         }
 210  
 
 211  
         protected void processForeignKeys(DatabaseMetaData dbMetaData, String curTable, Element table) throws SQLException {
 212  0
                 Map<String, ForeignKey> foreignKeys = getForeignKeys(dbMetaData, curTable);
 213  
 
 214  
                 // Foreign keys for this table.
 215  0
                 for (String fkName : foreignKeys.keySet()) {
 216  0
                         Element fk = getForeignKeyElement(fkName, foreignKeys);
 217  0
                         table.appendChild(fk);
 218  0
                 }
 219  0
         }
 220  
 
 221  
         protected Element getForeignKeyElement(String fkName, Map<String, ForeignKey> foreignKeys) {
 222  0
                 Element fk = doc.createElement("foreign-key");
 223  0
                 fk.setAttribute("name", fkName);
 224  0
                 ForeignKey forKey = foreignKeys.get(fkName);
 225  0
                 String foreignKeyTable = forKey.getRefTableName();
 226  0
                 List<Reference> refs = forKey.getReferences();
 227  0
                 fk.setAttribute("foreignTable", foreignKeyTable);
 228  0
                 String onDelete = forKey.getOnDelete();
 229  
                 // gmcgrego - just adding onDelete if it's cascade so as not to affect kfs behavior
 230  0
                 if (onDelete == "cascade") {
 231  0
                         fk.setAttribute("onDelete", onDelete);
 232  
                 }
 233  0
                 for (Reference refData : refs) {
 234  0
                         Element ref = doc.createElement("reference");
 235  0
                         ref.setAttribute("local", refData.getLocalColumn());
 236  0
                         ref.setAttribute("foreign", refData.getForeignColumn());
 237  0
                         fk.appendChild(ref);
 238  0
                 }
 239  0
                 return fk;
 240  
         }
 241  
 
 242  
         protected void processIndexes(DatabaseMetaData dbMetaData, String curTable, Element table) throws SQLException {
 243  0
                 for (Index idx : getIndexes(dbMetaData, curTable)) {
 244  0
                         String tagName = idx.isUnique() ? "unique" : "index";
 245  0
                         Element index = doc.createElement(tagName);
 246  0
                         index.setAttribute("name", idx.getName());
 247  0
                         for (String colName : idx.getColumns()) {
 248  0
                                 Element col = doc.createElement(tagName + "-column");
 249  0
                                 col.setAttribute("name", colName);
 250  0
                                 index.appendChild(col);
 251  0
                         }
 252  0
                         table.appendChild(index);
 253  0
                 }
 254  0
         }
 255  
 
 256  
         protected void processTable(String curTable, Platform platform, DatabaseMetaData dbMetaData) throws SQLException {
 257  0
                 long start = System.currentTimeMillis();
 258  
 
 259  0
                 Element table = doc.createElement("table");
 260  0
                 table.setAttribute("name", curTable);
 261  
 
 262  
                 // Setup the primary keys.
 263  0
                 primaryKeys = getPrimaryKeys(platform, dbMetaData, curTable);
 264  
 
 265  
                 // Process columns
 266  0
                 processColumns(dbMetaData, curTable, table);
 267  
 
 268  
                 // Process foreign keys
 269  0
                 processForeignKeys(dbMetaData, curTable, table);
 270  
 
 271  
                 // Process indexes
 272  0
                 processIndexes(dbMetaData, curTable, table);
 273  
 
 274  
                 // Add this table to the XML
 275  0
                 databaseNode.appendChild(table);
 276  
 
 277  0
                 log(utils.pad("Processed " + curTable, System.currentTimeMillis() - start));
 278  0
         }
 279  
 
 280  
         protected void processTables(Platform platform, DatabaseMetaData dbMetaData) throws SQLException {
 281  0
                 if (!processTables) {
 282  0
                         return;
 283  
                 }
 284  
 
 285  0
                 List<String> tableList = platform.getTableNames(dbMetaData, schema);
 286  0
                 log("Found " + tableList.size() + " tables");
 287  0
                 StringFilter filterer = new StringFilter(includePatterns, excludePatterns);
 288  0
                 filterer.filter(tableList.iterator());
 289  0
                 log("Processing " + tableList.size() + " tables after filtering is applied");
 290  
 
 291  0
                 for (String curTable : tableList) {
 292  0
                         processTable(curTable, platform, dbMetaData);
 293  
                 }
 294  0
         }
 295  
 
 296  
         protected void processViews(Platform platform, DatabaseMetaData dbMetaData) throws SQLException {
 297  0
                 if (!processViews) {
 298  0
                         return;
 299  
                 }
 300  0
                 List<String> viewNames = getViewNames(dbMetaData);
 301  0
                 for (String viewName : viewNames) {
 302  0
                         Element view = doc.createElement("view");
 303  0
                         view.setAttribute("name", viewName);
 304  
                         /**
 305  
                          * <view name="" viewdefinition="" />
 306  
                          */
 307  0
                         String definition = platform.getViewDefinition(dbMetaData.getConnection(), schema, viewName);
 308  0
                         definition = definition.replaceAll("\0", "");
 309  0
                         view.setAttribute("viewdefinition", definition);
 310  0
                         databaseNode.appendChild(view);
 311  0
                 }
 312  0
         }
 313  
 
 314  
         protected void processSequences(Platform platform, DatabaseMetaData dbMetaData) throws SQLException {
 315  0
                 if (!processSequences) {
 316  0
                         return;
 317  
                 }
 318  0
                 List<String> sequenceNames = getSequenceNames(dbMetaData);
 319  0
                 for (String sequenceName : sequenceNames) {
 320  0
                         Element sequence = doc.createElement("sequence");
 321  0
                         sequence.setAttribute("name", sequenceName);
 322  
                         /*
 323  
                          * <view name="" nextval="" />
 324  
                          */
 325  0
                         Long nextVal = platform.getSequenceNextVal(dbMetaData.getConnection(), schema, sequenceName);
 326  0
                         sequence.setAttribute("nextval", nextVal.toString());
 327  
 
 328  0
                         databaseNode.appendChild(sequence);
 329  0
                 }
 330  0
                 doc.appendChild(databaseNode);
 331  0
         }
 332  
 
 333  
         protected String getName() {
 334  0
                 return artifactId;
 335  
         }
 336  
 
 337  
         /**
 338  
          * Generates an XML database schema from JDBC metadata.
 339  
          * 
 340  
          * @throws Exception
 341  
          *             a generic exception.
 342  
          */
 343  
         protected void generateXML(Platform platform) throws Exception {
 344  
 
 345  0
                 Connection connection = null;
 346  
                 try {
 347  
                         // Attempt to connect to a database.
 348  0
                         connection = getConnection();
 349  
 
 350  
                         // Get the database Metadata.
 351  0
                         DatabaseMetaData dbMetaData = connection.getMetaData();
 352  
 
 353  0
                         databaseNode = doc.createElement("database");
 354  0
                         databaseNode.setAttribute("name", getName());
 355  
                         // JHK added naming method
 356  0
                         databaseNode.setAttribute("defaultJavaNamingMethod", "nochange");
 357  
 
 358  0
                         processTables(platform, dbMetaData);
 359  0
                         processViews(platform, dbMetaData);
 360  0
                         processSequences(platform, dbMetaData);
 361  
                 } finally {
 362  0
                         closeQuietly(connection);
 363  0
                 }
 364  0
         }
 365  
 
 366  
         public List<String> getViewNames(DatabaseMetaData dbMeta) throws SQLException {
 367  0
                 log("Getting view list...");
 368  0
                 List<String> tables = new ArrayList<String>();
 369  0
                 ResultSet tableNames = null;
 370  
                 // these are the entity types we want from the database
 371  0
                 String[] types = { "VIEW" }; // JHK: removed views from list
 372  
                 try {
 373  0
                         tableNames = dbMeta.getTables(null, schema, null, types);
 374  0
                         while (tableNames.next()) {
 375  0
                                 String name = tableNames.getString(3);
 376  0
                                 tables.add(name);
 377  0
                         }
 378  
                 } finally {
 379  0
                         if (tableNames != null) {
 380  0
                                 tableNames.close();
 381  
                         }
 382  
                 }
 383  0
                 log("Found " + tables.size() + " views.");
 384  0
                 return tables;
 385  
         }
 386  
 
 387  
         public boolean isSequence(String sequenceName) {
 388  0
                 return sequenceName.toUpperCase().startsWith("SEQ_") || sequenceName.toUpperCase().startsWith("SEQUENCE_")
 389  
                                 || sequenceName.toUpperCase().endsWith("_SEQ") || sequenceName.toUpperCase().endsWith("_SEQUENCE")
 390  
                                 || sequenceName.toUpperCase().endsWith("_ID") || sequenceName.toUpperCase().endsWith("_S");
 391  
         }
 392  
 
 393  
         public List<String> getSequenceNames(DatabaseMetaData dbMeta) throws SQLException {
 394  0
                 log("Getting sequence list...");
 395  0
                 List<String> tables = new ArrayList<String>();
 396  0
                 ResultSet tableNames = null;
 397  
                 // these are the entity types we want from the database
 398  0
                 String[] types = { "TABLE", "SEQUENCE" }; // JHK: removed views from list
 399  
                 try {
 400  0
                         tableNames = dbMeta.getTables(null, schema, null, types);
 401  0
                         while (tableNames.next()) {
 402  0
                                 String name = tableNames.getString(3);
 403  0
                                 if (isSequence(name)) {
 404  0
                                         tables.add(name);
 405  
                                 }
 406  0
                         }
 407  
                 } finally {
 408  0
                         if (tableNames != null) {
 409  0
                                 tableNames.close();
 410  
                         }
 411  
                 }
 412  0
                 log("Found " + tables.size() + " sequences.");
 413  0
                 return tables;
 414  
         }
 415  
 
 416  
         // for ( int i = 1; i <= tableNames.getMetaData().getColumnCount(); i++ ) {
 417  
         // System.out.print( tableNames.getMetaData().getColumnName( i ) + "," );
 418  
         // }
 419  
         // System.out.println();
 420  
         // for ( int i = 1; i <= tableNames.getMetaData().getColumnCount(); i++ ) {
 421  
         // System.out.print( tableNames.getString( i ) + "," );
 422  
         // }
 423  
         // System.out.println();
 424  
 
 425  
         /**
 426  
          * Retrieves all the column names and types for a given table from JDBC metadata. It returns a List of Lists. Each
 427  
          * element of the returned List is a List with:
 428  
          * 
 429  
          * element 0 => a String object for the column name. element 1 => an Integer object for the column type. element 2
 430  
          * => size of the column. element 3 => null type.
 431  
          * 
 432  
          * @param dbMeta
 433  
          *            JDBC metadata.
 434  
          * @param tableName
 435  
          *            Table from which to retrieve column information.
 436  
          * @return The list of columns in <code>tableName</code>.
 437  
          * @throws SQLException
 438  
          */
 439  
         protected List<Column> getColumns(DatabaseMetaData dbMeta, String tableName) throws SQLException {
 440  0
                 List<Column> columns = new ArrayList<Column>();
 441  0
                 ResultSet columnSet = null;
 442  
                 try {
 443  0
                         columnSet = dbMeta.getColumns(null, schema, tableName, null);
 444  0
                         while (columnSet.next()) {
 445  0
                                 String name = columnSet.getString(4);
 446  0
                                 Integer sqlType = new Integer(columnSet.getString(5));
 447  0
                                 Integer size = new Integer(columnSet.getInt(7));
 448  0
                                 Integer decimalDigits = new Integer(columnSet.getInt(9));
 449  0
                                 Integer nullType = new Integer(columnSet.getInt(11));
 450  0
                                 String defValue = columnSet.getString(13);
 451  
 
 452  0
                                 Column col = new Column();
 453  0
                                 col.setName(name);
 454  0
                                 col.setSqlType(sqlType);
 455  0
                                 col.setSize(size);
 456  0
                                 col.setNullType(nullType);
 457  0
                                 col.setDefValue(defValue);
 458  0
                                 col.setDecimalDigits(decimalDigits);
 459  0
                                 columns.add(col);
 460  0
                         }
 461  
                 } finally {
 462  0
                         closeQuietly(columnSet);
 463  0
                 }
 464  0
                 return columns;
 465  
         }
 466  
 
 467  
         protected String getOnDelete(ResultSet foreignKeys) throws SQLException {
 468  0
                 int deleteRule = foreignKeys.getInt(11);
 469  0
                 String onDelete = "none";
 470  0
                 if (deleteRule == DatabaseMetaData.importedKeyCascade) {
 471  0
                         onDelete = "cascade";
 472  0
                 } else if (deleteRule == DatabaseMetaData.importedKeyRestrict) {
 473  0
                         onDelete = "restrict";
 474  0
                 } else if (deleteRule == DatabaseMetaData.importedKeySetNull) {
 475  0
                         onDelete = "setnull";
 476  
                 }
 477  0
                 return onDelete;
 478  
         }
 479  
 
 480  
         protected String getForeignKeyName(ResultSet foreignKeys, String refTableName) throws SQLException {
 481  0
                 String fkName = foreignKeys.getString(12);
 482  
                 // if FK has no name - make it up (use tablename instead)
 483  0
                 if (fkName == null) {
 484  0
                         fkName = refTableName;
 485  
                 }
 486  0
                 return fkName;
 487  
         }
 488  
 
 489  
         protected ForeignKey getNewKualiForeignKey(String refTableName, String onDelete) {
 490  0
                 ForeignKey fk = new ForeignKey();
 491  0
                 fk.setRefTableName(refTableName); // referenced table name
 492  0
                 fk.setReferences(new ArrayList<Reference>());
 493  0
                 fk.setOnDelete(onDelete);
 494  0
                 return fk;
 495  
         }
 496  
 
 497  
         protected void addForeignKey(Map<String, ForeignKey> fks, String fkName, String refTableName, String onDelete,
 498  
                         ResultSet foreignKeys) throws SQLException {
 499  0
                 ForeignKey fk = (ForeignKey) fks.get(fkName);
 500  0
                 if (fk == null) {
 501  0
                         fk = getNewKualiForeignKey(refTableName, onDelete);
 502  0
                         fks.put(fkName, fk);
 503  
                 }
 504  0
                 List<Reference> references = fk.getReferences();
 505  0
                 Reference reference = new Reference();
 506  0
                 reference.setLocalColumn(foreignKeys.getString(8)); // local column
 507  0
                 reference.setForeignColumn(foreignKeys.getString(4)); // foreign column
 508  0
                 references.add(reference);
 509  0
         }
 510  
 
 511  
         /**
 512  
          * Retrieves a list of foreign key columns for a given table.
 513  
          * 
 514  
          * @param dbMeta
 515  
          *            JDBC metadata.
 516  
          * @param tableName
 517  
          *            Table from which to retrieve FK information.
 518  
          * @return A list of foreign keys in <code>tableName</code>.
 519  
          * @throws SQLException
 520  
          */
 521  
         protected Map<String, ForeignKey> getForeignKeys(DatabaseMetaData dbMeta, String tableName) throws SQLException {
 522  0
                 Map<String, ForeignKey> fks = new HashMap<String, ForeignKey>();
 523  0
                 ResultSet foreignKeys = null;
 524  
                 try {
 525  0
                         foreignKeys = dbMeta.getImportedKeys(null, schema, tableName);
 526  0
                         while (foreignKeys.next()) {
 527  0
                                 String refTableName = foreignKeys.getString(3);
 528  0
                                 String fkName = getForeignKeyName(foreignKeys, refTableName);
 529  0
                                 String onDelete = getOnDelete(foreignKeys);
 530  0
                                 addForeignKey(fks, fkName, refTableName, onDelete, foreignKeys);
 531  0
                         }
 532  0
                 } catch (SQLException e) {
 533  
                         // this seems to be happening in some db drivers (sybase)
 534  
                         // when retrieving foreign keys from views.
 535  0
                         log("Could not read foreign keys for Table " + tableName + " : " + e.getMessage(), Project.MSG_WARN);
 536  
                 } finally {
 537  0
                         closeQuietly(foreignKeys);
 538  0
                 }
 539  0
                 return fks;
 540  
         }
 541  
 
 542  
         protected String getPrimaryKeyName(String tableName, DatabaseMetaData dbMeta) throws SQLException {
 543  0
                 ResultSet pkInfo = null;
 544  
                 try {
 545  0
                         pkInfo = dbMeta.getPrimaryKeys(null, schema, tableName);
 546  0
                         if (pkInfo.next()) {
 547  0
                                 return pkInfo.getString("PK_NAME");
 548  
                         }
 549  0
                 } catch (SQLException e) {
 550  0
                         log("Could not locate primary key info for " + tableName + " : " + e.getMessage(), Project.MSG_WARN);
 551  
                 } finally {
 552  0
                         closeQuietly(pkInfo);
 553  0
                 }
 554  0
                 return null;
 555  
         }
 556  
 
 557  
         protected Index getTableIndex(ResultSet indexInfo, String pkName) throws SQLException {
 558  0
                 Index index = new Index();
 559  0
                 index.setName(indexInfo.getString("INDEX_NAME"));
 560  0
                 index.setUnique(!indexInfo.getBoolean("NON_UNIQUE"));
 561  0
                 return index;
 562  
         }
 563  
 
 564  
         protected void addIndexIfNotPK(Index index, String pkName, List<Index> indexes) {
 565  
                 // if has the same name as the PK, don't add it to the index list
 566  0
                 if (pkName == null || !pkName.equals(index.getName())) {
 567  0
                         indexes.add(index);
 568  0
                         log("Added " + index.getName() + " to index list", Project.MSG_DEBUG);
 569  
                 } else {
 570  0
                         log("Skipping PK: " + index.getName(), Project.MSG_DEBUG);
 571  
                 }
 572  0
         }
 573  
 
 574  
         public List<Index> getIndexes(DatabaseMetaData dbMeta, String tableName) throws SQLException {
 575  0
                 List<Index> indexes = new ArrayList<Index>();
 576  
 
 577  
                 // need to ensure that the PK is not returned as an index
 578  0
                 String pkName = getPrimaryKeyName(tableName, dbMeta);
 579  
 
 580  0
                 ResultSet indexInfo = null;
 581  
                 try {
 582  0
                         indexInfo = dbMeta.getIndexInfo(null, schema, tableName, false, true);
 583  0
                         Index currIndex = null;
 584  0
                         while (indexInfo.next()) {
 585  
 
 586  
                                 // Extract the name of the index
 587  0
                                 String name = indexInfo.getString("INDEX_NAME");
 588  0
                                 if (name == null) {
 589  
                                         // If there is no name, we are done
 590  0
                                         continue;
 591  
                                 }
 592  
 
 593  
                                 // If this is the first time we are assigning a value to currIndex, OR
 594  
                                 // we have scrolled to the next row in the result set and are now on a
 595  
                                 // new index, we need to add to our list of indexes
 596  0
                                 if (currIndex == null || !name.equals(currIndex.getName())) {
 597  
                                         // Get a new TableIndex object
 598  0
                                         currIndex = getTableIndex(indexInfo, pkName);
 599  
                                         // Add this index to the list if it is not the primary key index
 600  
                                         // The PK is handled elsewhere
 601  0
                                         addIndexIfNotPK(currIndex, pkName, indexes);
 602  
                                 }
 603  
 
 604  
                                 // Add column information to the current index
 605  0
                                 currIndex.getColumns().add(indexInfo.getString("COLUMN_NAME"));
 606  0
                         }
 607  0
                 } catch (SQLException e) {
 608  0
                         log("Could not read indexes for Table " + tableName + " : " + e.getMessage(), Project.MSG_WARN);
 609  
                 } finally {
 610  0
                         closeQuietly(indexInfo);
 611  0
                 }
 612  0
                 return indexes;
 613  
         }
 614  
 
 615  
         public DocumentImpl getDoc() {
 616  0
                 return doc;
 617  
         }
 618  
 
 619  
         public void setDoc(DocumentImpl doc) {
 620  0
                 this.doc = doc;
 621  0
         }
 622  
 
 623  
         public Element getDatabaseNode() {
 624  0
                 return databaseNode;
 625  
         }
 626  
 
 627  
         public void setDatabaseNode(Element databaseNode) {
 628  0
                 this.databaseNode = databaseNode;
 629  0
         }
 630  
 
 631  
         public Map<String, String> getPrimaryKeys() {
 632  0
                 return primaryKeys;
 633  
         }
 634  
 
 635  
         public void setPrimaryKeys(Map<String, String> primaryKeys) {
 636  0
                 this.primaryKeys = primaryKeys;
 637  0
         }
 638  
 
 639  
         public boolean isProcessTables() {
 640  0
                 return processTables;
 641  
         }
 642  
 
 643  
         public boolean isProcessViews() {
 644  0
                 return processViews;
 645  
         }
 646  
 
 647  
         public boolean isProcessSequences() {
 648  0
                 return processSequences;
 649  
         }
 650  
 
 651  
         public File getSchemaXMLFile() {
 652  0
                 return schemaXMLFile;
 653  
         }
 654  
 
 655  
         public void setSchemaXMLFile(File schemaXMLFile) {
 656  0
                 this.schemaXMLFile = schemaXMLFile;
 657  0
         }
 658  
 
 659  
         public void setProcessTables(boolean processTables) {
 660  0
                 this.processTables = processTables;
 661  0
         }
 662  
 
 663  
         public void setProcessViews(boolean processViews) {
 664  0
                 this.processViews = processViews;
 665  0
         }
 666  
 
 667  
         public void setProcessSequences(boolean processSequences) {
 668  0
                 this.processSequences = processSequences;
 669  0
         }
 670  
 }