Coverage report

  %line %branch
org.apache.torque.task.TorqueJDBCTransformTask
0% 
0% 

 1  
 package org.apache.torque.task;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.io.FileOutputStream;
 20  
 import java.io.PrintWriter;
 21  
 
 22  
 import java.sql.Connection;
 23  
 import java.sql.DatabaseMetaData;
 24  
 import java.sql.DriverManager;
 25  
 import java.sql.ResultSet;
 26  
 import java.sql.SQLException;
 27  
 import java.sql.Types;
 28  
 
 29  
 import java.util.ArrayList;
 30  
 import java.util.Collection;
 31  
 import java.util.Hashtable;
 32  
 import java.util.Iterator;
 33  
 import java.util.List;
 34  
 
 35  
 import org.apache.tools.ant.BuildException;
 36  
 import org.apache.tools.ant.Task;
 37  
 
 38  
 import org.apache.torque.engine.database.model.TypeMap;
 39  
 import org.apache.torque.engine.database.transform.DTDResolver;
 40  
 
 41  
 import org.apache.xerces.dom.DocumentImpl;
 42  
 import org.apache.xerces.dom.DocumentTypeImpl;
 43  
 
 44  
 import org.apache.xml.serialize.Method;
 45  
 import org.apache.xml.serialize.OutputFormat;
 46  
 import org.apache.xml.serialize.XMLSerializer;
 47  
 
 48  
 import org.w3c.dom.Element;
 49  
 import org.w3c.dom.Node;
 50  
 
 51  
 /**
 52  
  * This class generates an XML schema of an existing database from
 53  
  * JDBC metadata.
 54  
  *
 55  
  * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
 56  
  * @author <a href="mailto:fedor.karpelevitch@barra.com">Fedor Karpelevitch</a>
 57  
  * @version $Id: TorqueJDBCTransformTask.java 239626 2005-08-24 12:19:51Z henning $
 58  
  */
 59  0
 public class TorqueJDBCTransformTask extends Task
 60  
 {
 61  
     /** Name of XML database schema produced. */
 62  
     protected String xmlSchema;
 63  
 
 64  
     /** JDBC URL. */
 65  
     protected String dbUrl;
 66  
 
 67  
     /** JDBC driver. */
 68  
     protected String dbDriver;
 69  
 
 70  
     /** JDBC user name. */
 71  
     protected String dbUser;
 72  
 
 73  
     /** JDBC password. */
 74  
     protected String dbPassword;
 75  
 
 76  
     /** DB schema to use. */
 77  
     protected String dbSchema;
 78  
 
 79  
     /** DOM document produced. */
 80  
     protected DocumentImpl doc;
 81  
 
 82  
     /** The document root element. */
 83  
     protected Element databaseNode;
 84  
 
 85  
     /** Hashtable of columns that have primary keys. */
 86  
     protected Hashtable primaryKeys;
 87  
 
 88  
     /** Hashtable to track what table a column belongs to. */
 89  
     protected Hashtable columnTableMap;
 90  
 
 91  
     protected boolean sameJavaName;
 92  
 
 93  
     private XMLSerializer xmlSerializer;
 94  
 
 95  
     public String getDbSchema()
 96  
     {
 97  0
         return dbSchema;
 98  
     }
 99  
 
 100  
     public void setDbSchema(String dbSchema)
 101  
     {
 102  0
         this.dbSchema = dbSchema;
 103  0
     }
 104  
 
 105  
     public void setDbUrl(String v)
 106  
     {
 107  0
         dbUrl = v;
 108  0
     }
 109  
 
 110  
     public void setDbDriver(String v)
 111  
     {
 112  0
         dbDriver = v;
 113  0
     }
 114  
 
 115  
     public void setDbUser(String v)
 116  
     {
 117  0
         dbUser = v;
 118  0
     }
 119  
 
 120  
     public void setDbPassword(String v)
 121  
     {
 122  0
         dbPassword = v;
 123  0
     }
 124  
 
 125  
     public void setOutputFile (String v)
 126  
     {
 127  0
         xmlSchema = v;
 128  0
     }
 129  
 
 130  
     public void setSameJavaName(boolean v)
 131  
     {
 132  0
         this.sameJavaName = v;
 133  0
     }
 134  
 
 135  
     public boolean isSameJavaName()
 136  
     {
 137  0
         return this.sameJavaName;
 138  
     }
 139  
 
 140  
     /**
 141  
      * Default constructor.
 142  
      *
 143  
      * @throws BuildException
 144  
      */
 145  
     public void execute() throws BuildException
 146  
     {
 147  0
         log("Torque - JDBCToXMLSchema starting");
 148  0
         log("Your DB settings are:");
 149  0
         log("driver : " + dbDriver);
 150  0
         log("URL : " + dbUrl);
 151  0
         log("user : " + dbUser);
 152  
         // log("password : " + dbPassword);
 153  0
         log("schema : " + dbSchema);
 154  
 
 155  0
         DocumentTypeImpl docType = new DocumentTypeImpl(null, "database", null,
 156  
                 DTDResolver.WEB_SITE_DTD);
 157  0
         doc = new DocumentImpl(docType);
 158  0
         doc.appendChild(doc.createComment(
 159  
                 " Autogenerated by JDBCToXMLSchema! "));
 160  
 
 161  
         try
 162  
         {
 163  0
             generateXML();
 164  0
             log(xmlSchema);
 165  0
             xmlSerializer = new XMLSerializer(
 166  
                     new PrintWriter(
 167  
                     new FileOutputStream(xmlSchema)),
 168  
                     new OutputFormat(Method.XML, null, true));
 169  0
             xmlSerializer.serialize(doc);
 170  
         }
 171  0
         catch (Exception e)
 172  
         {
 173  0
             throw new BuildException(e);
 174  0
         }
 175  0
         log("Torque - JDBCToXMLSchema finished");
 176  0
     }
 177  
 
 178  
     /**
 179  
      * Generates an XML database schema from JDBC metadata.
 180  
      *
 181  
      * @throws Exception a generic exception.
 182  
      */
 183  
     public void generateXML() throws Exception
 184  
     {
 185  
         // Load the Interbase Driver.
 186  0
         Class.forName(dbDriver);
 187  0
         log("DB driver sucessfuly instantiated");
 188  
 
 189  0
         Connection con = null;
 190  
         try
 191  
         {
 192  
             // Attempt to connect to a database.
 193  0
             con = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
 194  0
             log("DB connection established");
 195  
 
 196  
             // Get the database Metadata.
 197  0
             DatabaseMetaData dbMetaData = con.getMetaData();
 198  
 
 199  
             // The database map.
 200  0
             List tableList = getTableNames(dbMetaData);
 201  
 
 202  0
             databaseNode = doc.createElement("database");
 203  0
             databaseNode.setAttribute("name", dbUser);
 204  
 
 205  
             // Build a database-wide column -> table map.
 206  0
             columnTableMap = new Hashtable();
 207  
 
 208  0
             log("Building column/table map...");
 209  0
             for (int i = 0; i < tableList.size(); i++)
 210  
             {
 211  0
                 String curTable = (String) tableList.get(i);
 212  0
                 List columns = getColumns(dbMetaData, curTable);
 213  
 
 214  0
                 for (int j = 0; j < columns.size(); j++)
 215  
                 {
 216  0
                     List col = (List) columns.get(j);
 217  0
                     String name = (String) col.get(0);
 218  
 
 219  0
                     columnTableMap.put(name, curTable);
 220  
                 }
 221  
             }
 222  
 
 223  0
             for (int i = 0; i < tableList.size(); i++)
 224  
             {
 225  
                 // Add Table.
 226  0
                 String curTable = (String) tableList.get(i);
 227  
                 // dbMap.addTable(curTable);
 228  0
                 log("Processing table: " + curTable);
 229  
 
 230  0
                 Element table = doc.createElement("table");
 231  0
                 table.setAttribute("name", curTable);
 232  0
                 if (isSameJavaName())
 233  
                 {
 234  0
                     table.setAttribute("javaName", curTable);
 235  
                 }
 236  
 
 237  
                 // Add Columns.
 238  
                 // TableMap tblMap = dbMap.getTable(curTable);
 239  
 
 240  0
                 List columns = getColumns(dbMetaData, curTable);
 241  0
                 List primKeys = getPrimaryKeys(dbMetaData, curTable);
 242  0
                 Collection forgnKeys = getForeignKeys(dbMetaData, curTable);
 243  
 
 244  
                 // Set the primary keys.
 245  0
                 primaryKeys = new Hashtable();
 246  
 
 247  0
                 for (int k = 0; k < primKeys.size(); k++)
 248  
                 {
 249  0
                     String curPrimaryKey = (String) primKeys.get(k);
 250  0
                     primaryKeys.put(curPrimaryKey, curPrimaryKey);
 251  
                 }
 252  
 
 253  0
                 for (int j = 0; j < columns.size(); j++)
 254  
                 {
 255  0
                     List col = (List) columns.get(j);
 256  0
                     String name = (String) col.get(0);
 257  0
                     Integer type = ((Integer) col.get(1));
 258  0
                     int size = ((Integer) col.get(2)).class="keyword">intValue();
 259  
 
 260  
                     // From DatabaseMetaData.java
 261  
                     //
 262  
                     // Indicates column might not allow NULL values.  Huh?
 263  
                     // Might? Boy, that's a definitive answer.
 264  
                     /* int columnNoNulls = 0; */
 265  
 
 266  
                     // Indicates column definitely allows NULL values.
 267  
                     /* int columnNullable = 1; */
 268  
 
 269  
                     // Indicates NULLABILITY of column is unknown.
 270  
                     /* int columnNullableUnknown = 2; */
 271  
 
 272  0
                     Integer nullType = (Integer) col.get(3);
 273  0
                     String defValue = (String) col.get(4);
 274  
 
 275  0
                     Element column = doc.createElement("column");
 276  0
                     column.setAttribute("name", name);
 277  0
                     if (isSameJavaName())
 278  
                     {
 279  0
                         column.setAttribute("javaName", name);
 280  
                     }
 281  0
                     column.setAttribute("type", TypeMap.getTorqueType(type).getName());
 282  
 
 283  0
                     if (size > 0 && (type.intValue() == Types.CHAR
 284  
                             || type.intValue() == Types.VARCHAR
 285  
                             || type.intValue() == Types.LONGVARCHAR
 286  
                             || type.intValue() == Types.DECIMAL
 287  
                             || type.intValue() == Types.NUMERIC))
 288  
                     {
 289  0
                         column.setAttribute("size", String.valueOf(size));
 290  
                     }
 291  
 
 292  0
                     if (nullType.intValue() == 0)
 293  
                     {
 294  0
                         column.setAttribute("required", "true");
 295  
                     }
 296  
 
 297  0
                     if (primaryKeys.containsKey(name))
 298  
                     {
 299  0
                         column.setAttribute("primaryKey", "true");
 300  
                     }
 301  
 
 302  0
                     if (defValue != null)
 303  
                     {
 304  
                         // trim out parens & quotes out of def value.
 305  
                         // makes sense for MSSQL. not sure about others.
 306  0
                         if (defValue.startsWith("(") && defValue.endsWith(")"))
 307  
                         {
 308  0
                             defValue = defValue.substring(1, defValue.length() - 1);
 309  
                         }
 310  
 
 311  0
                         if (defValue.startsWith("'") && defValue.endsWith("'"))
 312  
                         {
 313  0
                             defValue = defValue.substring(1, defValue.length() - 1);
 314  
                         }
 315  
 
 316  0
                         column.setAttribute("default", defValue);
 317  
                     }
 318  0
                     table.appendChild(column);
 319  
                 }
 320  
 
 321  
                 // Foreign keys for this table.
 322  0
                 for (Iterator l = class="keyword">forgnKeys.iterator(); l.hasNext();)
 323  
                 {
 324  0
                     Object[] forKey = (Object[]) l.next();
 325  0
                     String foreignKeyTable = (String) forKey[0];
 326  0
                     List refs = (List) forKey[1];
 327  0
                     Element fk = doc.createElement("foreign-key");
 328  0
                     fk.setAttribute("foreignTable", foreignKeyTable);
 329  0
                     for (int m = 0; m < refs.size(); m++)
 330  
                     {
 331  0
                         Element ref = doc.createElement("reference");
 332  0
                         String[] refData = (String[]) refs.get(m);
 333  0
                         ref.setAttribute("local", refData[0]);
 334  0
                         ref.setAttribute("foreign", refData[1]);
 335  0
                         fk.appendChild(ref);
 336  
                     }
 337  0
                     table.appendChild(fk);
 338  
                 }
 339  0
                 databaseNode.appendChild(table);
 340  
             }
 341  0
             doc.appendChild(databaseNode);
 342  0
         }
 343  
         finally {
 344  0
             if (con != null)
 345  
             {
 346  0
                 con.close();
 347  0
                 con = null;
 348  
             }
 349  0
         }
 350  0
     }
 351  
 
 352  
     /**
 353  
      * Get all the table names in the current database that are not
 354  
      * system tables.
 355  
      *
 356  
      * @param dbMeta JDBC database metadata.
 357  
      * @return The list of all the tables in a database.
 358  
      * @throws SQLException
 359  
      */
 360  
     public List getTableNames(DatabaseMetaData dbMeta)
 361  
         throws SQLException
 362  
     {
 363  0
         log("Getting table list...");
 364  0
         List tables = new ArrayList();
 365  0
         ResultSet tableNames = null;
 366  
         // these are the entity types we want from the database
 367  0
         String[] types = {"TABLE", "VIEW"};
 368  
         try
 369  
         {
 370  0
             tableNames = dbMeta.getTables(null, dbSchema, "%", types);
 371  0
             while (tableNames.next())
 372  
             {
 373  0
                 String name = tableNames.getString(3);
 374  0
                 String type = tableNames.getString(4);
 375  0
                 tables.add(name);
 376  
             }
 377  
         }
 378  
         finally
 379  
         {
 380  0
             if (tableNames != null)
 381  
             {
 382  0
                 tableNames.close();
 383  
             }
 384  
         }
 385  0
         return tables;
 386  
     }
 387  
 
 388  
     /**
 389  
      * Retrieves all the column names and types for a given table from
 390  
      * JDBC metadata.  It returns a List of Lists.  Each element
 391  
      * of the returned List is a List with:
 392  
      *
 393  
      * element 0 => a String object for the column name.
 394  
      * element 1 => an Integer object for the column type.
 395  
      * element 2 => size of the column.
 396  
      * element 3 => null type.
 397  
      *
 398  
      * @param dbMeta JDBC metadata.
 399  
      * @param tableName Table from which to retrieve column information.
 400  
      * @return The list of columns in <code>tableName</code>.
 401  
      * @throws SQLException
 402  
      */
 403  
     public List getColumns(DatabaseMetaData dbMeta, String tableName)
 404  
             throws SQLException
 405  
     {
 406  0
         List columns = new ArrayList();
 407  0
         ResultSet columnSet = null;
 408  
         try
 409  
         {
 410  0
             columnSet = dbMeta.getColumns(null, dbSchema, tableName, class="keyword">null);
 411  0
             while (columnSet.next())
 412  
             {
 413  0
                 String name = columnSet.getString(4);
 414  0
                 Integer sqlType = new Integer(columnSet.getString(5));
 415  0
                 Integer size = new Integer(columnSet.getInt(7));
 416  0
                 Integer nullType = new Integer(columnSet.getInt(11));
 417  0
                 String defValue = columnSet.getString(13);
 418  
 
 419  0
                 List col = new ArrayList(5);
 420  0
                 col.add(name);
 421  0
                 col.add(sqlType);
 422  0
                 col.add(size);
 423  0
                 col.add(nullType);
 424  0
                 col.add(defValue);
 425  0
                 columns.add(col);
 426  
             }
 427  
         }
 428  
         finally
 429  
         {
 430  0
             if (columnSet != null)
 431  
             {
 432  0
                 columnSet.close();
 433  
             }
 434  
         }
 435  0
         return columns;
 436  
     }
 437  
 
 438  
     /**
 439  
      * Retrieves a list of the columns composing the primary key for a given
 440  
      * table.
 441  
      *
 442  
      * @param dbMeta JDBC metadata.
 443  
      * @param tableName Table from which to retrieve PK information.
 444  
      * @return A list of the primary key parts for <code>tableName</code>.
 445  
      * @throws SQLException
 446  
      */
 447  
     public List getPrimaryKeys(DatabaseMetaData dbMeta, String tableName)
 448  
             throws SQLException
 449  
     {
 450  0
         List pk = new ArrayList();
 451  0
         ResultSet parts = null;
 452  
         try
 453  
         {
 454  0
             parts = dbMeta.getPrimaryKeys(null, dbSchema, tableName);
 455  0
             while (parts.next())
 456  
             {
 457  0
                 pk.add(parts.getString(4));
 458  
             }
 459  
         }
 460  
         finally
 461  
         {
 462  0
             if (parts != null)
 463  
             {
 464  0
                 parts.close();
 465  
             }
 466  
         }
 467  0
         return pk;
 468  
     }
 469  
 
 470  
     /**
 471  
      * Retrieves a list of foreign key columns for a given table.
 472  
      *
 473  
      * @param dbMeta JDBC metadata.
 474  
      * @param tableName Table from which to retrieve FK information.
 475  
      * @return A list of foreign keys in <code>tableName</code>.
 476  
      * @throws SQLException
 477  
      */
 478  
     public Collection getForeignKeys(DatabaseMetaData dbMeta, String tableName)
 479  
         throws SQLException
 480  
     {
 481  0
         Hashtable fks = new Hashtable();
 482  0
         ResultSet foreignKeys = null;
 483  
         try
 484  
         {
 485  0
             foreignKeys = dbMeta.getImportedKeys(null, dbSchema, tableName);
 486  0
             while (foreignKeys.next())
 487  
             {
 488  0
                 String refTableName = foreignKeys.getString(3);
 489  0
                 String fkName = foreignKeys.getString(12);
 490  
                 // if FK has no name - make it up (use tablename instead)
 491  0
                 if (fkName == null)
 492  
                 {
 493  0
                     fkName = refTableName;
 494  
                 }
 495  0
                 Object[] fk = (Object[]) fks.get(fkName);
 496  
                 List refs;
 497  0
                 if (fk == null)
 498  
                 {
 499  0
                     fk = new Object[2];
 500  0
                     fk[0] = refTableName; //referenced table name
 501  0
                     refs = new ArrayList();
 502  0
                     fk[1] = refs;
 503  0
                     fks.put(fkName, fk);
 504  
                 }
 505  
                 else
 506  
                 {
 507  0
                     refs = (ArrayList) fk[1];
 508  
                 }
 509  0
                 String[] ref = new String[2];
 510  0
                 ref[0] = foreignKeys.getString(8); //local column
 511  0
                 ref[1] = foreignKeys.getString(4); //foreign column
 512  0
                 refs.add(ref);
 513  
             }
 514  
         }
 515  
         finally
 516  
         {
 517  0
             if (foreignKeys != null)
 518  
             {
 519  0
                 foreignKeys.close();
 520  
             }
 521  
         }
 522  0
         return fks.values();
 523  
     }
 524  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.