diff --git a/integration-tests/src/test/java/org/wildfly/prospero/it/cli/InstallTest.java b/integration-tests/src/test/java/org/wildfly/prospero/it/cli/InstallTest.java index f79b8f460..cf7737789 100644 --- a/integration-tests/src/test/java/org/wildfly/prospero/it/cli/InstallTest.java +++ b/integration-tests/src/test/java/org/wildfly/prospero/it/cli/InstallTest.java @@ -20,13 +20,12 @@ import java.io.File; import java.net.URL; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.wildfly.prospero.cli.ReturnCodes; import org.wildfly.prospero.cli.commands.CliConstants; import org.wildfly.prospero.it.ExecutionUtils; @@ -36,15 +35,12 @@ public class InstallTest extends CliTestBase { - @Rule - public TemporaryFolder tempDir = new TemporaryFolder(); - private File targetDir; @Before public void setUp() throws Exception { super.setUp(); - targetDir = tempDir.newFolder(); + targetDir = temp.newFolder(); } @Test @@ -62,8 +58,8 @@ public void testInstallWithProvisionConfig() throws Exception { @Test public void testInstallWithLocalRepositories() throws Exception { - final Path manifestPath = tempDir.newFile().toPath(); - final Path provisionConfig = tempDir.newFile().toPath(); + final Path manifestPath = temp.newFile().toPath(); + final Path provisionConfig = temp.newFile().toPath(); MetadataTestUtils.copyManifest("manifests/wfcore-base.yaml", manifestPath); MetadataTestUtils.prepareChannel(provisionConfig, List.of(manifestPath.toUri().toURL())); @@ -73,10 +69,12 @@ public void testInstallWithLocalRepositories() throws Exception { final URL temporaryRepo = mockTemporaryRepo(true); + Path relativePath = Paths.get(System.getProperty("user.dir")).relativize(Path.of(temporaryRepo.toURI())); + ExecutionUtils.prosperoExecution(CliConstants.Commands.UPDATE, CliConstants.Commands.PERFORM, - CliConstants.REPOSITORIES, temporaryRepo.toString(), + CliConstants.REPOSITORIES, relativePath.toString(), CliConstants.Y, - CliConstants.NO_LOCAL_MAVEN_CACHE, + CliConstants.VERBOSE, CliConstants.DIR, targetDir.getAbsolutePath()) .execute() .assertReturnCode(ReturnCodes.SUCCESS); diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java index 4ff8ae8b2..276f079c7 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java @@ -420,6 +420,10 @@ default ArgumentParsingException invalidRepositoryDefinition(String repoKey) { return new ArgumentParsingException(format(bundle.getString("prospero.general.validation.repo_format"), repoKey)); } + default ArgumentParsingException invalidFilePath(String repoKey) { + return new ArgumentParsingException(format(bundle.getString("prospero.general.validation.file_path.not_exists"), repoKey)); + } + default IllegalArgumentException updateCandidateStateNotMatched(Path targetDir, Path updateDir) { return new IllegalArgumentException(format(bundle.getString("prospero.updates.apply.validation.candidate.outdated"), targetDir, updateDir)); } diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/RepositoryDefinition.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/RepositoryDefinition.java index 482470a1f..70a1f8045 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/RepositoryDefinition.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/RepositoryDefinition.java @@ -17,34 +17,44 @@ package org.wildfly.prospero.cli; +import org.jboss.logging.Logger; import org.wildfly.channel.Repository; import java.io.File; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; public class RepositoryDefinition { + private static final Logger logger = Logger.getLogger(RepositoryDefinition.class.getName()); + public static List from(List repos) throws ArgumentParsingException { ArrayList repositories = new ArrayList<>(repos.size()); for (int i = 0; i < repos.size(); i++) { - final String text = repos.get(i); - if(text.contains("::")) { - final String[] parts = text.split("::"); + String repoInfo = repos.get(i); + if(repoInfo.contains("::")) { + final String[] parts = repoInfo.split("::"); if (parts.length != 2 || parts[0].isEmpty() || parts[1].isEmpty() || !isValidUrl(parts[1])) { - throw CliMessages.MESSAGES.invalidRepositoryDefinition(text); + throw CliMessages.MESSAGES.invalidRepositoryDefinition(repoInfo); } - repositories.add(new Repository(parts[0], parts[1])); } else { - if (!isValidUrl(text)) { - throw CliMessages.MESSAGES.invalidRepositoryDefinition(text); + if (!(repoInfo.startsWith("http://") || repoInfo.startsWith("https://")) && !repoInfo.isEmpty()) { + try { + repoInfo = getAbsoluteFileURI(repoInfo).toString(); + } catch (URISyntaxException e) { + logger.warn("An error occurred while processing URI"); + } } - - repositories.add(new Repository("temp-repo-" + i, text)); + if (!isValidUrl(repoInfo)){ + throw CliMessages.MESSAGES.invalidRepositoryDefinition(repoInfo); + } + repositories.add(new Repository("temp-repo-" + i, repoInfo)); } } return repositories; @@ -52,15 +62,32 @@ public static List from(List repos) throws ArgumentParsingEx private static boolean isValidUrl(String text) { try { - URL url = new URL(text); - if (text.startsWith("file")){ - String path = Paths.get(url.getPath()).normalize().toString(); - File f = new File(path); - return f.exists(); - } + new URL(text); return true; } catch (MalformedURLException e) { return false; } } + + public static URI getAbsoluteFileURI(String repoInfo) throws ArgumentParsingException, URISyntaxException { + File file = new File(getPath(repoInfo)); + if (file.exists()) { + return file.toURI(); + } else { + throw CliMessages.MESSAGES.invalidFilePath(repoInfo); + } + } + + public static String getPath(String repoInfo) throws URISyntaxException { + if (repoInfo.startsWith("file:")) { + URI inputUri = new URI(repoInfo); + if (inputUri.getScheme().equals("file") && + !inputUri.getSchemeSpecificPart().startsWith("/")) { + return Path.of(inputUri.getSchemeSpecificPart()).toAbsolutePath().normalize().toString(); + } + return Path.of(inputUri).normalize().toFile().getAbsolutePath(); + } else { + return Path.of(repoInfo).toAbsolutePath().normalize().toString(); + } + } } diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/AbstractInstallCommand.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/AbstractInstallCommand.java index 984688b55..5b49da8bf 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/AbstractInstallCommand.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/AbstractInstallCommand.java @@ -25,7 +25,6 @@ import org.wildfly.prospero.api.MavenOptions; import org.wildfly.prospero.api.ProvisioningDefinition; import org.wildfly.prospero.api.exceptions.ChannelDefinitionException; -import org.wildfly.prospero.api.exceptions.MetadataException; import org.wildfly.prospero.api.exceptions.NoChannelException; import org.wildfly.prospero.cli.ActionFactory; import org.wildfly.prospero.cli.ArgumentParsingException; @@ -100,7 +99,7 @@ protected MavenOptions getMavenOptions() throws ArgumentParsingException { return mavenOptions.build(); } - protected ProvisioningDefinition.Builder buildDefinition() throws MetadataException, NoChannelException, ArgumentParsingException { + protected ProvisioningDefinition.Builder buildDefinition() throws ArgumentParsingException { return ProvisioningDefinition.builder() .setFpl(featurePackOrDefinition.fpl.orElse(null)) .setProfile(featurePackOrDefinition.profile.orElse(null)) diff --git a/prospero-cli/src/main/resources/UsageMessages.properties b/prospero-cli/src/main/resources/UsageMessages.properties index b4f968475..35926d35d 100644 --- a/prospero-cli/src/main/resources/UsageMessages.properties +++ b/prospero-cli/src/main/resources/UsageMessages.properties @@ -340,6 +340,7 @@ prospero.general.error.resolve.streams.header=Required artifact streams are not prospero.general.validation.conflicting_options=Only one of %s and %s can be set. prospero.general.validation.local_repo.not_directory=Repository path `%s` is a file not a directory. prospero.general.validation.repo_format=Repository definition [%s] is invalid. The definition format should be [id::url] or [url]. +prospero.general.validation.file_path.not_exists= The given file path [%s] is invalid. prospero.general.error.missing_file=Required file at `%s` cannot be opened. prospero.general.error.galleon.parse=Failed to parse provisioning configuration: %s prospero.general.error.feature_pack.not_found=The feature pack `%s` is not available in the subscribed channels. diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/RepositoryDefinitionTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/RepositoryDefinitionTest.java index de85ca47a..3f1c322ea 100644 --- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/RepositoryDefinitionTest.java +++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/RepositoryDefinitionTest.java @@ -19,35 +19,26 @@ import org.apache.commons.lang3.StringUtils; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.wildfly.channel.Repository; import java.io.File; +import java.nio.file.Path; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.Assert.*; import static org.wildfly.prospero.cli.RepositoryDefinition.from; public class RepositoryDefinitionTest { - @Rule - public TemporaryFolder tempDir = new TemporaryFolder(); - - public String fileURL; - - public String filePath; + private String tempRepoURL; @Before public void setUp() throws Exception { - File target = tempDir.newFolder(); - filePath = target.getAbsolutePath(); - fileURL = target.toURI().toURL().toString(); + tempRepoURL = Path.of(".").normalize().toAbsolutePath().toUri().toString().replace("///","/"); } @Test @@ -97,17 +88,47 @@ public void throwsErrorIfFormatIsIncorrect() throws Exception { } @Test - public void throwsErrorIfFormatIsIncorrectForFileURLOrPathDoesNotExist() throws Exception { - assertThrows(ArgumentParsingException.class, ()->from(List.of("::"+fileURL))); + public void throwsErrorIfFormatIsIncorrectForFileURLorPathDoesNotExist() throws Exception { + assertThrows(ArgumentParsingException.class, ()->from(List.of("::"+tempRepoURL))); assertThrows(ArgumentParsingException.class, ()->from(List.of("repo-1::"))); - assertThrows(ArgumentParsingException.class, ()->from(List.of("repo-1:::"+fileURL))); + assertThrows(ArgumentParsingException.class, ()->from(List.of("repo-1:::"+tempRepoURL))); + + assertThrows(ArgumentParsingException.class, ()->from(List.of("foo::bar::"+tempRepoURL))); + } + + @Test + public void testCorrectRelativeOrAbsolutePathForFileURL() throws Exception { + Repository repository = new Repository("temp-repo-0", tempRepoURL); + List actualList = from(List.of("file:../prospero-cli")); + + assertNotNull(actualList); + assertEquals(1, actualList.size()); + assertTrue(actualList.contains(repository)); + + actualList = from(List.of(("file:/"+(System.getProperty("user.dir").replaceAll("\\\\","/"))).replace("//","/"))); + + assertNotNull(actualList); + assertEquals(1, actualList.size()); + assertTrue(actualList.contains(repository)); + + actualList = from(List.of(("file:///"+(System.getProperty("user.dir").replaceAll("\\\\","/"))).replace("////","///"))); + + assertNotNull(actualList); + assertEquals(1, actualList.size()); + assertTrue(actualList.contains(repository)); + + actualList = from(List.of(System.getProperty("user.dir"))); - assertThrows(ArgumentParsingException.class, ()->from(List.of("foo::bar::"+fileURL))); + assertNotNull(actualList); + assertEquals(1, actualList.size()); + assertTrue(actualList.contains(repository)); - assertThrows(ArgumentParsingException.class, ()->from(List.of("file:/path/to/repo"))); + actualList = from(List.of(".."+File.separator+"prospero-cli")); - assertThrows(ArgumentParsingException.class, ()->from(List.of(filePath))); + assertNotNull(actualList); + assertEquals(1, actualList.size()); + assertTrue(actualList.contains(repository)); } } \ No newline at end of file diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/InstallCommandTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/InstallCommandTest.java index e7ddfa9b8..af05abca6 100644 --- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/InstallCommandTest.java +++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/InstallCommandTest.java @@ -241,33 +241,37 @@ public void provisionConfigAndChannelSet() throws IOException { @Test public void provisionConfigAndRemoteRepoSet() throws Exception { Path channelsFile = temporaryFolder.newFile().toPath(); - String test = temporaryFolder.newFolder().toURI().toURL().toString(); + + File installDir = temporaryFolder.newFolder(); + String testURL = installDir.toURI().toString(); MetadataTestUtils.prepareChannel(channelsFile, List.of(new URL("file:some-manifest.yaml"))); - int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, test, + int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, installDir.getName(), CliConstants.CHANNELS, channelsFile.toString(), - CliConstants.REPOSITORIES, test, + CliConstants.REPOSITORIES, testURL, CliConstants.FPL, "g:a"); assertEquals(ReturnCodes.SUCCESS, exitCode); Mockito.verify(provisionAction).provision(configCaptor.capture(), channelCaptor.capture(), any()); assertThat(channelCaptor.getValue().get(0).getRepositories() .stream().map(Repository::getUrl).collect(Collectors.toList())) - .containsOnly(test); + .containsOnly(testURL); } @SuppressWarnings("unchecked") @Test public void passShadowRepositories() throws Exception { Path channelsFile = temporaryFolder.newFile().toPath(); - String test = temporaryFolder.newFolder().toURI().toURL().toString(); + + File installDir = temporaryFolder.newFolder(); + String testURL = installDir.toURI().toString(); MetadataTestUtils.prepareChannel(channelsFile, List.of(new URL("file:some-manifest.yaml"))); - int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, test, + int exitCode = commandLine.execute(CliConstants.Commands.INSTALL, CliConstants.DIR, installDir.getName(), CliConstants.CHANNELS, channelsFile.toString(), - CliConstants.SHADE_REPOSITORIES, test, + CliConstants.SHADE_REPOSITORIES, testURL, CliConstants.FPL, "g:a"); assertEquals(ReturnCodes.SUCCESS, exitCode); @@ -275,7 +279,7 @@ public void passShadowRepositories() throws Exception { Mockito.verify(provisionAction).provision(configCaptor.capture(), channelCaptor.capture(), listArgumentCaptor.capture()); assertThat(listArgumentCaptor.getValue()) .map(Repository::getUrl) - .contains(test); + .contains(testURL); } @Test