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

com.github.zeger_tak.enversvalidationplugin.EnversValidationMojo Maven / Gradle / Ivy

Go to download

This is a Maven plugin that allows for easy validation of database auditing with Hibernate and is intended to be used by projects that do not always rely on Envers to create the audit history.

There is a newer version: 0.6
Show newest version
package com.github.zeger_tak.enversvalidationplugin;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.github.zeger_tak.enversvalidationplugin.annotation.Parameterized;
import com.github.zeger_tak.enversvalidationplugin.annotation.Validate;
import com.github.zeger_tak.enversvalidationplugin.annotation.ValidationType;
import com.github.zeger_tak.enversvalidationplugin.connection.ConnectionProviderInstance;
import com.github.zeger_tak.enversvalidationplugin.entities.AuditTableInformation;
import com.github.zeger_tak.enversvalidationplugin.entities.ValidationResults;
import com.github.zeger_tak.enversvalidationplugin.exceptions.ValidationException;
import com.github.zeger_tak.enversvalidationplugin.execution.SetupExecutor;
import com.github.zeger_tak.enversvalidationplugin.utils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

@Mojo(name = "validate")
public class EnversValidationMojo extends AbstractMojo
{
	private static final String PACKAGE_TO_ALWAYS_SCAN_FOR_EXECUTORS = "com.github.zeger_tak.enversvalidationplugin.validate";
	private static final String USERNAME_PROPERTY_KEY = "username";
	private static final String PASSWORD_PROPERTY_KEY = "password";
	private static final String DRIVER_PROPERTY_KEY = "driver";
	private static final String URL_PROPERTY_KEY = "url";
	private static final String AUDIT_TABLE_INFORMATION_FILE_PROPERTY_KEY = "auditTableInformationFile";
	private static final String CONNECTION_PROPERTY_FILE_PROPERTY_KEY = "connectionPropertyFile";
	private static final String PACKAGE_TO_SCAN_FOR_VALIDATORS_PROPERTY_KEY = "packageToScanForValidators";
	private static final String IGNORABLES_PROPERTY_KEY = "ignorables";

	/**
	 * Database username used to connect with the database.
	 * This parameter may also be provided in the {@link #connectionPropertyFile}.
	 */
	@Parameter(property = USERNAME_PROPERTY_KEY)
	private String username;

	/**
	 * Database user password used to connect with the database.
	 * This parameter may also be provided in the {@link #connectionPropertyFile}.
	 */
	@Parameter(property = PASSWORD_PROPERTY_KEY)
	private String password;

	/**
	 * Database driver class used to connect with the database.
	 * This parameter may also be provided in the {@link #connectionPropertyFile}.
	 */
	@Parameter(property = DRIVER_PROPERTY_KEY)
	private String driver;

	/**
	 * JDBC connection string. (E.g. 'jdbc:postgresql://localhost/schemaToTest').
	 * This parameter may also be provided in the {@link #connectionPropertyFile}.
	 */
	@Parameter(property = URL_PROPERTY_KEY)
	private String url;

	/**
	 * Contains audit table information.
	 * This parameter may also be provided in the {@link #connectionPropertyFile}.
	 */
	@Parameter(property = AUDIT_TABLE_INFORMATION_FILE_PROPERTY_KEY)
	private String auditTableInformationFile;

	/**
	 * Alternative to providing other parameters directly.
	 */
	@Parameter(property = CONNECTION_PROPERTY_FILE_PROPERTY_KEY)
	private File connectionPropertyFile;

	/**
	 * Used to define packages which hold user defined validators.
	 * WARNING: Untested feature.
	 *
	 * Validators within these packages will be found based on the {@link ValidationType} annotation.
	 * The actual validator methods should be annotated with the {@link Validate} annotation.
	 */
	@Parameter(property = PACKAGE_TO_SCAN_FOR_VALIDATORS_PROPERTY_KEY)
	private List packageToScanForValidators = new ArrayList<>();

