use of org.flywaydb.core.api.FlywayException in project flyway by flyway.
the class ClassPathScanner method findResourceNamesAndParentURLs.
private Set<Pair<String, String>> findResourceNamesAndParentURLs() {
Set<Pair<String, String>> resourceNamesAndParentURLs = new TreeSet<>();
List<URL> locationUrls = getLocationUrlsForPath(location);
for (URL locationUrl : locationUrls) {
LOG.debug("Scanning URL: " + locationUrl.toExternalForm());
UrlResolver urlResolver = createUrlResolver(locationUrl.getProtocol());
URL resolvedUrl = urlResolver.toStandardJavaUrl(locationUrl);
String protocol = resolvedUrl.getProtocol();
ClassPathLocationScanner classPathLocationScanner = createLocationScanner(protocol);
if (classPathLocationScanner == null) {
String scanRoot = UrlUtils.toFilePath(resolvedUrl);
LOG.warn("Unable to scan location: " + scanRoot + " (unsupported protocol: " + protocol + ")");
} else {
Set<String> names = resourceNameCache.get(classPathLocationScanner, resolvedUrl);
if (names == null) {
names = classPathLocationScanner.findResourceNames(location.getRootPath(), resolvedUrl);
resourceNameCache.put(classPathLocationScanner, resolvedUrl, names);
}
Set<String> filteredNames = new HashSet<>();
for (String name : names) {
if (location.matchesPath(name)) {
filteredNames.add(name);
}
}
for (String filteredName : filteredNames) {
resourceNamesAndParentURLs.add(Pair.of(filteredName, resolvedUrl.getPath()));
}
}
}
// Make an additional attempt at finding resources in jar files in case the URL scanning method above didn't
// yield any results.
boolean locationResolved = !locationUrls.isEmpty();
// Starting with Java 11, resources at the root of the classpath aren't being found using the URL scanning
// method above and we need to revert to Jar file walking.
boolean isClassPathRoot = location.isClassPath() && "".equals(location.getRootPath());
if (!locationResolved || isClassPathRoot) {
if (classLoader instanceof URLClassLoader) {
URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
for (URL url : urlClassLoader.getURLs()) {
if ("file".equals(url.getProtocol()) && url.getPath().endsWith(".jar") && !url.getPath().matches(".*" + Pattern.quote("/jre/lib/") + ".*")) {
// All non-system jars on disk
JarFile jarFile;
try {
try {
jarFile = new JarFile(url.toURI().getSchemeSpecificPart());
} catch (URISyntaxException ex) {
// Fallback for URLs that are not valid URIs (should hardly ever happen).
jarFile = new JarFile(url.getPath().substring("file:".length()));
}
} catch (IOException | SecurityException e) {
LOG.warn("Skipping unloadable jar file: " + url + " (" + e.getMessage() + ")");
continue;
}
try {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
String entryName = entries.nextElement().getName();
if (entryName.startsWith(location.getRootPath())) {
locationResolved = true;
resourceNamesAndParentURLs.add(Pair.of(entryName, url.getPath()));
}
}
} finally {
try {
jarFile.close();
} catch (IOException e) {
// Ignore
}
}
}
}
}
}
if (!locationResolved) {
String message = "Unable to resolve location " + location + ".";
if (throwOnMissingLocations) {
throw new FlywayException(message);
} else {
LOG.debug(message);
}
}
return resourceNamesAndParentURLs;
}
use of org.flywaydb.core.api.FlywayException in project flyway by flyway.
the class AwsS3Scanner method scanForResources.
/**
* Scans S3 for the resources. In AWS SDK v2, only the region that the client is configured with can be used.
* The format of the path is expected to be {@code s3:{bucketName}/{optional prefix}}.
*
* @param location The location in S3 to start searching. Subdirectories are also searched.
* @return The resources that were found.
*/
@Override
public Collection<LoadableResource> scanForResources(final Location location) {
String bucketName = getBucketName(location);
String prefix = getPrefix(bucketName, location.getPath());
S3Client s3Client = S3ClientFactory.getClient();
try {
ListObjectsV2Request.Builder builder = ListObjectsV2Request.builder().bucket(bucketName).prefix(prefix);
ListObjectsV2Request request = builder.build();
ListObjectsV2Response listObjectResult = s3Client.listObjectsV2(request);
return getLoadableResources(bucketName, listObjectResult);
} catch (SdkClientException e) {
if (throwOnMissingLocations) {
throw new FlywayException("Could not access s3 location:" + bucketName + prefix + " due to error: " + e.getMessage());
}
LOG.error("Skipping s3 location:" + bucketName + prefix + " due to error: " + e.getMessage());
return Collections.emptyList();
}
}
use of org.flywaydb.core.api.FlywayException in project flyway by flyway.
the class CompositeMigrationResolver method checkForIncompatibilities.
/**
* Checks for incompatible migrations.
*
* @param migrations The migrations to check.
* @throws FlywayException when two different migration with the same version number are found.
*/
static void checkForIncompatibilities(List<ResolvedMigration> migrations) {
ResolvedMigrationComparator resolvedMigrationComparator = new ResolvedMigrationComparator();
// check for more than one migration with same version
for (int i = 0; i < migrations.size() - 1; i++) {
ResolvedMigration current = migrations.get(i);
ResolvedMigration next = migrations.get(i + 1);
if (resolvedMigrationComparator.compare(current, next) == 0) {
if (current.getVersion() != null) {
throw new FlywayException(String.format("Found more than one migration with version %s\nOffenders:\n-> %s (%s)\n-> %s (%s)", current.getVersion(), current.getPhysicalLocation(), current.getType(), next.getPhysicalLocation(), next.getType()), ErrorCode.DUPLICATE_VERSIONED_MIGRATION);
}
throw new FlywayException(String.format("Found more than one repeatable migration with description %s\nOffenders:\n-> %s (%s)\n-> %s (%s)", current.getDescription(), current.getPhysicalLocation(), current.getType(), next.getPhysicalLocation(), next.getType()), ErrorCode.DUPLICATE_REPEATABLE_MIGRATION);
}
}
}
use of org.flywaydb.core.api.FlywayException in project flyway by flyway.
the class ResourceNameValidator method validateSQLMigrationNaming.
/**
* Validates the names of all SQL resources returned by the ResourceProvider
*
* @param provider The ResourceProvider to validate
* @param configuration The configuration to use
*/
public void validateSQLMigrationNaming(ResourceProvider provider, Configuration configuration) {
List<String> errorsFound = new ArrayList<>();
ResourceNameParser resourceNameParser = new ResourceNameParser(configuration);
for (Resource resource : getAllSqlResources(provider, configuration)) {
String filename = resource.getFilename();
LOG.debug("Validating " + filename);
// Filter out special purpose files that the parser will not identify.
if (isSpecialResourceFile(configuration, filename)) {
continue;
}
ResourceName result = resourceNameParser.parse(filename);
if (!result.isValid()) {
errorsFound.add(result.getValidityMessage());
}
}
if (!errorsFound.isEmpty()) {
if (configuration.isValidateMigrationNaming()) {
throw new FlywayException("Invalid SQL filenames found:\r\n" + StringUtils.collectionToDelimitedString(errorsFound, "\r\n"));
} else {
LOG.info(errorsFound.size() + " SQL migrations were detected but not run because they did not follow the filename convention.");
LOG.info("If this is in error, enable debug logging or 'validateMigrationNaming' to fail fast and see a list of the invalid file names.");
}
}
}
use of org.flywaydb.core.api.FlywayException in project flyway by flyway.
the class ChecksumCalculator method calculateChecksumForResource.
private static int calculateChecksumForResource(LoadableResource resource) {
final CRC32 crc32 = new CRC32();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(resource.read(), 4096);
String line = bufferedReader.readLine();
if (line != null) {
line = BomFilter.FilterBomFromString(line);
do {
// noinspection Since15
crc32.update(line.getBytes(StandardCharsets.UTF_8));
} while ((line = bufferedReader.readLine()) != null);
}
} catch (IOException e) {
throw new FlywayException("Unable to calculate checksum of " + resource.getFilename() + "\r\n" + e.getMessage(), e);
} finally {
IOUtils.close(bufferedReader);
}
return (int) crc32.getValue();
}
Aggregations