Fix loading of core plugins on Windows [2020-06-07T13:26:26.841+0300] [plugin-manager-preloader] ERROR com.googlesource.gerrit.plugins.manager.repository.CorePluginsRepository : Invalid plugin filename java.net.URISyntaxException: Illegal character in opaque part at index 11: Jar:file:c:\Projects\gerrit\bin\gerrit.war!/WEB-INF/plugins/gitiles.jar at java.base/java.net.URI$Parser.fail(URI.java:2915) at java.base/java.net.URI$Parser.checkChars(URI.java:3086) at java.base/java.net.URI$Parser.parse(URI.java:3122) at java.base/java.net.URI.<init>(URI.java:600) at com.googlesource.gerrit.plugins.manager.repository.CorePluginsRepository.extractPluginInfoFromJarEntry(CorePluginsRepository.java:59) Bug: Issue 12885 Change-Id: Icade084c2c156ca3caa1bffd9ae6dcde61a43c3e
diff --git a/src/main/java/com/googlesource/gerrit/plugins/manager/repository/CorePluginsRepository.java b/src/main/java/com/googlesource/gerrit/plugins/manager/repository/CorePluginsRepository.java index 55b4639..9ff15fb 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/manager/repository/CorePluginsRepository.java +++ b/src/main/java/com/googlesource/gerrit/plugins/manager/repository/CorePluginsRepository.java
@@ -16,8 +16,8 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static java.util.Comparator.comparing; -import static java.util.Objects.requireNonNull; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; import com.google.gerrit.common.Nullable; @@ -41,21 +41,30 @@ private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private static final String GERRIT_VERSION = Version.getVersion(); - private final SitePaths site; private final CorePluginsDescriptions pluginsDescriptions; + private final String gerritWarUri; + private final Path siteGerritWar; + private static final char WINDOWS_FILE_SEPARATOR = '\\'; + private static final char UNIX_FILE_SEPARATOR = '/'; @Inject public CorePluginsRepository(SitePaths site, CorePluginsDescriptions pd) { - this.site = site; + this(site.gerrit_war, site.gerrit_war.toString(), pd); + } + + @VisibleForTesting + public CorePluginsRepository(Path siteGerritWar, String gerritWar, CorePluginsDescriptions pd) { this.pluginsDescriptions = pd; + final String normalizedWar = gerritWar.replace(WINDOWS_FILE_SEPARATOR, UNIX_FILE_SEPARATOR); + this.gerritWarUri = Paths.get(normalizedWar).toUri().toString(); + this.siteGerritWar = siteGerritWar; } @Nullable private PluginInfo extractPluginInfoFromJarEntry(JarEntry entry) { try { Path entryName = Paths.get(entry.getName()); - URI pluginUrl = - new URI("jar:file:" + requireNonNull(site.gerrit_war) + "!/" + entry.getName()); + URI pluginUrl = new URI("jar:" + gerritWarUri + "!/" + entry.getName()); try (JarInputStream pluginJar = new JarInputStream(pluginUrl.toURL().openStream())) { return getManifestEntry(pluginJar) .map( @@ -114,12 +123,12 @@ return ImmutableList.of(); } - if (site.gerrit_war == null) { + if (siteGerritWar == null) { logger.atWarning().log("Core plugins not available in non-war Gerrit distributions"); return ImmutableList.of(); } - try (JarFile gerritWar = new JarFile(site.gerrit_war.toFile())) { + try (JarFile gerritWar = new JarFile(siteGerritWar.toFile())) { return gerritWar.stream() .filter(e -> e.getName().startsWith("WEB-INF/plugins") && e.getName().endsWith(".jar")) .map(this::extractPluginInfoFromJarEntry)
diff --git a/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java b/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java index d01d287..bd74235 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java
@@ -46,14 +46,9 @@ @Test public void corePluginsRepositoryShouldReturnCorePluginsFromReleaseWar() throws IOException { - SitePaths site = new SitePaths(random()); - PluginsRepository pluginRepo = new CorePluginsRepository(site, new CorePluginsDescriptions()); + SitePaths site = prepareSiteDirWithReleaseWar(); - Path pathToReleaseWar = - Paths.get(getenv("TEST_SRCDIR"), getenv("TEST_WORKSPACE"), "release.war"); - assume().that(pathToReleaseWar.toFile().exists()).isTrue(); - Files.createDirectories(site.bin_dir); - Files.createSymbolicLink(site.gerrit_war, pathToReleaseWar); + PluginsRepository pluginRepo = new CorePluginsRepository(site, new CorePluginsDescriptions()); Collection<PluginInfo> plugins = pluginRepo.list(Version.getVersion()); assertThat(plugins.stream().map(p -> p.name).sorted().collect(toList())) @@ -61,6 +56,30 @@ .inOrder(); } + @Test + public void corePluginsListFromReleaseWarShouldNotBeEmptyOnWindows() throws IOException { + char windowsSeparator = '\\'; + SitePaths site = prepareSiteDirWithReleaseWar(); + + PluginsRepository pluginRepo = + new CorePluginsRepository( + site.gerrit_war, + site.gerrit_war.toString().replace('/', windowsSeparator), + new CorePluginsDescriptions()); + + assertThat(pluginRepo.list(Version.getVersion())).isNotEmpty(); + } + + private SitePaths prepareSiteDirWithReleaseWar() throws IOException { + SitePaths site = new SitePaths(random()); + Path pathToReleaseWar = + Paths.get(getenv("TEST_SRCDIR"), getenv("TEST_WORKSPACE"), "release.war"); + assume().that(pathToReleaseWar.toFile().exists()).isTrue(); + Files.createDirectories(site.bin_dir); + Files.createSymbolicLink(site.gerrit_war, pathToReleaseWar); + return site; + } + private static String getenv(String name) { String value = System.getenv(name); assume().that(value).isNotNull();