	/**
	 * Used to define validator classes/method that should be ignored.
	 * Validators can be ignored based on their unique identifier, the following cases are supported.
	 *
	 * Class level: E.g. RevisionValidator
	 * Method level: E.g. RevisionValidator.validateHistoryIsAValidFlow
	 * Individual runs: E.g. RevisionValidator.validateHistoryIsAValidFlow.AUDIT_TABLE_TO_IGNORE.
	 * (In case of a {@link Validate} method with data generated by a {@link Parameterized} method)
	 */
	@Parameter(property = IGNORABLES_PROPERTY_KEY)
	private List ignorables;

	@Override
	public void execute() throws MojoFailureException
	{
		final ConnectionProviderInstance connectionProvider = createConnectionProvider(connectionPropertyFile);
		final Map auditTableInformationMap = PropertyUtils.getAuditTableInformationMap(connectionProvider.getAuditTableInformationFile(), connectionProvider.getQueries().getAuditTablePostFix());

		final ValidationResults validationResults = new ValidationResults();
		packageToScanForValidators.add(PACKAGE_TO_ALWAYS_SCAN_FOR_EXECUTORS);
		try
		{
			new SetupExecutor(getLog(), ignorables, connectionProvider).execute(packageToScanForValidators, auditTableInformationMap, validationResults);
		}
		catch (RuntimeException e)
		{
			getLog().error(e);
			throw new MojoFailureException("Exception occurred: " + e.getMessage());
		}

		final List validatorClassesIgnored = validationResults.getValidatorClassesIgnored();
		if (!validatorClassesIgnored.isEmpty())
		{
			getLog().info("The following validators were ignored: " + validatorClassesIgnored);
		}

		final int executionsFailed = validationResults.getExecutionsFailed();
		if (executionsFailed > 0)
		{
			throw new ValidationException(executionsFailed + " validations failed, see log above for details.");
		}
	}

	@Nonnull
	private ConnectionProviderInstance createConnectionProvider(@Nullable File file) throws MojoFailureException
	{
		updatePropertiesFromPropertyFile(file);
		validateAllRequiredPropertiesAreAvailable();

		return new ConnectionProviderInstance(url, driver, username, password, auditTableInformationFile);
	}

	private void updatePropertiesFromPropertyFile(@Nullable File file) throws MojoFailureException
	{
		if (file == null)
		{
			return;
		}

		final Properties connectionPropertiesInFile = PropertyUtils.getPropertiesFromFile(file);
		if (username == null)
		{
			username = connectionPropertiesInFile.getProperty(USERNAME_PROPERTY_KEY);
		}
		if (password == null)
		{
			password = connectionPropertiesInFile.getProperty(PASSWORD_PROPERTY_KEY);
		}
		if (driver == null)
		{
			driver = connectionPropertiesInFile.getProperty(DRIVER_PROPERTY_KEY);
		}
		if (url == null)
		{
			url = connectionPropertiesInFile.getProperty(URL_PROPERTY_KEY);
		}
		if (auditTableInformationFile == null)
		{
			auditTableInformationFile = connectionPropertiesInFile.getProperty(AUDIT_TABLE_INFORMATION_FILE_PROPERTY_KEY);
		}
		if (ignorables == null)
		{
			ignorables = (List) connectionPropertiesInFile.get(IGNORABLES_PROPERTY_KEY);
		}
	}

	private void validateAllRequiredPropertiesAreAvailable() throws MojoFailureException
	{
		final List propertyKeysMissing = new ArrayList<>();
		if (StringUtils.isBlank(username))
		{
			propertyKeysMissing.add(USERNAME_PROPERTY_KEY);
		}
		if (StringUtils.isBlank(password))
		{
			propertyKeysMissing.add(PASSWORD_PROPERTY_KEY);
		}
		if (StringUtils.isBlank(driver))
		{
			propertyKeysMissing.add(DRIVER_PROPERTY_KEY);
		}
		if (StringUtils.isBlank(url))
		{
			propertyKeysMissing.add(URL_PROPERTY_KEY);
		}
		if (StringUtils.isBlank(auditTableInformationFile))
		{
			propertyKeysMissing.add(AUDIT_TABLE_INFORMATION_FILE_PROPERTY_KEY);
		}
		if (!propertyKeysMissing.isEmpty())
		{
			throw new MojoFailureException("The following required connection are missing from the connection property file: " + propertyKeysMissing);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy