diff --git a/gerrit-common/BUCK b/gerrit-common/BUCK index 88e503e93b..484136a7b2 100644 --- a/gerrit-common/BUCK +++ b/gerrit-common/BUCK @@ -51,6 +51,7 @@ java_library( '//lib:guava', '//lib/jgit:jgit', '//lib/joda:joda-time', + '//lib/log:api', ], visibility = ['PUBLIC'], ) diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java index c45d9f9f64..9a306968cb 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java @@ -16,7 +16,6 @@ package com.google.gerrit.common; import com.google.common.collect.Sets; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -25,6 +24,7 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Path; import java.util.Arrays; import java.util.Set; @@ -53,7 +53,7 @@ public final class IoUtil { }.start(); } - public static void loadJARs(File... jars) { + public static void loadJARs(Iterable jars) { ClassLoader cl = IoUtil.class.getClassLoader(); if (!(cl instanceof URLClassLoader)) { throw noAddURL("Not loaded by URLClassLoader", null); @@ -71,9 +71,9 @@ public final class IoUtil { } Set have = Sets.newHashSet(Arrays.asList(urlClassLoader.getURLs())); - for (File path : jars) { + for (Path path : jars) { try { - URL url = path.toURI().toURL(); + URL url = path.toUri().toURL(); if (have.add(url)) { addURL.invoke(cl, url); } @@ -86,6 +86,10 @@ public final class IoUtil { } } + public static void loadJARs(Path... jars) { + loadJARs(Arrays.asList(jars)); + } + private static UnsupportedOperationException noAddURL(String m, Throwable why) { String prefix = "Cannot extend classpath: "; return new UnsupportedOperationException(prefix + m, why); diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java index a98e0a58ea..9309b18940 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java @@ -14,41 +14,59 @@ package com.google.gerrit.common; -import java.io.File; -import java.io.FileFilter; -import java.util.Arrays; -import java.util.Comparator; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.Ordering; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; public final class SiteLibraryLoaderUtil { + private static final Logger log = + LoggerFactory.getLogger(SiteLibraryLoaderUtil.class); - public static void loadSiteLib(File libdir) { - File[] jars = listJars(libdir); - if (jars != null && 0 < jars.length) { - Arrays.sort(jars, new Comparator() { - @Override - public int compare(File a, File b) { - // Sort by reverse last-modified time so newer JARs are first. - int cmp = Long.compare(b.lastModified(), a.lastModified()); - if (cmp != 0) { - return cmp; - } - return a.getName().compareTo(b.getName()); - } - }); - IoUtil.loadJARs(jars); + public static void loadSiteLib(Path libdir) { + try { + IoUtil.loadJARs(listJars(libdir)); + } catch (IOException e) { + log.error("Error scanning lib directory " + libdir, e); } } - public static File[] listJars(File libdir) { - File[] jars = libdir.listFiles(new FileFilter() { + private static long lastModified(Path p) { + try { + return Files.getLastModifiedTime(p).toMillis(); + } catch (IOException e) { + return 0; + } + } + + public static List listJars(Path dir) throws IOException { + DirectoryStream.Filter filter = new DirectoryStream.Filter() { @Override - public boolean accept(File path) { - String name = path.getName(); - return (name.endsWith(".jar") || name.endsWith(".zip")) - && path.isFile(); + public boolean accept(Path entry) throws IOException { + String name = entry.getFileName().toString(); + return (name.endsWith(".jar") || name.endsWith(".zip")) + && Files.isRegularFile(entry); } - }); - return jars; + }; + try (DirectoryStream jars = Files.newDirectoryStream(dir, filter)) { + return new Ordering() { + @Override + public int compare(Path a, Path b) { + // Sort by reverse last-modified time so newer JARs are first. + return ComparisonChain.start() + .compare(lastModified(b), lastModified(a)) + .compare(a, b) + .result(); + } + }.sortedCopy(jars); + } } private SiteLibraryLoaderUtil() { diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java index 31ff107879..b617384273 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java @@ -24,6 +24,7 @@ import com.google.common.base.Strings; import com.google.common.cache.Cache; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.io.ByteStreams; import com.google.common.net.HttpHeaders; import com.google.gerrit.extensions.registration.RegistrationHandle; import com.google.gerrit.httpd.resources.Resource; @@ -55,14 +56,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.Enumeration; import java.util.List; @@ -303,7 +304,8 @@ class HttpPluginServlet extends HttpServlet } if (!entry.isPresent() && file.endsWith("/index.html")) { String pfx = file.substring(0, file.length() - "index.html".length()); - long pluginLastModified = holder.plugin.getSrcFile().lastModified(); + long pluginLastModified = + Files.getLastModifiedTime(holder.plugin.getSrcFile()).toMillis(); if (hasUpToDateCachedResource(rsc, pluginLastModified)) { rsc.send(req, res); } else { @@ -608,12 +610,12 @@ class HttpPluginServlet extends HttpServlet private void sendJsPlugin(Plugin plugin, PluginResourceKey key, HttpServletRequest req, HttpServletResponse res) throws IOException { - File pluginFile = plugin.getSrcFile(); + Path path = plugin.getSrcFile(); if (req.getRequestURI().endsWith(getJsPluginPath(plugin)) - && pluginFile.exists()) { - res.setHeader("Content-Length", Long.toString(pluginFile.length())); + && Files.exists(path)) { + res.setHeader("Content-Length", Long.toString(Files.size(path))); res.setContentType("application/javascript"); - writeToResponse(res, new FileInputStream(pluginFile)); + writeToResponse(res, Files.newInputStream(path)); } else { resourceCache.put(key, Resource.NOT_FOUND); Resource.NOT_FOUND.send(req, res); @@ -621,25 +623,15 @@ class HttpPluginServlet extends HttpServlet } private static String getJsPluginPath(Plugin plugin) { - return String.format("/plugins/%s/static/%s", plugin.getName(), plugin.getSrcFile() - .getName()); + return String.format("/plugins/%s/static/%s", plugin.getName(), + plugin.getSrcFile().getFileName()); } - private void writeToResponse(HttpServletResponse res, InputStream in) + private void writeToResponse(HttpServletResponse res, InputStream inputStream) throws IOException { - try { - OutputStream out = res.getOutputStream(); - try { - byte[] tmp = new byte[1024]; - int n; - while ((n = in.read(tmp)) > 0) { - out.write(tmp, 0, n); - } - } finally { - out.close(); - } - } finally { - in.close(); + try (OutputStream out = res.getOutputStream(); + InputStream in = inputStream) { + ByteStreams.copy(in, out); } } @@ -671,9 +663,9 @@ class HttpPluginServlet extends HttpServlet } private static String getPrefix(Plugin plugin, String attr, String def) { - File srcFile = plugin.getSrcFile(); + Path path = plugin.getSrcFile(); PluginContentScanner scanner = plugin.getContentScanner(); - if (srcFile == null || scanner == PluginContentScanner.EMPTY) { + if (path == null || scanner == PluginContentScanner.EMPTY) { return def; } try { diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java index 90322d5d98..ac84e827fe 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java @@ -19,7 +19,6 @@ import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_ import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Iterables; -import com.google.common.io.Files; import com.google.gerrit.common.IoUtil; import com.google.gerrit.common.SiteLibraryLoaderUtil; import com.google.gerrit.pgm.util.SiteProgram; @@ -37,8 +36,10 @@ import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.jar.JarFile; @@ -67,14 +68,14 @@ public class SwitchSecureStore extends SiteProgram { @Override public int run() throws Exception { SitePaths sitePaths = new SitePaths(getSitePath()); - File newSecureStoreFile = new File(newSecureStoreLib); - if (!newSecureStoreFile.exists()) { - log.error(String.format("File %s doesn't exists", - newSecureStoreFile.getAbsolutePath())); + Path newSecureStorePath = Paths.get(newSecureStoreLib); + if (!Files.exists(newSecureStorePath)) { + log.error(String.format("File %s doesn't exist", + newSecureStorePath.toAbsolutePath())); return -1; } - String newSecureStore = getNewSecureStoreClassName(newSecureStoreFile); + String newSecureStore = getNewSecureStoreClassName(newSecureStorePath); String currentSecureStoreName = getCurrentSecureStoreClassName(sitePaths); if (currentSecureStoreName.equals(newSecureStore)) { @@ -83,7 +84,7 @@ public class SwitchSecureStore extends SiteProgram { return -1; } - IoUtil.loadJARs(newSecureStoreFile); + IoUtil.loadJARs(newSecureStorePath); SiteLibraryLoaderUtil.loadSiteLib(sitePaths.lib_dir); log.info("Current secureStoreClass property ({}) will be replaced with {}", @@ -96,7 +97,7 @@ public class SwitchSecureStore extends SiteProgram { migrateProperties(currentStore, newStore); removeOldLib(sitePaths, currentSecureStoreName); - copyNewLib(sitePaths, newSecureStoreFile); + copyNewLib(sitePaths, newSecureStorePath); updateGerritConfig(sitePaths, newSecureStore); @@ -123,14 +124,17 @@ public class SwitchSecureStore extends SiteProgram { } } - private void removeOldLib(SitePaths sitePaths, String currentSecureStoreName) { - File oldSecureStore = + private void removeOldLib(SitePaths sitePaths, String currentSecureStoreName) + throws IOException { + Path oldSecureStore = findJarWithSecureStore(sitePaths, currentSecureStoreName); if (oldSecureStore != null) { log.info("Removing old SecureStore ({}) from lib/ directory", - oldSecureStore.getName()); - if (!oldSecureStore.delete()) { - log.error("Cannot remove {}", oldSecureStore.getAbsolutePath()); + oldSecureStore.getFileName()); + try { + Files.delete(oldSecureStore); + } catch (IOException e) { + log.error("Cannot remove {}", oldSecureStore.toAbsolutePath(), e); } } else { log.info("Cannot find jar with old SecureStore ({}) in lib/ directory", @@ -138,12 +142,12 @@ public class SwitchSecureStore extends SiteProgram { } } - private void copyNewLib(SitePaths sitePaths, File newSecureStoreFile) + private void copyNewLib(SitePaths sitePaths, Path newSecureStorePath) throws IOException { log.info("Copy new SecureStore ({}) into lib/ directory", - newSecureStoreFile.getName()); - Files.copy(newSecureStoreFile, new File(sitePaths.lib_dir, - newSecureStoreFile.getName())); + newSecureStorePath.getFileName()); + Files.copy(newSecureStorePath, + sitePaths.lib_dir.resolve(newSecureStorePath.getFileName())); } private void updateGerritConfig(SitePaths sitePaths, String newSecureStore) @@ -157,7 +161,7 @@ public class SwitchSecureStore extends SiteProgram { config.save(); } - private String getNewSecureStoreClassName(File secureStore) + private String getNewSecureStoreClassName(Path secureStore) throws IOException { JarScanner scanner = new JarScanner(secureStore); List newSecureStores = @@ -165,12 +169,12 @@ public class SwitchSecureStore extends SiteProgram { if (newSecureStores.isEmpty()) { throw new RuntimeException(String.format( "Cannot find implementation of SecureStore interface in %s", - secureStore.getAbsolutePath())); + secureStore.toAbsolutePath())); } if (newSecureStores.size() > 1) { throw new RuntimeException(String.format( "Found too many implementations of SecureStore:\n%s\nin %s", Joiner - .on("\n").join(newSecureStores), secureStore.getAbsolutePath())); + .on("\n").join(newSecureStores), secureStore.toAbsolutePath())); } return Iterables.getOnlyElement(newSecureStores); } @@ -195,15 +199,12 @@ public class SwitchSecureStore extends SiteProgram { } } - private File findJarWithSecureStore(SitePaths sitePaths, - String secureStoreClass) { - File[] jars = SiteLibraryLoaderUtil.listJars(sitePaths.lib_dir); - if (jars == null || jars.length == 0) { - return null; - } + private Path findJarWithSecureStore(SitePaths sitePaths, + String secureStoreClass) throws IOException { + List jars = SiteLibraryLoaderUtil.listJars(sitePaths.lib_dir); String secureStoreClassPath = secureStoreClass.replace('.', '/') + ".class"; - for (File jar : jars) { - try (JarFile jarFile = new JarFile(jar)) { + for (Path jar : jars) { + try (JarFile jarFile = new JarFile(jar.toFile())) { ZipEntry entry = jarFile.getEntry(secureStoreClassPath); if (entry != null) { return jar; diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java index 7b10135baf..534ef0508f 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java @@ -56,12 +56,12 @@ import com.google.inject.util.Providers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; @@ -292,8 +292,8 @@ public class BaseInit extends SiteProgram { } try { - File secureStoreLib = new File(secureStore); - if (!secureStoreLib.exists()) { + Path secureStoreLib = Paths.get(secureStore); + if (!Files.exists(secureStoreLib)) { throw new InvalidSecureStoreException(String.format( "File %s doesn't exist", secureStore)); } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java index 4bf1c886d7..5863d482a3 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java @@ -15,21 +15,19 @@ package com.google.gerrit.pgm.init; import com.google.common.base.Strings; -import com.google.common.io.Files; +import com.google.common.hash.Funnels; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; +import com.google.common.io.ByteStreams; import com.google.gerrit.common.Die; import com.google.gerrit.common.IoUtil; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.server.config.SitePaths; import com.google.inject.Inject; -import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.util.HttpSupport; -import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -38,15 +36,17 @@ import java.net.Proxy; import java.net.ProxySelector; import java.net.URISyntaxException; import java.net.URL; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; /** Get optional or required 3rd party library files into $site_path/lib. */ class LibraryDownloader { private final ConsoleUI ui; - private final File lib_dir; + private final Path lib_dir; private boolean required; private String name; @@ -55,7 +55,7 @@ class LibraryDownloader { private String remove; private List needs; private LibraryDownloader neededBy; - private File dst; + private Path dst; private boolean download; // download or copy private boolean exists; @@ -118,8 +118,8 @@ class LibraryDownloader { name = jarName; } - dst = new File(lib_dir, jarName); - if (dst.exists()) { + dst = lib_dir.resolve(jarName); + if (Files.exists(dst)) { exists = true; } else if (shouldGet()) { doGet(); @@ -158,8 +158,12 @@ class LibraryDownloader { } private void doGet() { - if (!lib_dir.exists() && !lib_dir.mkdirs()) { - throw new Die("Cannot create " + lib_dir); + if (!Files.exists(lib_dir)) { + try { + Files.createDirectories(lib_dir); + } catch (IOException e) { + throw new Die("Cannot create " + lib_dir, e); + } } try { @@ -171,7 +175,11 @@ class LibraryDownloader { } verifyFileChecksum(); } catch (IOException err) { - dst.delete(); + try { + Files.delete(dst); + } catch (IOException e) { + // Delete failed; leave alone. + } if (ui.isBatch()) { throw new Die("error: Cannot get " + jarUrl, err); @@ -186,13 +194,13 @@ class LibraryDownloader { System.err.println(); System.err.println("and save as:"); System.err.println(); - System.err.println(" " + dst.getAbsolutePath()); + System.err.println(" " + dst.toAbsolutePath()); System.err.println(); System.err.flush(); ui.waitForUser(); - if (dst.exists()) { + if (Files.exists(dst)) { verifyFileChecksum(); } else if (!ui.yesno(!required, "Continue without this library")) { @@ -200,7 +208,7 @@ class LibraryDownloader { } } - if (dst.exists()) { + if (Files.exists(dst)) { exists = true; IoUtil.loadJARs(dst); } @@ -208,19 +216,27 @@ class LibraryDownloader { private void removeStaleVersions() { if (!Strings.isNullOrEmpty(remove)) { - String[] names = lib_dir.list(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.matches("^" + remove + "$"); - } - }); - if (names != null) { - for (String old : names) { - String bak = "." + old + ".backup"; - ui.message("Renaming %s to %s", old, bak); - if (!new File(lib_dir, old).renameTo(new File(lib_dir, bak))) { - throw new Die("cannot rename " + old); - } + Iterable paths; + try { + paths = Files.newDirectoryStream(lib_dir, + new DirectoryStream.Filter() { + @Override + public boolean accept(Path entry) { + return entry.getFileName().toString() + .matches("^" + remove + "$"); + } + }); + } catch (IOException e) { + throw new Die("cannot remove stale library versions", e); + } + for (Path p : paths) { + String old = p.getFileName().toString(); + String bak = "." + old + ".backup"; + ui.message("Renaming %s to %s", old, bak); + try { + Files.move(p, p.resolveSibling(bak)); + } catch (IOException e) { + throw new Die("cannot rename " + old, e); } } } @@ -228,111 +244,93 @@ class LibraryDownloader { private void doGetByLocalCopy() throws IOException { System.err.print("Copying " + jarUrl + " ..."); - File f = url2file(jarUrl); - if (!f.exists()) { + Path p = url2file(jarUrl); + if (!Files.exists(p)) { StringBuilder msg = new StringBuilder() .append("\n") .append("Can not find the %s at this location: %s\n") .append("Please provide alternative URL"); - f = url2file(ui.readString(null, msg.toString(), name, jarUrl)); + p = url2file(ui.readString(null, msg.toString(), name, jarUrl)); } - Files.copy(f, dst); + Files.copy(p, dst); } - private static File url2file(final String urlString) throws IOException { + private static Path url2file(final String urlString) throws IOException { final URL url = new URL(urlString); try { - return new File(url.toURI()); + return Paths.get(url.toURI()); } catch (URISyntaxException e) { - return new File(url.getPath()); + return Paths.get(url.getPath()); } } private void doGetByHttp() throws IOException { System.err.print("Downloading " + jarUrl + " ..."); System.err.flush(); - try { - final ProxySelector proxySelector = ProxySelector.getDefault(); - final URL url = new URL(jarUrl); - final Proxy proxy = HttpSupport.proxyFor(proxySelector, url); - final HttpURLConnection c = (HttpURLConnection) url.openConnection(proxy); - final InputStream in; - - switch (HttpSupport.response(c)) { - case HttpURLConnection.HTTP_OK: - in = c.getInputStream(); - break; - - case HttpURLConnection.HTTP_NOT_FOUND: - throw new FileNotFoundException(url.toString()); - - default: - throw new IOException(url.toString() + ": " + HttpSupport.response(c) - + " " + c.getResponseMessage()); - } - - try { - final OutputStream out = new FileOutputStream(dst); - try { - final byte[] buf = new byte[8192]; - int n; - while ((n = in.read(buf)) > 0) { - out.write(buf, 0, n); - } - } finally { - out.close(); - } - } finally { - in.close(); - } + try (InputStream in = openHttpStream(jarUrl); + OutputStream out = Files.newOutputStream(dst)) { + ByteStreams.copy(in, out); System.err.println(" OK"); System.err.flush(); } catch (IOException err) { - dst.delete(); + deleteDst(); System.err.println(" !! FAIL !!"); System.err.flush(); throw err; } } + private static InputStream openHttpStream(String urlStr) throws IOException { + ProxySelector proxySelector = ProxySelector.getDefault(); + URL url = new URL(urlStr); + Proxy proxy = HttpSupport.proxyFor(proxySelector, url); + HttpURLConnection c = (HttpURLConnection) url.openConnection(proxy); + + switch (HttpSupport.response(c)) { + case HttpURLConnection.HTTP_OK: + return c.getInputStream(); + + case HttpURLConnection.HTTP_NOT_FOUND: + throw new FileNotFoundException(url.toString()); + + default: + throw new IOException(url.toString() + ": " + HttpSupport.response(c) + + " " + c.getResponseMessage()); + } + } + private void verifyFileChecksum() { - if (sha1 != null) { - try { - final MessageDigest md = MessageDigest.getInstance("SHA-1"); - final FileInputStream in = new FileInputStream(dst); - try { - final byte[] buf = new byte[8192]; - int n; - while ((n = in.read(buf)) > 0) { - md.update(buf, 0, n); - } - } finally { - in.close(); - } + if (sha1 == null) { + return; + } + Hasher h = Hashing.sha1().newHasher(); + try (InputStream in = Files.newInputStream(dst); + OutputStream out = Funnels.asOutputStream(h)) { + ByteStreams.copy(in, out); + } catch (IOException e) { + deleteDst(); + throw new Die("cannot checksum " + dst, e); + } + if (sha1.equals(h.hash().toString())) { + System.err.println("Checksum " + dst.getFileName() + " OK"); + System.err.flush(); + } else if (ui.isBatch()) { + deleteDst(); + throw new Die(dst + " SHA-1 checksum does not match"); - if (sha1.equals(ObjectId.fromRaw(md.digest()).name())) { - System.err.println("Checksum " + dst.getName() + " OK"); - System.err.flush(); + } else if (!ui.yesno(null /* force an answer */, + "error: SHA-1 checksum does not match\n" + "Use %s anyway",// + dst.getFileName())) { + deleteDst(); + throw new Die("aborted by user"); + } + } - } else if (ui.isBatch()) { - dst.delete(); - throw new Die(dst + " SHA-1 checksum does not match"); - - } else if (!ui.yesno(null /* force an answer */, - "error: SHA-1 checksum does not match\n" + "Use %s anyway",// - dst.getName())) { - dst.delete(); - throw new Die("aborted by user"); - } - - } catch (IOException checksumError) { - dst.delete(); - throw new Die("cannot checksum " + dst, checksumError); - - } catch (NoSuchAlgorithmException checksumError) { - dst.delete(); - throw new Die("cannot checksum " + dst, checksumError); - } + private void deleteDst() { + try { + Files.delete(dst); + } catch (IOException e) { + System.err.println(" Failed to clean up lib: " + dst); } } } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java index 8926759d90..49877dc8d3 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java @@ -14,13 +14,13 @@ package com.google.gerrit.pgm.init; -import java.io.File; +import java.nio.file.Path; class SecureStoreInitData { - final File jarFile; + final Path jarFile; final String className; - SecureStoreInitData(File jar, String className) { + SecureStoreInitData(Path jar, String className) { this.className = className; this.jarFile = jar; } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java index d4cf24c730..f8678292ca 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java @@ -21,7 +21,6 @@ import static com.google.gerrit.pgm.init.api.InitUtil.mkdir; import static com.google.gerrit.pgm.init.api.InitUtil.savePublic; import static com.google.gerrit.pgm.init.api.InitUtil.version; -import com.google.common.io.Files; import com.google.gerrit.common.Nullable; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitFlags; @@ -37,6 +36,8 @@ import com.google.inject.TypeLiteral; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -132,7 +133,8 @@ public class SitePathInitializer { private void saveSecureStore() throws IOException { if (secureStoreInitData != null) { - File dst = new File(site.lib_dir, secureStoreInitData.jarFile.getName()); + Path dst = + site.lib_dir.resolve(secureStoreInitData.jarFile.getFileName()); Files.copy(secureStoreInitData.jarFile, dst); Section gerritSection = sectionFactory.get("gerrit", null); gerritSection.set("secureStoreClass", secureStoreInitData.className); diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java index c713b79869..048c2eed12 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java @@ -24,14 +24,14 @@ import com.google.inject.Singleton; import org.eclipse.jgit.lib.Config; -import java.io.File; +import java.nio.file.Path; import javax.sql.DataSource; /** Loads the site library if not yet loaded. */ @Singleton public class SiteLibraryBasedDataSourceProvider extends DataSourceProvider { - private final File libdir; + private final Path libdir; private boolean init; @Inject diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java index b5ff22ff2c..a3e7924834 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java @@ -32,7 +32,7 @@ public final class SitePaths { public final File site_path; public final Path bin_dir; public final Path etc_dir; - public final File lib_dir; + public final Path lib_dir; public final Path tmp_dir; public final File logs_dir; public final File plugins_dir; @@ -72,7 +72,7 @@ public final class SitePaths { bin_dir = p.resolve("bin"); etc_dir = p.resolve("etc"); - lib_dir = new File(site_path, "lib"); + lib_dir = p.resolve("lib"); tmp_dir = p.resolve("tmp"); plugins_dir = new File(site_path, "plugins"); data_dir = new File(site_path, "data"); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java index 5c0b41c5d6..37c05d556f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java @@ -32,6 +32,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; +import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -85,7 +86,8 @@ public class JarPluginProvider implements ServerPluginProvider { String extension = getExtension(srcFile); try (FileInputStream in = new FileInputStream(srcFile)) { File tmp = asTemp(in, tempNameFor(name), extension, tmpDir); - return loadJarPlugin(name, srcFile, snapshot, tmp, description); + return loadJarPlugin(name, srcFile.toPath(), snapshot, tmp, + description); } } catch (IOException e) { throw new InvalidPluginException("Cannot load Jar plugin " + srcFile, e); @@ -120,7 +122,7 @@ public class JarPluginProvider implements ServerPluginProvider { sitePaths.tmp_dir.toFile()); } - private ServerPlugin loadJarPlugin(String name, File srcJar, + private ServerPlugin loadJarPlugin(String name, Path srcJar, FileSnapshot snapshot, File tmp, PluginDescription description) throws IOException, InvalidPluginException, MalformedURLException { JarFile jarFile = new JarFile(tmp); @@ -146,10 +148,9 @@ public class JarPluginProvider implements ServerPluginProvider { PluginLoader.parentFor(type)); JarScanner jarScanner = createJarScanner(srcJar); - ServerPlugin plugin = - new ServerPlugin(name, description.canonicalUrl, description.user, - srcJar, snapshot, jarScanner, description.dataDir, - pluginLoader); + ServerPlugin plugin = new ServerPlugin(name, description.canonicalUrl, + description.user, srcJar.toFile(), snapshot, jarScanner, + description.dataDir, pluginLoader); plugin.setCleanupHandle(new CleanupHandle(tmp, jarFile)); keep = true; return plugin; @@ -160,7 +161,7 @@ public class JarPluginProvider implements ServerPluginProvider { } } - private JarScanner createJarScanner(File srcJar) + private JarScanner createJarScanner(Path srcJar) throws InvalidPluginException { try { return new JarScanner(srcJar); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java index a8600fe683..0f4aa6ce75 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java @@ -39,10 +39,10 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -69,8 +69,8 @@ public class JarScanner implements PluginContentScanner { private final JarFile jarFile; - public JarScanner(File srcFile) throws IOException { - this.jarFile = new JarFile(srcFile); + public JarScanner(Path src) throws IOException { + this.jarFile = new JarFile(src.toFile()); } @Override diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java index 63f69b510e..8da8cc1efb 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java @@ -27,12 +27,12 @@ import com.google.inject.Injector; import org.eclipse.jgit.internal.storage.file.FileSnapshot; -import java.io.File; +import java.nio.file.Path; class JsPlugin extends Plugin { private Injector httpInjector; - JsPlugin(String name, File srcFile, PluginUser pluginUser, + JsPlugin(String name, Path srcFile, PluginUser pluginUser, FileSnapshot snapshot) { super(name, srcFile, pluginUser, snapshot, ApiType.JS); } @@ -40,7 +40,7 @@ class JsPlugin extends Plugin { @Override @Nullable public String getVersion() { - String fileName = getSrcFile().getName(); + String fileName = getSrcFile().getFileName().toString(); int firstDash = fileName.indexOf("-"); if (firstDash > 0) { return fileName.substring(firstDash + 1, fileName.lastIndexOf(".js")); @@ -51,7 +51,7 @@ class JsPlugin extends Plugin { @Override public void start(PluginGuiceEnvironment env) throws Exception { manager = new LifecycleManager(); - String fileName = getSrcFile().getName(); + String fileName = getSrcFile().getFileName().toString(); httpInjector = Guice.createInjector(new StandaloneJsPluginModule(getName(), fileName)); manager.start(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java index 54f05f05f7..1d717efa77 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java @@ -90,7 +90,7 @@ public class ListPlugins implements RestReadView { stdout.format("%-30s %-10s %-8s %s\n", p.getName(), Strings.nullToEmpty(info.version), p.isDisabled() ? "DISABLED" : "ENABLED", - p.getSrcFile().getName()); + p.getSrcFile().getFileName()); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java index b227909747..1be65aa335 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java @@ -26,6 +26,7 @@ import com.google.inject.Injector; import org.eclipse.jgit.internal.storage.file.FileSnapshot; import java.io.File; +import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.jar.Attributes; @@ -67,7 +68,7 @@ public abstract class Plugin { } private final String name; - private final File srcFile; + private final Path srcFile; private final ApiType apiType; private final boolean disabled; private final CacheKey cacheKey; @@ -80,17 +81,18 @@ public abstract class Plugin { private List> reloadableHandles; public Plugin(String name, - File srcFile, + Path srcFile, PluginUser pluginUser, FileSnapshot snapshot, ApiType apiType) { this.name = name; + // TODO(dborowitz): Rename to srcPath or something. this.srcFile = srcFile; this.apiType = apiType; this.snapshot = snapshot; this.pluginUser = pluginUser; this.cacheKey = new Plugin.CacheKey(name); - this.disabled = srcFile.getName().endsWith(".disabled"); + this.disabled = srcFile.getFileName().toString().endsWith(".disabled"); } public CleanupHandle getCleanupHandle() { @@ -105,7 +107,7 @@ public abstract class Plugin { return pluginUser; } - public File getSrcFile() { + public Path getSrcFile() { return srcFile; } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java index b51359df8c..3fee7d7592 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java @@ -50,6 +50,7 @@ import java.io.FileFilter; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; @@ -172,11 +173,11 @@ public class PluginLoader implements LifecycleListener { synchronized (this) { Plugin active = running.get(name); if (active != null) { - fileName = active.getSrcFile().getName(); + fileName = active.getSrcFile().getFileName().toString(); log.info(String.format("Replacing plugin %s", active.getName())); File old = new File(pluginsDir, ".last_" + fileName); old.delete(); - active.getSrcFile().renameTo(old); + active.getSrcFile().toFile().renameTo(old); } new File(pluginsDir, fileName + ".disabled").delete(); @@ -241,7 +242,7 @@ public class PluginLoader implements LifecycleListener { log.info(String.format("Disabling plugin %s", active.getName())); File off = new File(active.getSrcFile() + ".disabled"); - active.getSrcFile().renameTo(off); + active.getSrcFile().toFile().renameTo(off); unloadPlugin(active); try { @@ -274,12 +275,12 @@ public class PluginLoader implements LifecycleListener { } log.info(String.format("Enabling plugin %s", name)); - String n = off.getSrcFile().getName(); + String n = off.getSrcFile().toFile().getName(); if (n.endsWith(".disabled")) { n = n.substring(0, n.lastIndexOf('.')); } File on = new File(pluginsDir, n); - off.getSrcFile().renameTo(on); + off.getSrcFile().toFile().renameTo(on); disabled.remove(name); runPlugin(name, on, null); @@ -342,7 +343,7 @@ public class PluginLoader implements LifecycleListener { String name = active.getName(); try { log.info(String.format("Reloading plugin %s", name)); - runPlugin(name, active.getSrcFile(), active); + runPlugin(name, active.getSrcFile().toFile(), active); } catch (PluginInstallException e) { log.warn(String.format("Cannot reload plugin %s", name), e.getCause()); throw e; @@ -549,7 +550,7 @@ public class PluginLoader implements LifecycleListener { throws InvalidPluginException { String pluginName = srcPlugin.getName(); if (isJsPlugin(pluginName)) { - return loadJsPlugin(name, srcPlugin, snapshot); + return loadJsPlugin(name, srcPlugin.toPath(), snapshot); } else if (serverPluginFactory.handles(srcPlugin)) { return loadServerPlugin(srcPlugin, snapshot); } else { @@ -569,7 +570,7 @@ public class PluginLoader implements LifecycleListener { return url; } - private Plugin loadJsPlugin(String name, File srcJar, FileSnapshot snapshot) { + private Plugin loadJsPlugin(String name, Path srcJar, FileSnapshot snapshot) { return new JsPlugin(name, srcJar, pluginUserFactory.create(name), snapshot); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java index 0b037fb678..15888008a2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java @@ -80,7 +80,8 @@ public class ServerPlugin extends Plugin { PluginContentScanner scanner, File dataDir, ClassLoader classLoader) throws InvalidPluginException { - super(name, srcJar, pluginUser, snapshot, Plugin.getApiType(getPluginManifest(scanner))); + super(name, srcJar.toPath(), pluginUser, snapshot, + Plugin.getApiType(getPluginManifest(scanner))); this.pluginCanonicalWebUrl = pluginCanonicalWebUrl; this.scanner = scanner; this.dataDir = dataDir; @@ -128,7 +129,7 @@ public class ServerPlugin extends Plugin { } File getSrcJar() { - return getSrcFile(); + return getSrcFile().toFile(); } private static Manifest getPluginManifest(PluginContentScanner scanner) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java index 37fed9b477..a529b6d814 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java @@ -31,6 +31,7 @@ import java.io.File; * group them into a directory tree and then load the directory * root as a single plugin. */ +// TODO(dborowitz): Convert to NIO; ensure clients can migrate. @ExtensionPoint public interface ServerPluginProvider { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java index e8305906f0..99127d8865 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java @@ -26,14 +26,14 @@ import com.google.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; @Singleton public class SecureStoreProvider implements Provider { private static final Logger log = LoggerFactory .getLogger(SecureStoreProvider.class); - private final File libdir; + private final Path libdir; private final Injector injector; private final String className;