Coverage Report - liquibase.Liquibase
 
Classes in this File Line Coverage Branch Coverage Complexity
Liquibase
2%
11/367
7%
2/28
2
 
 1  
 package liquibase;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.IOException;
 5  
 import java.io.PrintStream;
 6  
 import java.io.Writer;
 7  
 import java.text.DateFormat;
 8  
 import java.util.Date;
 9  
 import java.util.List;
 10  
 
 11  
 import liquibase.changelog.ChangeLogIterator;
 12  
 import liquibase.changelog.ChangeLogParameters;
 13  
 import liquibase.changelog.ChangeSet;
 14  
 import liquibase.changelog.DatabaseChangeLog;
 15  
 import liquibase.changelog.RanChangeSet;
 16  
 import liquibase.changelog.filter.AfterTagChangeSetFilter;
 17  
 import liquibase.changelog.filter.AlreadyRanChangeSetFilter;
 18  
 import liquibase.changelog.filter.ContextChangeSetFilter;
 19  
 import liquibase.changelog.filter.CountChangeSetFilter;
 20  
 import liquibase.changelog.filter.DbmsChangeSetFilter;
 21  
 import liquibase.changelog.filter.ExecutedAfterChangeSetFilter;
 22  
 import liquibase.changelog.filter.NotRanChangeSetFilter;
 23  
 import liquibase.changelog.filter.ShouldRunChangeSetFilter;
 24  
 import liquibase.changelog.visitor.ChangeLogSyncVisitor;
 25  
 import liquibase.changelog.visitor.DBDocVisitor;
 26  
 import liquibase.changelog.visitor.ListVisitor;
 27  
 import liquibase.changelog.visitor.RollbackVisitor;
 28  
 import liquibase.changelog.visitor.UpdateVisitor;
 29  
 import liquibase.database.Database;
 30  
 import liquibase.database.DatabaseConnection;
 31  
 import liquibase.database.DatabaseFactory;
 32  
 import liquibase.diff.Diff;
 33  
 import liquibase.exception.DatabaseException;
 34  
 import liquibase.exception.LiquibaseException;
 35  
 import liquibase.exception.LockException;
 36  
 import liquibase.executor.Executor;
 37  
 import liquibase.executor.ExecutorService;
 38  
 import liquibase.executor.LoggingExecutor;
 39  
 import liquibase.lockservice.DatabaseChangeLogLock;
 40  
 import liquibase.lockservice.LockService;
 41  
 import liquibase.logging.LogFactory;
 42  
 import liquibase.logging.Logger;
 43  
 import liquibase.parser.ChangeLogParserFactory;
 44  
 import liquibase.resource.ResourceAccessor;
 45  
 import liquibase.statement.core.UpdateStatement;
 46  
 import liquibase.util.LiquibaseUtil;
 47  
 import liquibase.util.StreamUtil;
 48  
 import liquibase.util.StringUtils;
 49  
 
 50  
 /**
 51  
  * Core Liquibase facade. Although there are several ways of executing Liquibase (Ant, command line, etc.) they are all
 52  
  * wrappers around this class.
 53  
  */
 54  
 public class Liquibase {
 55  
 
 56  
     public static final String SHOULD_RUN_SYSTEM_PROPERTY = "liquibase.should.run";
 57  
 
 58  
     private String changeLogFile;
 59  
     private ResourceAccessor resourceAccessor;
 60  
 
 61  
     protected Database database;
 62  
     private Logger log;
 63  
 
 64  
     private ChangeLogParameters changeLogParameters;
 65  
 
 66  
     public Liquibase(String changeLogFile, ResourceAccessor resourceAccessor, DatabaseConnection conn)
 67  
             throws LiquibaseException {
 68  0
         this(changeLogFile, resourceAccessor, DatabaseFactory.getInstance().findCorrectDatabaseImplementation(conn));
 69  0
     }
 70  
 
 71  
     public Liquibase(String changeLogFile, ResourceAccessor resourceAccessor, Database database)
 72  1
             throws LiquibaseException {
 73  1
         log = LogFactory.getLogger();
 74  
 
 75  1
         if (changeLogFile != null) {
 76  1
             this.changeLogFile = changeLogFile.replace('\\', '/'); // convert to standard / if usign absolute path on
 77  
             // windows
 78  
         }
 79  1
         this.resourceAccessor = resourceAccessor;
 80  
 
 81  1
         changeLogParameters = new ChangeLogParameters(database);
 82  1
         setDatabase(database);
 83  
 
 84  1
     }
 85  
 
 86  
     public ChangeLogParameters getChangeLogParameters() {
 87  0
         return changeLogParameters;
 88  
     }
 89  
 
 90  
     public Database getDatabase() {
 91  0
         return database;
 92  
     }
 93  
 
 94  
     private void setDatabase(Database database) throws DatabaseException {
 95  1
         this.database = database;
 96  1
         if (database != null) // Some tests use a null database
 97  0
             setDatabasePropertiesAsChangelogParameters(database);
 98  1
     }
 99  
 
 100  
     /**
 101  
      * FileOpener to use for accessing changelog files.
 102  
      */
 103  
     public ResourceAccessor getFileOpener() {
 104  0
         return resourceAccessor;
 105  
     }
 106  
 
 107  
     /**
 108  
      * Use this function to override the current date/time function used to insert dates into the database. Especially
 109  
      * useful when using an unsupported database.
 110  
      */
 111  
     public void setCurrentDateTimeFunction(String currentDateTimeFunction) {
 112  0
         if (currentDateTimeFunction != null) {
 113  0
             this.database.setCurrentDateTimeFunction(currentDateTimeFunction);
 114  
         }
 115  0
     }
 116  
 
 117  
     public void update(String contexts) throws LiquibaseException {
 118  
 
 119  0
         LockService lockService = LockService.getInstance(database);
 120  0
         lockService.waitForLock();
 121  
 
 122  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 123  
 
 124  
         try {
 125  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 126  
                     .getParser(changeLogFile, resourceAccessor)
 127  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 128  
 
 129  0
             checkDatabaseChangeLogTable(true, changeLog, contexts);
 130  
 
 131  0
             changeLog.validate(database, contexts);
 132  0
             ChangeLogIterator changeLogIterator = getStandardChangelogIterator(contexts, changeLog);
 133  
 
 134  0
             changeLogIterator.run(new UpdateVisitor(database), database);
 135  
         } finally {
 136  0
             try {
 137  0
                 lockService.releaseLock();
 138  0
             } catch (LockException e) {
 139  0
                 log.severe("Could not release lock", e);
 140  0
             }
 141  0
         }
 142  0
     }
 143  
 
 144  
     private ChangeLogIterator getStandardChangelogIterator(String contexts, DatabaseChangeLog changeLog)
 145  
             throws DatabaseException {
 146  0
         return new ChangeLogIterator(changeLog, new ShouldRunChangeSetFilter(database), new ContextChangeSetFilter(
 147  
                 contexts), new DbmsChangeSetFilter(database));
 148  
     }
 149  
 
 150  
     public void update(String contexts, Writer output) throws LiquibaseException {
 151  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 152  
 
 153  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 154  0
         LoggingExecutor loggingExecutor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database),
 155  
                 output, database);
 156  0
         ExecutorService.getInstance().setExecutor(database, loggingExecutor);
 157  
 
 158  0
         outputHeader("Update Database Script");
 159  
 
 160  0
         LockService lockService = LockService.getInstance(database);
 161  0
         lockService.waitForLock();
 162  
 
 163  
         try {
 164  
 
 165  0
             update(contexts);
 166  
 
 167  0
             output.flush();
 168  0
         } catch (IOException e) {
 169  0
             throw new LiquibaseException(e);
 170  
         } finally {
 171  0
             lockService.releaseLock();
 172  0
         }
 173  
 
 174  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 175  0
     }
 176  
 
 177  
     public void update(int changesToApply, String contexts) throws LiquibaseException {
 178  
 
 179  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 180  
 
 181  0
         LockService lockService = LockService.getInstance(database);
 182  0
         lockService.waitForLock();
 183  
 
 184  
         try {
 185  
 
 186  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 187  
                     .getParser(changeLogFile, resourceAccessor)
 188  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 189  
 
 190  0
             checkDatabaseChangeLogTable(true, changeLog, contexts);
 191  0
             changeLog.validate(database, contexts);
 192  
 
 193  0
             ChangeLogIterator logIterator = new ChangeLogIterator(changeLog, new ShouldRunChangeSetFilter(database),
 194  
                     new ContextChangeSetFilter(contexts), new DbmsChangeSetFilter(database), new CountChangeSetFilter(
 195  
                             changesToApply));
 196  
 
 197  0
             logIterator.run(new UpdateVisitor(database), database);
 198  
         } finally {
 199  0
             lockService.releaseLock();
 200  0
         }
 201  0
     }
 202  
 
 203  
     public void update(int changesToApply, String contexts, Writer output) throws LiquibaseException {
 204  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 205  
 
 206  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 207  0
         LoggingExecutor loggingExecutor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database),
 208  
                 output, database);
 209  0
         ExecutorService.getInstance().setExecutor(database, loggingExecutor);
 210  
 
 211  0
         outputHeader("Update " + changesToApply + " Change Sets Database Script");
 212  
 
 213  0
         update(changesToApply, contexts);
 214  
 
 215  
         try {
 216  0
             output.flush();
 217  0
         } catch (IOException e) {
 218  0
             throw new LiquibaseException(e);
 219  0
         }
 220  
 
 221  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 222  0
     }
 223  
 
 224  
     private void outputHeader(String message) throws DatabaseException {
 225  0
         Executor executor = ExecutorService.getInstance().getExecutor(database);
 226  0
         executor.comment("*********************************************************************");
 227  0
         executor.comment(message);
 228  0
         executor.comment("*********************************************************************");
 229  0
         executor.comment("Change Log: " + changeLogFile);
 230  0
         executor.comment("Ran at: "
 231  
                 + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date()));
 232  0
         executor.comment("Against: " + getDatabase().getConnection().getConnectionUserName() + "@"
 233  
                 + getDatabase().getConnection().getURL());
 234  0
         executor.comment("Liquibase version: " + LiquibaseUtil.getBuildVersion());
 235  0
         executor.comment("*********************************************************************"
 236  
                 + StreamUtil.getLineSeparator());
 237  0
     }
 238  
 
 239  
     public void rollback(int changesToRollback, String contexts, Writer output) throws LiquibaseException {
 240  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 241  
 
 242  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 243  0
         ExecutorService.getInstance().setExecutor(database,
 244  
                 new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), output, database));
 245  
 
 246  0
         outputHeader("Rollback " + changesToRollback + " Change(s) Script");
 247  
 
 248  0
         rollback(changesToRollback, contexts);
 249  
 
 250  
         try {
 251  0
             output.flush();
 252  0
         } catch (IOException e) {
 253  0
             throw new LiquibaseException(e);
 254  0
         }
 255  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 256  0
     }
 257  
 
 258  
     public void rollback(int changesToRollback, String contexts) throws LiquibaseException {
 259  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 260  
 
 261  0
         LockService lockService = LockService.getInstance(database);
 262  0
         lockService.waitForLock();
 263  
 
 264  
         try {
 265  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 266  
                     .getParser(changeLogFile, resourceAccessor)
 267  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 268  0
             checkDatabaseChangeLogTable(false, changeLog, contexts);
 269  
 
 270  0
             changeLog.validate(database, contexts);
 271  
 
 272  0
             ChangeLogIterator logIterator = new ChangeLogIterator(database.getRanChangeSetList(), changeLog,
 273  
                     new AlreadyRanChangeSetFilter(database.getRanChangeSetList()),
 274  
                     new ContextChangeSetFilter(contexts), new DbmsChangeSetFilter(database), new CountChangeSetFilter(
 275  
                             changesToRollback));
 276  
 
 277  0
             logIterator.run(new RollbackVisitor(database), database);
 278  
         } finally {
 279  0
             try {
 280  0
                 lockService.releaseLock();
 281  0
             } catch (LockException e) {
 282  0
                 log.severe("Error releasing lock", e);
 283  0
             }
 284  0
         }
 285  0
     }
 286  
 
 287  
     public void rollback(String tagToRollBackTo, String contexts, Writer output) throws LiquibaseException {
 288  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 289  
 
 290  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 291  0
         ExecutorService.getInstance().setExecutor(database,
 292  
                 new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), output, database));
 293  
 
 294  0
         outputHeader("Rollback to '" + tagToRollBackTo + "' Script");
 295  
 
 296  0
         rollback(tagToRollBackTo, contexts);
 297  
 
 298  
         try {
 299  0
             output.flush();
 300  0
         } catch (IOException e) {
 301  0
             throw new LiquibaseException(e);
 302  0
         }
 303  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 304  0
     }
 305  
 
 306  
     public void rollback(String tagToRollBackTo, String contexts) throws LiquibaseException {
 307  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 308  
 
 309  0
         LockService lockService = LockService.getInstance(database);
 310  0
         lockService.waitForLock();
 311  
 
 312  
         try {
 313  
 
 314  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 315  
                     .getParser(changeLogFile, resourceAccessor)
 316  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 317  0
             checkDatabaseChangeLogTable(false, changeLog, contexts);
 318  
 
 319  0
             changeLog.validate(database, contexts);
 320  
 
 321  0
             List<RanChangeSet> ranChangeSetList = database.getRanChangeSetList();
 322  0
             ChangeLogIterator logIterator = new ChangeLogIterator(ranChangeSetList, changeLog,
 323  
                     new AfterTagChangeSetFilter(tagToRollBackTo, ranChangeSetList), new AlreadyRanChangeSetFilter(
 324  
                             ranChangeSetList), new ContextChangeSetFilter(contexts), new DbmsChangeSetFilter(database));
 325  
 
 326  0
             logIterator.run(new RollbackVisitor(database), database);
 327  
         } finally {
 328  0
             lockService.releaseLock();
 329  0
         }
 330  0
     }
 331  
 
 332  
     public void rollback(Date dateToRollBackTo, String contexts, Writer output) throws LiquibaseException {
 333  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 334  
 
 335  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 336  0
         ExecutorService.getInstance().setExecutor(database,
 337  
                 new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), output, database));
 338  
 
 339  0
         outputHeader("Rollback to " + dateToRollBackTo + " Script");
 340  
 
 341  0
         rollback(dateToRollBackTo, contexts);
 342  
 
 343  
         try {
 344  0
             output.flush();
 345  0
         } catch (IOException e) {
 346  0
             throw new LiquibaseException(e);
 347  0
         }
 348  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 349  0
     }
 350  
 
 351  
     public void rollback(Date dateToRollBackTo, String contexts) throws LiquibaseException {
 352  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 353  
 
 354  0
         LockService lockService = LockService.getInstance(database);
 355  0
         lockService.waitForLock();
 356  
 
 357  
         try {
 358  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 359  
                     .getParser(changeLogFile, resourceAccessor)
 360  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 361  0
             checkDatabaseChangeLogTable(false, changeLog, contexts);
 362  0
             changeLog.validate(database, contexts);
 363  
 
 364  0
             List<RanChangeSet> ranChangeSetList = database.getRanChangeSetList();
 365  0
             ChangeLogIterator logIterator = new ChangeLogIterator(ranChangeSetList, changeLog,
 366  
                     new ExecutedAfterChangeSetFilter(dateToRollBackTo, ranChangeSetList),
 367  
                     new AlreadyRanChangeSetFilter(ranChangeSetList), new ContextChangeSetFilter(contexts),
 368  
                     new DbmsChangeSetFilter(database));
 369  
 
 370  0
             logIterator.run(new RollbackVisitor(database), database);
 371  
         } finally {
 372  0
             lockService.releaseLock();
 373  0
         }
 374  0
     }
 375  
 
 376  
     public void changeLogSync(String contexts, Writer output) throws LiquibaseException {
 377  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 378  
 
 379  0
         LoggingExecutor outputTemplate = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database),
 380  
                 output, database);
 381  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 382  0
         ExecutorService.getInstance().setExecutor(database, outputTemplate);
 383  
 
 384  0
         outputHeader("SQL to add all changesets to database history table");
 385  
 
 386  0
         changeLogSync(contexts);
 387  
 
 388  
         try {
 389  0
             output.flush();
 390  0
         } catch (IOException e) {
 391  0
             throw new LiquibaseException(e);
 392  0
         }
 393  
 
 394  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 395  0
     }
 396  
 
 397  
     public void changeLogSync(String contexts) throws LiquibaseException {
 398  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 399  
 
 400  0
         LockService lockService = LockService.getInstance(database);
 401  0
         lockService.waitForLock();
 402  
 
 403  
         try {
 404  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 405  
                     .getParser(changeLogFile, resourceAccessor)
 406  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 407  0
             checkDatabaseChangeLogTable(true, changeLog, contexts);
 408  0
             changeLog.validate(database, contexts);
 409  
 
 410  0
             ChangeLogIterator logIterator = new ChangeLogIterator(changeLog, new NotRanChangeSetFilter(
 411  
                     database.getRanChangeSetList()), new ContextChangeSetFilter(contexts), new DbmsChangeSetFilter(
 412  
                     database));
 413  
 
 414  0
             logIterator.run(new ChangeLogSyncVisitor(database), database);
 415  
         } finally {
 416  0
             lockService.releaseLock();
 417  0
         }
 418  0
     }
 419  
 
 420  
     public void markNextChangeSetRan(String contexts, Writer output) throws LiquibaseException {
 421  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 422  
 
 423  0
         LoggingExecutor outputTemplate = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database),
 424  
                 output, database);
 425  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 426  0
         ExecutorService.getInstance().setExecutor(database, outputTemplate);
 427  
 
 428  0
         outputHeader("SQL to add all changesets to database history table");
 429  
 
 430  0
         markNextChangeSetRan(contexts);
 431  
 
 432  
         try {
 433  0
             output.flush();
 434  0
         } catch (IOException e) {
 435  0
             throw new LiquibaseException(e);
 436  0
         }
 437  
 
 438  0
         ExecutorService.getInstance().setExecutor(database, oldTemplate);
 439  0
     }
 440  
 
 441  
     public void markNextChangeSetRan(String contexts) throws LiquibaseException {
 442  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 443  
 
 444  0
         LockService lockService = LockService.getInstance(database);
 445  0
         lockService.waitForLock();
 446  
 
 447  
         try {
 448  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 449  
                     .getParser(changeLogFile, resourceAccessor)
 450  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 451  0
             checkDatabaseChangeLogTable(false, changeLog, contexts);
 452  0
             changeLog.validate(database, contexts);
 453  
 
 454  0
             ChangeLogIterator logIterator = new ChangeLogIterator(changeLog, new NotRanChangeSetFilter(
 455  
                     database.getRanChangeSetList()), new ContextChangeSetFilter(contexts), new DbmsChangeSetFilter(
 456  
                     database), new CountChangeSetFilter(1));
 457  
 
 458  0
             logIterator.run(new ChangeLogSyncVisitor(database), database);
 459  
         } finally {
 460  0
             lockService.releaseLock();
 461  0
         }
 462  0
     }
 463  
 
 464  
     public void futureRollbackSQL(String contexts, Writer output) throws LiquibaseException {
 465  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 466  
 
 467  0
         LoggingExecutor outputTemplate = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database),
 468  
                 output, database);
 469  0
         Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
 470  0
         ExecutorService.getInstance().setExecutor(database, outputTemplate);
 471  
 
 472  0
         outputHeader("SQL to roll back currently unexecuted changes");
 473  
 
 474  0
         LockService lockService = LockService.getInstance(database);
 475  0
         lockService.waitForLock();
 476  
 
 477  
         try {
 478  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 479  
                     .getParser(changeLogFile, resourceAccessor)
 480  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 481  0
             checkDatabaseChangeLogTable(false, changeLog, contexts);
 482  0
             changeLog.validate(database, contexts);
 483  
 
 484  0
             ChangeLogIterator logIterator = new ChangeLogIterator(changeLog, new NotRanChangeSetFilter(
 485  
                     database.getRanChangeSetList()), new ContextChangeSetFilter(contexts), new DbmsChangeSetFilter(
 486  
                     database));
 487  
 
 488  0
             logIterator.run(new RollbackVisitor(database), database);
 489  
         } finally {
 490  0
             ExecutorService.getInstance().setExecutor(database, oldTemplate);
 491  0
             lockService.releaseLock();
 492  0
         }
 493  
 
 494  
         try {
 495  0
             output.flush();
 496  0
         } catch (IOException e) {
 497  0
             throw new LiquibaseException(e);
 498  0
         }
 499  
 
 500  0
     }
 501  
 
 502  
     /**
 503  
      * Drops all database objects owned by the current user.
 504  
      */
 505  
     public final void dropAll() throws DatabaseException, LockException {
 506  0
         dropAll(getDatabase().getDefaultSchemaName());
 507  0
     }
 508  
 
 509  
     /**
 510  
      * Drops all database objects owned by the current user.
 511  
      */
 512  
     public final void dropAll(String... schemas) throws DatabaseException {
 513  
         try {
 514  0
             LockService.getInstance(database).waitForLock();
 515  
 
 516  0
             for (String schema : schemas) {
 517  0
                 log.info("Dropping Database Objects in schema: " + database.convertRequestedSchemaToSchema(schema));
 518  0
                 checkDatabaseChangeLogTable(false, null, null);
 519  0
                 getDatabase().dropDatabaseObjects(schema);
 520  0
                 checkDatabaseChangeLogTable(false, null, null);
 521  0
                 log.debug("Objects dropped successfully");
 522  
             }
 523  0
         } catch (DatabaseException e) {
 524  0
             throw e;
 525  0
         } catch (Exception e) {
 526  0
             throw new DatabaseException(e);
 527  
         } finally {
 528  0
             try {
 529  0
                 LockService.getInstance(database).releaseLock();
 530  0
             } catch (LockException e) {
 531  0
                 log.severe("Unable to release lock: " + e.getMessage());
 532  0
             }
 533  0
         }
 534  0
     }
 535  
 
 536  
     /**
 537  
      * 'Tags' the database for future rollback
 538  
      */
 539  
     public void tag(String tagString) throws LiquibaseException {
 540  0
         LockService lockService = LockService.getInstance(database);
 541  0
         lockService.waitForLock();
 542  
 
 543  
         try {
 544  0
             checkDatabaseChangeLogTable(false, null, null);
 545  0
             getDatabase().tag(tagString);
 546  
         } finally {
 547  0
             lockService.releaseLock();
 548  0
         }
 549  0
     }
 550  
 
 551  
     public void updateTestingRollback(String contexts) throws LiquibaseException {
 552  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 553  
 
 554  0
         Date baseDate = new Date();
 555  0
         update(contexts);
 556  0
         rollback(baseDate, contexts);
 557  0
         update(contexts);
 558  0
     }
 559  
 
 560  
     public void checkDatabaseChangeLogTable(boolean updateExistingNullChecksums, DatabaseChangeLog databaseChangeLog,
 561  
             String contexts) throws LiquibaseException {
 562  0
         if (updateExistingNullChecksums && databaseChangeLog == null) {
 563  0
             throw new LiquibaseException("changeLog parameter is required if updating existing checksums");
 564  
         }
 565  0
         String[] splitContexts = null;
 566  0
         if (StringUtils.trimToNull(contexts) != null) {
 567  0
             splitContexts = contexts.split(",");
 568  
         }
 569  0
         getDatabase().checkDatabaseChangeLogTable(updateExistingNullChecksums, databaseChangeLog, splitContexts);
 570  0
         if (!LockService.getInstance(database).hasChangeLogLock()) {
 571  0
             getDatabase().checkDatabaseChangeLogLockTable();
 572  
         }
 573  0
     }
 574  
 
 575  
     /**
 576  
      * Returns true if it is "save" to migrate the database. Currently, "safe" is defined as running in an output-sql
 577  
      * mode or against a database on localhost. It is fine to run Liquibase against a "non-safe" database, the method is
 578  
      * mainly used to determine if the user should be prompted before continuing.
 579  
      */
 580  
     public boolean isSafeToRunMigration() throws DatabaseException {
 581  0
         return getDatabase().isLocalDatabase();
 582  
     }
 583  
 
 584  
     /**
 585  
      * Display change log lock information.
 586  
      */
 587  
     public DatabaseChangeLogLock[] listLocks() throws LiquibaseException {
 588  0
         checkDatabaseChangeLogTable(false, null, null);
 589  
 
 590  0
         return LockService.getInstance(getDatabase()).listLocks();
 591  
     }
 592  
 
 593  
     public void reportLocks(PrintStream out) throws LiquibaseException {
 594  0
         DatabaseChangeLogLock[] locks = listLocks();
 595  0
         out.println("Database change log locks for " + getDatabase().getConnection().getConnectionUserName() + "@"
 596  
                 + getDatabase().getConnection().getURL());
 597  0
         if (locks.length == 0) {
 598  0
             out.println(" - No locks");
 599  
         }
 600  0
         for (DatabaseChangeLogLock lock : locks) {
 601  0
             out.println(" - " + lock.getLockedBy() + " at "
 602  
                     + DateFormat.getDateTimeInstance().format(lock.getLockGranted()));
 603  
         }
 604  
 
 605  0
     }
 606  
 
 607  
     public void forceReleaseLocks() throws LiquibaseException {
 608  0
         checkDatabaseChangeLogTable(false, null, null);
 609  
 
 610  0
         LockService.getInstance(getDatabase()).forceReleaseLock();
 611  0
     }
 612  
 
 613  
     public List<ChangeSet> listUnrunChangeSets(String contexts) throws LiquibaseException {
 614  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 615  
 
 616  0
         DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance().getParser(changeLogFile, resourceAccessor)
 617  
                 .parse(changeLogFile, changeLogParameters, resourceAccessor);
 618  
 
 619  0
         changeLog.validate(database, contexts);
 620  
 
 621  0
         ChangeLogIterator logIterator = getStandardChangelogIterator(contexts, changeLog);
 622  
 
 623  0
         ListVisitor visitor = new ListVisitor();
 624  0
         logIterator.run(visitor, database);
 625  0
         return visitor.getSeenChangeSets();
 626  
     }
 627  
 
 628  
     public void reportStatus(boolean verbose, String contexts, Writer out) throws LiquibaseException {
 629  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 630  
 
 631  
         try {
 632  0
             List<ChangeSet> unrunChangeSets = listUnrunChangeSets(contexts);
 633  0
             if (unrunChangeSets.size() == 0) {
 634  0
                 out.append(getDatabase().getConnection().getConnectionUserName());
 635  0
                 out.append("@");
 636  0
                 out.append(getDatabase().getConnection().getURL());
 637  0
                 out.append(" is up to date");
 638  0
                 out.append(StreamUtil.getLineSeparator());
 639  
             } else {
 640  0
                 out.append(String.valueOf(unrunChangeSets.size()));
 641  0
                 out.append(" change sets have not been applied to ");
 642  0
                 out.append(getDatabase().getConnection().getConnectionUserName());
 643  0
                 out.append("@");
 644  0
                 out.append(getDatabase().getConnection().getURL());
 645  0
                 out.append(StreamUtil.getLineSeparator());
 646  0
                 if (verbose) {
 647  0
                     for (ChangeSet changeSet : unrunChangeSets) {
 648  0
                         out.append("     ").append(changeSet.toString(false)).append(StreamUtil.getLineSeparator());
 649  
                     }
 650  
                 }
 651  
             }
 652  
 
 653  0
             out.flush();
 654  0
         } catch (IOException e) {
 655  0
             throw new LiquibaseException(e);
 656  0
         }
 657  
 
 658  0
     }
 659  
 
 660  
     /**
 661  
      * Sets checksums to null so they will be repopulated next run
 662  
      */
 663  
     public void clearCheckSums() throws LiquibaseException {
 664  0
         log.info("Clearing database change log checksums");
 665  0
         LockService lockService = LockService.getInstance(database);
 666  0
         lockService.waitForLock();
 667  
 
 668  
         try {
 669  0
             checkDatabaseChangeLogTable(false, null, null);
 670  
 
 671  0
             UpdateStatement updateStatement = new UpdateStatement(getDatabase().getLiquibaseSchemaName(), getDatabase()
 672  
                     .getDatabaseChangeLogTableName());
 673  0
             updateStatement.addNewColumnValue("MD5SUM", null);
 674  0
             ExecutorService.getInstance().getExecutor(database).execute(updateStatement);
 675  0
             getDatabase().commit();
 676  
         } finally {
 677  0
             lockService.releaseLock();
 678  0
         }
 679  0
     }
 680  
 
 681  
     public void generateDocumentation(String outputDirectory) throws LiquibaseException {
 682  
         // call without context
 683  0
         generateDocumentation(outputDirectory, null);
 684  0
     }
 685  
 
 686  
     public void generateDocumentation(String outputDirectory, String contexts) throws LiquibaseException {
 687  0
         log.info("Generating Database Documentation");
 688  0
         changeLogParameters.setContexts(StringUtils.splitAndTrim(contexts, ","));
 689  0
         LockService lockService = LockService.getInstance(database);
 690  0
         lockService.waitForLock();
 691  
 
 692  
         try {
 693  0
             DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance()
 694  
                     .getParser(changeLogFile, resourceAccessor)
 695  
                     .parse(changeLogFile, changeLogParameters, resourceAccessor);
 696  0
             checkDatabaseChangeLogTable(false, changeLog, null);
 697  
 
 698  0
             String[] splitContexts = null;
 699  0
             if (StringUtils.trimToNull(contexts) != null) {
 700  0
                 splitContexts = contexts.split(",");
 701  
             }
 702  0
             changeLog.validate(database, splitContexts);
 703  
 
 704  0
             ChangeLogIterator logIterator = new ChangeLogIterator(changeLog, new DbmsChangeSetFilter(database));
 705  
 
 706  0
             DBDocVisitor visitor = new DBDocVisitor(database);
 707  0
             logIterator.run(visitor, database);
 708  
 
 709  0
             visitor.writeHTML(new File(outputDirectory), resourceAccessor);
 710  0
         } catch (IOException e) {
 711  0
             throw new LiquibaseException(e);
 712  
         } finally {
 713  0
             lockService.releaseLock();
 714  0
         }
 715  
 
 716  
         // try {
 717  
         // if (!LockService.getExecutor(database).waitForLock()) {
 718  
         // return;
 719  
         // }
 720  
         //
 721  
         // DBDocChangeLogHandler changeLogHandler = new DBDocChangeLogHandler(outputDirectory, this,
 722  
         // changeLogFile,resourceAccessor);
 723  
         // runChangeLogs(changeLogHandler);
 724  
         //
 725  
         // changeLogHandler.writeHTML(this);
 726  
         // } finally {
 727  
         // releaseLock();
 728  
         // }
 729  0
     }
 730  
 
 731  
     public Diff diff(Database referenceDatabase, Database targetDatabase) {
 732  0
         return new Diff(referenceDatabase, targetDatabase);
 733  
     }
 734  
 
 735  
     /**
 736  
      * Checks changelogs for bad MD5Sums and preconditions before attempting a migration
 737  
      */
 738  
     public void validate() throws LiquibaseException {
 739  
 
 740  0
         DatabaseChangeLog changeLog = ChangeLogParserFactory.getInstance().getParser(changeLogFile, resourceAccessor)
 741  
                 .parse(changeLogFile, changeLogParameters, resourceAccessor);
 742  0
         changeLog.validate(database);
 743  0
     }
 744  
 
 745  
     public void setChangeLogParameter(String key, Object value) {
 746  0
         this.changeLogParameters.set(key, value);
 747  0
     }
 748  
 
 749  
     /**
 750  
      * Add safe database properties as changelog parameters.<br/>
 751  
      * Safe properties are the ones that doesn't have side effects in liquibase state and also don't change in during
 752  
      * the liquibase execution
 753  
      * 
 754  
      * @param database
 755  
      *            Database which propeties are put in the changelog
 756  
      * @throws DatabaseException
 757  
      */
 758  
     private void setDatabasePropertiesAsChangelogParameters(Database database) throws DatabaseException {
 759  0
         setChangeLogParameter("database.autoIncrementClause", database.getAutoIncrementClause());
 760  0
         setChangeLogParameter("database.currentDateTimeFunction", database.getCurrentDateTimeFunction());
 761  0
         setChangeLogParameter("database.databaseChangeLogLockTableName", database.getDatabaseChangeLogLockTableName());
 762  0
         setChangeLogParameter("database.databaseChangeLogTableName", database.getDatabaseChangeLogTableName());
 763  0
         setChangeLogParameter("database.databaseMajorVersion", database.getDatabaseMajorVersion());
 764  0
         setChangeLogParameter("database.databaseMinorVersion", database.getDatabaseMinorVersion());
 765  0
         setChangeLogParameter("database.databaseProductName", database.getDatabaseProductName());
 766  0
         setChangeLogParameter("database.databaseProductVersion", database.getDatabaseProductVersion());
 767  0
         setChangeLogParameter("database.defaultCatalogName", database.getDefaultCatalogName());
 768  0
         setChangeLogParameter("database.defaultSchemaName", database.getDefaultSchemaName());
 769  0
         setChangeLogParameter("database.lineComment", database.getLineComment());
 770  0
         setChangeLogParameter("database.liquibaseSchemaName", database.getLiquibaseSchemaName());
 771  0
         setChangeLogParameter("database.typeName", database.getTypeName());
 772  0
         setChangeLogParameter("database.isLocalDatabase", database.isLocalDatabase());
 773  0
         setChangeLogParameter("database.requiresPassword", database.requiresPassword());
 774  0
         setChangeLogParameter("database.requiresUsername", database.requiresUsername());
 775  0
         setChangeLogParameter("database.supportsForeignKeyDisable", database.supportsForeignKeyDisable());
 776  0
         setChangeLogParameter("database.supportsInitiallyDeferrableColumns",
 777  
                 database.supportsInitiallyDeferrableColumns());
 778  0
         setChangeLogParameter("database.supportsRestrictForeignKeys", database.supportsRestrictForeignKeys());
 779  0
         setChangeLogParameter("database.supportsSchemas", database.supportsSchemas());
 780  0
         setChangeLogParameter("database.supportsSequences", database.supportsSequences());
 781  0
         setChangeLogParameter("database.supportsTablespaces", database.supportsTablespaces());
 782  0
     }
 783  
 }