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

com.contrastsecurity.cassandra.migration.resolver.cql.CqlMigrationResolver Maven / Gradle / Ivy

package com.contrastsecurity.cassandra.migration.resolver.cql;

import com.contrastsecurity.cassandra.migration.config.MigrationType;
import com.contrastsecurity.cassandra.migration.config.ScriptsLocation;
import com.contrastsecurity.cassandra.migration.info.MigrationVersion;
import com.contrastsecurity.cassandra.migration.info.ResolvedMigration;
import com.contrastsecurity.cassandra.migration.resolver.MigrationInfoHelper;
import com.contrastsecurity.cassandra.migration.resolver.MigrationResolver;
import com.contrastsecurity.cassandra.migration.resolver.ResolvedMigrationComparator;
import com.contrastsecurity.cassandra.migration.utils.Pair;
import com.contrastsecurity.cassandra.migration.utils.scanner.Resource;
import com.contrastsecurity.cassandra.migration.utils.scanner.Scanner;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.zip.CRC32;

/**
 * Migration resolver for cql files on the classpath. The cql files must have names like
 * V1__Description.cql or V1_1__Description.cql.
 */
public class CqlMigrationResolver implements MigrationResolver {

    /**
     * The scanner to use.
     */
    private final Scanner scanner;

    /**
     * The base directory on the classpath where to migrations are located.
     */
    private final ScriptsLocation location;

    /**
     * The encoding of Cql migrations.
     */
    private final String encoding;

    /**
     * The prefix for cql migrations
     */
    private final static String CQL_MIGRATION_PREFIX = "V";
    ;

    /**
     * The separator for cql migrations
     */
    private final static String CQL_MIGRATION_SEPARATOR = "__";

    /**
     * The suffix for cql migrations
     */
    private final static String CQL_MIGRATION_SUFFIX = ".cql";

    /**
     * Creates a new instance.
     *
     * @param classLoader The ClassLoader for loading migrations on the classpath.
     * @param location    The location on the classpath where to migrations are located.
     * @param encoding    The encoding of the .cql file.
     */
    public CqlMigrationResolver(ClassLoader classLoader, ScriptsLocation location, String encoding) {
        this.scanner = new Scanner(classLoader);
        this.location = location;
        this.encoding = encoding;
    }

    public List resolveMigrations() {
        List migrations = new ArrayList<>();

        Resource[] resources = scanner.scanForResources(location, CQL_MIGRATION_PREFIX, CQL_MIGRATION_SUFFIX);
        for (Resource resource : resources) {
            ResolvedMigration resolvedMigration = extractMigrationInfo(resource);
            resolvedMigration.setPhysicalLocation(resource.getLocationOnDisk());
            resolvedMigration.setExecutor(new CqlMigrationExecutor(resource, encoding));

            migrations.add(resolvedMigration);
        }

        Collections.sort(migrations, new ResolvedMigrationComparator());
        return migrations;
    }

    /**
     * Extracts the migration info for this resource.
     *
     * @param resource The resource to analyse.
     * @return The migration info.
     */
    private ResolvedMigration extractMigrationInfo(Resource resource) {
        ResolvedMigration migration = new ResolvedMigration();

        Pair info =
                MigrationInfoHelper.extractVersionAndDescription(resource.getFilename(),
                        CQL_MIGRATION_PREFIX, CQL_MIGRATION_SEPARATOR, CQL_MIGRATION_SUFFIX);
        migration.setVersion(info.getLeft());
        migration.setDescription(info.getRight());

        migration.setScript(extractScriptName(resource));

        migration.setChecksum(calculateChecksum(resource.loadAsBytes()));
        migration.setType(MigrationType.CQL);
        return migration;
    }

    /**
     * Extracts the script name from this resource.
     *
     * @param resource The resource to process.
     * @return The script name.
     */
    /* private -> for testing */ String extractScriptName(Resource resource) {
        if (location.getPath().isEmpty()) {
            return resource.getLocation();
        }

        return resource.getLocation().substring(location.getPath().length() + 1);
    }

    /**
     * Calculates the checksum of these bytes.
     *
     * @param bytes The bytes to calculate the checksum for.
     * @return The crc-32 checksum of the bytes.
     */
    private static int calculateChecksum(byte[] bytes) {
        final CRC32 crc32 = new CRC32();
        crc32.update(bytes);
        return (int) crc32.getValue();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy