diff --git a/src/main/java/com/contrastsecurity/cassandra/migration/resolver/CompositeMigrationResolver.java b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/CompositeMigrationResolver.java index 2177a0b..d4295dc 100644 --- a/src/main/java/com/contrastsecurity/cassandra/migration/resolver/CompositeMigrationResolver.java +++ b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/CompositeMigrationResolver.java @@ -20,8 +20,13 @@ import com.contrastsecurity.cassandra.migration.config.ScriptsLocations; import com.contrastsecurity.cassandra.migration.info.ResolvedMigration; import com.contrastsecurity.cassandra.migration.resolver.cql.CqlMigrationResolver; +import com.contrastsecurity.cassandra.migration.resolver.java.ExternalJavaMigrationResolver; import com.contrastsecurity.cassandra.migration.resolver.java.JavaMigrationResolver; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.*; /** @@ -54,6 +59,11 @@ public CompositeMigrationResolver(ClassLoader classLoader, ScriptsLocations loca for (ScriptsLocation location : locations.getLocations()) { migrationResolvers.add(new CqlMigrationResolver(classLoader, location, encoding)); migrationResolvers.add(new JavaMigrationResolver(classLoader, location)); + try { + migrationResolvers.add(new ExternalJavaMigrationResolver(new URLClassLoader(new URL[]{new File(location.getPath()).toURI().toURL()}, this.getClass().getClassLoader()), location)); + } catch (MalformedURLException e) { + throw new CassandraMigrationException("Unable to add external url for classes migrations in location: " + location, e); + } } migrationResolvers.addAll(Arrays.asList(customMigrationResolvers)); diff --git a/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/CommonJavaResolver.java b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/CommonJavaResolver.java new file mode 100644 index 0000000..ef0ff42 --- /dev/null +++ b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/CommonJavaResolver.java @@ -0,0 +1,87 @@ +package com.contrastsecurity.cassandra.migration.resolver.java; + +import com.contrastsecurity.cassandra.migration.CassandraMigrationException; +import com.contrastsecurity.cassandra.migration.api.JavaMigration; +import com.contrastsecurity.cassandra.migration.api.MigrationChecksumProvider; +import com.contrastsecurity.cassandra.migration.api.MigrationInfoProvider; +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.utils.ClassUtils; +import com.contrastsecurity.cassandra.migration.utils.Pair; +import com.contrastsecurity.cassandra.migration.utils.StringUtils; +import com.contrastsecurity.cassandra.migration.utils.scanner.Scanner; + +import java.util.LinkedList; +import java.util.List; + +/** + * Created by Adam Król on 06.04.2017. + * + * @author Adam Król + */ +class CommonJavaResolver { + + List loadJavaMigrationFiles(ClassLoader classLoader, ScriptsLocation location) { + try { + Class[] classes = new Scanner(classLoader).scanForClasses(location, JavaMigration.class); + List migrations = new LinkedList<>(); + for (Class clazz : classes) { + JavaMigration javaMigration = ClassUtils.instantiate(clazz.getName(), classLoader); + + ResolvedMigration migrationInfo = extractMigrationInfo(javaMigration); + migrationInfo.setPhysicalLocation(ClassUtils.getLocationOnDisk(clazz)); + migrationInfo.setExecutor(new JavaMigrationExecutor(javaMigration)); + + migrations.add(migrationInfo); + } + return migrations; + } catch (Exception e) { + throw new CassandraMigrationException("Unable to resolve Java migrations in location: " + location, e); + } + } + + /** + * Extracts the migration info from this migration. + * + * @param javaMigration The migration to analyse. + * @return The migration info. + */ + ResolvedMigration extractMigrationInfo(JavaMigration javaMigration) { + Integer checksum = null; + if (javaMigration instanceof MigrationChecksumProvider) { + MigrationChecksumProvider checksumProvider = (MigrationChecksumProvider) javaMigration; + checksum = checksumProvider.getChecksum(); + } + + MigrationVersion version; + String description; + if (javaMigration instanceof MigrationInfoProvider) { + MigrationInfoProvider infoProvider = (MigrationInfoProvider) javaMigration; + version = infoProvider.getVersion(); + description = infoProvider.getDescription(); + if (!StringUtils.hasText(description)) { + throw new CassandraMigrationException("Missing description for migration " + version); + } + } else { + Pair info = + MigrationInfoHelper.extractVersionAndDescription( + ClassUtils.getShortName(javaMigration.getClass()), "V", "__", ""); + version = info.getLeft(); + description = info.getRight(); + } + + String script = javaMigration.getClass().getName(); + + + ResolvedMigration resolvedMigration = new ResolvedMigration(); + resolvedMigration.setVersion(version); + resolvedMigration.setDescription(description); + resolvedMigration.setScript(script); + resolvedMigration.setChecksum(checksum); + resolvedMigration.setType(MigrationType.JAVA_DRIVER); + return resolvedMigration; + } +} diff --git a/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/ExternalJavaMigrationResolver.java b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/ExternalJavaMigrationResolver.java new file mode 100644 index 0000000..df140c7 --- /dev/null +++ b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/ExternalJavaMigrationResolver.java @@ -0,0 +1,64 @@ +/** + * Copyright 2010-2015 Axel Fontaine + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.contrastsecurity.cassandra.migration.resolver.java; + +import com.contrastsecurity.cassandra.migration.config.ScriptsLocation; +import com.contrastsecurity.cassandra.migration.info.ResolvedMigration; +import com.contrastsecurity.cassandra.migration.resolver.MigrationResolver; +import com.contrastsecurity.cassandra.migration.resolver.ResolvedMigrationComparator; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Migration resolver for Java migrations. The classes must have a name like V1 or V1_1_3 or V1__Description + * or V1_1_3__Description. + */ +public class ExternalJavaMigrationResolver extends CommonJavaResolver implements MigrationResolver { + /** + * The base package on the classpath where to migrations are located. + */ + private final ScriptsLocation location; + + /** + * The ClassLoader to use. + */ + private ClassLoader classLoader; + + /** + * Creates a new instance. + * + * @param location The base package on the classpath where to migrations are located. + * @param classLoader The ClassLoader for loading migrations on the classpath. + */ + public ExternalJavaMigrationResolver(ClassLoader classLoader, ScriptsLocation location) { + this.location = location; + this.classLoader = classLoader; + } + + public List resolveMigrations() { + + if (!location.isFileSystem()) { + return Collections.emptyList(); + } + + List migrations = loadJavaMigrationFiles(classLoader, new ScriptsLocation("")); + + Collections.sort(migrations, new ResolvedMigrationComparator()); + return migrations; + } +} diff --git a/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/JavaMigrationResolver.java b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/JavaMigrationResolver.java index c85c430..ab50ba4 100644 --- a/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/JavaMigrationResolver.java +++ b/src/main/java/com/contrastsecurity/cassandra/migration/resolver/java/JavaMigrationResolver.java @@ -15,21 +15,10 @@ */ package com.contrastsecurity.cassandra.migration.resolver.java; -import com.contrastsecurity.cassandra.migration.CassandraMigrationException; -import com.contrastsecurity.cassandra.migration.api.MigrationChecksumProvider; -import com.contrastsecurity.cassandra.migration.api.MigrationInfoProvider; -import com.contrastsecurity.cassandra.migration.api.JavaMigration; -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.ClassUtils; -import com.contrastsecurity.cassandra.migration.utils.Pair; -import com.contrastsecurity.cassandra.migration.utils.StringUtils; -import com.contrastsecurity.cassandra.migration.utils.scanner.Scanner; import java.util.ArrayList; import java.util.Collections; @@ -39,7 +28,7 @@ * Migration resolver for Java migrations. The classes must have a name like V1 or V1_1_3 or V1__Description * or V1_1_3__Description. */ -public class JavaMigrationResolver implements MigrationResolver { +public class JavaMigrationResolver extends CommonJavaResolver implements MigrationResolver { /** * The base package on the classpath where to migrations are located. */ @@ -62,70 +51,15 @@ public JavaMigrationResolver(ClassLoader classLoader, ScriptsLocation location) } public List resolveMigrations() { - List migrations = new ArrayList(); - if (!location.isClassPath()) { - return migrations; + return Collections.emptyList(); } - try { - Class[] classes = new Scanner(classLoader).scanForClasses(location, JavaMigration.class); - for (Class clazz : classes) { - JavaMigration javaMigration = ClassUtils.instantiate(clazz.getName(), classLoader); - - ResolvedMigration migrationInfo = extractMigrationInfo(javaMigration); - migrationInfo.setPhysicalLocation(ClassUtils.getLocationOnDisk(clazz)); - migrationInfo.setExecutor(new JavaMigrationExecutor(javaMigration)); - - migrations.add(migrationInfo); - } - } catch (Exception e) { - throw new CassandraMigrationException("Unable to resolve Java migrations in location: " + location, e); - } + List migrations = loadJavaMigrationFiles(classLoader, location); Collections.sort(migrations, new ResolvedMigrationComparator()); return migrations; } - /** - * Extracts the migration info from this migration. - * - * @param javaMigration The migration to analyse. - * @return The migration info. - */ - ResolvedMigration extractMigrationInfo(JavaMigration javaMigration) { - Integer checksum = null; - if (javaMigration instanceof MigrationChecksumProvider) { - MigrationChecksumProvider checksumProvider = (MigrationChecksumProvider) javaMigration; - checksum = checksumProvider.getChecksum(); - } - - MigrationVersion version; - String description; - if (javaMigration instanceof MigrationInfoProvider) { - MigrationInfoProvider infoProvider = (MigrationInfoProvider) javaMigration; - version = infoProvider.getVersion(); - description = infoProvider.getDescription(); - if (!StringUtils.hasText(description)) { - throw new CassandraMigrationException("Missing description for migration " + version); - } - } else { - Pair info = - MigrationInfoHelper.extractVersionAndDescription( - ClassUtils.getShortName(javaMigration.getClass()), "V", "__", ""); - version = info.getLeft(); - description = info.getRight(); - } - String script = javaMigration.getClass().getName(); - - - ResolvedMigration resolvedMigration = new ResolvedMigration(); - resolvedMigration.setVersion(version); - resolvedMigration.setDescription(description); - resolvedMigration.setScript(script); - resolvedMigration.setChecksum(checksum); - resolvedMigration.setType(MigrationType.JAVA_DRIVER); - return resolvedMigration; - } }