/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.liquibase.impl; import liquibase.changelog.ChangeLogParameters; import liquibase.changelog.ChangeSet; import liquibase.changelog.DatabaseChangeLog; import liquibase.changelog.RanChangeSet; import liquibase.database.Database; import liquibase.exception.LiquibaseException; import liquibase.parser.ChangeLogParser; import liquibase.parser.ChangeLogParserFactory; import liquibase.resource.ClassLoaderResourceAccessor; import liquibase.resource.ResourceAccessor; import java.util.Iterator; import java.util.LinkedList; import java.util.List; final class Source { final DatabaseChangeLog databaseChangeLog; private Source(DatabaseChangeLog changeLog) { this.databaseChangeLog = changeLog; } public static Source create(String changeLog, ClassLoader classLoader) throws LiquibaseException { final ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(changeLog, classLoader); final ChangeLogParser parser = ChangeLogParserFactory.getInstance().getParser(changeLog, resourceAccessor); final ChangeLogParameters changeLogParameters = new ChangeLogParameters(); return new Source(parser.parse(changeLog, changeLogParameters, resourceAccessor)); } private static String asString(RanChangeSet change) { return change.getId() + ":" + change.getAuthor() + ":" + change.getChangeLog() + ":(" + change.getLastCheckSum() + ")"; } public Changes getChanges(String from, String to) throws LiquibaseException { final Iterator<ChangeSet> i = getFromIterator(from); final LinkedList<ChangeSet> changes = new LinkedList<ChangeSet>(); while (i.hasNext()) { final ChangeSet item = i.next(); changes.add(item); if (item.getId().equals(to)) { return new Changes(databaseChangeLog, changes); } } if (to != null && !to.equals(from)) { throw new LiquibaseException("Can't found TO version " + to); } return new Changes(databaseChangeLog, changes); } public String getVersion(final String appVersion) { final String fullVersion = trimToNull(appVersion); if (fullVersion == null) { throw new IllegalStateException("Can't detect App version"); } int delimeter = fullVersion.indexOf('_'); if (delimeter < 0) { return fullVersion; } if (delimeter == 0) { throw new IllegalStateException("App version not in format dbVersion_codeVersion"); } String dbVersion = trimToNull(fullVersion.substring(0, delimeter)); if (dbVersion == null) { throw new IllegalStateException("Invalid db version in '" + fullVersion + "'"); } if (indexOf(dbVersion) < 0) { throw new IllegalStateException("Invalid version " + dbVersion); } return dbVersion; } private int indexOf(final String id) { int index = 0; for (ChangeSet changeSet : databaseChangeLog.getChangeSets()) { if (changeSet.getId().equals(id)) { return index; } index++; } return -1; } public String getVersion(Database targetDb, String upperVersion) throws LiquibaseException { targetDb.checkDatabaseChangeLogTable(false, databaseChangeLog, null); databaseChangeLog.validate(targetDb, null); final List<ChangeSet> src = databaseChangeLog.getChangeSets(); final List<RanChangeSet> dst = targetDb.getRanChangeSetList(); Iterator<ChangeSet> srcIter = src.iterator(); Iterator<RanChangeSet> dstIter = dst.iterator(); boolean hasUpperVersion = false; String lastVersion = null; while (srcIter.hasNext() && dstIter.hasNext()) { ChangeSet required = srcIter.next(); RanChangeSet actual = dstIter.next(); if (!actual.getId().equalsIgnoreCase(required.getId()) || !actual.getAuthor().equalsIgnoreCase(required.getAuthor()) || !actual.getChangeLog().equalsIgnoreCase(required.getFilePath())) { throw new LiquibaseException("Required " + required + " != " + asString(actual)); } if (hasUpperVersion) { throw new LiquibaseException("To " + upperVersion + " < " + asString(actual)); } if (actual.getId().equalsIgnoreCase(upperVersion)) { hasUpperVersion = true; } lastVersion = required.getId(); } if (dstIter.hasNext()) { RanChangeSet actual = dstIter.next(); throw new LiquibaseException("To " + upperVersion + " < " + asString(actual)); } return lastVersion; } private Iterator<ChangeSet> getFromIterator(String from) throws LiquibaseException { final Iterator<ChangeSet> i = databaseChangeLog.getChangeSets().iterator(); if (from != null) { while (i.hasNext()) { ChangeSet changes = i.next(); if (changes.getId().equals(from)) { return i; } } throw new LiquibaseException("Can't found FROM version " + from); } return i; } private String trimToNull(final String str) { if (str == null) { return null; } final String trimmed = str.trim(); if (trimmed.isEmpty()) { return null; } return trimmed; } }