All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jurr.liquibase.releaseplugin.context.DatabaseChangeLogFile Maven / Gradle / Ivy

package org.jurr.liquibase.releaseplugin.context;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.XMLEvent;

import org.jurr.liquibase.releaseplugin.PrettyPrintXMLEventWriter;

public abstract class DatabaseChangeLogFile
{
	public static final String LIQUIBASE_NAMESPACE = "http://www.liquibase.org/xml/ns/dbchangelog";

	protected static final XMLEventFactory XML_EVENT_FACTORY = XMLEventFactory.newInstance();

	private static final XMLInputFactory XML_INPUT_FACTORY;
	private static final XMLOutputFactory XML_OUTPUT_FACTORY;
	static
	{
		XML_INPUT_FACTORY = XMLInputFactory.newInstance();
		XML_INPUT_FACTORY.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE);

		XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance();
		XML_OUTPUT_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
	}

	public static final QName DATABASE_CHANGELOG_TAG = new QName(LIQUIBASE_NAMESPACE, "databaseChangeLog");
	public static final QName CHANGE_SET_TAG = new QName(LIQUIBASE_NAMESPACE, "changeSet");
	public static final QName CHANGE_SET_TAG_ID_ATTRIBUTE = new QName("", "id");
	public static final QName CHANGE_SET_TAG_AUTHOR_ATTRIBUTE = new QName("", "author");
	public static final QName CHANGE_SET_TAG_CONTEXT_ATTRIBUTE = new QName("", "context");
	public static final QName INCLUDE_TAG = new QName(LIQUIBASE_NAMESPACE, "include");
	public static final QName INCLUDE_TAG_FILE_ATTRIBUTE = new QName("", "file");
	public static final QName INCLUDE_TAG_RELATIVE_TO_CHANGE_LOG_FILE_ATTRIBUTE = new QName("", "relativeToChangelogFile");
	public static final QName TAG_DATABASE_TAG = new QName(LIQUIBASE_NAMESPACE, "tagDatabase");
	public static final QName TAG_DATABASE_TAG_ATTRIBUTE = new QName("", "tag");

	private final Path path;

	private boolean fileRead = false;
	private LiquibaseProject liquibaseProject;
	private byte[] newLatestFile;

	DatabaseChangeLogFile(@Nonnull final Path path)
	{
		if (Files.notExists(path))
		{
			throw new IllegalArgumentException("File " + path + " does not exist");
		}
		if (!Files.isReadable(path))
		{
			throw new IllegalArgumentException("File " + path + " is not readable");
		}
		this.path = path;
	}

	@Nonnull
	LiquibaseProject getLiquibaseProject()
	{
		return liquibaseProject;
	}

	void setLiquibaseProject(@Nonnull final LiquibaseProject liquibaseProject)
	{
		this.liquibaseProject = liquibaseProject;
	}

	@Nonnull
	Path getPath()
	{
		return path;
	}

	@Nonnull
	byte[] getNewLatestFile()
	{
		return newLatestFile;
	}

	void readFile()
	{
		if (fileRead)
		{
			return;
		}

		try (BufferedReader masterFileBR = Files.newBufferedReader(path, Charset.defaultCharset()))
		{
			try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
			{
				final XMLEventReader xmlEventReader = XML_INPUT_FACTORY.createXMLEventReader(masterFileBR);
				final XMLEventWriter xmlEventWriter = new PrettyPrintXMLEventWriter(XML_OUTPUT_FACTORY.createXMLEventWriter(baos), "\t");
				while (xmlEventReader.hasNext())
				{
					final XMLEvent xmlEvent = xmlEventReader.nextEvent();
					switch (xmlEvent.getEventType())
					{
					case XMLStreamConstants.START_DOCUMENT:
						final StartDocument xmlStartDocument = (StartDocument) xmlEvent;
						readStartDocumentTag(xmlEventReader, xmlStartDocument, xmlEventWriter);
						break;
					default:
						throw new IllegalArgumentException("Unknown tag in file " + path + " at line " + xmlEvent.getLocation().getLineNumber() + ", column " + xmlEvent.getLocation().getColumnNumber());
					}
				}

				xmlEventWriter.flush();
				newLatestFile = baos.toByteArray();
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("IO error while reading " + path, e);
		}
		catch (XMLStreamException e)
		{
			throw new RuntimeException("XML exception while reading " + path, e);
		}

		fileRead = true;
	}

	abstract void readStartDocumentTag(@Nonnull final XMLEventReader xmlEventReader, @Nonnull final StartDocument startDocumentElement, @Nonnull final XMLEventWriter xmlEventWriter) throws XMLStreamException;

	/**
	 * This method will actually create the required files for the new database version.
	 *
	 * @throws IOException whenever there is an exception while creating or moving files
	 */
	abstract void createNewVersion() throws IOException;

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + (path == null ? 0 : path.hashCode());
		return result;
	}

	@Override
	public boolean equals(@Nullable final Object obj)
	{
		if (this == obj)
		{
			return true;
		}
		if (obj == null)
		{
			return false;
		}
		if (getClass() != obj.getClass())
		{
			return false;
		}
		DatabaseChangeLogFile other = (IncludeFile) obj;
		if (path == null)
		{
			if (other.path != null)
			{
				return false;
			}
		}
		else if (!path.equals(other.path))
		{
			return false;
		}
		return true;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy