diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java index 8548b5ccba..8f4c2d41db 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java @@ -43,7 +43,8 @@ import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.eclipse.jgit.lib.Config; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; class InMemoryTestingDatabaseModule extends LifecycleModule { private final Config cfg; @@ -58,9 +59,10 @@ class InMemoryTestingDatabaseModule extends LifecycleModule { .annotatedWith(GerritServerConfig.class) .toInstance(cfg); - bind(File.class) + // TODO(dborowitz): Use jimfs. + bind(Path.class) .annotatedWith(SitePath.class) - .toInstance(new File("UNIT_TEST_GERRIT_SITE")); + .toInstance(Paths.get("UNIT_TEST_GERRIT_SITE")); bind(GitRepositoryManager.class) .toInstance(new InMemoryRepositoryManager()); diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java index bed10d656a..aa2fcbc36e 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java @@ -21,6 +21,7 @@ import org.eclipse.jgit.util.IO; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; import java.util.Arrays; public class FileUtil { @@ -42,6 +43,11 @@ public class FileUtil { } } + public static void chmod(final int mode, final Path path) { + // TODO(dborowitz): Is there a portable way to do this with NIO? + chmod(mode, path.toFile()); + } + public static void chmod(final int mode, final File path) { path.setReadable(false, false /* all */); path.setWritable(false, false /* all */); @@ -63,4 +69,4 @@ public class FileUtil { private FileUtil() { } -} \ No newline at end of file +} diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java index 9d479770b0..c19c8173e8 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java @@ -14,6 +14,9 @@ package com.google.gerrit.httpd; +import static java.nio.file.Files.isExecutable; +import static java.nio.file.Files.isRegularFile; + import com.google.gerrit.common.data.GitWebType; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; @@ -23,16 +26,17 @@ import org.eclipse.jgit.lib.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; public class GitWebConfig { private static final Logger log = LoggerFactory.getLogger(GitWebConfig.class); private final String url; - private final File gitweb_cgi; - private final File gitweb_css; - private final File gitweb_js; - private final File git_logo_png; + private final Path gitweb_cgi; + private final Path gitweb_css; + private final Path gitweb_js; + private final Path git_logo_png; private GitWebType type; @Inject @@ -117,20 +121,20 @@ public class GitWebConfig { return; } - final File pkgCgi = new File("/usr/lib/cgi-bin/gitweb.cgi"); + final Path pkgCgi = Paths.get("/usr/lib/cgi-bin/gitweb.cgi"); String[] resourcePaths = {"/usr/share/gitweb/static", "/usr/share/gitweb", "/var/www/static", "/var/www"}; - File cgi; + Path cgi; if (cfgCgi != null) { // Use the CGI script configured by the administrator, failing if it // cannot be used as specified. // - cgi = sitePaths.resolve(cfgCgi); - if (!cgi.isFile()) { + cgi = sitePaths.resolve(cfgCgi).toPath(); + if (!isRegularFile(cgi)) { throw new IllegalStateException("Cannot find gitweb.cgi: " + cgi); } - if (!cgi.canExecute()) { + if (!isExecutable(cgi)) { throw new IllegalStateException("Cannot execute gitweb.cgi: " + cgi); } @@ -138,11 +142,11 @@ public class GitWebConfig { // Assume the administrator pointed us to the distribution, // which also has the corresponding CSS and logo file. // - String absPath = cgi.getParentFile().getAbsolutePath(); + String absPath = cgi.getParent().toAbsolutePath().toString(); resourcePaths = new String[] {absPath + "/static", absPath}; } - } else if (pkgCgi.isFile() && pkgCgi.canExecute()) { + } else if (isRegularFile(pkgCgi) && isExecutable(pkgCgi)) { // Use the OS packaged CGI. // log.debug("Assuming gitweb at " + pkgCgi); @@ -154,13 +158,13 @@ public class GitWebConfig { resourcePaths = new String[] {}; } - File css = null, js = null, logo = null; + Path css = null, js = null, logo = null; for (String path : resourcePaths) { - File dir = new File(path); - css = new File(dir, "gitweb.css"); - js = new File(dir, "gitweb.js"); - logo = new File(dir, "git-logo.png"); - if (css.isFile() && logo.isFile()) { + Path dir = Paths.get(path); + css = dir.resolve("gitweb.css"); + js = dir.resolve("gitweb.js"); + logo = dir.resolve("git-logo.png"); + if (isRegularFile(css) && isRegularFile(logo)) { break; } } @@ -191,22 +195,22 @@ public class GitWebConfig { } /** @return local path to the CGI executable; null if we shouldn't execute. */ - public File getGitwebCGI() { + public Path getGitwebCGI() { return gitweb_cgi; } /** @return local path of the {@code gitweb.css} matching the CGI. */ - public File getGitwebCSS() { + public Path getGitwebCSS() { return gitweb_css; } /** @return local path of the {@code gitweb.js} for the CGI. */ - public File getGitwebJS() { + public Path getGitwebJS() { return gitweb_js; } /** @return local path of the {@code git-logo.png} for the CGI. */ - public File getGitLogoPNG() { + public Path getGitLogoPNG() { return git_logo_png; } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java index 8e86cf4ac7..868c186c53 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java @@ -23,14 +23,14 @@ import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.zip.GZIPOutputStream; import javax.xml.parsers.DocumentBuilder; @@ -187,8 +187,8 @@ public class HtmlDomUtil { } /** Parse an XHTML file from the local drive and return the instance. */ - public static Document parseFile(File path) throws IOException { - try (InputStream in = new FileInputStream(path)) { + public static Document parseFile(Path path) throws IOException { + try (InputStream in = Files.newInputStream(path)) { Document doc = newBuilder().parse(in); compact(doc); return doc; @@ -200,13 +200,13 @@ public class HtmlDomUtil { } /** Read a UTF-8 text file from the local drive. */ - public static String readFile(File parentDir, String name) + public static String readFile(Path parentDir, String name) throws IOException { if (parentDir == null) { return null; } - File path = new File(parentDir, name); - try (FileInputStream in = new FileInputStream(path)) { + Path path = parentDir.resolve(name); + try (InputStream in = Files.newInputStream(path)) { return new String(ByteStreams.toByteArray(in), ENC); } catch (FileNotFoundException e) { return null; diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java index 41aa552cf3..31e66a856f 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java @@ -14,16 +14,17 @@ package com.google.gerrit.httpd.gitweb; +import com.google.common.io.ByteStreams; import com.google.gerrit.httpd.GitWebConfig; import com.google.gwtexpui.server.CacheHeaders; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.eclipse.jgit.util.IO; - -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import javax.servlet.ServletOutputStream; @@ -38,16 +39,16 @@ class GitLogoServlet extends HttpServlet { private final byte[] raw; @Inject - GitLogoServlet(final GitWebConfig gitWebConfig) throws IOException { + GitLogoServlet(GitWebConfig gitWebConfig) throws IOException { byte[] png; - final File src = gitWebConfig.getGitLogoPNG(); + Path src = gitWebConfig.getGitLogoPNG(); if (src != null) { - try { - png = IO.readFully(src); + try (InputStream in = Files.newInputStream(src)) { + png = ByteStreams.toByteArray(in); } catch (FileNotFoundException e) { png = null; } - modified = src.lastModified(); + modified = Files.getLastModifiedTime(src).toMillis(); } else { modified = -1; png = null; diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java index 4a39b97f6f..d217937bc1 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java @@ -22,8 +22,9 @@ import com.google.gwtjsonrpc.server.RPCServletUtils; import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import javax.servlet.ServletOutputStream; @@ -55,14 +56,14 @@ abstract class GitWebCssServlet extends HttpServlet { private final byte[] raw_css; private final byte[] gz_css; - GitWebCssServlet(final File src) + GitWebCssServlet(final Path src) throws IOException { if (src != null) { - final File dir = src.getParentFile(); - final String name = src.getName(); + final Path dir = src.getParent(); + final String name = src.getFileName().toString(); final String raw = HtmlDomUtil.readFile(dir, name); if (raw != null) { - modified = src.lastModified(); + modified = Files.getLastModifiedTime(src).toMillis(); raw_css = raw.getBytes(ENC); gz_css = HtmlDomUtil.compress(raw_css); } else { diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java index d71732a894..c21b7aa565 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java @@ -14,16 +14,17 @@ package com.google.gerrit.httpd.gitweb; +import com.google.common.io.ByteStreams; import com.google.gerrit.httpd.GitWebConfig; import com.google.gwtexpui.server.CacheHeaders; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.eclipse.jgit.util.IO; - -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import javax.servlet.ServletOutputStream; @@ -40,14 +41,14 @@ class GitWebJavaScriptServlet extends HttpServlet { @Inject GitWebJavaScriptServlet(final GitWebConfig gitWebConfig) throws IOException { byte[] png; - final File src = gitWebConfig.getGitwebJS(); + Path src = gitWebConfig.getGitwebJS(); if (src != null) { - try { - png = IO.readFully(src); + try (InputStream in = Files.newInputStream(src)) { + png = ByteStreams.toByteArray(in); } catch (FileNotFoundException e) { png = null; } - modified = src.lastModified(); + modified = Files.getLastModifiedTime(src).toMillis(); } else { modified = -1; png = null; diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java index 9a7cab01bf..de619c3b71 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java @@ -29,6 +29,8 @@ package com.google.gerrit.httpd.gitweb; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.gerrit.common.data.GerritConfig; import com.google.gerrit.extensions.restapi.Url; import com.google.gerrit.httpd.GitWebConfig; @@ -54,7 +56,6 @@ import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.EOFException; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -62,6 +63,8 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -81,7 +84,7 @@ class GitWebServlet extends HttpServlet { private final Set deniedActions; private final int bufferSize = 8192; - private final File gitwebCgi; + private final Path gitwebCgi; private final URI gitwebUrl; private final LocalDiskRepositoryManager repoManager; private final ProjectControl.Factory projectControl; @@ -143,26 +146,28 @@ class GitWebServlet extends HttpServlet { private void makeSiteConfig(final SitePaths site, final GerritConfig gerritConfig) throws IOException { - if (!site.tmp_dir.exists()) { - site.tmp_dir.mkdirs(); + if (!Files.exists(site.tmp_dir)) { + Files.createDirectories(site.tmp_dir); } - File myconf = File.createTempFile("gitweb_config", ".perl", site.tmp_dir); + Path myconf = Files.createTempFile(site.tmp_dir, "gitweb_config", ".perl"); // To make our configuration file only readable or writable by us; // this reduces the chances of someone tampering with the file. // - myconf.setWritable(false, false /* all */); - myconf.setReadable(false, false /* all */); - myconf.setExecutable(false, false /* all */); + // TODO(dborowitz): Is there a portable way to do this with NIO? + File myconfFile = myconf.toFile(); + myconfFile.setWritable(false, false /* all */); + myconfFile.setReadable(false, false /* all */); + myconfFile.setExecutable(false, false /* all */); - myconf.setWritable(true, true /* owner only */); - myconf.setReadable(true, true /* owner only */); + myconfFile.setWritable(true, true /* owner only */); + myconfFile.setReadable(true, true /* owner only */); _env.set("GIT_DIR", "."); - _env.set("GITWEB_CONFIG", myconf.getAbsolutePath()); + _env.set("GITWEB_CONFIG", myconf.toAbsolutePath().toString()); - final PrintWriter p = new PrintWriter(new FileWriter(myconf)); - try { + try (PrintWriter p = + new PrintWriter(Files.newBufferedWriter(myconf, UTF_8))) { p.print("# Autogenerated by Gerrit Code Review \n"); p.print("# DO NOT EDIT\n"); p.print("\n"); @@ -170,12 +175,12 @@ class GitWebServlet extends HttpServlet { // We are mounted at the same level in the context as the main // UI, so we can include the same header and footer scheme. // - final File hdr = site.site_header; - if (hdr.isFile()) { + Path hdr = site.site_header; + if (Files.isRegularFile(hdr)) { p.print("$site_header = " + quoteForPerl(hdr) + ";\n"); } - final File ftr = site.site_footer; - if (ftr.isFile()) { + Path ftr = site.site_footer; + if (Files.isRegularFile(ftr)) { p.print("$site_footer = " + quoteForPerl(ftr) + ";\n"); } @@ -188,8 +193,8 @@ class GitWebServlet extends HttpServlet { p.print("$logo = 'gitweb-logo.png';\n"); p.print("$javascript = 'gitweb.js';\n"); p.print("@stylesheets = ('gitweb-default.css');\n"); - final File css = site.site_css; - if (css.isFile()) { + Path css = site.site_css; + if (Files.isRegularFile(css)) { p.print("push @stylesheets, 'gitweb-site.css';\n"); } @@ -290,15 +295,15 @@ class GitWebServlet extends HttpServlet { // If the administrator has created a site-specific gitweb_config, // load that before we perform any final overrides. // - final File sitecfg = site.site_gitweb; - if (sitecfg.isFile()) { + Path sitecfg = site.site_gitweb; + if (Files.isRegularFile(sitecfg)) { p.print("$GITWEB_CONFIG = " + quoteForPerl(sitecfg) + ";\n"); p.print("if (-e $GITWEB_CONFIG) {\n"); p.print(" do " + quoteForPerl(sitecfg) + ";\n"); p.print("}\n"); } - final File root = repoManager.getBasePath(); + Path root = repoManager.getBasePath().toPath(); p.print("$projectroot = " + quoteForPerl(root) + ";\n"); // Permit exporting only the project we were started for. @@ -322,18 +327,16 @@ class GitWebServlet extends HttpServlet { // p.print("$feature{'forks'}{'override'} = 0;\n"); p.print("$feature{'forks'}{'default'} = [0];\n"); - } finally { - p.close(); } - myconf.setReadOnly(); + myconfFile.setReadOnly(); } - private String quoteForPerl(File value) { - return quoteForPerl(value.getAbsolutePath()); + private static String quoteForPerl(Path value) { + return quoteForPerl(value.toAbsolutePath().toString()); } - private String quoteForPerl(String value) { + private static String quoteForPerl(String value) { if (value == null || value.isEmpty()) { return "''"; } @@ -442,9 +445,10 @@ class GitWebServlet extends HttpServlet { private void exec(final HttpServletRequest req, final HttpServletResponse rsp, final ProjectControl project) throws IOException { final Process proc = - Runtime.getRuntime().exec(new String[] {gitwebCgi.getAbsolutePath()}, + Runtime.getRuntime().exec( + new String[] {gitwebCgi.toAbsolutePath().toString()}, makeEnv(req, project), - gitwebCgi.getAbsoluteFile().getParentFile()); + gitwebCgi.toAbsolutePath().getParent().toFile()); copyStderrToLog(proc.getErrorStream()); if (0 < req.getContentLength()) { @@ -522,7 +526,7 @@ class GitWebServlet extends HttpServlet { // env.set("REQUEST_METHOD", req.getMethod()); env.set("SCRIPT_NAME", req.getContextPath() + req.getServletPath()); - env.set("SCRIPT_FILENAME", gitwebCgi.getAbsolutePath()); + env.set("SCRIPT_FILENAME", gitwebCgi.toAbsolutePath().toString()); env.set("SERVER_NAME", req.getServerName()); env.set("SERVER_PORT", Integer.toString(req.getServerPort())); env.set("SERVER_PROTOCOL", req.getProtocol()); diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java index 22066b66fa..c642418feb 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java @@ -14,6 +14,8 @@ package com.google.gerrit.httpd.raw; +import static java.nio.file.Files.getLastModifiedTime; + import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.hash.Hasher; @@ -47,12 +49,13 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.List; @@ -160,16 +163,13 @@ public class HostPageServlet extends HttpServlet { private Page get() { Page p = page; - if (refreshHeaderFooter && p.isStale()) { - final Page newPage; - try { - newPage = new Page(); - } catch (IOException e) { - log.error("Cannot refresh site header/footer", e); - return p; + try { + if (refreshHeaderFooter && p.isStale()) { + p = new Page(); + page = p; } - p = newPage; - page = p; + } catch (IOException e) { + log.error("Cannot refresh site header/footer", e); } return p; } @@ -288,16 +288,16 @@ public class HostPageServlet extends HttpServlet { } private static class FileInfo { - private final File path; - private final long time; + private final Path path; + private final FileTime time; - FileInfo(final File p) { + FileInfo(Path p) throws IOException { path = p; - time = path.lastModified(); + time = getLastModifiedTime(path); } - boolean isStale() { - return time != path.lastModified(); + boolean isStale() throws IOException { + return !time.equals(getLastModifiedTime(path)); } } @@ -340,7 +340,7 @@ public class HostPageServlet extends HttpServlet { debug = new Content(hostDoc); } - boolean isStale() { + boolean isStale() throws IOException { return css.isStale() || header.isStale() || footer.isStale(); } @@ -364,8 +364,8 @@ public class HostPageServlet extends HttpServlet { } } - private FileInfo injectCssFile(final Document hostDoc, final String id, - final File src) throws IOException { + private FileInfo injectCssFile(Document hostDoc, String id, Path src) + throws IOException { final FileInfo info = new FileInfo(src); final Element banner = HtmlDomUtil.find(hostDoc, id); if (banner == null) { @@ -376,7 +376,8 @@ public class HostPageServlet extends HttpServlet { banner.removeChild(banner.getFirstChild()); } - String css = HtmlDomUtil.readFile(src.getParentFile(), src.getName()); + String css = + HtmlDomUtil.readFile(src.getParent(), src.getFileName().toString()); if (css == null) { return info; } @@ -385,8 +386,8 @@ public class HostPageServlet extends HttpServlet { return info; } - private FileInfo injectXmlFile(final Document hostDoc, final String id, - final File src) throws IOException { + private FileInfo injectXmlFile(Document hostDoc, String id, Path src) + throws IOException { final FileInfo info = new FileInfo(src); final Element banner = HtmlDomUtil.find(hostDoc, id); if (banner == null) { diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java index 321f032ba4..65ce13c02c 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java @@ -27,8 +27,10 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; @Singleton public class SiteHeaderFooter { @@ -43,13 +45,13 @@ public class SiteHeaderFooter { this.refreshHeaderFooter = cfg.getBoolean("site", "refreshHeaderFooter", true); this.sitePaths = sitePaths; - Template t = new Template(sitePaths); try { + Template t = new Template(sitePaths); t.load(); + template = t; } catch (IOException e) { log.warn("Cannot load site header or footer", e); } - template = t; } public Document parse(Class clazz, String name) throws IOException { @@ -110,7 +112,7 @@ public class SiteHeaderFooter { Element header; Element footer; - Template(SitePaths site) { + Template(SitePaths site) throws IOException { cssFile = new FileInfo(site.site_css); headerFile = new FileInfo(site.site_header); footerFile = new FileInfo(site.site_footer); @@ -118,13 +120,13 @@ public class SiteHeaderFooter { void load() throws IOException { css = HtmlDomUtil.readFile( - cssFile.path.getParentFile(), - cssFile.path.getName()); + cssFile.path.getParent(), + cssFile.path.getFileName().toString()); header = readXml(headerFile); footer = readXml(footerFile); } - boolean isStale() { + boolean isStale() throws IOException { return cssFile.isStale() || headerFile.isStale() || footerFile.isStale(); } @@ -135,16 +137,16 @@ public class SiteHeaderFooter { } private static class FileInfo { - final File path; - final long time; + final Path path; + final FileTime time; - FileInfo(File p) { + FileInfo(Path p) throws IOException { path = p; - time = path.lastModified(); + time = Files.getLastModifiedTime(path); } - boolean isStale() { - return time != path.lastModified(); + boolean isStale() throws IOException { + return !time.equals(Files.getLastModifiedTime(path)); } } } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java index 7709b246e3..ed0b268df0 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java @@ -16,6 +16,8 @@ package com.google.gerrit.pgm; import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.gerrit.common.ChangeHookRunner; @@ -92,10 +94,10 @@ import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.lang.Thread.UncaughtExceptionHandler; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -147,7 +149,7 @@ public class Daemon extends SiteProgram { private Injector sshInjector; private Injector webInjector; private Injector httpdInjector; - private File runFile; + private Path runFile; private boolean test; private AbstractModule luceneModule; @@ -183,7 +185,7 @@ public class Daemon extends SiteProgram { }); if (runId != null) { - runFile = new File(new File(getSitePath(), "logs"), "gerrit.run"); + runFile = getSitePath().resolve("logs").resolve("gerrit.run"); } if (httpd == null) { @@ -207,7 +209,11 @@ public class Daemon extends SiteProgram { public void run() { log.info("caught shutdown, cleaning up"); if (runId != null) { - runFile.delete(); + try { + Files.delete(runFile); + } catch (IOException err) { + log.warn("failed to delete " + runFile, err); + } } manager.stop(); } @@ -216,15 +222,8 @@ public class Daemon extends SiteProgram { log.info("Gerrit Code Review " + myVersion() + " ready"); if (runId != null) { try { - runFile.createNewFile(); - runFile.setReadable(true, false); - - FileOutputStream out = new FileOutputStream(runFile); - try { - out.write((runId + "\n").getBytes("UTF-8")); - } finally { - out.close(); - } + Files.write(runFile, (runId + "\n").getBytes(UTF_8)); + runFile.toFile().setReadable(true, false); } catch (IOException err) { log.warn("Cannot write --run-id to " + runFile, err); } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java index 29ab49034c..0b58d0606f 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java @@ -37,8 +37,8 @@ import com.google.inject.util.Providers; import org.kohsuke.args4j.Option; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -70,7 +70,7 @@ public class Init extends BaseInit { super(new WarDistribution(), null); } - public Init(File sitePath) { + public Init(Path sitePath) { super(sitePath, true, true, new WarDistribution(), null); batchMode = true; noAutoStart = true; @@ -106,7 +106,7 @@ public class Init extends BaseInit { modules.add(new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(getSitePath()); + bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath()); bind(Browser.class); bind(String.class).annotatedWith(SecureStoreClassName.class) .toProvider(Providers.of(getConfiguredSecureStoreClass())); 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 c9e76c83e0..7b10135baf 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 @@ -59,6 +59,11 @@ 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.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -86,12 +91,12 @@ public class BaseInit extends SiteProgram { this.pluginsToInstall = pluginsToInstall; } - public BaseInit(File sitePath, boolean standalone, boolean initDb, + public BaseInit(Path sitePath, boolean standalone, boolean initDb, PluginsDistribution pluginsDistribution, List pluginsToInstall) { this(sitePath, null, standalone, initDb, pluginsDistribution, pluginsToInstall); } - public BaseInit(File sitePath, final Provider dsProvider, + public BaseInit(Path sitePath, final Provider dsProvider, boolean standalone, boolean initDb, PluginsDistribution pluginsDistribution, List pluginsToInstall) { super(sitePath, dsProvider); @@ -132,7 +137,7 @@ public class BaseInit extends SiteProgram { throw failure; } - System.err.println("Initialized " + getSitePath().getCanonicalPath()); + System.err.println("Initialized " + getSitePath().toRealPath().normalize()); afterInit(run); return 0; } @@ -208,7 +213,7 @@ public class BaseInit extends SiteProgram { private SiteInit createSiteInit() { final ConsoleUI ui = getConsoleUI(); - final File sitePath = getSitePath(); + final Path sitePath = getSitePath(); final List m = new ArrayList<>(); final SecureStoreInitData secureStoreInitData = discoverSecureStoreClass(); final String currentSecureStoreClassName = getConfiguredSecureStoreClass(); @@ -228,7 +233,7 @@ public class BaseInit extends SiteProgram { @Override protected void configure() { bind(ConsoleUI.class).toInstance(ui); - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); List plugins = MoreObjects.firstNonNull( getInstallPlugins(), Lists. newArrayList()); @@ -408,15 +413,41 @@ public class BaseInit extends SiteProgram { return sysInjector; } - private static void recursiveDelete(File path) { - File[] entries = path.listFiles(); - if (entries != null) { - for (File e : entries) { - recursiveDelete(e); - } - } - if (!path.delete() && path.exists()) { - System.err.println("warn: Cannot remove " + path); + private static void recursiveDelete(Path path) { + final String msg = "warn: Cannot remove "; + try { + Files.walkFileTree(path, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path f, BasicFileAttributes attrs) + throws IOException { + try { + Files.delete(f); + } catch (IOException e) { + System.err.println(msg + f); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException err) { + try { + // Previously warned if err was not null; if dir is not empty as a + // result, will cause an error that will be logged below. + Files.delete(dir); + } catch (IOException e) { + System.err.println(msg + dir); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path f, IOException e) { + System.err.println(msg + f); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + System.err.println(msg + path); } } } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java index 881208d552..ac911a472c 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java @@ -34,6 +34,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; /** Utility functions to help initialize a site. */ public class InitUtil { @@ -51,9 +53,18 @@ public class InitUtil { } } - public static void mkdir(final File path) { - if (!path.isDirectory() && !path.mkdir()) { - throw die("Cannot make directory " + path); + public static void mkdir(File file) { + mkdir(file.toPath()); + } + + public static void mkdir(Path path) { + if (Files.isDirectory(path)) { + return; + } + try { + Files.createDirectory(path); + } catch (IOException e) { + throw die("Cannot make directory " + path, e); } } diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java index a766d1edc7..c947ac33d5 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java @@ -27,6 +27,7 @@ import org.apache.log4j.PatternLayout; import java.io.File; import java.io.FileNotFoundException; +import java.nio.file.Path; public class ErrorLogFile { static final String LOG_NAME = "error_log"; @@ -47,7 +48,7 @@ public class ErrorLogFile { root.addAppender(dst); } - public static LifecycleListener start(final File sitePath) + public static LifecycleListener start(final Path sitePath) throws FileNotFoundException { final File logdir = new SitePaths(sitePath).logs_dir; if (!logdir.exists() && !logdir.mkdirs()) { diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java index 7d33a36cc2..3a8223ce12 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java @@ -26,10 +26,11 @@ import org.apache.log4j.PatternLayout; import java.io.File; import java.io.FileNotFoundException; +import java.nio.file.Path; public class GarbageCollectionLogFile { - public static LifecycleListener start(File sitePath) + public static LifecycleListener start(Path sitePath) throws FileNotFoundException { File logdir = new SitePaths(sitePath).logs_dir; if (!logdir.exists() && !logdir.mkdirs()) { diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java index 02a8eac46e..53c5bb0c7c 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java @@ -54,9 +54,11 @@ import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.kohsuke.args4j.Option; -import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; @@ -66,30 +68,30 @@ import javax.sql.DataSource; public abstract class SiteProgram extends AbstractProgram { @Option(name = "--site-path", aliases = {"-d"}, usage = "Local directory containing site data") - private File sitePath = new File("."); + private void setSitePath(String path) { + sitePath = Paths.get(path); + } protected Provider dsProvider; + private Path sitePath; + protected SiteProgram() { } - protected SiteProgram(File sitePath, final Provider dsProvider) { + protected SiteProgram(Path sitePath, final Provider dsProvider) { this.sitePath = sitePath; this.dsProvider = dsProvider; } /** @return the site path specified on the command line. */ - protected File getSitePath() { - File path = sitePath.getAbsoluteFile(); - if (".".equals(path.getName())) { - path = path.getParentFile(); - } - return path; + protected Path getSitePath() { + return sitePath; } /** Ensures we are running inside of a valid site, otherwise throws a Die. */ protected void mustHaveValidSite() throws Die { - if (!new File(new File(getSitePath(), "etc"), "gerrit.config").exists()) { + if (!Files.exists(sitePath.resolve("etc").resolve("gerrit.config"))) { throw die("not a Gerrit site: '" + getSitePath() + "'\n" + "Perhaps you need to run init first?"); } @@ -97,13 +99,13 @@ public abstract class SiteProgram extends AbstractProgram { /** @return provides database connectivity and site path. */ protected Injector createDbInjector(final DataSourceProvider.Context context) { - final File sitePath = getSitePath(); + final Path sitePath = getSitePath(); final List modules = new ArrayList<>(); Module sitePathModule = new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); bind(String.class).annotatedWith(SecureStoreClassName.class) .toProvider(Providers.of(getConfiguredSecureStoreClass())); } @@ -191,7 +193,7 @@ public abstract class SiteProgram extends AbstractProgram { Module m = new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); bind(SitePaths.class); } }; @@ -222,7 +224,7 @@ public abstract class SiteProgram extends AbstractProgram { modules.add(new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); } }); modules.add(new GerritServerConfigModule()); diff --git a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java index 4d7370bfb7..150309e3f1 100644 --- a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java +++ b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java @@ -16,11 +16,11 @@ package com.google.gerrit.pgm.init; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; public abstract class InitTestCase extends LocalDiskRepositoryTestCase { - protected File newSitePath() throws IOException { - return new File(createWorkRepository().getWorkTree(), "test_site"); + protected Path newSitePath() throws IOException { + return createWorkRepository().getWorkTree().toPath().resolve("test_site"); } } diff --git a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java index a37c97d27d..7b0890221c 100644 --- a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java +++ b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java @@ -25,13 +25,13 @@ import com.google.inject.Provider; import org.junit.Test; -import java.io.File; import java.io.FileNotFoundException; +import java.nio.file.Paths; public class LibrariesTest { @Test public void testCreate() throws FileNotFoundException { - final SitePaths site = new SitePaths(new File(".")); + final SitePaths site = new SitePaths(Paths.get(".")); final ConsoleUI ui = createStrictMock(ConsoleUI.class); replay(ui); diff --git a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java index 720d1082cd..2335e50dcb 100644 --- a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java +++ b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java @@ -14,6 +14,8 @@ package com.google.gerrit.pgm.init; +import static java.nio.charset.StandardCharsets.UTF_8; + import static org.easymock.EasyMock.createStrictMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; @@ -38,9 +40,9 @@ import org.eclipse.jgit.util.IO; import org.junit.Test; import java.io.File; -import java.io.FileWriter; import java.io.IOException; -import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -49,23 +51,18 @@ public class UpgradeFrom2_0_xTest extends InitTestCase { @Test public void testUpgrade() throws IOException, ConfigInvalidException { - final File p = newSitePath(); + final Path p = newSitePath(); final SitePaths site = new SitePaths(p); assertTrue(site.isNew); assertTrue(site.site_path.mkdir()); assertTrue(site.etc_dir.mkdir()); for (String n : UpgradeFrom2_0_x.etcFiles) { - Writer w = new FileWriter(new File(p, n)); - try { - w.write("# " + n + "\n"); - } finally { - w.close(); - } + Files.write(p.resolve(n), ("# " + n + "\n").getBytes(UTF_8)); } FileBasedConfig old = - new FileBasedConfig(new File(p, "gerrit.config"), FS.DETECTED); + new FileBasedConfig(p.resolve("gerrit.config").toFile(), FS.DETECTED); old.setString("ldap", null, "username", "ldap.user"); old.setString("ldap", null, "password", "ldap.s3kr3t"); @@ -85,8 +82,11 @@ public class UpgradeFrom2_0_xTest extends InitTestCase { } }; - expect(ui.yesno(eq(true), eq("Upgrade '%s'"), eq(p.getCanonicalPath()))) - .andReturn(true); + expect(ui.yesno( + eq(true), + eq("Upgrade '%s'"), + eq(p.toRealPath().normalize().toString()))) + .andReturn(true); replay(ui); UpgradeFrom2_0_x u = new UpgradeFrom2_0_x(site, flags, ui, sections); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java index 9aa859067b..feac4737b0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java @@ -24,7 +24,6 @@ import com.google.inject.Inject; import org.eclipse.jgit.internal.storage.file.WindowCacheStatAccessor; import org.kohsuke.args4j.Option; -import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; @@ -33,6 +32,8 @@ import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.net.InetAddress; import java.net.UnknownHostException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -43,7 +44,7 @@ import java.util.Map; public class GetSummary implements RestReadView { private final WorkQueue workQueue; - private final File sitePath; + private final Path sitePath; @Option(name = "--gc", usage = "perform Java GC before retrieving memory stats") private boolean gc; @@ -62,7 +63,7 @@ public class GetSummary implements RestReadView { } @Inject - public GetSummary(WorkQueue workQueue, @SitePath File sitePath) { + public GetSummary(WorkQueue workQueue, @SitePath Path sitePath) { this.workQueue = workQueue; this.sitePath = sitePath; } @@ -186,7 +187,8 @@ public class GetSummary implements RestReadView { } catch (UnknownHostException e) { } - jvmSummary.currentWorkingDirectory = path(new File(".").getAbsoluteFile().getParentFile()); + jvmSummary.currentWorkingDirectory = + path(Paths.get(".").toAbsolutePath().getParent()); jvmSummary.site = path(sitePath); return jvmSummary; } @@ -210,11 +212,11 @@ public class GetSummary implements RestReadView { return String.format("%1$6.2f%2$s", value, suffix).trim(); } - private static String path(File file) { + private static String path(Path path) { try { - return file.getCanonicalPath(); + return path.toRealPath().normalize().toString(); } catch (IOException err) { - return file.getAbsolutePath(); + return path.toAbsolutePath().normalize().toString(); } } 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 fbff7c45cf..44f03405bc 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 @@ -20,6 +20,7 @@ import com.google.inject.Singleton; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; /** Important paths within a {@link SitePath}. */ @Singleton @@ -32,7 +33,7 @@ public final class SitePaths { public final File bin_dir; public final File etc_dir; public final File lib_dir; - public final File tmp_dir; + public final Path tmp_dir; public final File logs_dir; public final File plugins_dir; public final File data_dir; @@ -55,22 +56,24 @@ public final class SitePaths { public final File ssh_dsa; public final File peer_keys; - public final File site_css; - public final File site_header; - public final File site_footer; - public final File site_gitweb; + public final Path site_css; + public final Path site_header; + public final Path site_footer; + public final Path site_gitweb; /** {@code true} if {@link #site_path} has not been initialized. */ public final boolean isNew; @Inject - public SitePaths(final @SitePath File sitePath) throws FileNotFoundException { - site_path = sitePath; + public SitePaths(final @SitePath Path sitePath) throws FileNotFoundException { + // TODO(dborowitz): Convert all of these to Paths. + site_path = sitePath.toFile(); + Path p = sitePath; bin_dir = new File(site_path, "bin"); etc_dir = new File(site_path, "etc"); lib_dir = new File(site_path, "lib"); - tmp_dir = new File(site_path, "tmp"); + tmp_dir = p.resolve("tmp"); plugins_dir = new File(site_path, "plugins"); data_dir = new File(site_path, "data"); logs_dir = new File(site_path, "logs"); @@ -93,10 +96,11 @@ public final class SitePaths { ssh_dsa = new File(etc_dir, "ssh_host_dsa_key"); peer_keys = new File(etc_dir, "peer_keys"); - site_css = new File(etc_dir, CSS_FILENAME); - site_header = new File(etc_dir, HEADER_FILENAME); - site_footer = new File(etc_dir, FOOTER_FILENAME); - site_gitweb = new File(etc_dir, "gitweb_config.perl"); + Path etcDirPath = etc_dir.toPath(); + site_css = etcDirPath.resolve(CSS_FILENAME); + site_header = etcDirPath.resolve(HEADER_FILENAME); + site_footer = etcDirPath.resolve(FOOTER_FILENAME); + site_gitweb = etcDirPath.resolve("gitweb_config.perl"); if (site_path.exists()) { final String[] contents = site_path.list(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java index 7252617086..1d4233a345 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java @@ -33,7 +33,7 @@ import com.google.inject.Singleton; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.PersonIdent; -import java.io.File; +import java.nio.file.Path; /** * Copies critical objects from the {@code dbInjector} into a plugin. @@ -47,11 +47,11 @@ import java.io.File; class CopyConfigModule extends AbstractModule { @Inject @SitePath - private File sitePath; + private Path sitePath; @Provides @SitePath - File getSitePath() { + Path getSitePath() { return sitePath; } 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 53f39f1cb5..5c0b41c5d6 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 @@ -31,6 +31,7 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Files; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -47,7 +48,8 @@ public class JarPluginProvider implements ServerPluginProvider { @Inject JarPluginProvider(SitePaths sitePaths) { - tmpDir = sitePaths.tmp_dir; + // TODO(dborowitz): Convert to NIO. + tmpDir = sitePaths.tmp_dir.toFile(); } @Override @@ -111,10 +113,11 @@ public class JarPluginProvider implements ServerPluginProvider { public static File storeInTemp(String pluginName, InputStream in, SitePaths sitePaths) throws IOException { - if (!sitePaths.tmp_dir.exists()) { - sitePaths.tmp_dir.mkdirs(); + if (!Files.exists(sitePaths.tmp_dir)) { + Files.createDirectories(sitePaths.tmp_dir); } - return asTemp(in, tempNameFor(pluginName), ".jar", sitePaths.tmp_dir); + return asTemp(in, tempNameFor(pluginName), ".jar", + sitePaths.tmp_dir.toFile()); } private ServerPlugin loadJarPlugin(String name, File srcJar, diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java index daf1d4d679..8829ac3d4d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java @@ -32,14 +32,14 @@ import com.google.inject.Inject; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.PersonIdent; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.Collections; /** Creates the current database schema and populates initial code rows. */ public class SchemaCreator { private final @SitePath - File site_path; + Path site_path; private final AllProjectsCreator allProjectsCreator; private final AllUsersCreator allUsersCreator; @@ -55,10 +55,10 @@ public class SchemaCreator { AllUsersCreator auc, @GerritPersonIdent PersonIdent au, DataSourceType dst) { - this(site.site_path, ap, auc, au, dst); + this(site.site_path.toPath(), ap, auc, au, dst); } - public SchemaCreator(@SitePath File site, + public SchemaCreator(@SitePath Path site, AllProjectsCreator ap, AllUsersCreator auc, @GerritPersonIdent PersonIdent au, @@ -117,9 +117,9 @@ public class SchemaCreator { final SystemConfig s = SystemConfig.create(); try { - s.sitePath = site_path.getCanonicalPath(); + s.sitePath = site_path.toRealPath().normalize().toString(); } catch (IOException e) { - s.sitePath = site_path.getAbsolutePath(); + s.sitePath = site_path.toAbsolutePath().normalize().toString(); } c.systemConfig().insert(Collections.singleton(s)); return s; diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java index 5fdecf0415..25a452ee2e 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java @@ -28,85 +28,86 @@ import org.junit.Test; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; public class SitePathsTest { @Test public void testCreate_NotExisting() throws IOException { - final File root = random(); + final Path root = random(); final SitePaths site = new SitePaths(root); assertTrue(site.isNew); - assertEquals(root, site.site_path); - assertEquals(new File(root, "etc"), site.etc_dir); + assertEquals(root.toFile(), site.site_path); + assertEquals(root.resolve("etc").toFile(), site.etc_dir); } @Test public void testCreate_Empty() throws IOException { - final File root = random(); + final Path root = random(); try { - assertTrue(root.mkdir()); + Files.createDirectory(root); final SitePaths site = new SitePaths(root); assertTrue(site.isNew); - assertEquals(root, site.site_path); + assertEquals(root.toFile(), site.site_path); } finally { - root.delete(); + Files.delete(root); } } @Test public void testCreate_NonEmpty() throws IOException { - final File root = random(); - final File txt = new File(root, "test.txt"); + final Path root = random(); + final Path txt = root.resolve("test.txt"); try { - assertTrue(root.mkdir()); - assertTrue(txt.createNewFile()); + Files.createDirectory(root); + Files.createFile(txt); final SitePaths site = new SitePaths(root); assertFalse(site.isNew); - assertEquals(root, site.site_path); + assertEquals(root.toFile(), site.site_path); } finally { - txt.delete(); - root.delete(); + Files.delete(txt); + Files.delete(root); } } @Test public void testCreate_NotDirectory() throws IOException { - final File root = random(); + final Path root = random(); try { - assertTrue(root.createNewFile()); + Files.createFile(root); try { new SitePaths(root); fail("Did not throw exception"); } catch (FileNotFoundException e) { - assertEquals("Not a directory: " + root.getPath(), e.getMessage()); + assertEquals("Not a directory: " + root, e.getMessage()); } } finally { - root.delete(); + Files.delete(root); } } @Test public void testResolve() throws IOException { - final File root = random(); + final Path root = random(); final SitePaths site = new SitePaths(root); assertNull(site.resolve(null)); assertNull(site.resolve("")); assertNotNull(site.resolve("a")); - assertEquals(new File(root, "a").getCanonicalFile(), site.resolve("a")); + assertEquals(root.resolve("a").toAbsolutePath().normalize().toFile(), + site.resolve("a")); final String pfx = HostPlatform.isWin32() ? "C:/" : "/"; assertNotNull(site.resolve(pfx + "a")); assertEquals(new File(pfx + "a").getCanonicalFile(), site.resolve(pfx + "a")); } - private static File random() throws IOException { - File tmp = File.createTempFile("gerrit_test_", "_site"); - if (!tmp.delete()) { - throw new IOException("Cannot create " + tmp.getPath()); - } + private static Path random() throws IOException { + Path tmp = Files.createTempFile("gerrit_test_", "_site"); + Files.deleteIfExists(tmp); return tmp; } } diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java index 8686fe6214..141c8e3baf 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java @@ -43,9 +43,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.UUID; @@ -67,7 +68,7 @@ public class SchemaUpdaterTest { IOException { db.create(); - final File site = new File(UUID.randomUUID().toString()); + final Path site = Paths.get(UUID.randomUUID().toString()); final SitePaths paths = new SitePaths(site); SchemaUpdater u = Guice.createInjector(new FactoryModule() { @Override diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java index 72495b3d6c..f33cfb23de 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java +++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java @@ -69,11 +69,12 @@ import com.google.inject.servlet.RequestScoped; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.PersonIdent; -import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.nio.file.Path; +import java.nio.file.Paths; public class InMemoryModule extends FactoryModule { public static Config newDefaultConfig() { @@ -125,7 +126,8 @@ public class InMemoryModule extends FactoryModule { bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST); - bind(File.class).annotatedWith(SitePath.class).toInstance(new File(".")); + // TODO(dborowitz): Use jimfs. + bind(Path.class).annotatedWith(SitePath.class).toInstance(Paths.get(".")); bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg); bind(SocketAddress.class).annotatedWith(RemotePeer.class).toInstance( new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1234)); diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java index 6bbbd8fc8f..ea4a3ea1a9 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java @@ -20,7 +20,8 @@ import com.google.gerrit.pgm.init.PluginsDistribution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -47,21 +48,19 @@ public final class SiteInitializer { public void init() { try { if (sitePath != null) { - File site = new File(sitePath); - LOG.info(String.format("Initializing site at %s", - site.getAbsolutePath())); + Path site = Paths.get(sitePath); + LOG.info("Initializing site at " + site.toRealPath().normalize()); new BaseInit(site, false, true, pluginsDistribution, pluginsToInstall).run(); return; } try (Connection conn = connectToDb()) { - File site = getSiteFromReviewDb(conn); + Path site = getSiteFromReviewDb(conn); if (site == null && initPath != null) { - site = new File(initPath); + site = Paths.get(initPath); } if (site != null) { - LOG.info(String.format("Initializing site at %s", - site.getAbsolutePath())); + LOG.info("Initializing site at " + site.toRealPath().normalize()); new BaseInit(site, new ReviewDbDataSourceProvider(), false, false, pluginsDistribution, pluginsToInstall).run(); } @@ -76,12 +75,12 @@ public final class SiteInitializer { return new ReviewDbDataSourceProvider().get().getConnection(); } - private File getSiteFromReviewDb(Connection conn) { + private Path getSiteFromReviewDb(Connection conn) { try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT site_path FROM system_config")) { if (rs.next()) { - return new File(rs.getString(1)); + return Paths.get(rs.getString(1)); } } catch (SQLException e) { return null; diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java index b97df3f0b8..60f389eb92 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java @@ -22,12 +22,13 @@ import com.google.gwtorm.server.SchemaFactory; import com.google.inject.Inject; import com.google.inject.Provider; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; -/** Provides {@link java.io.File} annotated with {@link SitePath}. */ -class SitePathFromSystemConfigProvider implements Provider { - private final File path; +/** Provides {@link Path} annotated with {@link SitePath}. */ +class SitePathFromSystemConfigProvider implements Provider { + private final Path path; @Inject SitePathFromSystemConfigProvider(SchemaFactory schemaFactory) @@ -36,18 +37,18 @@ class SitePathFromSystemConfigProvider implements Provider { } @Override - public File get() { + public Path get() { return path; } - private static File read(SchemaFactory schemaFactory) + private static Path read(SchemaFactory schemaFactory) throws OrmException { ReviewDb db = schemaFactory.open(); try { List all = db.systemConfig().all().toList(); switch (all.size()) { case 1: - return new File(all.get(0).sitePath); + return Paths.get(all.get(0).sitePath); case 0: throw new OrmException("system_config table is empty"); default: diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java index 15e2daa98f..eb4c792584 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java @@ -78,8 +78,9 @@ import org.eclipse.jgit.lib.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -101,7 +102,7 @@ public class WebAppInitializer extends GuiceServletContextListener private static final Logger log = LoggerFactory.getLogger(WebAppInitializer.class); - private File sitePath; + private Path sitePath; private Injector dbInjector; private Injector cfgInjector; private Injector sysInjector; @@ -122,7 +123,7 @@ public class WebAppInitializer extends GuiceServletContextListener if (manager == null) { final String path = System.getProperty("gerrit.site_path"); if (path != null) { - sitePath = new File(path); + sitePath = Paths.get(path); } if (System.getProperty("gerrit.init") != null) { @@ -209,7 +210,7 @@ public class WebAppInitializer extends GuiceServletContextListener Module sitePathModule = new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); } }; modules.add(sitePathModule); @@ -261,7 +262,7 @@ public class WebAppInitializer extends GuiceServletContextListener modules.add(new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toProvider( + bind(Path.class).annotatedWith(SitePath.class).toProvider( SitePathFromSystemConfigProvider.class).in(SINGLETON); } });