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

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