Coverage Report - org.apache.ojb.broker.ant.VerifyMappingsTask
 
Classes in this File Line Coverage Branch Coverage Complexity
VerifyMappingsTask
N/A
N/A
1.514
 
 1  
 package org.apache.ojb.broker.ant;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 import java.io.FileInputStream;
 18  
 import java.io.IOException;
 19  
 import java.util.Properties;
 20  
 import javax.xml.parsers.ParserConfigurationException;
 21  
 import javax.xml.parsers.SAXParser;
 22  
 import javax.xml.parsers.SAXParserFactory;
 23  
 import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldPrivilegedImpl;
 24  
 import org.apache.tools.ant.AntClassLoader;
 25  
 import org.apache.tools.ant.BuildException;
 26  
 import org.apache.tools.ant.Project;
 27  
 import org.apache.tools.ant.Task;
 28  
 import org.apache.tools.ant.types.Path;
 29  
 import org.apache.tools.ant.types.Reference;
 30  
 import org.xml.sax.ContentHandler;
 31  
 import org.xml.sax.SAXException;
 32  
 import org.xml.sax.XMLReader;
 33  
 
 34  
 /**
 35  
  * An Ant task that will read the OJB repository xml file and confirm the
 36  
  * following:
 37  
  * 
 38  
  * a)Mapped classes exist. b)Mapped class fields exist c)Mapped database tables
 39  
  * exist. d)Mapped database columns exist. e)Mapped database columns jdbc type
 40  
  * matches the <code><field-descriptor/></code> "jdbc-type" attribute.
 41  
  * 
 42  
  * Obviously you should have built your classes, written your OJB
 43  
  * repository.xml file and built your database schema before running this task.
 44  
  * 
 45  
  * @author <a href="mailto:daren@softwarearena.com">Daren Drummond</a>
 46  
  * @version $Id: VerifyMappingsTask.java,v 1.1 2007-08-24 22:17:41 ewestfal Exp $
 47  
  */
 48  
 public class VerifyMappingsTask extends Task
 49  
 {
 50  
     private int m_errorCount = 0;
 51  
     private int m_warningCount = 0;
 52  
     private String m_repositoryPath = null;
 53  
     private String m_PropertiesFile = null;
 54  
     private String m_jdbcDriver = null;
 55  
     private String m_url = null;
 56  
     private String m_logon = null;
 57  
     private String m_password = null;
 58  
     private boolean m_ignoreCase = false;
 59  
     private boolean m_UseStrictTypeChecking = true;
 60  
     private Class m_persistenceClass = null;
 61  
     private boolean m_useXMLValidation = true;
 62  
     private boolean m_failOnError = true;
 63  
 
 64  
     private Path _classpath;
 65  
     
 66  
     public void setRepositoryFile(String path)
 67  
     {
 68  
         m_repositoryPath = path;
 69  
     }
 70  
 
 71  
     /**
 72  
      * Gets the path to the OJB repository file. (Includes the file name)
 73  
      * 
 74  
      * @return The path and file name of the OJB repository file
 75  
      */
 76  
     public String getRepositoryFile()
 77  
     {
 78  
         return m_repositoryPath;
 79  
     }
 80  
 
 81  
     /**
 82  
      * Sets the fully qualified path and file name of the OJB properties file.
 83  
      * 
 84  
      * @param path The path and file name of the OJB properties file
 85  
      */
 86  
     public void setPropertiesFile(String path)
 87  
     {
 88  
         m_PropertiesFile = path;
 89  
     }
 90  
 
 91  
     /**
 92  
      * Gets the value set by setPropertiesFile(String path)
 93  
      * 
 94  
      * @return The path and file name of the OJB properties file
 95  
      */
 96  
     public String getPropertiesFile()
 97  
     {
 98  
         return m_PropertiesFile;
 99  
     }
 100  
 
 101  
     /**
 102  
      * Sets the fully qualified class name of the jdbc driver to use.
 103  
      * 
 104  
      * @param jdbcClass Fully qualified class name of the jdbc driver
 105  
      */
 106  
     public void setJdbcDriver(String jdbcClass)
 107  
     {
 108  
         m_jdbcDriver = jdbcClass;
 109  
     }
 110  
 
 111  
     /**
 112  
      * Gets the value set by setJdbcDriver(String jdbcClass)
 113  
      * 
 114  
      * @return Fully qualified class name of the jdbc driver
 115  
      */
 116  
     public String getJdbcDriver()
 117  
     {
 118  
         return m_jdbcDriver;
 119  
     }
 120  
 
 121  
     /**
 122  
      * Sets the url connection string for the jdbc driver.
 123  
      * 
 124  
      * @param url The connection string for the jdbc driver
 125  
      */
 126  
     public void setUrl(String url)
 127  
     {
 128  
         m_url = url;
 129  
     }
 130  
 
 131  
     /**
 132  
      * Gets the value set by setUrl(String url)
 133  
      * 
 134  
      * @return The connection string for the jdbc driver
 135  
      */
 136  
     public String getUrl()
 137  
     {
 138  
         return m_url;
 139  
     }
 140  
 
 141  
     /**
 142  
      * Sets the database logon account that the utility should use.
 143  
      * 
 144  
      * @param logon The database logon account
 145  
      */
 146  
     public void setLogon(String logon)
 147  
     {
 148  
         m_logon = logon;
 149  
     }
 150  
 
 151  
     /**
 152  
      * Gets the value set by setLogon(String logon)
 153  
      * 
 154  
      * @return The database logon account
 155  
      */
 156  
     public String getLogon()
 157  
     {
 158  
         return m_logon;
 159  
     }
 160  
 
 161  
     /**
 162  
      * Sets the password for the database logon account.
 163  
      * 
 164  
      * @param password The password for the database logon account
 165  
      */
 166  
     public void setPassword(String password)
 167  
     {
 168  
         m_password = password;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Gets the value set by setPassword(String password)
 173  
      * 
 174  
      * @return The password for the database logon account
 175  
      */
 176  
     public String getPassword()
 177  
     {
 178  
         return m_password;
 179  
     }
 180  
 
 181  
     /**
 182  
      * Turns on W3C xml validation of the OJB repository.xml file (on by default).
 183  
      * 
 184  
      * @param sValidationFlag Whether to validate the xml
 185  
      */
 186  
     public void setUseXMLValidation(String sValidationFlag)
 187  
     {
 188  
         m_useXMLValidation = Boolean.valueOf(sValidationFlag).booleanValue();
 189  
     }
 190  
 
 191  
     /**
 192  
      * Determines whether the xml syntax is verified.
 193  
      * 
 194  
      * @return A flag indicating if W3c xml validation will be used to
 195  
      *         verify the OJB repository.xml file
 196  
      */
 197  
     public boolean getUseXMLValidation()
 198  
     {
 199  
         return m_useXMLValidation;
 200  
     }
 201  
 
 202  
     /**
 203  
      * Sets a flag indicating that this Ant task should throw a BuildException
 204  
      * if it encounters any verification errors. In most cases, this will have
 205  
      * the effect of stopping the build process.
 206  
      * 
 207  
      * @param sFailFlag Whether to stop the task upon the first error
 208  
      */
 209  
     public void setFailOnError(String sFailFlag)
 210  
     {
 211  
         m_failOnError = Boolean.valueOf(sFailFlag).booleanValue();
 212  
     }
 213  
 
 214  
     /**
 215  
      * Determines whether this task stops by throwing a BuildException when the first
 216  
      * error is encountered.
 217  
      * 
 218  
      * @return A flag indicating that the Ant task will throw a
 219  
      *         BuildException if it encounters any validation errors
 220  
      */
 221  
     public boolean getFailOnError()
 222  
     {
 223  
         return m_failOnError;
 224  
     }
 225  
 
 226  
     /**
 227  
      * Sets the flag for ignoring the db column name case when looking for db
 228  
      * columns.
 229  
      * 
 230  
      * @param sIgnoreCaseFlag Whether the case of the db column name is ignored
 231  
      */
 232  
     public void setIgnoreFieldNameCase(String sIgnoreCaseFlag)
 233  
     {
 234  
         m_ignoreCase = Boolean.valueOf(sIgnoreCaseFlag).booleanValue();
 235  
     }
 236  
 
 237  
     /**
 238  
      * Determines whether the task ignores the case of the db column name case
 239  
      * when looking for db columns. 
 240  
      * 
 241  
      * @return Flag indicating if the field name case will be
 242  
      *         ignored when searching for table column names
 243  
      */
 244  
     public boolean getIgnoreFieldNameCase()
 245  
     {
 246  
         return m_ignoreCase;
 247  
     }
 248  
 
 249  
     /**
 250  
      * Sets the flag for stict type checking of database column types. If this
 251  
      * value is set to "true" then the task will log a warning if the table
 252  
      * column jdbc type doesn't match the type specified in the OJB repository
 253  
      * field descriptor.
 254  
      * 
 255  
      * @param sTypeCheckingFlag Whether to use strict type checking
 256  
      */
 257  
     public void setUseStrictTypeChecking(String sTypeCheckingFlag)
 258  
     {
 259  
         m_UseStrictTypeChecking = Boolean.valueOf(sTypeCheckingFlag)
 260  
         .booleanValue();
 261  
     }
 262  
 
 263  
     /**
 264  
      * Gets the boolean equivalent of the value set by
 265  
      * setUseStrictTypeChecking(String sTypeCheckingFlag)
 266  
      * 
 267  
      * @return Flag indicating if strict type checking will be
 268  
      *         used when searching for database table columns
 269  
      */
 270  
     public boolean getUseStrictTypeChecking()
 271  
     {
 272  
         return m_UseStrictTypeChecking;
 273  
     }
 274  
 
 275  
     /**
 276  
      * Set the classpath for loading the driver.
 277  
      *
 278  
      * @param classpath the classpath
 279  
      */
 280  
     public void setClasspath(Path classpath)
 281  
     {
 282  
         if (_classpath == null)
 283  
         {
 284  
             _classpath = classpath;
 285  
         }
 286  
         else
 287  
         {
 288  
             _classpath.append(classpath);
 289  
         }
 290  
         log("Verification classpath is "+ _classpath,
 291  
             Project.MSG_VERBOSE);
 292  
     }
 293  
 
 294  
     /**
 295  
      * Create the classpath for loading the driver.
 296  
      *
 297  
      * @return the classpath
 298  
      */
 299  
     public Path createClasspath()
 300  
     {
 301  
         if (_classpath == null)
 302  
         {
 303  
             _classpath = new Path(getProject());
 304  
         }
 305  
         return _classpath.createPath();
 306  
     }
 307  
 
 308  
     /**
 309  
      * Set the classpath for loading the driver using the classpath reference.
 310  
      *
 311  
      * @param r reference to the classpath
 312  
      */
 313  
     public void setClasspathRef(Reference r)
 314  
     {
 315  
         createClasspath().setRefid(r);
 316  
         log("Verification classpath is "+ _classpath,
 317  
             Project.MSG_VERBOSE);
 318  
     }
 319  
     
 320  
     public void execute() throws BuildException
 321  
     {
 322  
         if (getRepositoryFile() == null)
 323  
         {    
 324  
             throw new BuildException("Could not find the repository file.");
 325  
         }
 326  
         try
 327  
         {
 328  
             System.setProperty("OJB.properties", getPropertiesFile());
 329  
             //Thread.currentThread().setContextClassLoader(getClassLoader());
 330  
             logWarning("IgnoreFieldNameCase: " + String.valueOf(getIgnoreFieldNameCase()));
 331  
             logWarning("UseStrictTypeChecking: " + String.valueOf(getUseStrictTypeChecking()));
 332  
             logWarning("UseXMLValidation: " + String.valueOf(getUseXMLValidation()));
 333  
             logWarning("UseStrictTypeChecking: " + String.valueOf(getUseStrictTypeChecking()));
 334  
             verifyRepository(getRepositoryFile());
 335  
             logWarning(getSummaryString(getErrorCount(), getWarningCount()));
 336  
         }
 337  
         catch (Exception e)
 338  
         {
 339  
             logWarning("There was an exception while verifying the repsitory: " + e.getMessage());
 340  
             if (getFailOnError())
 341  
             {
 342  
                 throw new BuildException("There was an exception while verifying the repsitory.", e);
 343  
             }
 344  
         }
 345  
         if (getFailOnError() && (getErrorCount() > 0))
 346  
         {
 347  
             throw new BuildException("Failed because 'failonerror' = true and there are " +
 348  
                                      String.valueOf(getErrorCount()) + " mapping error(s).");
 349  
         }
 350  
     }
 351  
 
 352  
     private String getSummaryString(int iBadCount, int iWarningCount)
 353  
     {
 354  
         return "\n---------------------------------------------------\n       Found " +
 355  
                String.valueOf(iBadCount)+
 356  
                " error(s) in the repository. \n       Found "+
 357  
                String.valueOf(iWarningCount)+
 358  
                " warning(s) in the repository.      \n---------------------------------------------------";
 359  
     }
 360  
 
 361  
     private void verifyRepository(String repositoryFile) throws ParserConfigurationException,
 362  
                                                                 SAXException,
 363  
                                                                 IOException
 364  
     {
 365  
         log("verifyRepository: Entered.");
 366  
 
 367  
         long      start  = System.currentTimeMillis();
 368  
         SAXParser p      = SAXParserFactory.newInstance().newSAXParser();
 369  
         XMLReader reader = p.getXMLReader();
 370  
 
 371  
         reader.setFeature("http://xml.org/sax/features/validation",
 372  
                           getUseXMLValidation());
 373  
 
 374  
         // create handler for verifying the repository structure
 375  
         ContentHandler handler = new RepositoryVerifierHandler(this);
 376  
 
 377  
         logInfo("Starting Parser...");
 378  
         reader.setContentHandler(handler);
 379  
         reader.parse(repositoryFile);
 380  
         logInfo("Done Parsing.");
 381  
 
 382  
         long stop = System.currentTimeMillis();
 383  
 
 384  
         setErrorCount(((RepositoryVerifierHandler)handler).getErrorCount());
 385  
         setWarningCount(((RepositoryVerifierHandler)handler).getWarningCount());
 386  
         logWarning("loading XML took " + (stop - start) + " msecs");
 387  
     }
 388  
 
 389  
     /**
 390  
      * Log a warning with the Ant out stream.
 391  
      * 
 392  
      * @param msg The message to log
 393  
      */
 394  
     public void logWarning(String msg)
 395  
     {
 396  
         log(msg, Project.MSG_WARN);
 397  
     }
 398  
 
 399  
     /**
 400  
      * Log an Info message with the Ant out stream. Info messages can be
 401  
      * suppressed from the command line by starting ant with the -quiet option.
 402  
      * 
 403  
      * @param msg The message to log
 404  
      */
 405  
     public void logInfo(String msg)
 406  
     {
 407  
         log(msg, Project.MSG_INFO);
 408  
     }
 409  
 
 410  
     protected int getErrorCount()
 411  
     {
 412  
         return m_errorCount;
 413  
     }
 414  
 
 415  
     protected void setErrorCount(int count)
 416  
     {
 417  
         m_errorCount = count;
 418  
     }
 419  
 
 420  
     protected int getWarningCount()
 421  
     {
 422  
         return m_warningCount;
 423  
     }
 424  
 
 425  
     protected void setWarningCount(int count)
 426  
     {
 427  
         m_warningCount = count;
 428  
     }
 429  
 
 430  
     /**
 431  
      * Tests to see if the jdbc connection information was specified in the tag
 432  
      * xml.
 433  
      * 
 434  
      * @return <code>true</code> if the jdbc connection information was
 435  
      *         supplied in the tag xml
 436  
      */
 437  
     public boolean hasConnectionInfo()
 438  
     {
 439  
         return (m_jdbcDriver != null && m_url != null && m_logon != null && m_password != null);
 440  
     }
 441  
 
 442  
     Class loadClass(String className) throws ClassNotFoundException
 443  
     {
 444  
         if (_classpath != null)
 445  
         {
 446  
             log("Loading " + className + " using AntClassLoader with classpath " + _classpath,
 447  
                 Project.MSG_VERBOSE);
 448  
 
 449  
             AntClassLoader loader = new AntClassLoader(getProject(), _classpath);
 450  
 
 451  
             return loader.loadClass(className);
 452  
         }
 453  
         else
 454  
         {
 455  
             log("Loading " + className + " using system loader.",
 456  
                 Project.MSG_VERBOSE);
 457  
             return Class.forName(className);
 458  
         }
 459  
     }
 460  
     
 461  
     /**
 462  
      * Returns the Class object of the class specified in the OJB.properties
 463  
      * file for the "PersistentFieldClass" property.
 464  
      * 
 465  
      * @return Class The Class object of the "PersistentFieldClass" class
 466  
      *         specified in the OJB.properties file.
 467  
      */
 468  
     public Class getPersistentFieldClass()
 469  
     {
 470  
         if (m_persistenceClass == null)
 471  
         {
 472  
             Properties properties = new Properties();
 473  
             try
 474  
             {
 475  
                 this.logWarning("Loading properties file: " + getPropertiesFile());
 476  
                 properties.load(new FileInputStream(getPropertiesFile()));
 477  
             }
 478  
             catch (IOException e)
 479  
             {
 480  
                 this.logWarning("Could not load properties file '" + getPropertiesFile()
 481  
                         + "'. Using PersistentFieldDefaultImpl.");
 482  
                 e.printStackTrace();
 483  
             }
 484  
             try
 485  
             {
 486  
                 String className = properties.getProperty("PersistentFieldClass");
 487  
 
 488  
                 m_persistenceClass = loadClass(className);
 489  
             }
 490  
             catch (ClassNotFoundException e)
 491  
             {
 492  
                 e.printStackTrace();
 493  
                 m_persistenceClass = PersistentFieldPrivilegedImpl.class;
 494  
             }
 495  
             logWarning("PersistentFieldClass: " + m_persistenceClass.toString());
 496  
         }
 497  
         return m_persistenceClass;
 498  
     }
 499  
 }