Skip to content

Commit

Permalink
#18 Allow configuring the filename scanned from the maven artifact
Browse files Browse the repository at this point in the history
  • Loading branch information
galovics committed Mar 14, 2020
1 parent c18520b commit 2fdcdde
Show file tree
Hide file tree
Showing 17 changed files with 315 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.redskap.swagger.brake.cli;

import io.redskap.swagger.brake.cli.Cli;
import io.redskap.swagger.brake.cli.CliConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.SimpleCommandLinePropertySource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public abstract class CliOptions {

public static final String DEPRECATED_API_DELETION_ALLOWED = "deprecated-api-deletion-allowed";

public static final String API_FILENAME = "api-filename";

public static String getAsCliOption(String option) {
return "--" + option;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.redskap.swagger.brake.cli.options.handler;

import io.redskap.swagger.brake.cli.options.CliOptions;
import io.redskap.swagger.brake.runner.Options;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

@Component
public class ApiFilenameHandler implements CliOptionHandler {
@Override
public void handle(String propertyValue, Options options) {
if (StringUtils.isNotBlank(propertyValue)) {
options.setApiFilename(propertyValue);
}
}

@Override
public String getHandledPropertyName() {
return CliOptions.API_FILENAME;
}

@Override
public String getHelpMessage() {
return "Specifies the API filename Swagger Brake is going to search for";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ void set(CheckerOptions options) {
checkerOptions = options;
}


/**
* Returns the {@link CheckerOptions} from the context.
* @return the {@link CheckerOptions} if set, exception otherwise.
* @throws RuntimeException if no {@link CheckerOptions} has been set.
*/
public CheckerOptions get() {
if (checkerOptions == null) {
throw new RuntimeException("CheckerOptions has not been set up yet.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
public class LatestArtifactDownloaderFactory {
private final ApplicationContext applicationContext;

/**
* Factory that constructs a {@link LatestArtifactDownloader} instance.
* @param options the {@link Options} with which the {@link LatestArtifactDownloader} can be configured.
* @return the created {@link LatestArtifactDownloader} instance.
* @throws RuntimeException if the provided {@link Options} does not have the Options#mavenRepoUrl set.
*/
public LatestArtifactDownloader create(Options options) {
if (StringUtils.isNotBlank(options.getMavenRepoUrl())) {
return applicationContext.getBean("maven2LatestArtifactDownloader", LatestArtifactDownloader.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.nio.file.Files;
import java.util.jar.JarEntry;

import io.redskap.swagger.brake.maven.jar.filename.ApiFilenameCheckerFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
Expand All @@ -17,13 +18,15 @@
@Component
@RequiredArgsConstructor
@Slf4j
public class SwaggerFileJarResolver {
public class ApiFileJarResolver {
private final JarScanner jarScanner;
private final ApiFilenameCheckerFactory apiFilenameCheckerFactory;

public File resolve(File jarFile) {
public File resolve(ApiFileResolverParameter parameter) {
try {
File jarFile = parameter.getApiJar();
log.debug("Attempting to resolve swagger file from external JAR {}", jarFile.getAbsolutePath());
URL swaggerFile = findSwaggerFile(jarFile);
URL swaggerFile = findSwaggerFile(jarFile, parameter.getConfiguredApiFilename());
String fileName = new File(swaggerFile.getFile()).getName();
File destination = Files.createTempFile("swagger-brake", fileName).toFile();
log.debug("Extracting swagger file from {} to {}", swaggerFile, destination.getAbsolutePath());
Expand All @@ -35,8 +38,8 @@ public File resolve(File jarFile) {
}
}

private URL findSwaggerFile(File jarFile) throws IOException {
return jarScanner.find(jarFile, this::isSwaggerFile)
private URL findSwaggerFile(File jarFile, String configuredApiFilename) throws IOException {
return jarScanner.find(jarFile, entry -> isSwaggerFile(entry, configuredApiFilename))
.map(e -> getSwaggerFileUrl(jarFile, e))
.orElseThrow(() -> new IllegalStateException("Swagger file is not present in the artifact"));
}
Expand All @@ -50,10 +53,8 @@ private URL getSwaggerFileUrl(File jarFile, JarEntry entry) {
}
}

private boolean isSwaggerFile(JarEntry entry) {
private boolean isSwaggerFile(JarEntry entry, String configuredApiFilename) {
String entryName = entry.getName();
return entryName.endsWith("swagger.json")
|| entryName.endsWith("swagger.yml")
|| entryName.endsWith("swagger.yaml");
return apiFilenameCheckerFactory.create(configuredApiFilename).isApiFile(entryName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.redskap.swagger.brake.maven.jar;

import java.io.File;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
@EqualsAndHashCode
public class ApiFileResolverParameter {
private final File apiJar;
private final String configuredApiFilename;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.redskap.swagger.brake.maven.jar.filename;

import org.springframework.core.Ordered;

public interface ApiFileNameChecker extends Ordered {
boolean isApiFile(String fileName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.redskap.swagger.brake.maven.jar.filename;

import java.util.Collection;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
class ApiFileNameCheckerChain implements ApiFileNameChecker {
private final Collection<ApiFileNameChecker> checkers;

@Override
public boolean isApiFile(String fileName) {
for (ApiFileNameChecker checker : checkers) {
if (checker.isApiFile(fileName)) {
return true;
}
}
return false;
}

@Override
public int getOrder() {
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.redskap.swagger.brake.maven.jar.filename;

import java.util.Collection;
import java.util.TreeSet;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.OrderComparator;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class ApiFilenameCheckerFactory {
public ApiFileNameChecker create(String configuredApiFilename) {
Collection<ApiFileNameChecker> checkers = new TreeSet<>(OrderComparator.INSTANCE);
checkers.add(new SwaggerApiFileNameChecker());
if (StringUtils.isNotBlank(configuredApiFilename)) {
checkers.add(new ConfigurableApiFileNameChecker(configuredApiFilename));
}
return new ApiFileNameCheckerChain(checkers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.redskap.swagger.brake.maven.jar.filename;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.Ordered;

class ConfigurableApiFileNameChecker implements ApiFileNameChecker {
private final String apiFilename;

public ConfigurableApiFileNameChecker(String apiFilename) {
if (StringUtils.isBlank(apiFilename)) {
throw new IllegalArgumentException("apiFilename must not be empty");
}
this.apiFilename = apiFilename;
}

@Override
public boolean isApiFile(String fileName) {
return fileName.endsWith(apiFilename)
|| fileName.endsWith(apiFilename + ".yaml")
|| fileName.endsWith(apiFilename + ".yml")
|| fileName.endsWith(apiFilename + ".json");
}

@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.redskap.swagger.brake.maven.jar.filename;

import org.springframework.core.Ordered;

class SwaggerApiFileNameChecker implements ApiFileNameChecker {
@Override
public boolean isApiFile(String fileName) {
return fileName.endsWith("swagger.json")
|| fileName.endsWith("swagger.yml")
|| fileName.endsWith("swagger.yaml");
}

@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ public class Options {
private String mavenRepoPassword;

private Boolean deprecatedApiDeletionAllowed;

private String apiFilename;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import io.redskap.swagger.brake.maven.DownloadOptions;
import io.redskap.swagger.brake.maven.LatestArtifactDownloaderFactory;
import io.redskap.swagger.brake.maven.http.UnauthorizedException;
import io.redskap.swagger.brake.maven.jar.SwaggerFileJarResolver;
import io.redskap.swagger.brake.maven.jar.ApiFileJarResolver;
import io.redskap.swagger.brake.maven.jar.ApiFileResolverParameter;
import io.redskap.swagger.brake.runner.Options;
import io.redskap.swagger.brake.runner.exception.LatestArtifactDownloadException;
import lombok.RequiredArgsConstructor;
Expand All @@ -19,7 +20,7 @@
@Slf4j
public class ArtifactDownloaderHandler {
private final LatestArtifactDownloaderFactory downloaderFactory;
private final SwaggerFileJarResolver swaggerFileResolver;
private final ApiFileJarResolver apiFileResolver;
private final DownloadOptionsFactory downloadOptionsFactory;

public void handle(Options options) {
Expand All @@ -33,7 +34,8 @@ public void handle(Options options) {
log.info("Downloading latest artifact from repository '{}' with groupId '{}' artifactId '{}'", url, groupId, artifactId);
DownloadOptions downloadOptions = downloadOptionsFactory.create(url, groupId, artifactId, username, password);
File apiJar = downloaderFactory.create(options).download(downloadOptions);
File swaggerFile = swaggerFileResolver.resolve(apiJar);
ApiFileResolverParameter apiFileResolverParameter = new ApiFileResolverParameter(apiJar, options.getApiFilename());
File swaggerFile = apiFileResolver.resolve(apiFileResolverParameter);
options.setOldApiPath(swaggerFile.getAbsolutePath());
} catch (UnauthorizedException e) {
throw new LatestArtifactDownloadException("Cannot access Maven repository due to insufficient privileges. Consider providing username and password.", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package io.redskap.swagger.brake.maven.jar.filename;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;

public class ConfigurableApiFileNameCheckerTest {
@Test(expected = IllegalArgumentException.class)
public void testConstructorShouldThrowExceptionIfNullParameterIsGiven() {
// given
// when
new ConfigurableApiFileNameChecker(null);
// then exception thrown
}

@Test(expected = IllegalArgumentException.class)
public void testConstructorShouldThrowExceptionIfEmptyStringParameterIsGiven() {
// given
// when
new ConfigurableApiFileNameChecker(" ");
// then exception thrown
}

@Test
public void testIsApiShouldReturnFalseWhenDoesntMatch() {
// given
ConfigurableApiFileNameChecker underTest = new ConfigurableApiFileNameChecker("openapi");
// when
boolean result = underTest.isApiFile("c:/api/swagger.yaml");
// then
assertThat(result).isFalse();
}

@Test
public void testIsApiShouldReturnTrueWhenYamlMatchesFullPath() {
// given
ConfigurableApiFileNameChecker underTest = new ConfigurableApiFileNameChecker("openapi");
// when
boolean result = underTest.isApiFile("c:/api/openapi.yaml");
// then
assertThat(result).isTrue();
}

@Test
public void testIsApiShouldReturnTrueWhenYamlMatches() {
// given
ConfigurableApiFileNameChecker underTest = new ConfigurableApiFileNameChecker("openapi");
// when
boolean result = underTest.isApiFile("openapi.yaml");
// then
assertThat(result).isTrue();
}

@Test
public void testIsApiShouldReturnTrueWhenYmlMatches() {
// given
ConfigurableApiFileNameChecker underTest = new ConfigurableApiFileNameChecker("openapi");
// when
boolean result = underTest.isApiFile("openapi.yml");
// then
assertThat(result).isTrue();
}

@Test
public void testIsApiShouldReturnTrueWhenJsonMatches() {
// given
ConfigurableApiFileNameChecker underTest = new ConfigurableApiFileNameChecker("openapi");
// when
boolean result = underTest.isApiFile("openapi.json");
// then
assertThat(result).isTrue();
}

@Test
public void testIsApiShouldReturnTrueWhenExtensionIsProvidedAndMatches() {
// given
ConfigurableApiFileNameChecker underTest = new ConfigurableApiFileNameChecker("openapi.txt");
// when
boolean result = underTest.isApiFile("openapi.txt");
// then
assertThat(result).isTrue();
}
}
Loading

0 comments on commit 2fdcdde

Please sign in to comment.