Search in sources :

Example 1 with ChangeLogParseException

use of liquibase.exception.ChangeLogParseException in project liquibase by liquibase.

the class FormattedSqlChangeLogParser method parse.

@Override
public DatabaseChangeLog parse(String physicalChangeLogLocation, ChangeLogParameters changeLogParameters, ResourceAccessor resourceAccessor) throws ChangeLogParseException {
    DatabaseChangeLog changeLog = new DatabaseChangeLog();
    changeLog.setChangeLogParameters(changeLogParameters);
    changeLog.setPhysicalFilePath(physicalChangeLogLocation);
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new UtfBomAwareReader(openChangeLogFile(physicalChangeLogLocation, resourceAccessor)));
        StringBuffer currentSql = new StringBuffer();
        StringBuffer currentRollbackSql = new StringBuffer();
        ChangeSet changeSet = null;
        RawSQLChange change = null;
        Pattern changeLogPattern = Pattern.compile("\\-\\-\\s*liquibase formatted.*", Pattern.CASE_INSENSITIVE);
        Pattern changeSetPattern = Pattern.compile("\\-\\-[\\s]*changeset\\s+([^:]+):(\\S+).*", Pattern.CASE_INSENSITIVE);
        Pattern rollbackPattern = Pattern.compile("\\s*\\-\\-[\\s]*rollback (.*)", Pattern.CASE_INSENSITIVE);
        Pattern preconditionsPattern = Pattern.compile("\\s*\\-\\-[\\s]*preconditions(.*)", Pattern.CASE_INSENSITIVE);
        Pattern preconditionPattern = Pattern.compile("\\s*\\-\\-[\\s]*precondition\\-([a-zA-Z0-9-]+) (.*)", Pattern.CASE_INSENSITIVE);
        Pattern stripCommentsPattern = Pattern.compile(".*stripComments:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern splitStatementsPattern = Pattern.compile(".*splitStatements:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern rollbackSplitStatementsPattern = Pattern.compile(".*rollbackSplitStatements:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern endDelimiterPattern = Pattern.compile(".*endDelimiter:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern rollbackEndDelimiterPattern = Pattern.compile(".*rollbackEndDelimiter:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern commentPattern = Pattern.compile("\\-\\-[\\s]*comment:? (.*)", Pattern.CASE_INSENSITIVE);
        Pattern validCheckSumPattern = Pattern.compile("\\-\\-[\\s]*validCheckSum:? (.*)", Pattern.CASE_INSENSITIVE);
        Pattern runOnChangePattern = Pattern.compile(".*runOnChange:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern runAlwaysPattern = Pattern.compile(".*runAlways:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern contextPattern = Pattern.compile(".*context:(\".*\"|\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern logicalFilePathPattern = Pattern.compile(".*logicalFilePath:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern labelsPattern = Pattern.compile(".*labels:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern runInTransactionPattern = Pattern.compile(".*runInTransaction:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern dbmsPattern = Pattern.compile(".*dbms:([^,][\\w!,]+).*", Pattern.CASE_INSENSITIVE);
        Pattern failOnErrorPattern = Pattern.compile(".*failOnError:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern onFailPattern = Pattern.compile(".*onFail:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern onErrorPattern = Pattern.compile(".*onError:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern onUpdateSqlPattern = Pattern.compile(".*onUpdateSQL:(\\w+).*", Pattern.CASE_INSENSITIVE);
        boolean rollbackSplitStatements = true;
        String rollbackEndDelimiter = null;
        String line;
        while ((line = reader.readLine()) != null) {
            Matcher changeLogPatterMatcher = changeLogPattern.matcher(line);
            if (changeLogPatterMatcher.matches()) {
                Matcher logicalFilePathMatcher = logicalFilePathPattern.matcher(line);
                changeLog.setLogicalFilePath(parseString(logicalFilePathMatcher));
            }
            Matcher changeSetPatternMatcher = changeSetPattern.matcher(line);
            if (changeSetPatternMatcher.matches()) {
                String finalCurrentSql = changeLogParameters.expandExpressions(StringUtils.trimToNull(currentSql.toString()), changeLog);
                if (changeSet != null) {
                    if (finalCurrentSql == null) {
                        throw new ChangeLogParseException("No SQL for changeset " + changeSet.toString(false));
                    }
                    change.setSql(finalCurrentSql);
                    if (StringUtils.trimToNull(currentRollbackSql.toString()) != null) {
                        if (currentRollbackSql.toString().trim().toLowerCase().matches("^not required.*")) {
                            changeSet.addRollbackChange(new EmptyChange());
                        } else {
                            RawSQLChange rollbackChange = new RawSQLChange();
                            rollbackChange.setSql(changeLogParameters.expandExpressions(currentRollbackSql.toString(), changeLog));
                            changeSet.addRollbackChange(rollbackChange);
                        }
                    }
                }
                Matcher stripCommentsPatternMatcher = stripCommentsPattern.matcher(line);
                Matcher splitStatementsPatternMatcher = splitStatementsPattern.matcher(line);
                Matcher rollbackSplitStatementsPatternMatcher = rollbackSplitStatementsPattern.matcher(line);
                Matcher endDelimiterPatternMatcher = endDelimiterPattern.matcher(line);
                Matcher rollbackEndDelimiterPatternMatcher = rollbackEndDelimiterPattern.matcher(line);
                Matcher logicalFilePathMatcher = logicalFilePathPattern.matcher(line);
                Matcher runOnChangePatternMatcher = runOnChangePattern.matcher(line);
                Matcher runAlwaysPatternMatcher = runAlwaysPattern.matcher(line);
                Matcher contextPatternMatcher = contextPattern.matcher(line);
                Matcher labelsPatternMatcher = labelsPattern.matcher(line);
                Matcher runInTransactionPatternMatcher = runInTransactionPattern.matcher(line);
                Matcher dbmsPatternMatcher = dbmsPattern.matcher(line);
                Matcher failOnErrorPatternMatcher = failOnErrorPattern.matcher(line);
                boolean stripComments = parseBoolean(stripCommentsPatternMatcher, changeSet, true);
                boolean splitStatements = parseBoolean(splitStatementsPatternMatcher, changeSet, true);
                rollbackSplitStatements = parseBoolean(rollbackSplitStatementsPatternMatcher, changeSet, true);
                boolean runOnChange = parseBoolean(runOnChangePatternMatcher, changeSet, false);
                boolean runAlways = parseBoolean(runAlwaysPatternMatcher, changeSet, false);
                boolean runInTransaction = parseBoolean(runInTransactionPatternMatcher, changeSet, true);
                boolean failOnError = parseBoolean(failOnErrorPatternMatcher, changeSet, true);
                String endDelimiter = parseString(endDelimiterPatternMatcher);
                rollbackEndDelimiter = parseString(rollbackEndDelimiterPatternMatcher);
                String context = StringUtils.trimToNull(//remove surrounding quotes if they're in there
                StringUtils.trimToEmpty(parseString(contextPatternMatcher)).replaceFirst("^\"", "").replaceFirst("\"$", ""));
                String labels = parseString(labelsPatternMatcher);
                String logicalFilePath = parseString(logicalFilePathMatcher);
                if (logicalFilePath == null || "".equals(logicalFilePath)) {
                    logicalFilePath = changeLog.getLogicalFilePath();
                }
                String dbms = parseString(dbmsPatternMatcher);
                changeSet = new ChangeSet(changeSetPatternMatcher.group(2), changeSetPatternMatcher.group(1), runAlways, runOnChange, logicalFilePath, context, dbms, runInTransaction, changeLog.getObjectQuotingStrategy(), changeLog);
                changeSet.setLabels(new Labels(labels));
                changeSet.setFailOnError(failOnError);
                changeLog.addChangeSet(changeSet);
                change = new RawSQLChange();
                change.setSql(finalCurrentSql);
                change.setResourceAccessor(resourceAccessor);
                change.setSplitStatements(splitStatements);
                change.setStripComments(stripComments);
                change.setEndDelimiter(endDelimiter);
                changeSet.addChange(change);
                currentSql = new StringBuffer();
                currentRollbackSql = new StringBuffer();
            } else {
                if (changeSet != null) {
                    Matcher commentMatcher = commentPattern.matcher(line);
                    Matcher rollbackMatcher = rollbackPattern.matcher(line);
                    Matcher preconditionsMatcher = preconditionsPattern.matcher(line);
                    Matcher preconditionMatcher = preconditionPattern.matcher(line);
                    Matcher validCheckSumMatcher = validCheckSumPattern.matcher(line);
                    if (commentMatcher.matches()) {
                        if (commentMatcher.groupCount() == 1) {
                            changeSet.setComments(commentMatcher.group(1));
                        }
                    } else if (validCheckSumMatcher.matches()) {
                        if (validCheckSumMatcher.groupCount() == 1) {
                            changeSet.addValidCheckSum(validCheckSumMatcher.group(1));
                        }
                    } else if (rollbackMatcher.matches()) {
                        if (rollbackMatcher.groupCount() == 1) {
                            currentRollbackSql.append(rollbackMatcher.group(1)).append(SystemUtils.LINE_SEPARATOR);
                        }
                    } else if (preconditionsMatcher.matches()) {
                        if (preconditionsMatcher.groupCount() == 1) {
                            String body = preconditionsMatcher.group(1);
                            Matcher onFailMatcher = onFailPattern.matcher(body);
                            Matcher onErrorMatcher = onErrorPattern.matcher(body);
                            Matcher onUpdateSqlMatcher = onUpdateSqlPattern.matcher(body);
                            PreconditionContainer pc = new PreconditionContainer();
                            pc.setOnFail(StringUtils.trimToNull(parseString(onFailMatcher)));
                            pc.setOnError(StringUtils.trimToNull(parseString(onErrorMatcher)));
                            pc.setOnSqlOutput(StringUtils.trimToNull(parseString(onUpdateSqlMatcher)));
                            changeSet.setPreconditions(pc);
                        }
                    } else if (preconditionMatcher.matches()) {
                        if (changeSet.getPreconditions() == null) {
                            // create the defaults
                            changeSet.setPreconditions(new PreconditionContainer());
                        }
                        if (preconditionMatcher.groupCount() == 2) {
                            String name = StringUtils.trimToNull(preconditionMatcher.group(1));
                            if (name != null) {
                                String body = preconditionMatcher.group(2).trim();
                                if ("sql-check".equals(name)) {
                                    changeSet.getPreconditions().addNestedPrecondition(parseSqlCheckCondition(changeLogParameters.expandExpressions(StringUtils.trimToNull(body), changeSet.getChangeLog())));
                                } else {
                                    throw new ChangeLogParseException("The '" + name + "' precondition type is not supported.");
                                }
                            }
                        }
                    } else {
                        currentSql.append(line).append(SystemUtils.LINE_SEPARATOR);
                    }
                }
            }
        }
        if (changeSet != null) {
            change.setSql(changeLogParameters.expandExpressions(StringUtils.trimToNull(currentSql.toString()), changeSet.getChangeLog()));
            if (change.getEndDelimiter() == null && StringUtils.trimToEmpty(change.getSql()).endsWith("\n/")) {
                change.setEndDelimiter("\n/$");
            }
            if (StringUtils.trimToNull(currentRollbackSql.toString()) != null) {
                if (currentRollbackSql.toString().trim().toLowerCase().matches("^not required.*")) {
                    changeSet.addRollbackChange(new EmptyChange());
                } else {
                    RawSQLChange rollbackChange = new RawSQLChange();
                    rollbackChange.setSql(changeLogParameters.expandExpressions(currentRollbackSql.toString(), changeSet.getChangeLog()));
                    rollbackChange.setSplitStatements(rollbackSplitStatements);
                    if (rollbackEndDelimiter != null) {
                        rollbackChange.setEndDelimiter(rollbackEndDelimiter);
                    }
                    changeSet.addRollbackChange(rollbackChange);
                }
            }
        }
    } catch (IOException e) {
        throw new ChangeLogParseException(e);
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ignore) {
            }
        }
    }
    return changeLog;
}
Also used : RawSQLChange(liquibase.change.core.RawSQLChange) Pattern(java.util.regex.Pattern) PreconditionContainer(liquibase.precondition.core.PreconditionContainer) Matcher(java.util.regex.Matcher) Labels(liquibase.Labels) IOException(java.io.IOException) EmptyChange(liquibase.change.core.EmptyChange) DatabaseChangeLog(liquibase.changelog.DatabaseChangeLog) ChangeLogParseException(liquibase.exception.ChangeLogParseException) BufferedReader(java.io.BufferedReader) UtfBomAwareReader(liquibase.resource.UtfBomAwareReader) ChangeSet(liquibase.changelog.ChangeSet)

Example 2 with ChangeLogParseException

use of liquibase.exception.ChangeLogParseException in project liquibase by liquibase.

the class FormattedSqlChangeLogParser method parseSqlCheckCondition.

private SqlPrecondition parseSqlCheckCondition(String body) throws ChangeLogParseException {
    Pattern[] patterns = new Pattern[] { Pattern.compile("^(?:expectedResult:)?(\\w+) (.*)", Pattern.CASE_INSENSITIVE), Pattern.compile("^(?:expectedResult:)?'([^']+)' (.*)", Pattern.CASE_INSENSITIVE), Pattern.compile("^(?:expectedResult:)?\"([^\"]+)\" (.*)", Pattern.CASE_INSENSITIVE) };
    for (Pattern pattern : patterns) {
        Matcher matcher = pattern.matcher(body);
        if (matcher.matches() && matcher.groupCount() == 2) {
            SqlPrecondition p = new SqlPrecondition();
            p.setExpectedResult(matcher.group(1));
            p.setSql(matcher.group(2));
            return p;
        }
    }
    throw new ChangeLogParseException("Could not parse a SqlCheck precondition from '" + body + "'.");
}
Also used : Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) ChangeLogParseException(liquibase.exception.ChangeLogParseException) SqlPrecondition(liquibase.precondition.core.SqlPrecondition)

Example 3 with ChangeLogParseException

use of liquibase.exception.ChangeLogParseException in project liquibase by liquibase.

the class SqlChangeLogParser method parse.

@Override
public DatabaseChangeLog parse(String physicalChangeLogLocation, ChangeLogParameters changeLogParameters, ResourceAccessor resourceAccessor) throws ChangeLogParseException {
    DatabaseChangeLog changeLog = new DatabaseChangeLog();
    changeLog.setPhysicalFilePath(physicalChangeLogLocation);
    RawSQLChange change = new RawSQLChange();
    try {
        InputStream sqlStream = StreamUtil.singleInputStream(physicalChangeLogLocation, resourceAccessor);
        if (sqlStream == null) {
            throw new ChangeLogParseException("File does not exist: " + physicalChangeLogLocation);
        }
        String sql = StreamUtil.getStreamContents(sqlStream, null);
        change.setSql(sql);
    } catch (IOException e) {
        throw new ChangeLogParseException(e);
    }
    change.setResourceAccessor(resourceAccessor);
    change.setSplitStatements(false);
    change.setStripComments(false);
    ChangeSet changeSet = new ChangeSet("raw", "includeAll", false, false, physicalChangeLogLocation, null, null, true, ObjectQuotingStrategy.LEGACY, changeLog);
    changeSet.addChange(change);
    changeLog.addChangeSet(changeSet);
    return changeLog;
}
Also used : RawSQLChange(liquibase.change.core.RawSQLChange) InputStream(java.io.InputStream) ChangeLogParseException(liquibase.exception.ChangeLogParseException) IOException(java.io.IOException) ChangeSet(liquibase.changelog.ChangeSet) DatabaseChangeLog(liquibase.changelog.DatabaseChangeLog)

Example 4 with ChangeLogParseException

use of liquibase.exception.ChangeLogParseException in project liquibase by liquibase.

the class AbstractChangeLogParser method parse.

@Override
public DatabaseChangeLog parse(String physicalChangeLogLocation, ChangeLogParameters changeLogParameters, ResourceAccessor resourceAccessor) throws ChangeLogParseException {
    ParsedNode parsedNode = parseToNode(physicalChangeLogLocation, changeLogParameters, resourceAccessor);
    if (parsedNode == null) {
        return null;
    }
    DatabaseChangeLog changeLog = new DatabaseChangeLog(physicalChangeLogLocation);
    changeLog.setChangeLogParameters(changeLogParameters);
    try {
        changeLog.load(parsedNode, resourceAccessor);
    } catch (Exception e) {
        throw new ChangeLogParseException(e);
    }
    return changeLog;
}
Also used : ParsedNode(liquibase.parser.core.ParsedNode) ChangeLogParseException(liquibase.exception.ChangeLogParseException) DatabaseChangeLog(liquibase.changelog.DatabaseChangeLog) ChangeLogParseException(liquibase.exception.ChangeLogParseException) ParseException(java.text.ParseException)

Example 5 with ChangeLogParseException

use of liquibase.exception.ChangeLogParseException in project liquibase by liquibase.

the class XMLChangeLogSAXParser method parseToNode.

@Override
protected ParsedNode parseToNode(String physicalChangeLogLocation, ChangeLogParameters changeLogParameters, ResourceAccessor resourceAccessor) throws ChangeLogParseException {
    InputStream inputStream = null;
    try {
        SAXParser parser = saxParserFactory.newSAXParser();
        try {
            parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
        } catch (SAXNotRecognizedException e) {
        //ok, parser must not support it
        } catch (SAXNotSupportedException e) {
        //ok, parser must not support it
        }
        XMLReader xmlReader = parser.getXMLReader();
        LiquibaseEntityResolver resolver = new LiquibaseEntityResolver(this);
        resolver.useResoureAccessor(resourceAccessor, FilenameUtils.getFullPath(physicalChangeLogLocation));
        xmlReader.setEntityResolver(resolver);
        xmlReader.setErrorHandler(new ErrorHandler() {

            @Override
            public void warning(SAXParseException exception) throws SAXException {
                LogFactory.getLogger().warning(exception.getMessage());
                throw exception;
            }

            @Override
            public void error(SAXParseException exception) throws SAXException {
                LogFactory.getLogger().severe(exception.getMessage());
                throw exception;
            }

            @Override
            public void fatalError(SAXParseException exception) throws SAXException {
                LogFactory.getLogger().severe(exception.getMessage());
                throw exception;
            }
        });
        inputStream = StreamUtil.singleInputStream(physicalChangeLogLocation, resourceAccessor);
        if (inputStream == null) {
            if (physicalChangeLogLocation.startsWith("WEB-INF/classes/")) {
                physicalChangeLogLocation = physicalChangeLogLocation.replaceFirst("WEB-INF/classes/", "");
                inputStream = StreamUtil.singleInputStream(physicalChangeLogLocation, resourceAccessor);
            }
            if (inputStream == null) {
                throw new ChangeLogParseException(physicalChangeLogLocation + " does not exist");
            }
        }
        XMLChangeLogSAXHandler contentHandler = new XMLChangeLogSAXHandler(physicalChangeLogLocation, resourceAccessor, changeLogParameters);
        xmlReader.setContentHandler(contentHandler);
        xmlReader.parse(new InputSource(new UtfBomStripperInputStream(inputStream)));
        return contentHandler.getDatabaseChangeLogTree();
    } catch (ChangeLogParseException e) {
        throw e;
    } catch (IOException e) {
        throw new ChangeLogParseException("Error Reading Migration File: " + e.getMessage(), e);
    } catch (SAXParseException e) {
        throw new ChangeLogParseException("Error parsing line " + e.getLineNumber() + " column " + e.getColumnNumber() + " of " + physicalChangeLogLocation + ": " + e.getMessage(), e);
    } catch (SAXException e) {
        Throwable parentCause = e.getException();
        while (parentCause != null) {
            if (parentCause instanceof ChangeLogParseException) {
                throw ((ChangeLogParseException) parentCause);
            }
            parentCause = parentCause.getCause();
        }
        String reason = e.getMessage();
        String causeReason = null;
        if (e.getCause() != null) {
            causeReason = e.getCause().getMessage();
        }
        //            }
        if (reason == null) {
            if (causeReason != null) {
                reason = causeReason;
            } else {
                reason = "Unknown Reason";
            }
        }
        throw new ChangeLogParseException("Invalid Migration File: " + reason, e);
    } catch (Exception e) {
        throw new ChangeLogParseException(e);
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
            // probably ok
            }
        }
    }
}
Also used : ErrorHandler(org.xml.sax.ErrorHandler) InputSource(org.xml.sax.InputSource) UtfBomStripperInputStream(liquibase.resource.UtfBomStripperInputStream) InputStream(java.io.InputStream) SAXNotRecognizedException(org.xml.sax.SAXNotRecognizedException) UtfBomStripperInputStream(liquibase.resource.UtfBomStripperInputStream) IOException(java.io.IOException) SAXNotSupportedException(org.xml.sax.SAXNotSupportedException) IOException(java.io.IOException) ChangeLogParseException(liquibase.exception.ChangeLogParseException) SAXNotRecognizedException(org.xml.sax.SAXNotRecognizedException) SAXParseException(org.xml.sax.SAXParseException) SAXException(org.xml.sax.SAXException) SAXException(org.xml.sax.SAXException) SAXNotSupportedException(org.xml.sax.SAXNotSupportedException) SAXParseException(org.xml.sax.SAXParseException) ChangeLogParseException(liquibase.exception.ChangeLogParseException) SAXParser(javax.xml.parsers.SAXParser) XMLReader(org.xml.sax.XMLReader)

Aggregations

ChangeLogParseException (liquibase.exception.ChangeLogParseException)7 DatabaseChangeLog (liquibase.changelog.DatabaseChangeLog)4 IOException (java.io.IOException)3 InputStream (java.io.InputStream)3 Matcher (java.util.regex.Matcher)2 Pattern (java.util.regex.Pattern)2 Labels (liquibase.Labels)2 RawSQLChange (liquibase.change.core.RawSQLChange)2 ChangeSet (liquibase.changelog.ChangeSet)2 ParsedNode (liquibase.parser.core.ParsedNode)2 BufferedReader (java.io.BufferedReader)1 ParseException (java.text.ParseException)1 SAXParser (javax.xml.parsers.SAXParser)1 ContextExpression (liquibase.ContextExpression)1 Contexts (liquibase.Contexts)1 Liquibase (liquibase.Liquibase)1 EmptyChange (liquibase.change.core.EmptyChange)1 LockService (liquibase.lockservice.LockService)1 PreconditionContainer (liquibase.precondition.core.PreconditionContainer)1 SqlPrecondition (liquibase.precondition.core.SqlPrecondition)1