Merge branch 'stable-2.11'
* stable-2.11:
Update 2.11 release notes
Fix minor bugs in ChangeHookRunner
RebaseDialog: Organize imports
Force javac to use -encoding UTF-8
Fix NullPointerException when executing query with --comments option
Remove '--recheck-mergeable' option in 2.11 release notes
ReceiveCommits: Fix NPE when pushing to refs/changes/n
ChangeControl: Optimize creation by not re-reading changes
Change-Id: Iab97e14b80b1867f785034544ecb33bb39aab2ef
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 8f04d7c..adba1aa 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -844,6 +844,30 @@
+
Default is "Submit patch set ${patchSet} into ${branch}".
+[[change.submitWholeTopic]]change.submitWholeTopic::
++
+Determines if the submit button submits the whole topic instead of
+just the current change.
++
+Default is false.
+
+[[change.submitTopicLabel]]change.submitTopicLabel::
++
+If `change.submitWholeTopic` is set and a change has a topic,
+the label name for the submit button is given here instead of
+the configuration `change.submitLabel`.
++
+Defaults to "Submit whole topic"
+
+[[change.submitTopicTooltip]]change.submitTopicTooltip::
++
+If `change.submitWholeTopic` is configuerd to true and a change has a
+topic, this configuration determines the tooltip for the submit button
+instead of `change.submitTooltip`. The variable `${topicSize}` is available
+for the number of changes to be submitted.
++
+Defaults to "Submit all ${topicSize} changes within the topic".
+
[[change.replyLabel]]change.replyLabel::
+
Label name for the reply button. In the user interface an ellipsis (…)
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index cecb258..a672b177 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -36,7 +36,7 @@
----
mvn archetype:generate -DarchetypeGroupId=com.google.gerrit \
-DarchetypeArtifactId=gerrit-plugin-archetype \
- -DarchetypeVersion=2.10 \
+ -DarchetypeVersion=2.12-SNAPSHOT \
-DgroupId=com.googlesource.gerrit.plugins.testplugin \
-DartifactId=testplugin
----
@@ -1717,17 +1717,18 @@
[[data-directory]]
== Data Directory
-Plugins can request a data directory with a `@PluginData` File
-dependency. A data directory will be created automatically by the
-server in `$site_path/data/$plugin_name` and passed to the plugin.
+Plugins can request a data directory with a `@PluginData` Path (or File,
+deprecated) dependency. A data directory will be created automatically
+by the server in `$site_path/data/$plugin_name` and passed to the
+plugin.
Plugins can use this to store any data they want.
[source,java]
----
@Inject
-MyType(@PluginData java.io.File myDir) {
- new FileInputStream(new File(myDir, "my.config"));
+MyType(@PluginData java.nio.file.Path myDir) {
+ this.in = Files.newInputStream(myDir.resolve("my.config"));
}
----
diff --git a/VERSION b/VERSION
index b05afb0..83d3d2a 100644
--- a/VERSION
+++ b/VERSION
@@ -2,4 +2,4 @@
# Used by :api_install and :api_deploy targets
# when talking to the destination repository.
#
-GERRIT_VERSION = '2.11-SNAPSHOT'
+GERRIT_VERSION = '2.12-SNAPSHOT'
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 8548b5c..8f4c2d4 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.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 @@
.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-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 8945a22d..88fb422 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -22,6 +22,8 @@
import org.junit.Test;
+import java.util.List;
+
public class AccountIT extends AbstractDaemonTest {
@Test
@@ -59,4 +61,21 @@
.unstarChange(triplet);
assertThat(getChange(triplet).starred).isNull();
}
+
+ @Test
+ public void suggestAccounts() throws Exception {
+ String adminUsername = "admin";
+ List<AccountInfo> result = gApi.accounts()
+ .suggestAccounts().withQuery(adminUsername).get();
+ assertThat(result.size()).is(1);
+ assertThat(result.get(0).username.equals(adminUsername));
+
+ List<AccountInfo> resultShortcutApi = gApi.accounts()
+ .suggestAccounts(adminUsername).get();
+ assertThat(resultShortcutApi.size()).is(result.size());
+
+ List<AccountInfo> emptyResult = gApi.accounts()
+ .suggestAccounts("unknown").get();
+ assertThat(emptyResult).isEmpty();
+ }
}
diff --git a/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java b/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
index 5870f91..54a2246 100644
--- a/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
+++ b/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
@@ -37,7 +37,9 @@
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.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
@@ -51,7 +53,7 @@
private final DefaultCacheFactory defaultFactory;
private final Config config;
- private final File cacheDir;
+ private final Path cacheDir;
private final List<H2CacheImpl<?, ?>> caches;
private final DynamicMap<Cache<?, ?>> cacheMap;
private final ExecutorService executor;
@@ -65,23 +67,7 @@
DynamicMap<Cache<?, ?>> cacheMap) {
defaultFactory = defaultCacheFactory;
config = cfg;
-
- File loc = site.resolve(cfg.getString("cache", null, "directory"));
- if (loc == null) {
- cacheDir = null;
- } else if (loc.exists() || loc.mkdirs()) {
- if (loc.canWrite()) {
- log.info("Enabling disk cache " + loc.getAbsolutePath());
- cacheDir = loc;
- } else {
- log.warn("Can't write to disk cache: " + loc.getAbsolutePath());
- cacheDir = null;
- }
- } else {
- log.warn("Can't create disk cache: " + loc.getAbsolutePath());
- cacheDir = null;
- }
-
+ cacheDir = getCacheDir(site, cfg.getString("cache", null, "directory"));
caches = Lists.newLinkedList();
this.cacheMap = cacheMap;
@@ -103,6 +89,27 @@
}
}
+ private static Path getCacheDir(SitePaths site, String name) {
+ if (name == null) {
+ return null;
+ }
+ Path loc = site.resolve(name).toPath();
+ if (!Files.exists(loc)) {
+ try {
+ Files.createDirectories(loc);
+ } catch (IOException e) {
+ log.warn("Can't create disk cache: " + loc.toAbsolutePath());
+ return null;
+ }
+ }
+ if (!Files.isWritable(loc)) {
+ log.warn("Can't write to disk cache: " + loc.toAbsolutePath());
+ return null;
+ }
+ log.info("Enabling disk cache " + loc.toAbsolutePath());
+ return loc;
+ }
+
@Override
public void start() {
if (executor != null) {
@@ -213,8 +220,7 @@
TypeLiteral<K> keyType,
long maxSize,
Long expireAfterWrite) {
- File db = new File(cacheDir, name).getAbsoluteFile();
- String url = "jdbc:h2:" + db.toURI().toString();
+ String url = "jdbc:h2:" + cacheDir.resolve(name).toUri();
return new SqlStore<>(url, keyType, maxSize,
expireAfterWrite == null ? 0 : expireAfterWrite.longValue());
}
diff --git a/gerrit-common/BUCK b/gerrit-common/BUCK
index 88e503e..484136a 100644
--- a/gerrit-common/BUCK
+++ b/gerrit-common/BUCK
@@ -51,6 +51,7 @@
'//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/FileUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java
index bed10d6..2335b8d1 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,8 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
public class FileUtil {
@@ -42,6 +44,11 @@
}
}
+ 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 */);
@@ -61,6 +68,33 @@
}
}
+ /**
+ * Get the last modified time of a path.
+ * <p>
+ * Equivalent to {@code File#lastModified()}, returning 0 on errors, including
+ * file not found. Callers that prefer exceptions can use {@link
+ * Files#getLastModifiedTime(Path, java.nio.file.LinkOption...)}.
+ *
+ * @param p path.
+ * @return last modified time, in milliseconds since epoch.
+ */
+ public static long lastModified(Path p) {
+ try {
+ return Files.getLastModifiedTime(p).toMillis();
+ } catch (IOException e) {
+ return 0;
+ }
+ }
+
+ public static Path mkdirsOrDie(Path p, String errMsg) {
+ try {
+ Files.createDirectories(p);
+ return p;
+ } catch (IOException e) {
+ throw new Die(errMsg + ": " + p, e);
+ }
+ }
+
private FileUtil() {
}
-}
\ No newline at end of file
+}
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 c45d9f9..9a30696 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 @@
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.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 @@
}.start();
}
- public static void loadJARs(File... jars) {
+ public static void loadJARs(Iterable<Path> jars) {
ClassLoader cl = IoUtil.class.getClassLoader();
if (!(cl instanceof URLClassLoader)) {
throw noAddURL("Not loaded by URLClassLoader", null);
@@ -71,9 +71,9 @@
}
Set<URL> 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 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/PluginData.java b/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java
index ffdae9d..27dc639 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java
@@ -14,18 +14,18 @@
package com.google.gerrit.common;
-import java.io.File;
+import java.nio.file.Path;
import java.util.Objects;
public class PluginData {
public final String name;
public final String version;
- public final File pluginFile;
+ public final Path pluginPath;
- public PluginData(String name, String version, File pluginFile) {
+ public PluginData(String name, String version, Path pluginPath) {
this.name = name;
this.version = version;
- this.pluginFile = pluginFile;
+ this.pluginPath = pluginPath;
}
@Override
@@ -33,13 +33,13 @@
if (obj instanceof PluginData) {
PluginData o = (PluginData) obj;
return Objects.equals(name, o.name) && Objects.equals(version, o.version)
- && Objects.equals(pluginFile, o.pluginFile);
+ && Objects.equals(pluginPath, o.pluginPath);
}
return super.equals(obj);
}
@Override
public int hashCode() {
- return Objects.hash(name, version, pluginFile);
+ return Objects.hash(name, version, pluginPath);
}
-}
\ No newline at end of file
+}
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 a98e0a5..24451a4 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,53 @@
package com.google.gerrit.common;
-import java.io.File;
-import java.io.FileFilter;
-import java.util.Arrays;
-import java.util.Comparator;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
+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<File>() {
- @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() {
+ public static List<Path> listJars(Path dir) throws IOException {
+ DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@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<Path> jars = Files.newDirectoryStream(dir, filter)) {
+ return new Ordering<Path>() {
+ @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-extension-api/pom.xml b/gerrit-extension-api/pom.xml
index a0d9455..d0204e4 100644
--- a/gerrit-extension-api/pom.xml
+++ b/gerrit-extension-api/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-extension-api</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Extension API</name>
<description>API for Gerrit Extensions</description>
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java
index 75238a8..4893beff 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java
@@ -18,24 +18,25 @@
import com.google.inject.BindingAnnotation;
-import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
/**
* Local path where a plugin can store its own private data.
* <p>
* A plugin or extension may receive this string by Guice injection to discover
* a directory where it can store configuration or other data that is private:
+ * <p>
+ * This binding is on both {@link java.io.File} and {@link java.nio.file.Path},
+ * pointing to the same location. The {@code File} version should be considered
+ * deprecated and may be removed in a future version.
*
* <pre>
* {@literal @Inject}
- * MyType(@PluginData java.io.File myDir) {
- * new FileInputStream(new File(myDir, "my.config"));
+ * MyType(@PluginData java.nio.file.Path myDir) {
+ * this.in = Files.newInputStream(myDir.resolve("my.config"));
* }
* </pre>
*/
-@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RUNTIME)
@BindingAnnotation
public @interface PluginData {
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
index 71a93d3..32f8488 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
@@ -14,9 +14,12 @@
package com.google.gerrit.extensions.api.accounts;
+import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.NotImplementedException;
import com.google.gerrit.extensions.restapi.RestApiException;
+import java.util.List;
+
public interface Accounts {
/**
* Look up an account by ID.
@@ -42,6 +45,69 @@
AccountApi self() throws RestApiException;
/**
+ * Suggest users for a given query.
+ * <p>
+ * Example code:
+ * {@code suggestAccounts().withQuery("Reviewer").withLimit(5).get()}
+ *
+ * @return API for setting parameters and getting result.
+ */
+ SuggestAccountsRequest suggestAccounts() throws RestApiException;
+
+ /**
+ * Suggest users for a given query.
+ * <p>
+ * Shortcut API for {@code suggestAccounts().withQuery(String)}.
+ *
+ * @see #suggestAccounts()
+ */
+ SuggestAccountsRequest suggestAccounts(String query)
+ throws RestApiException;
+
+ /**
+ * API for setting parameters and getting result.
+ * Used for {@code suggestAccounts()}.
+ *
+ * @see #suggestAccounts()
+ */
+ public abstract class SuggestAccountsRequest {
+ private String query;
+ private int limit;
+
+ /**
+ * Executes query and returns a list of accounts.
+ */
+ public abstract List<AccountInfo> get() throws RestApiException;
+
+ /**
+ * Set query.
+ *
+ * @param query needs to be in human-readable form.
+ */
+ public SuggestAccountsRequest withQuery(String query) {
+ this.query = query;
+ return this;
+ }
+
+ /**
+ * Set limit for returned list of accounts.
+ * Optional; server-default is used when not provided.
+ */
+ public SuggestAccountsRequest withLimit(int limit) {
+ this.limit = limit;
+ return this;
+ }
+
+ public String getQuery() {
+ return query;
+ }
+
+ public int getLimit() {
+ return limit;
+ }
+ }
+
+ /**
* A default implementation which allows source compatibility
* when adding new methods to the interface.
**/
@@ -55,5 +121,16 @@
public AccountApi self() throws RestApiException {
throw new NotImplementedException();
}
+
+ @Override
+ public SuggestAccountsRequest suggestAccounts() throws RestApiException {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public SuggestAccountsRequest suggestAccounts(String query)
+ throws RestApiException {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java
index 525684d..37b90c4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java
@@ -65,7 +65,6 @@
private String message;
private String branch;
private String key;
- private boolean canSubmit;
Actions() {
initWidget(uiBinder.createAndBindUi(this));
@@ -87,7 +86,12 @@
changeInfo = info;
initChangeActions(info, hasUser);
- initRevisionActions(info, revInfo, hasUser);
+
+ NativeMap<ActionInfo> actionMap = revInfo.has_actions()
+ ? revInfo.actions()
+ : NativeMap.<ActionInfo> create();
+ actionMap.copyKeysIntoChildren("id");
+ reloadRevisionActions(actionMap);
}
private void initChangeActions(ChangeInfo info, boolean hasUser) {
@@ -107,30 +111,29 @@
}
}
- private void initRevisionActions(ChangeInfo info, RevisionInfo revInfo,
- boolean hasUser) {
- NativeMap<ActionInfo> actions = revInfo.has_actions()
- ? revInfo.actions()
- : NativeMap.<ActionInfo> create();
- actions.copyKeysIntoChildren("id");
+ void reloadRevisionActions(NativeMap<ActionInfo> actions) {
+ if (!Gerrit.isSignedIn()) {
+ return;
+ }
+ boolean canSubmit = actions.containsKey("submit");
+ if (canSubmit) {
+ ActionInfo action = actions.get("submit");
+ submit.setTitle(action.title());
+ submit.setEnabled(action.enabled());
+ submit.setHTML(new SafeHtmlBuilder()
+ .openDiv()
+ .append(action.label())
+ .closeDiv());
+ submit.setEnabled(action.enabled());
+ }
+ submit.setVisible(canSubmit);
- canSubmit = false;
- if (hasUser) {
- canSubmit = actions.containsKey("submit");
- if (canSubmit) {
- ActionInfo action = actions.get("submit");
- submit.setTitle(action.title());
- submit.setEnabled(action.enabled());
- submit.setHTML(new SafeHtmlBuilder()
- .openDiv()
- .append(action.label())
- .closeDiv());
- }
- a2b(actions, "cherrypick", cherrypick);
- a2b(actions, "rebase", rebase);
- for (String id : filterNonCore(actions)) {
- add(new ActionButton(info, revInfo, actions.get(id)));
- }
+ a2b(actions, "cherrypick", cherrypick);
+ a2b(actions, "rebase", rebase);
+
+ RevisionInfo revInfo = changeInfo.revision(revision);
+ for (String id : filterNonCore(actions)) {
+ add(new ActionButton(changeInfo, revInfo, actions.get(id)));
}
}
@@ -146,10 +149,6 @@
return ids;
}
- void setSubmitEnabled() {
- submit.setVisible(canSubmit);
- }
-
@UiHandler("followUp")
void onFollowUp(@SuppressWarnings("unused") ClickEvent e) {
if (followUpAction == null) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
index 8a27fd0..a6635f3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
@@ -134,8 +134,6 @@
private CommentLinkProcessor commentLinkProcessor;
private EditInfo edit;
- private KeyCommandSet keysNavigation;
- private KeyCommandSet keysAction;
private List<HandlerRegistration> handlers = new ArrayList<>(4);
private UpdateCheckTimer updateCheck;
private Timestamp lastDisplayedUpdate;
@@ -248,7 +246,7 @@
void loadChangeInfo(boolean fg, AsyncCallback<ChangeInfo> cb) {
RestApi call = ChangeApi.detail(changeId.get());
ChangeList.addOptions(call, EnumSet.of(
- ListChangesOption.CURRENT_ACTIONS,
+ ListChangesOption.CHANGE_ACTIONS,
ListChangesOption.ALL_REVISIONS));
if (!fg) {
call.background();
@@ -256,6 +254,18 @@
call.get(cb);
}
+ void loadRevisionInfo() {
+ RestApi call = ChangeApi.actions(changeId.get(), revision);
+ call.background();
+ call.get(new GerritCallback<NativeMap<ActionInfo>>() {
+ @Override
+ public void onSuccess(NativeMap<ActionInfo> actionMap) {
+ actionMap.copyKeysIntoChildren("id");
+ renderRevisionInfo(changeInfo, actionMap);
+ }
+ });
+ }
+
@Override
protected void onUnload() {
if (replyAction != null) {
@@ -281,69 +291,6 @@
labels.init(style);
reviewers.init(style, ccText);
hashtags.init(style);
-
- keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
- keysNavigation.add(new KeyCommand(0, 'u', Util.C.upToChangeList()) {
- @Override
- public void onKeyPress(final KeyPressEvent event) {
- Gerrit.displayLastChangeList();
- }
- });
- keysNavigation.add(new KeyCommand(0, 'R', Util.C.keyReloadChange()) {
- @Override
- public void onKeyPress(final KeyPressEvent event) {
- Gerrit.display(PageLinks.toChange(changeId));
- }
- });
- keysNavigation.add(new KeyCommand(0, 'n', Util.C.keyNextPatchSet()) {
- @Override
- public void onKeyPress(final KeyPressEvent event) {
- gotoSibling(1);
- }
- }, new KeyCommand(0, 'p', Util.C.keyPreviousPatchSet()) {
- @Override
- public void onKeyPress(final KeyPressEvent event) {
- gotoSibling(-1);
- }
- });
-
- keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
- keysAction.add(new KeyCommand(0, 'a', Util.C.keyPublishComments()) {
- @Override
- public void onKeyPress(KeyPressEvent event) {
- if (Gerrit.isSignedIn()) {
- onReply(null);
- } else {
- Gerrit.doSignIn(getToken());
- }
- }
- });
- keysAction.add(new KeyCommand(0, 'x', Util.C.keyExpandAllMessages()) {
- @Override
- public void onKeyPress(KeyPressEvent event) {
- onExpandAll(null);
- }
- });
- keysAction.add(new KeyCommand(0, 'z', Util.C.keyCollapseAllMessages()) {
- @Override
- public void onKeyPress(KeyPressEvent event) {
- onCollapseAll(null);
- }
- });
- if (Gerrit.isSignedIn()) {
- keysAction.add(new KeyCommand(0, 's', Util.C.changeTableStar()) {
- @Override
- public void onKeyPress(KeyPressEvent event) {
- star.setValue(!star.getValue(), true);
- }
- });
- keysAction.add(new KeyCommand(0, 'c', Util.C.keyAddReviewers()) {
- @Override
- public void onKeyPress(KeyPressEvent event) {
- reviewers.onOpenForm();
- }
- });
- }
}
private void initReplyButton(ChangeInfo info, String revision) {
@@ -403,7 +350,8 @@
}
}
- private void initRevisionsAction(ChangeInfo info, String revision) {
+ private void initRevisionsAction(ChangeInfo info, String revision,
+ NativeMap<ActionInfo> actions) {
int currentPatchSet;
if (info.current_revision() != null
&& info.revisions().containsKey(info.current_revision())) {
@@ -431,11 +379,6 @@
RevisionInfo revInfo = info.revision(revision);
if (revInfo.draft()) {
- NativeMap<ActionInfo> actions = revInfo.has_actions()
- ? revInfo.actions()
- : NativeMap.<ActionInfo> create();
- actions.copyKeysIntoChildren("id");
-
if (actions.containsKey("publish")) {
publish.setVisible(true);
publish.setTitle(actions.get("publish").title());
@@ -566,7 +509,88 @@
@Override
public void registerKeys() {
super.registerKeys();
+
+ KeyCommandSet keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
+ keysNavigation.add(new KeyCommand(0, 'u', Util.C.upToChangeList()) {
+ @Override
+ public void onKeyPress(final KeyPressEvent event) {
+ Gerrit.displayLastChangeList();
+ }
+ });
+ keysNavigation.add(new KeyCommand(0, 'R', Util.C.keyReloadChange()) {
+ @Override
+ public void onKeyPress(final KeyPressEvent event) {
+ Gerrit.display(PageLinks.toChange(changeId));
+ }
+ });
+ keysNavigation.add(new KeyCommand(0, 'n', Util.C.keyNextPatchSet()) {
+ @Override
+ public void onKeyPress(final KeyPressEvent event) {
+ gotoSibling(1);
+ }
+ }, new KeyCommand(0, 'p', Util.C.keyPreviousPatchSet()) {
+ @Override
+ public void onKeyPress(final KeyPressEvent event) {
+ gotoSibling(-1);
+ }
+ });
handlers.add(GlobalKey.add(this, keysNavigation));
+
+ KeyCommandSet keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
+ keysAction.add(new KeyCommand(0, 'a', Util.C.keyPublishComments()) {
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ if (Gerrit.isSignedIn()) {
+ onReply(null);
+ } else {
+ Gerrit.doSignIn(getToken());
+ }
+ }
+ });
+ keysAction.add(new KeyCommand(0, 'x', Util.C.keyExpandAllMessages()) {
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ onExpandAll(null);
+ }
+ });
+ keysAction.add(new KeyCommand(0, 'z', Util.C.keyCollapseAllMessages()) {
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ onCollapseAll(null);
+ }
+ });
+ keysAction.add(new KeyCommand(0, 's', Util.C.changeTableStar()) {
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ if (Gerrit.isSignedIn()) {
+ star.setValue(!star.getValue(), true);
+ } else {
+ Gerrit.doSignIn(getToken());
+ }
+ }
+ });
+ keysAction.add(new KeyCommand(0, 'c', Util.C.keyAddReviewers()) {
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ if (Gerrit.isSignedIn()) {
+ reviewers.onOpenForm();
+ } else {
+ Gerrit.doSignIn(getToken());
+ }
+ }
+ });
+ keysAction.add(new KeyCommand(0, 't', Util.C.keyEditTopic()) {
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ if (Gerrit.isSignedIn()) {
+ if (topic.canEdit()) {
+ topic.onEdit();
+ }
+ } else {
+ Gerrit.doSignIn(getToken());
+ }
+ }
+ });
handlers.add(GlobalKey.add(this, keysAction));
files.registerKeys();
}
@@ -806,6 +830,7 @@
commentLinkProcessor = result.getCommentLinkProcessor();
setTheme(result.getTheme());
renderChangeInfo(info);
+ loadRevisionInfo();
}
}));
}
@@ -933,7 +958,6 @@
private void loadSubmitType(final Change.Status status, final boolean canSubmit) {
if (canSubmit) {
- actions.setSubmitEnabled();
if (status == Change.Status.NEW) {
statusText.setInnerText(Util.C.readyToSubmit());
}
@@ -1043,19 +1067,7 @@
private void renderChangeInfo(ChangeInfo info) {
changeInfo = info;
lastDisplayedUpdate = info.updated();
- RevisionInfo revisionInfo = info.revision(revision);
- boolean current = info.status().isOpen()
- && revision.equals(info.current_revision())
- && !revisionInfo.is_edit();
- if (revisionInfo.is_edit()) {
- statusText.setInnerText(Util.C.changeEdit());
- } else if (!current && info.status() == Change.Status.NEW) {
- statusText.setInnerText(Util.C.notCurrent());
- labels.setVisible(false);
- } else {
- statusText.setInnerText(Util.toLongString(info.status()));
- }
labels.set(info);
renderOwner(info);
@@ -1064,7 +1076,6 @@
initReplyButton(info, revision);
initIncludedInAction(info);
initChangeAction(info);
- initRevisionsAction(info, revision);
initDownloadAction(info, revision);
initProjectLinks(info);
initBranchLink(info);
@@ -1084,17 +1095,44 @@
setVisible(hashtagTableRow, false);
}
+ StringBuilder sb = new StringBuilder();
+ sb.append(Util.M.changeScreenTitleId(info.id_abbreviated()));
+ if (info.subject() != null) {
+ sb.append(": ");
+ sb.append(info.subject());
+ }
+ setWindowTitle(sb.toString());
+
+ // Properly render revision actions initially while waiting for
+ // the callback to populate them correctly.
+ NativeMap<ActionInfo> emptyMap = NativeMap.<ActionInfo> create();
+ initRevisionsAction(info, revision, emptyMap);
+ quickApprove.setVisible(false);
+ setVisible(strategy, false);
+ actions.reloadRevisionActions(emptyMap);
+ }
+
+ private void renderRevisionInfo(ChangeInfo info,
+ NativeMap<ActionInfo> actionMap) {
+ RevisionInfo revisionInfo = info.revision(revision);
+ boolean current = info.status().isOpen()
+ && revision.equals(info.current_revision())
+ && !revisionInfo.is_edit();
+
+ if (revisionInfo.is_edit()) {
+ statusText.setInnerText(Util.C.changeEdit());
+ } else if (!current && info.status() == Change.Status.NEW) {
+ statusText.setInnerText(Util.C.notCurrent());
+ labels.setVisible(false);
+ } else {
+ statusText.setInnerText(Util.toLongString(info.status()));
+ }
+
+ initRevisionsAction(info, revision, actionMap);
+
if (Gerrit.isSignedIn()) {
replyAction = new ReplyAction(info, revision,
style, commentLinkProcessor, reply, quickApprove);
- if (topic.canEdit()) {
- keysAction.add(new KeyCommand(0, 't', Util.C.keyEditTopic()) {
- @Override
- public void onKeyPress(KeyPressEvent event) {
- topic.onEdit();
- }
- });
- }
}
history.set(commentLinkProcessor, replyAction, changeId, info);
@@ -1105,14 +1143,7 @@
quickApprove.setVisible(false);
setVisible(strategy, false);
}
-
- StringBuilder sb = new StringBuilder();
- sb.append(Util.M.changeScreenTitleId(info.id_abbreviated()));
- if (info.subject() != null) {
- sb.append(": ");
- sb.append(info.subject());
- }
- setWindowTitle(sb.toString());
+ actions.reloadRevisionActions(actionMap);
}
private void renderOwner(ChangeInfo info) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
index 98595e7..1135491 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
@@ -95,6 +95,13 @@
return call(id, "detail");
}
+ public static RestApi actions(int id, String revision) {
+ if (revision == null || revision.equals("")) {
+ revision = "current";
+ }
+ return call(id, revision, "actions");
+ }
+
public static void edit(int id, AsyncCallback<EditInfo> cb) {
edit(id).get(cb);
}
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 9d47977..c19c817 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.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 @@
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 @@
// 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 @@
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 @@
}
/** @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 1a2d3f6..1eb88b1 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
@@ -14,6 +14,8 @@
package com.google.gerrit.httpd;
+import com.google.common.io.ByteStreams;
+
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -21,14 +23,14 @@
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.InputStreamReader;
import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
import java.util.zip.GZIPOutputStream;
import javax.xml.parsers.DocumentBuilder;
@@ -36,7 +38,6 @@
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
@@ -49,21 +50,21 @@
/** Utility functions to deal with HTML using W3C DOM operations. */
public class HtmlDomUtil {
/** Standard character encoding we prefer (UTF-8). */
- public static final String ENC = "UTF-8";
+ public static final Charset ENC = StandardCharsets.UTF_8;
/** DOCTYPE for a standards mode HTML document. */
public static final String HTML_STRICT =
"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd";
/** Convert a document to a UTF-8 byte sequence. */
- public static byte[] toUTF8(final Document hostDoc) throws IOException {
+ public static byte[] toUTF8(Document hostDoc) throws IOException {
return toString(hostDoc).getBytes(ENC);
}
/** Compress the document. */
- public static byte[] compress(final byte[] raw) throws IOException {
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
- final GZIPOutputStream gz = new GZIPOutputStream(out);
+ public static byte[] compress(byte[] raw) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ GZIPOutputStream gz = new GZIPOutputStream(out);
gz.write(raw);
gz.finish();
gz.flush();
@@ -71,43 +72,39 @@
}
/** Convert a document to a String, assuming later encoding to UTF-8. */
- public static String toString(final Document hostDoc) throws IOException {
+ public static String toString(Document hostDoc) throws IOException {
try {
- final StringWriter out = new StringWriter();
- final DOMSource domSource = new DOMSource(hostDoc);
- final StreamResult streamResult = new StreamResult(out);
- final TransformerFactory tf = TransformerFactory.newInstance();
- final Transformer serializer = tf.newTransformer();
- serializer.setOutputProperty(OutputKeys.ENCODING, ENC);
+ StringWriter out = new StringWriter();
+ DOMSource domSource = new DOMSource(hostDoc);
+ StreamResult streamResult = new StreamResult(out);
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer serializer = tf.newTransformer();
+ serializer.setOutputProperty(OutputKeys.ENCODING, ENC.name());
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.setOutputProperty(OutputKeys.INDENT, "no");
serializer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
HtmlDomUtil.HTML_STRICT);
serializer.transform(domSource, streamResult);
return out.toString();
- } catch (TransformerConfigurationException e) {
- final IOException r = new IOException("Error transforming page");
- r.initCause(e);
- throw r;
} catch (TransformerException e) {
- final IOException r = new IOException("Error transforming page");
+ IOException r = new IOException("Error transforming page");
r.initCause(e);
throw r;
}
}
/** Find an element by its "id" attribute; null if no element is found. */
- public static Element find(final Node parent, final String name) {
- final NodeList list = parent.getChildNodes();
+ public static Element find(Node parent, String name) {
+ NodeList list = parent.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
- final Node n = list.item(i);
+ Node n = list.item(i);
if (n instanceof Element) {
- final Element e = (Element) n;
+ Element e = (Element) n;
if (name.equals(e.getAttribute("id"))) {
return e;
}
}
- final Element r = find(n, name);
+ Element r = find(n, name);
if (r != null) {
return r;
}
@@ -116,9 +113,8 @@
}
/** Append an HTML <input type="hidden"> to the form. */
- public static void addHidden(final Element form, final String name,
- final String value) {
- final Element in = form.getOwnerDocument().createElement("input");
+ public static void addHidden(Element form, String name, String value) {
+ Element in = form.getOwnerDocument().createElement("input");
in.setAttribute("type", "hidden");
in.setAttribute("name", name);
in.setAttribute("value", value);
@@ -135,51 +131,38 @@
}
/** Clone a document so it can be safely modified on a per-request basis. */
- public static Document clone(final Document doc) throws IOException {
- final Document d;
+ public static Document clone(Document doc) throws IOException {
+ Document d;
try {
d = newBuilder().newDocument();
} catch (ParserConfigurationException e) {
throw new IOException("Cannot clone document");
}
- final Node n = d.importNode(doc.getDocumentElement(), true);
+ Node n = d.importNode(doc.getDocumentElement(), true);
d.appendChild(n);
return d;
}
/** Parse an XHTML file from our CLASSPATH and return the instance. */
- public static Document parseFile(final Class<?> context, final String name)
+ public static Document parseFile(Class<?> context, String name)
throws IOException {
- final InputStream in;
-
- in = context.getResourceAsStream(name);
- if (in == null) {
- return null;
- }
- try {
- try {
- try {
- final Document doc = newBuilder().parse(in);
- compact(doc);
- return doc;
- } catch (SAXException e) {
- throw new IOException("Error reading " + name, e);
- } catch (ParserConfigurationException e) {
- throw new IOException("Error reading " + name, e);
- }
- } finally {
- in.close();
+ try (InputStream in = context.getResourceAsStream(name)) {
+ if (in == null) {
+ return null;
}
- } catch (IOException e) {
+ Document doc = newBuilder().parse(in);
+ compact(doc);
+ return doc;
+ } catch (SAXException | ParserConfigurationException | IOException e) {
throw new IOException("Error reading " + name, e);
}
}
- private static void compact(final Document doc) {
+ private static void compact(Document doc) {
try {
- final String expr = "//text()[normalize-space(.) = '']";
- final XPathFactory xp = XPathFactory.newInstance();
- final XPathExpression e = xp.newXPath().compile(expr);
+ String expr = "//text()[normalize-space(.) = '']";
+ XPathFactory xp = XPathFactory.newInstance();
+ XPathExpression e = xp.newXPath().compile(expr);
NodeList empty = (NodeList) e.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < empty.getLength(); i++) {
Node node = empty.item(i);
@@ -191,78 +174,50 @@
}
/** Read a Read a UTF-8 text file from our CLASSPATH and return it. */
- public static String readFile(final Class<?> context, final String name)
+ public static String readFile(Class<?> context, String name)
throws IOException {
- final InputStream in = context.getResourceAsStream(name);
- if (in == null) {
- return null;
- }
- try {
- return asString(in);
+ try (InputStream in = context.getResourceAsStream(name)) {
+ if (in == null) {
+ return null;
+ }
+ return new String(ByteStreams.toByteArray(in), ENC);
} catch (IOException e) {
throw new IOException("Error reading " + name, e);
}
}
/** Parse an XHTML file from the local drive and return the instance. */
- public static Document parseFile(final File path) throws IOException {
- try {
- final InputStream in = new FileInputStream(path);
- try {
- try {
- final Document doc = newBuilder().parse(in);
- compact(doc);
- return doc;
- } catch (SAXException e) {
- throw new IOException("Error reading " + path, e);
- } catch (ParserConfigurationException e) {
- throw new IOException("Error reading " + path, e);
- }
- } finally {
- in.close();
- }
- } catch (FileNotFoundException e) {
+ public static Document parseFile(Path path) throws IOException {
+ try (InputStream in = Files.newInputStream(path)) {
+ Document doc = newBuilder().parse(in);
+ compact(doc);
+ return doc;
+ } catch (NoSuchFileException e) {
return null;
- } catch (IOException e) {
+ } catch (SAXException | ParserConfigurationException | IOException e) {
throw new IOException("Error reading " + path, e);
}
}
/** Read a UTF-8 text file from the local drive. */
- public static String readFile(final File parentDir, final String name)
+ public static String readFile(Path parentDir, String name)
throws IOException {
if (parentDir == null) {
return null;
}
- final File path = new File(parentDir, name);
- try {
- return asString(new FileInputStream(path));
- } catch (FileNotFoundException e) {
+ Path path = parentDir.resolve(name);
+ try (InputStream in = Files.newInputStream(path)) {
+ return new String(ByteStreams.toByteArray(in), ENC);
+ } catch (NoSuchFileException e) {
return null;
} catch (IOException e) {
throw new IOException("Error reading " + path, e);
}
}
- private static String asString(final InputStream in)
- throws UnsupportedEncodingException, IOException {
- try {
- final StringBuilder w = new StringBuilder();
- final InputStreamReader r = new InputStreamReader(in, ENC);
- final char[] buf = new char[512];
- int n;
- while ((n = r.read(buf)) > 0) {
- w.append(buf, 0, n);
- }
- return w.toString();
- } finally {
- in.close();
- }
- }
-
private static DocumentBuilder newBuilder()
throws ParserConfigurationException {
- final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setExpandEntityReferences(false);
factory.setIgnoringComments(true);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
index b8a8092..ed84caf 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
@@ -104,7 +104,7 @@
throw new ServletException(e);
}
rsp.setContentType("text/html");
- rsp.setCharacterEncoding(HtmlDomUtil.ENC);
+ rsp.setCharacterEncoding(HtmlDomUtil.ENC.name());
rsp.setContentLength(raw.length);
final OutputStream out = rsp.getOutputStream();
try {
@@ -138,7 +138,7 @@
} else {
rsp.setContentType("text/html");
- rsp.setCharacterEncoding(HtmlDomUtil.ENC);
+ rsp.setCharacterEncoding(HtmlDomUtil.ENC.name());
final Writer out = rsp.getWriter();
out.write("<html>");
out.write("<body>");
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
index 19c8342..b5400b2 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
@@ -110,7 +110,7 @@
CacheHeaders.setNotCacheable(rsp);
rsp.setContentType("text/html");
- rsp.setCharacterEncoding(HtmlDomUtil.ENC);
+ rsp.setCharacterEncoding(HtmlDomUtil.ENC.name());
rsp.setContentLength(tosend.length);
final OutputStream out = rsp.getOutputStream();
try {
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 41aa552..3396f2b 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,19 @@
package com.google.gerrit.httpd.gitweb;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
+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.NoSuchFileException;
+import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletOutputStream;
@@ -38,16 +41,16 @@
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);
- } catch (FileNotFoundException e) {
+ try (InputStream in = Files.newInputStream(src)) {
+ png = ByteStreams.toByteArray(in);
+ } catch (NoSuchFileException e) {
png = null;
}
- modified = src.lastModified();
+ modified = lastModified(src);
} 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 4a39b97..5625334 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
@@ -14,6 +14,8 @@
package com.google.gerrit.httpd.gitweb;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
import com.google.gerrit.httpd.GitWebConfig;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.server.config.SitePaths;
@@ -22,8 +24,8 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletOutputStream;
@@ -55,14 +57,14 @@
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 = lastModified(src);
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 d71732a..6926afd 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,19 @@
package com.google.gerrit.httpd.gitweb;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
+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.NoSuchFileException;
+import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletOutputStream;
@@ -40,14 +43,14 @@
@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);
- } catch (FileNotFoundException e) {
+ try (InputStream in = Files.newInputStream(src)) {
+ png = ByteStreams.toByteArray(in);
+ } catch (NoSuchFileException e) {
png = null;
}
- modified = src.lastModified();
+ modified = lastModified(src);
} 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 9a7cab0..de619c3 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.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.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 @@
private final Set<String> 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
//
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 @@
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 @@
//
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/plugins/HttpPluginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java
index 31ff107..fd26837 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
@@ -14,6 +14,7 @@
package com.google.gerrit.httpd.plugins;
+import static com.google.gerrit.common.FileUtil.lastModified;
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CHARACTER_ENCODING;
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CONTENT_TYPE;
@@ -24,6 +25,7 @@
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 +57,14 @@
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 +305,7 @@
}
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 = lastModified(holder.plugin.getSrcFile());
if (hasUpToDateCachedResource(rsc, pluginLastModified)) {
rsc.send(req, res);
} else {
@@ -608,12 +610,12 @@
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 @@
}
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 @@
}
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-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 90c5ff4..1bc1125 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 com.google.gerrit.common.FileUtil.lastModified;
+
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.hash.Hasher;
@@ -47,12 +49,12 @@
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.util.ArrayList;
import java.util.List;
@@ -160,16 +162,13 @@
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;
}
@@ -216,7 +215,7 @@
CacheHeaders.setNotCacheable(rsp);
rsp.setContentType("text/html");
- rsp.setCharacterEncoding(HtmlDomUtil.ENC);
+ rsp.setCharacterEncoding(HtmlDomUtil.ENC.name());
rsp.setContentLength(tosend.length);
final OutputStream out = rsp.getOutputStream();
try {
@@ -288,16 +287,16 @@
}
private static class FileInfo {
- private final File path;
+ private final Path path;
private final long time;
- FileInfo(final File p) {
+ FileInfo(Path p) {
path = p;
- time = path.lastModified();
+ time = lastModified(path);
}
boolean isStale() {
- return time != path.lastModified();
+ return time != lastModified(path);
}
}
@@ -364,8 +363,8 @@
}
}
- 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 +375,8 @@
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 +385,8 @@
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/raw/LegacyGerritServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
index 9c267a8..00568f0 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
@@ -68,7 +68,7 @@
CacheHeaders.setNotCacheable(rsp);
rsp.setContentType("text/html");
- rsp.setCharacterEncoding(HtmlDomUtil.ENC);
+ rsp.setCharacterEncoding(HtmlDomUtil.ENC.name());
rsp.setContentLength(tosend.length);
final OutputStream out = rsp.getOutputStream();
try {
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 321f032..9c067de 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
@@ -14,6 +14,8 @@
package com.google.gerrit.httpd.template;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
import com.google.common.base.Strings;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.server.config.GerritServerConfig;
@@ -27,8 +29,8 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
@Singleton
public class SiteHeaderFooter {
@@ -43,13 +45,13 @@
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 {
@@ -118,8 +120,8 @@
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);
}
@@ -135,16 +137,16 @@
}
private static class FileInfo {
- final File path;
+ final Path path;
final long time;
- FileInfo(File p) {
+ FileInfo(Path p) {
path = p;
- time = path.lastModified();
+ time = lastModified(p);
}
boolean isStale() {
- return time != path.lastModified();
+ return time != lastModified(path);
}
}
}
diff --git a/gerrit-pgm/BUCK b/gerrit-pgm/BUCK
index 4b34629..763b7ae 100644
--- a/gerrit-pgm/BUCK
+++ b/gerrit-pgm/BUCK
@@ -125,6 +125,7 @@
':init-api',
':pgm',
'//gerrit-server:server',
+ '//lib:guava',
'//lib:junit',
'//lib/easymock:easymock',
'//lib/guice:guice',
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 7709b24..3f7d653 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
@@ -15,6 +15,7 @@
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;
@@ -92,10 +93,10 @@
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 +148,7 @@
private Injector sshInjector;
private Injector webInjector;
private Injector httpdInjector;
- private File runFile;
+ private Path runFile;
private boolean test;
private AbstractModule luceneModule;
@@ -183,7 +184,7 @@
});
if (runId != null) {
- runFile = new File(new File(getSitePath(), "logs"), "gerrit.run");
+ runFile = getSitePath().resolve("logs").resolve("gerrit.run");
}
if (httpd == null) {
@@ -207,7 +208,11 @@
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 +221,8 @@
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 29ab490..efc97f9 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 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 @@
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 @@
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()));
@@ -157,8 +157,8 @@
}
void startDaemon(SiteRun run) {
- final String[] argv = {run.site.gerrit_sh.getAbsolutePath(), "start"};
- final Process proc;
+ String[] argv = {run.site.gerrit_sh.toAbsolutePath().toString(), "start"};
+ Process proc;
try {
System.err.println("Executing " + argv[0] + " " + argv[1]);
proc = Runtime.getRuntime().exec(argv);
@@ -177,7 +177,7 @@
for (;;) {
try {
- final int rc = proc.waitFor();
+ int rc = proc.waitFor();
if (rc != 0) {
System.err.println("error: cannot start Gerrit: exit status " + rc);
}
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 f2feae1..ac84e82 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 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.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;
@@ -47,7 +48,7 @@
public class SwitchSecureStore extends SiteProgram {
private static String getSecureStoreClassFromGerritConfig(SitePaths sitePaths) {
FileBasedConfig cfg =
- new FileBasedConfig(sitePaths.gerrit_config, FS.DETECTED);
+ new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED);
try {
cfg.load();
} catch (IOException | ConfigInvalidException e) {
@@ -67,14 +68,14 @@
@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 @@
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 @@
migrateProperties(currentStore, newStore);
removeOldLib(sitePaths, currentSecureStoreName);
- copyNewLib(sitePaths, newSecureStoreFile);
+ copyNewLib(sitePaths, newSecureStorePath);
updateGerritConfig(sitePaths, newSecureStore);
@@ -123,14 +124,17 @@
}
}
- 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 @@
}
}
- 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)
@@ -151,13 +155,13 @@
log.info("Set gerrit.secureStoreClass property of gerrit.config to {}",
newSecureStore);
FileBasedConfig config =
- new FileBasedConfig(sitePaths.gerrit_config, FS.DETECTED);
+ new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED);
config.load();
config.setString("gerrit", null, "secureStoreClass", newSecureStore);
config.save();
}
- private String getNewSecureStoreClassName(File secureStore)
+ private String getNewSecureStoreClassName(Path secureStore)
throws IOException {
JarScanner scanner = new JarScanner(secureStore);
List<String> newSecureStores =
@@ -165,12 +169,12 @@
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 @@
}
}
- 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<Path> 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 c9e76c8..534ef050 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,9 +56,14 @@
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;
import java.util.Collections;
import java.util.Iterator;
@@ -86,12 +91,12 @@
this.pluginsToInstall = pluginsToInstall;
}
- public BaseInit(File sitePath, boolean standalone, boolean initDb,
+ public BaseInit(Path sitePath, boolean standalone, boolean initDb,
PluginsDistribution pluginsDistribution, List<String> pluginsToInstall) {
this(sitePath, null, standalone, initDb, pluginsDistribution, pluginsToInstall);
}
- public BaseInit(File sitePath, final Provider<DataSource> dsProvider,
+ public BaseInit(Path sitePath, final Provider<DataSource> dsProvider,
boolean standalone, boolean initDb,
PluginsDistribution pluginsDistribution, List<String> pluginsToInstall) {
super(sitePath, dsProvider);
@@ -132,7 +137,7 @@
throw failure;
}
- System.err.println("Initialized " + getSitePath().getCanonicalPath());
+ System.err.println("Initialized " + getSitePath().toRealPath().normalize());
afterInit(run);
return 0;
}
@@ -208,7 +213,7 @@
private SiteInit createSiteInit() {
final ConsoleUI ui = getConsoleUI();
- final File sitePath = getSitePath();
+ final Path sitePath = getSitePath();
final List<Module> m = new ArrayList<>();
final SecureStoreInitData secureStoreInitData = discoverSecureStoreClass();
final String currentSecureStoreClassName = getConfiguredSecureStoreClass();
@@ -228,7 +233,7 @@
@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<String> plugins =
MoreObjects.firstNonNull(
getInstallPlugins(), Lists.<String> newArrayList());
@@ -287,8 +292,8 @@
}
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));
}
@@ -408,15 +413,41 @@
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<Path>() {
+ @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/InitContainer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java
index f830854..60ff665 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java
@@ -17,6 +17,7 @@
import static com.google.gerrit.pgm.init.api.InitUtil.die;
import static com.google.gerrit.pgm.init.api.InitUtil.username;
+import com.google.common.io.ByteStreams;
import com.google.gerrit.launcher.GerritLauncher;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitStep;
@@ -28,11 +29,12 @@
import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.util.FS;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
/** Initialize the {@code container} configuration section. */
@Singleton
@@ -56,9 +58,9 @@
container.string("Run as", "user", username());
container.string("Java runtime", "javaHome", javaHome());
- File myWar;
+ Path myWar;
try {
- myWar = GerritLauncher.getDistributionArchive();
+ myWar = GerritLauncher.getDistributionArchive().toPath();
} catch (FileNotFoundException e) {
System.err.println("warn: Cannot find distribution archive (e.g. gerrit.war)");
myWar = null;
@@ -66,53 +68,41 @@
String path = container.get("war");
if (path != null) {
- path = container.string("Gerrit runtime", "war", //
- myWar != null ? myWar.getAbsolutePath() : null);
+ path = container.string("Gerrit runtime", "war",
+ myWar != null ? myWar.toAbsolutePath().toString() : null);
if (path == null || path.isEmpty()) {
throw die("container.war is required");
}
} else if (myWar != null) {
final boolean copy;
- final File siteWar = site.gerrit_war;
- if (siteWar.exists()) {
- copy = ui.yesno(true, "Upgrade %s", siteWar.getPath());
+ final Path siteWar = site.gerrit_war;
+ if (Files.exists(siteWar)) {
+ copy = ui.yesno(true, "Upgrade %s", siteWar);
} else {
- copy = ui.yesno(true, "Copy %s to %s", myWar.getName(), siteWar.getPath());
+ copy = ui.yesno(true, "Copy %s to %s", myWar.getFileName(), siteWar);
if (copy) {
container.unset("war");
} else {
- container.set("war", myWar.getAbsolutePath());
+ container.set("war", myWar.toAbsolutePath().toString());
}
}
if (copy) {
if (!ui.isBatch()) {
- System.err.format("Copying %s to %s", myWar.getName(), siteWar.getPath());
+ System.err.format("Copying %s to %s", myWar.getFileName(), siteWar);
System.err.println();
}
- FileInputStream in = new FileInputStream(myWar);
- try {
- siteWar.getParentFile().mkdirs();
+ try (InputStream in = Files.newInputStream(myWar)) {
+ Files.createDirectories(siteWar.getParent());
- LockFile lf = new LockFile(siteWar, FS.DETECTED);
+ LockFile lf = new LockFile(siteWar.toFile(), FS.DETECTED);
if (!lf.lock()) {
throw new IOException("Cannot lock " + siteWar);
}
-
try {
- final OutputStream out = lf.getOutputStream();
- try {
- final byte[] tmp = new byte[4096];
- for (;;) {
- int n = in.read(tmp);
- if (n < 0) {
- break;
- }
- out.write(tmp, 0, n);
- }
- } finally {
- out.close();
+ try (OutputStream out = lf.getOutputStream()) {
+ ByteStreams.copy(in, out);
}
if (!lf.commit()) {
throw new IOException("Cannot commit " + siteWar);
@@ -120,8 +110,6 @@
} finally {
lf.unlock();
}
- } finally {
- in.close();
}
}
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
index c8f1cd7..bf373ea 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
@@ -29,10 +29,11 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
/** Initialize the {@code httpd} configuration section. */
@Singleton
@@ -149,8 +150,9 @@
return;
}
- final File store = site.ssl_keystore;
- if (!ui.yesno(!store.exists(), "Create new self-signed SSL certificate")) {
+ Path store = site.ssl_keystore;
+ if (!ui.yesno(!Files.exists(store),
+ "Create new self-signed SSL certificate")) {
return;
}
@@ -167,15 +169,17 @@
final String dname =
"CN=" + hostname + ",OU=Gerrit Code Review,O=" + domainOf(hostname);
- final File tmpdir = new File(site.etc_dir, "tmp.sslcertgen");
- if (!tmpdir.mkdir()) {
- throw die("Cannot create directory " + tmpdir);
+ Path tmpdir = site.etc_dir.resolve("tmp.sslcertgen");
+ try {
+ Files.createDirectory(tmpdir);
+ } catch (IOException e) {
+ throw die("Cannot create directory " + tmpdir, e);
}
chmod(0600, tmpdir);
- final File tmpstore = new File(tmpdir, "keystore");
+ Path tmpstore = tmpdir.resolve("keystore");
Runtime.getRuntime().exec(new String[] {"keytool", //
- "-keystore", tmpstore.getAbsolutePath(), //
+ "-keystore", tmpstore.toAbsolutePath().toString(), //
"-storepass", ssl_pass, //
"-genkeypair", //
"-alias", hostname, //
@@ -186,11 +190,15 @@
}).waitFor();
chmod(0600, tmpstore);
- if (!tmpstore.renameTo(store)) {
- throw die("Cannot rename " + tmpstore + " to " + store);
+ try {
+ Files.move(tmpstore, store);
+ } catch (IOException e) {
+ throw die("Cannot rename " + tmpstore + " to " + store, e);
}
- if (!tmpdir.delete()) {
- throw die("Cannot delete " + tmpdir);
+ try {
+ Files.delete(tmpdir);
+ } catch (IOException e) {
+ throw die("Cannot delete " + tmpdir, e);
}
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java
index 893f00d..2cffe42 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java
@@ -15,6 +15,7 @@
package com.google.gerrit.pgm.init;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.Ordering;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitStep;
@@ -26,23 +27,22 @@
import com.google.inject.Injector;
import com.google.inject.Singleton;
-import java.io.File;
-import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
@Singleton
public class InitPluginStepsLoader {
- private final File pluginsDir;
+ private final Path pluginsDir;
private final Injector initInjector;
final ConsoleUI ui;
@@ -55,10 +55,10 @@
}
public Collection<InitStep> getInitSteps() {
- List<File> jars = scanJarsInPluginsDirectory();
+ List<Path> jars = scanJarsInPluginsDirectory();
ArrayList<InitStep> pluginsInitSteps = new ArrayList<>();
- for (File jar : jars) {
+ for (Path jar : jars) {
InitStep init = loadInitStep(jar);
if (init != null) {
pluginsInitSteps.add(init);
@@ -68,12 +68,12 @@
}
@SuppressWarnings("resource")
- private InitStep loadInitStep(File jar) {
+ private InitStep loadInitStep(Path jar) {
try {
URLClassLoader pluginLoader =
- new URLClassLoader(new URL[] {jar.toURI().toURL()},
+ new URLClassLoader(new URL[] {jar.toUri().toURL()},
InitPluginStepsLoader.class.getClassLoader());
- try (JarFile jarFile = new JarFile(jar)) {
+ try (JarFile jarFile = new JarFile(jar.toFile())) {
Attributes jarFileAttributes = jarFile.getManifest().getMainAttributes();
String initClassName = jarFileAttributes.getValue("Gerrit-InitStep");
if (initClassName == null) {
@@ -86,7 +86,7 @@
} catch (ClassCastException e) {
ui.message(
"WARN: InitStep from plugin %s does not implement %s (Exception: %s)",
- jar.getName(), InitStep.class.getName(), e.getMessage());
+ jar.getFileName(), InitStep.class.getName(), e.getMessage());
return null;
}
} catch (Exception e) {
@@ -97,11 +97,10 @@
}
}
- private Injector getPluginInjector(final File jarFile) throws IOException {
- final String pluginName =
- MoreObjects.firstNonNull(
- JarPluginProvider.getJarPluginName(jarFile),
- PluginLoader.nameOf(jarFile));
+ private Injector getPluginInjector(Path jarPath) throws IOException {
+ final String pluginName = MoreObjects.firstNonNull(
+ JarPluginProvider.getJarPluginName(jarPath),
+ PluginLoader.nameOf(jarPath));
return initInjector.createChildInjector(new AbstractModule() {
@Override
protected void configure() {
@@ -111,27 +110,24 @@
});
}
- private List<File> scanJarsInPluginsDirectory() {
- if (pluginsDir == null || !pluginsDir.exists()) {
+ private List<Path> scanJarsInPluginsDirectory() {
+ if (pluginsDir == null || !Files.isDirectory(pluginsDir)) {
return Collections.emptyList();
}
- File[] matches = pluginsDir.listFiles(new FileFilter() {
+ DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
- public boolean accept(File pathname) {
- String n = pathname.getName();
- return (n.endsWith(".jar") && pathname.isFile());
+ public boolean accept(Path entry) throws IOException {
+ return entry.getFileName().toString().endsWith(".jar")
+ && Files.isRegularFile(entry);
}
- });
- if (matches == null) {
- ui.message("WARN: Cannot list %s", pluginsDir.getAbsolutePath());
+ };
+ try (DirectoryStream<Path> paths =
+ Files.newDirectoryStream(pluginsDir, filter)) {
+ return Ordering.natural().sortedCopy(paths);
+ } catch (IOException e) {
+ ui.message("WARN: Cannot list %s: %s", pluginsDir.toAbsolutePath(),
+ e.getMessage());
return Collections.emptyList();
}
- Arrays.sort(matches, new Comparator<File>() {
- @Override
- public int compare(File o1, File o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
- return Arrays.asList(matches);
}
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java
index cc076b5..ca4b949 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java
@@ -25,9 +25,10 @@
import com.google.inject.Injector;
import com.google.inject.Singleton;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
@@ -55,10 +56,10 @@
pluginsDistribution.foreach(new PluginsDistribution.Processor() {
@Override
public void process(String pluginName, InputStream in) throws IOException {
- File tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site);
+ Path tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site);
String pluginVersion = getVersion(tmpPlugin);
if (deleteTempPluginFile) {
- tmpPlugin.delete();
+ Files.delete(tmpPlugin);
}
result.add(new PluginData(pluginName, pluginVersion, tmpPlugin));
}
@@ -108,37 +109,39 @@
for (PluginData plugin : plugins) {
String pluginName = plugin.name;
try {
- final File tmpPlugin = plugin.pluginFile;
+ final Path tmpPlugin = plugin.pluginPath;
if (!(initFlags.installPlugins.contains(pluginName) || ui.yesno(false,
"Install plugin %s version %s", pluginName, plugin.version))) {
- tmpPlugin.delete();
+ Files.deleteIfExists(tmpPlugin);
continue;
}
- final File p = new File(site.plugins_dir, plugin.name + ".jar");
- if (p.exists()) {
+ final Path p = site.plugins_dir.resolve(plugin.name + ".jar");
+ if (Files.exists(p)) {
final String installedPluginVersion = getVersion(p);
if (!ui.yesno(false,
"version %s is already installed, overwrite it",
installedPluginVersion)) {
- tmpPlugin.delete();
+ Files.deleteIfExists(tmpPlugin);
continue;
}
- if (!p.delete()) {
+ try {
+ Files.delete(p);
+ } catch (IOException e) {
throw new IOException("Failed to delete plugin " + pluginName
- + ": " + p.getAbsolutePath());
+ + ": " + p.toAbsolutePath(), e);
}
}
- if (!tmpPlugin.renameTo(p)) {
+ try {
+ Files.move(tmpPlugin, p);
+ } catch (IOException e) {
throw new IOException("Failed to install plugin " + pluginName
- + ": " + tmpPlugin.getAbsolutePath() + " -> "
- + p.getAbsolutePath());
+ + ": " + tmpPlugin.toAbsolutePath() + " -> "
+ + p.toAbsolutePath(), e);
}
} finally {
- if (plugin.pluginFile.exists()) {
- plugin.pluginFile.delete();
- }
+ Files.deleteIfExists(plugin.pluginPath);
}
}
if (plugins.isEmpty()) {
@@ -159,11 +162,11 @@
}
}
- private static String getVersion(final File plugin) throws IOException {
- final JarFile jarFile = new JarFile(plugin);
+ private static String getVersion(Path plugin) throws IOException {
+ JarFile jarFile = new JarFile(plugin.toFile());
try {
- final Manifest manifest = jarFile.getManifest();
- final Attributes main = manifest.getMainAttributes();
+ Manifest manifest = jarFile.getManifest();
+ Attributes main = manifest.getMainAttributes();
return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
} finally {
jarFile.close();
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java
index 51eaa22..5c7eefd 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java
@@ -25,6 +25,8 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import java.nio.file.Files;
+
/** Initialize the {@code sendemail} configuration section. */
@Singleton
class InitSendEmail implements InitStep {
@@ -54,7 +56,7 @@
true);
String username = null;
- if (site.gerrit_config.exists()) {
+ if (Files.exists(site.gerrit_config)) {
username = sendemail.get("smtpUser");
} else if ((enc != null && enc != Encryption.NONE) || !isLocal(hostname)) {
username = username();
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java
index ed18d73..c654c8d 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java
@@ -17,6 +17,7 @@
import static com.google.gerrit.common.FileUtil.chmod;
import static com.google.gerrit.pgm.init.api.InitUtil.die;
import static com.google.gerrit.pgm.init.api.InitUtil.hostname;
+import static java.nio.file.Files.exists;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitStep;
@@ -29,9 +30,10 @@
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
-import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Path;
/** Initialize the {@code sshd} configuration section. */
@Singleton
@@ -74,9 +76,9 @@
port = ui.readInt(port, "Listen on port");
sshd.set("listenAddress", SocketUtil.format(hostname, port));
- if (site.ssh_rsa.exists() || site.ssh_dsa.exists()) {
+ if (exists(site.ssh_rsa) || exists(site.ssh_dsa)) {
libraries.bouncyCastleSSL.downloadRequired();
- } else if (!site.ssh_key.exists()) {
+ } else if (!exists(site.ssh_key)) {
libraries.bouncyCastleSSL.downloadOptional();
}
@@ -90,9 +92,9 @@
}
private void generateSshHostKeys() throws InterruptedException, IOException {
- if (!site.ssh_key.exists() //
- && !site.ssh_rsa.exists() //
- && !site.ssh_dsa.exists()) {
+ if (!exists(site.ssh_key) //
+ && !exists(site.ssh_rsa) //
+ && !exists(site.ssh_dsa)) {
System.err.print("Generating SSH host key ...");
System.err.flush();
@@ -108,7 +110,7 @@
"-t", "rsa", //
"-P", "", //
"-C", comment, //
- "-f", site.ssh_rsa.getAbsolutePath() //
+ "-f", site.ssh_rsa.toAbsolutePath().toString() //
}).waitFor();
System.err.print(" dsa...");
@@ -118,7 +120,7 @@
"-t", "dsa", //
"-P", "", //
"-C", comment, //
- "-f", site.ssh_dsa.getAbsolutePath() //
+ "-f", site.ssh_dsa.toAbsolutePath().toString() //
}).waitFor();
} else {
@@ -128,28 +130,34 @@
// short period of time. We try to reduce that risk by creating
// the key within a temporary directory.
//
- final File tmpdir = new File(site.etc_dir, "tmp.sshkeygen");
- if (!tmpdir.mkdir()) {
- throw die("Cannot create directory " + tmpdir);
+ Path tmpdir = site.etc_dir.resolve("tmp.sshkeygen");
+ try {
+ Files.createDirectory(tmpdir);
+ } catch (IOException e) {
+ throw die("Cannot create directory " + tmpdir, e);
}
chmod(0600, tmpdir);
- final File tmpkey = new File(tmpdir, site.ssh_key.getName());
- final SimpleGeneratorHostKeyProvider p;
+ Path tmpkey = tmpdir.resolve(site.ssh_key.getFileName().toString());
+ SimpleGeneratorHostKeyProvider p;
System.err.print(" rsa(simple)...");
System.err.flush();
p = new SimpleGeneratorHostKeyProvider();
- p.setPath(tmpkey.getAbsolutePath());
+ p.setPath(tmpkey.toAbsolutePath().toString());
p.setAlgorithm("RSA");
p.loadKeys(); // forces the key to generate.
chmod(0600, tmpkey);
- if (!tmpkey.renameTo(site.ssh_key)) {
- throw die("Cannot rename " + tmpkey + " to " + site.ssh_key);
+ try {
+ Files.move(tmpkey, site.ssh_key);
+ } catch (IOException e) {
+ throw die("Cannot rename " + tmpkey + " to " + site.ssh_key, e);
}
- if (!tmpdir.delete()) {
- throw die("Cannot delete " + tmpdir);
+ try {
+ Files.delete(tmpdir);
+ } catch (IOException e) {
+ throw die("Cannot delete " + tmpdir, e);
}
}
System.err.println(" done");
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 4bf1c88..5863d48 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.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 @@
private String remove;
private List<LibraryDownloader> needs;
private LibraryDownloader neededBy;
- private File dst;
+ private Path dst;
private boolean download; // download or copy
private boolean exists;
@@ -118,8 +118,8 @@
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 @@
}
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 @@
}
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 @@
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 @@
}
}
- if (dst.exists()) {
+ if (Files.exists(dst)) {
exists = true;
IoUtil.loadJARs(dst);
}
@@ -208,19 +216,27 @@
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<Path> paths;
+ try {
+ paths = Files.newDirectoryStream(lib_dir,
+ new DirectoryStream.Filter<Path>() {
+ @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 @@
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 8926759..49877dc 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 10c9bad..f867829 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.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 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 @@
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);
@@ -141,7 +143,7 @@
private void extractMailExample(String orig) throws Exception {
File ex = new File(site.mail_dir, orig + ".example");
- extract(ex, OutgoingEmail.class, orig);
+ extract(ex.toPath(), OutgoingEmail.class, orig);
chmod(0444, ex);
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java
index 8c13540..46f87ee 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java
@@ -37,6 +37,8 @@
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
@@ -65,7 +67,7 @@
private final FileBasedConfig cfg;
private final SecureStore sec;
private final File site_path;
- private final File etc_dir;
+ private final Path etc_dir;
private final Section.Factory sections;
@Inject
@@ -100,14 +102,16 @@
}
for (String name : etcFiles) {
- final File src = new File(site_path, name);
- final File dst = new File(etc_dir, name);
- if (src.exists()) {
- if (dst.exists()) {
+ Path src = site_path.toPath().resolve(name);
+ Path dst = etc_dir.resolve(name);
+ if (Files.exists(src)) {
+ if (Files.exists(dst)) {
throw die("File " + src + " would overwrite " + dst);
}
- if (!src.renameTo(dst)) {
- throw die("Cannot rename " + src + " to " + dst);
+ try {
+ Files.move(src, dst);
+ } catch (IOException e) {
+ throw die("Cannot rename " + src + " to " + dst, e);
}
}
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java
index 2a8155e..07137bc 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java
@@ -51,7 +51,7 @@
ConfigInvalidException {
sec = secureStore;
this.installPlugins = installPlugins;
- cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED);
+ cfg = new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
cfg.load();
}
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 881208d..904af2f 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
@@ -16,14 +16,15 @@
import static com.google.gerrit.common.FileUtil.modified;
+import com.google.common.io.ByteStreams;
import com.google.gerrit.common.Die;
import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
-import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.SystemReader;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -33,7 +34,10 @@
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.NoSuchFileException;
+import java.nio.file.Path;
+import java.util.Arrays;
/** Utility functions to help initialize a site. */
public class InitUtil {
@@ -51,9 +55,18 @@
}
}
- 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);
}
}
@@ -109,12 +122,11 @@
return name;
}
- public static void extract(final File dst, final Class<?> sibling,
- final String name) throws IOException {
+ public static void extract(Path dst, Class<?> sibling, String name)
+ throws IOException {
try (InputStream in = open(sibling, name)) {
if (in != null) {
- ByteBuffer buf = IO.readWholeStream(in, 8192);
- copy(dst, buf);
+ copy(dst, ByteStreams.toByteArray(in));
}
}
}
@@ -136,35 +148,28 @@
return in;
}
- public static void copy(final File dst, final ByteBuffer buf)
+ public static void copy(Path dst, byte[] buf)
throws FileNotFoundException, IOException {
// If the file already has the content we want to put there,
// don't attempt to overwrite the file.
//
- try {
- if (buf.equals(ByteBuffer.wrap(IO.readFully(dst)))) {
+ try (InputStream in = Files.newInputStream(dst)) {
+ if (Arrays.equals(buf, ByteStreams.toByteArray(in))) {
return;
}
- } catch (FileNotFoundException notFound) {
+ } catch (NoSuchFileException notFound) {
// Fall through and write the file.
}
- dst.getParentFile().mkdirs();
- LockFile lf = new LockFile(dst, FS.DETECTED);
+ Files.createDirectories(dst.getParent());
+ LockFile lf = new LockFile(dst.toFile(), FS.DETECTED);
if (!lf.lock()) {
throw new IOException("Cannot lock " + dst);
}
try {
- final OutputStream out = lf.getOutputStream();
- try {
- final byte[] tmp = new byte[4096];
- while (0 < buf.remaining()) {
- int n = Math.min(buf.remaining(), tmp.length);
- buf.get(tmp, 0, n);
- out.write(tmp, 0, n);
- }
- } finally {
- out.close();
+ try (InputStream in = new ByteArrayInputStream(buf);
+ OutputStream out = lf.getOutputStream()) {
+ ByteStreams.copy(in, out);
}
if (!lf.commit()) {
throw new IOException("Cannot commit " + dst);
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 a766d1e..3b1714e 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
@@ -14,7 +14,7 @@
package com.google.gerrit.pgm.util;
-import com.google.gerrit.common.Die;
+import com.google.gerrit.common.FileUtil;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.util.SystemLog;
@@ -25,8 +25,8 @@
import org.apache.log4j.Logger;
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,12 +47,10 @@
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()) {
- throw new Die("Cannot create log directory: " + logdir);
- }
+ Path logdir = FileUtil.mkdirsOrDie(new SitePaths(sitePath).logs_dir,
+ "Cannot create log directory");
if (SystemLog.shouldConfigure()) {
initLogSystem(logdir);
}
@@ -69,7 +67,7 @@
};
}
- private static void initLogSystem(final File logdir) {
+ private static void initLogSystem(Path logdir) {
final Logger root = LogManager.getRootLogger();
root.removeAllAppenders();
root.addAppender(SystemLog.createAppender(logdir, LOG_NAME,
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 7d33a36..3d2b8e1 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
@@ -14,7 +14,7 @@
package com.google.gerrit.pgm.util;
-import com.google.gerrit.common.Die;
+import com.google.gerrit.common.FileUtil;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GarbageCollection;
@@ -24,17 +24,14 @@
import org.apache.log4j.Logger;
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()) {
- throw new Die("Cannot create log directory: " + logdir);
- }
+ Path logdir = FileUtil.mkdirsOrDie(new SitePaths(sitePath).logs_dir,
+ "Cannot create log directory");
if (SystemLog.shouldConfigure()) {
initLogSystem(logdir);
}
@@ -51,7 +48,7 @@
};
}
- private static void initLogSystem(File logdir) {
+ private static void initLogSystem(Path logdir) {
Logger gcLogger = LogManager.getLogger(GarbageCollection.LOG_NAME);
gcLogger.removeAllAppenders();
gcLogger.addAppender(SystemLog.createAppender(logdir,
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java
index db74ac3..1107208 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java
@@ -16,6 +16,7 @@
import static java.util.concurrent.TimeUnit.HOURS;
+import com.google.common.io.ByteStreams;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.SitePaths;
@@ -25,12 +26,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.zip.GZIPOutputStream;
/** Compresses the old error logs. */
@@ -65,76 +66,78 @@
}
}
- private final File logs_dir;
+ private final Path logs_dir;
@Inject
LogFileCompressor(final SitePaths site) {
logs_dir = resolve(site.logs_dir);
}
- private static File resolve(final File logs_dir) {
+ private static Path resolve(Path p) {
try {
- return logs_dir.getCanonicalFile();
+ return p.toRealPath().normalize();
} catch (IOException e) {
- return logs_dir.getAbsoluteFile();
+ return p.toAbsolutePath().normalize();
}
}
@Override
public void run() {
- final File[] list = logs_dir.listFiles();
- if (list == null) {
+ if (!Files.isDirectory(logs_dir)) {
return;
}
-
- for (final File entry : list) {
- if (!isLive(entry) && !isCompressed(entry) && isLogFile(entry)) {
- compress(entry);
+ try (DirectoryStream<Path> list = Files.newDirectoryStream(logs_dir)) {
+ for (Path entry : list) {
+ if (!isLive(entry) && !isCompressed(entry) && isLogFile(entry)) {
+ compress(entry);
+ }
}
+ } catch (IOException e) {
+ log.error("Error listing logs to compress in " + logs_dir, e);
}
}
- private boolean isLive(final File entry) {
- final String name = entry.getName();
+ private boolean isLive(Path entry) {
+ String name = entry.getFileName().toString();
return name.endsWith("_log")
|| name.endsWith(".log")
|| name.endsWith(".run")
|| name.endsWith(".pid");
}
- private boolean isCompressed(final File entry) {
- final String name = entry.getName();
+ private boolean isCompressed(Path entry) {
+ String name = entry.getFileName().toString();
return name.endsWith(".gz") //
|| name.endsWith(".zip") //
|| name.endsWith(".bz2");
}
- private boolean isLogFile(final File entry) {
- return entry.isFile();
+ private boolean isLogFile(Path entry) {
+ return Files.isRegularFile(entry);
}
- private void compress(final File src) {
- final File dir = src.getParentFile();
- final File dst = new File(dir, src.getName() + ".gz");
- final File tmp = new File(dir, ".tmp." + src.getName());
+ private void compress(Path src) {
+ Path dst = src.resolveSibling(src.getFileName() + ".gz");
+ Path tmp = src.resolveSibling(".tmp." + src.getFileName());
try {
- try (InputStream in = new FileInputStream(src);
- FileOutputStream fo = new FileOutputStream(tmp);
- OutputStream out = new GZIPOutputStream(fo)) {
- final byte[] buf = new byte[2048];
- int n;
- while (0 < (n = in.read(buf))) {
- out.write(buf, 0, n);
- }
- tmp.setReadOnly();
+ try (InputStream in = Files.newInputStream(src);
+ OutputStream out = new GZIPOutputStream(Files.newOutputStream(tmp))) {
+ ByteStreams.copy(in, out);
}
- if (!tmp.renameTo(dst)) {
- throw new IOException("Cannot rename " + tmp + " to " + dst);
+ tmp.toFile().setReadOnly();
+ try {
+ Files.move(tmp, dst);
+ } catch (IOException e) {
+ throw new IOException("Cannot rename " + tmp + " to " + dst, e);
}
- src.delete();
+ Files.delete(src);
} catch (IOException e) {
log.error("Cannot compress " + src, e);
- tmp.delete();
+ try {
+ Files.deleteIfExists(tmp);
+ } catch (IOException e2) {
+ log.warn("Failed to delete temporary log file " + tmp, e2);
+ }
}
}
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 c713b79..048c2ee 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 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-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 02a8eac..010ea75 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.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 @@
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<DataSource> dsProvider;
+ private Path sitePath;
+
protected SiteProgram() {
}
- protected SiteProgram(File sitePath, final Provider<DataSource> dsProvider) {
+ protected SiteProgram(Path sitePath, final Provider<DataSource> 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 @@
/** @return provides database connectivity and site path. */
protected Injector createDbInjector(final DataSourceProvider.Context context) {
- final File sitePath = getSitePath();
+ final Path sitePath = getSitePath();
final List<Module> 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,13 +193,14 @@
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);
}
};
Injector i = Guice.createInjector(m);
SitePaths site = i.getInstance(SitePaths.class);
- FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED);
+ FileBasedConfig cfg =
+ new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
if (!cfg.getFile().exists()) {
return null;
}
@@ -222,7 +225,7 @@
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 4d7370b..150309e 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 @@
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 a37c97d..7b08902 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 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 720d108..bb2fb94 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,7 @@
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;
@@ -24,6 +25,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import com.google.common.io.ByteStreams;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.Section;
@@ -34,13 +36,12 @@
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
-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.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
@@ -49,23 +50,18 @@
@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());
+ Files.createDirectory(site.etc_dir);
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 +81,11 @@
}
};
- 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);
@@ -98,11 +97,14 @@
for (String n : UpgradeFrom2_0_x.etcFiles) {
if ("gerrit.config".equals(n)) continue;
if ("secure.config".equals(n)) continue;
- assertEquals("# " + n + "\n",//
- new String(IO.readFully(new File(site.etc_dir, n)), "UTF-8"));
+ try (InputStream in = Files.newInputStream(site.etc_dir.resolve(n))) {
+ assertEquals("# " + n + "\n",
+ new String(ByteStreams.toByteArray(in), UTF_8));
+ }
}
- FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED);
+ FileBasedConfig cfg =
+ new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
cfg.load();
assertEquals("email.user", cfg.getString("sendemail", null, "smtpUser"));
diff --git a/gerrit-plugin-api/pom.xml b/gerrit-plugin-api/pom.xml
index 40767e0..eb2ec31 100644
--- a/gerrit-plugin-api/pom.xml
+++ b/gerrit-plugin-api/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-api</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Plugin API</name>
<description>API for Gerrit Plugins</description>
diff --git a/gerrit-plugin-archetype/pom.xml b/gerrit-plugin-archetype/pom.xml
index b117b29..1da5d51 100644
--- a/gerrit-plugin-archetype/pom.xml
+++ b/gerrit-plugin-archetype/pom.xml
@@ -20,7 +20,7 @@
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-archetype</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<name>Gerrit Code Review - Plugin Archetype</name>
<description>Maven Archetype for Gerrit Plugins</description>
<url>http://code.google.com/p/gerrit/</url>
diff --git a/gerrit-plugin-gwt-archetype/pom.xml b/gerrit-plugin-gwt-archetype/pom.xml
index a7f2bbf..bd4d738 100644
--- a/gerrit-plugin-gwt-archetype/pom.xml
+++ b/gerrit-plugin-gwt-archetype/pom.xml
@@ -20,7 +20,7 @@
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-gwt-archetype</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<name>Gerrit Code Review - Web UI GWT Plugin Archetype</name>
<description>Maven Archetype for Gerrit Web UI GWT Plugins</description>
<url>http://code.google.com/p/gerrit/</url>
diff --git a/gerrit-plugin-gwtui/pom.xml b/gerrit-plugin-gwtui/pom.xml
index fd6fc9b..fa261be 100644
--- a/gerrit-plugin-gwtui/pom.xml
+++ b/gerrit-plugin-gwtui/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-gwtui</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Plugin GWT UI</name>
<description>Common Classes for Gerrit GWT UI Plugins</description>
diff --git a/gerrit-plugin-js-archetype/pom.xml b/gerrit-plugin-js-archetype/pom.xml
index 796df19..11d4d83 100644
--- a/gerrit-plugin-js-archetype/pom.xml
+++ b/gerrit-plugin-js-archetype/pom.xml
@@ -20,7 +20,7 @@
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-js-archetype</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<name>Gerrit Code Review - Web UI JavaScript Plugin Archetype</name>
<description>Maven Archetype for Gerrit Web UI JavaScript Plugins</description>
<url>http://code.google.com/p/gerrit/</url>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java
index 07936d9..d181c35 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java
@@ -39,7 +39,7 @@
import java.util.List;
import java.util.Map;
-class SuggestAccounts implements RestReadView<TopLevelResource> {
+public class SuggestAccounts implements RestReadView<TopLevelResource> {
private static final int MAX_RESULTS = 100;
private static final String MAX_SUFFIX = "\u9fa5";
@@ -50,9 +50,10 @@
private final int suggestFrom;
private int limit = 10;
+ private String query;
@Option(name = "--limit", aliases = {"-n"}, metaVar = "CNT", usage = "maximum number of users to return")
- void setLimit(int n) {
+ public void setLimit(int n) {
if (n < 0) {
limit = 10;
} else if (n == 0) {
@@ -63,7 +64,9 @@
}
@Option(name = "--query", aliases = {"-q"}, metaVar = "QUERY", usage = "match users")
- private String query;
+ public void setQuery(String query) {
+ this.query = query;
+ }
@Inject
SuggestAccounts(AccountControl.Factory accountControlFactory,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
index 0c02c99..cf041fd4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
@@ -16,6 +16,7 @@
import com.google.gerrit.extensions.api.accounts.AccountApi;
import com.google.gerrit.extensions.api.accounts.Accounts;
+import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -24,24 +25,30 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.AccountsCollection;
+import com.google.gerrit.server.account.SuggestAccounts;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import java.util.List;
+
@Singleton
public class AccountsImpl extends Accounts.NotImplemented implements Accounts {
private final AccountsCollection accounts;
private final AccountApiImpl.Factory api;
private final Provider<CurrentUser> self;
+ private final Provider<SuggestAccounts> suggestAccountsProvider;
@Inject
AccountsImpl(AccountsCollection accounts,
AccountApiImpl.Factory api,
- Provider<CurrentUser> self) {
+ Provider<CurrentUser> self,
+ Provider<SuggestAccounts> suggestAccountsProvider) {
this.accounts = accounts;
this.api = api;
this.self = self;
+ this.suggestAccountsProvider = suggestAccountsProvider;
}
@Override
@@ -61,4 +68,32 @@
}
return api.create(new AccountResource((IdentifiedUser)self.get()));
}
+
+ @Override
+ public SuggestAccountsRequest suggestAccounts() throws RestApiException {
+ return new SuggestAccountsRequest() {
+ @Override
+ public List<AccountInfo> get() throws RestApiException {
+ return AccountsImpl.this.suggestAccounts(this);
+ }
+ };
+ }
+
+ @Override
+ public SuggestAccountsRequest suggestAccounts(String query)
+ throws RestApiException {
+ return suggestAccounts().withQuery(query);
+ }
+
+ private List<AccountInfo> suggestAccounts(SuggestAccountsRequest r)
+ throws RestApiException {
+ try {
+ SuggestAccounts mySuggestAccounts = suggestAccountsProvider.get();
+ mySuggestAccounts.setQuery(r.getQuery());
+ mySuggestAccounts.setLimit(r.getLimit());
+ return mySuggestAccounts.apply(TopLevelResource.INSTANCE);
+ } catch (OrmException e) {
+ throw new RestApiException("Cannot retrieve suggested accounts", e);
+ }
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
index 16472e3..1555cdd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
@@ -57,17 +57,15 @@
return getControl().getNotes();
}
- @Override
- public String getETag() {
- CurrentUser user = control.getCurrentUser();
- Hasher h = Hashing.md5().newHasher()
- .putLong(getChange().getLastUpdatedOn().getTime())
+
+ // This includes all information relevant for ETag computation
+ // unrelated to the UI.
+ public void prepareETag(Hasher h, CurrentUser user) {
+ h.putLong(getChange().getLastUpdatedOn().getTime())
.putInt(getChange().getRowVersion())
- .putBoolean(user.getStarredChanges().contains(getChange().getId()))
.putInt(user.isIdentifiedUser()
? ((IdentifiedUser) user).getAccountId().get()
: 0);
-
byte[] buf = new byte[20];
ObjectId noteId;
try {
@@ -82,6 +80,14 @@
for (ProjectState p : control.getProjectControl().getProjectState().tree()) {
hashObjectId(h, p.getConfig().getRevision(), buf);
}
+ }
+
+ @Override
+ public String getETag() {
+ CurrentUser user = control.getCurrentUser();
+ Hasher h = Hashing.md5().newHasher()
+ .putBoolean(user.getStarredChanges().contains(getChange().getId()));
+ prepareETag(h, user);
return h.hash().toString();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java
index d58c8d2..b21bee2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java
@@ -14,22 +14,59 @@
package com.google.gerrit.server.change;
+import com.google.common.base.Strings;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+import com.google.gerrit.extensions.restapi.ETagView;
import com.google.gerrit.extensions.restapi.Response;
-import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.OrmRuntimeException;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
-@Singleton
-public class GetRevisionActions implements RestReadView<RevisionResource> {
- private final ActionJson delegate;
+import org.eclipse.jgit.lib.Config;
+@Singleton
+public class GetRevisionActions implements ETagView<RevisionResource> {
+ private final ActionJson delegate;
+ private final Provider<InternalChangeQuery> queryProvider;
+ private final Config config;
@Inject
- GetRevisionActions(ActionJson delegate) {
+ GetRevisionActions(
+ ActionJson delegate,
+ Provider<InternalChangeQuery> queryProvider,
+ @GerritServerConfig Config config) {
this.delegate = delegate;
+ this.queryProvider = queryProvider;
+ this.config = config;
}
@Override
public Object apply(RevisionResource rsrc) {
return Response.withMustRevalidate(delegate.format(rsrc));
}
+
+ @Override
+ public String getETag(RevisionResource rsrc) {
+ String topic = rsrc.getChange().getTopic();
+ if (!Submit.wholeTopicEnabled(config)
+ || Strings.isNullOrEmpty(topic)) {
+ return rsrc.getETag();
+ }
+ Hasher h = Hashing.md5().newHasher();
+ CurrentUser user = rsrc.getControl().getCurrentUser();
+ try {
+ for (ChangeData c : queryProvider.get().byTopicOpen(topic)) {
+ new ChangeResource(c.changeControl()).prepareETag(h, user);
+ }
+ } catch (OrmException e){
+ throw new OrmRuntimeException(e);
+ }
+ return h.hash().toString();
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
index 41151ae..03bc7f1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -169,7 +169,7 @@
this.titlePattern = new ParameterizedString(MoreObjects.firstNonNull(
cfg.getString("change", null, "submitTooltip"),
DEFAULT_TOOLTIP));
- submitWholeTopic = cfg.getBoolean("change", null, "submitWholeTopic" , false);
+ submitWholeTopic = wholeTopicEnabled(cfg);
this.submitTopicLabel = MoreObjects.firstNonNull(
Strings.emptyToNull(cfg.getString("change", null, "submitTopicLabel")),
"Submit whole topic");
@@ -206,17 +206,19 @@
rsrc.getPatchSet().getRevision().get()));
}
- change = submit(rsrc, caller, false);
- if (change == null) {
- throw new ResourceConflictException("change is "
- + status(dbProvider.get().changes().get(rsrc.getChange().getId())));
- }
+ List<Change> submittedChanges = submit(rsrc, caller, false);
if (input.waitForMerge) {
- mergeQueue.merge(change.getDest());
+ for (Change c : submittedChanges) {
+ // TODO(sbeller): We should make schedule return a Future, then we
+ // could do these all in parallel and still block until they're done.
+ mergeQueue.merge(c.getDest());
+ }
change = dbProvider.get().changes().get(change.getId());
} else {
- mergeQueue.schedule(change.getDest());
+ for (Change c : submittedChanges) {
+ mergeQueue.schedule(c.getDest());
+ }
}
if (change == null) {
@@ -345,9 +347,10 @@
.orNull();
}
- private Change submitToDatabase(ReviewDb db, Change.Id changeId,
- final Timestamp timestamp) throws OrmException {
- return db.changes().atomicUpdate(changeId,
+ private Change submitToDatabase(final ReviewDb db, final Change.Id changeId,
+ final Timestamp timestamp) throws OrmException,
+ ResourceConflictException {
+ Change ret = db.changes().atomicUpdate(changeId,
new AtomicUpdate<Change>() {
@Override
public Change update(Change change) {
@@ -359,6 +362,12 @@
return null;
}
});
+ if (ret != null) {
+ return ret;
+ } else {
+ throw new ResourceConflictException("change " + changeId + " is "
+ + status(db.changes().get(changeId)));
+ }
}
private Change submitThisChange(RevisionResource rsrc, IdentifiedUser caller,
@@ -380,9 +389,6 @@
// Write update commit after all normalized label commits.
batch.write(update, new CommitBuilder());
change = submitToDatabase(db, change.getId(), timestamp);
- if (change == null) {
- return null;
- }
db.commit();
} finally {
db.rollback();
@@ -391,7 +397,7 @@
return change;
}
- private Change submitWholeTopic(RevisionResource rsrc, IdentifiedUser caller,
+ private List<Change> submitWholeTopic(RevisionResource rsrc, IdentifiedUser caller,
boolean force, String topic) throws ResourceConflictException, OrmException,
IOException {
Preconditions.checkNotNull(topic);
@@ -420,30 +426,31 @@
batch.write(update, new CommitBuilder());
for (ChangeData c : changesByTopic) {
- if (submitToDatabase(db, c.getId(), timestamp) == null) {
- return null;
- }
+ submitToDatabase(db, c.getId(), timestamp);
}
db.commit();
} finally {
db.rollback();
}
List<Change.Id> ids = new ArrayList<>(changesByTopic.size());
+ List<Change> ret = new ArrayList<>(changesByTopic.size());
for (ChangeData c : changesByTopic) {
ids.add(c.getId());
+ ret.add(c.change());
}
indexer.indexAsync(ids).checkedGet();
- return change;
+
+ return ret;
}
- public Change submit(RevisionResource rsrc, IdentifiedUser caller,
+ public List<Change> submit(RevisionResource rsrc, IdentifiedUser caller,
boolean force) throws ResourceConflictException, OrmException,
IOException {
String topic = rsrc.getChange().getTopic();
if (submitWholeTopic && !Strings.isNullOrEmpty(topic)) {
return submitWholeTopic(rsrc, caller, force, topic);
} else {
- return submitThisChange(rsrc, caller, force);
+ return Arrays.asList(submitThisChange(rsrc, caller, force));
}
}
@@ -654,6 +661,10 @@
return new RevisionResource(changes.parse(target), rsrc.getPatchSet());
}
+ static boolean wholeTopicEnabled(Config config) {
+ return config.getBoolean("change", null, "submitWholeTopic" , false);
+ }
+
public static class CurrentRevision implements
RestModifyView<ChangeResource, SubmitInput> {
private final Provider<ReviewDb> dbProvider;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java
index aa699c5..4b1236b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java
@@ -44,10 +44,11 @@
@Override
public Config get() {
- FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED);
+ FileBasedConfig cfg =
+ new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
if (!cfg.getFile().exists()) {
- log.info("No " + site.gerrit_config.getAbsolutePath()
+ log.info("No " + site.gerrit_config.toAbsolutePath()
+ "; assuming defaults");
return new GerritConfig(cfg, secureStore);
}
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 9aa8590..feac473 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 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.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 @@
public class GetSummary implements RestReadView<ConfigResource> {
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 @@
}
@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 @@
} 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 @@
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/PluginConfigFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java
index 76f5323..3754674 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java
@@ -35,6 +35,7 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.Map;
@Singleton
@@ -61,7 +62,7 @@
this.projectStateFactory = projectStateFactory;
this.pluginConfigs = Maps.newHashMap();
- this.cfgSnapshot = FileSnapshot.save(site.gerrit_config);
+ this.cfgSnapshot = FileSnapshot.save(site.gerrit_config.toFile());
this.cfg = cfgProvider.get();
}
@@ -103,8 +104,9 @@
* @return the plugin configuration from the 'gerrit.config' file
*/
public PluginConfig getFromGerritConfig(String pluginName, boolean refresh) {
- if (refresh && cfgSnapshot.isModified(site.gerrit_config)) {
- cfgSnapshot = FileSnapshot.save(site.gerrit_config);
+ File configFile = site.gerrit_config.toFile();
+ if (refresh && cfgSnapshot.isModified(configFile)) {
+ cfgSnapshot = FileSnapshot.save(configFile);
cfg = cfgProvider.get();
}
return new PluginConfig(pluginName, cfg);
@@ -250,20 +252,21 @@
return pluginConfigs.get(pluginName);
}
- File pluginConfigFile = new File(site.etc_dir, pluginName + ".config");
- FileBasedConfig cfg = new FileBasedConfig(pluginConfigFile, FS.DETECTED);
+ Path pluginConfigFile = site.etc_dir.resolve(pluginName + ".config");
+ FileBasedConfig cfg =
+ new FileBasedConfig(pluginConfigFile.toFile(), FS.DETECTED);
pluginConfigs.put(pluginName, cfg);
if (!cfg.getFile().exists()) {
- log.info("No " + pluginConfigFile.getAbsolutePath() + "; assuming defaults");
+ log.info("No " + pluginConfigFile.toAbsolutePath() + "; assuming defaults");
return cfg;
}
try {
cfg.load();
} catch (IOException e) {
- log.warn("Failed to load " + pluginConfigFile.getAbsolutePath(), e);
+ log.warn("Failed to load " + pluginConfigFile.toAbsolutePath(), e);
} catch (ConfigInvalidException e) {
- log.warn("Failed to load " + pluginConfigFile.getAbsolutePath(), e);
+ log.warn("Failed to load " + pluginConfigFile.toAbsolutePath(), e);
}
return cfg;
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 fbff7c4..1b8f373 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 java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.file.Path;
/** Important paths within a {@link SitePath}. */
@Singleton
@@ -29,74 +30,76 @@
public static final String FOOTER_FILENAME = "GerritSiteFooter.html";
public final File site_path;
- public final File bin_dir;
- public final File etc_dir;
- public final File lib_dir;
- public final File tmp_dir;
- public final File logs_dir;
- public final File plugins_dir;
- public final File data_dir;
+ public final Path bin_dir;
+ public final Path etc_dir;
+ public final Path lib_dir;
+ public final Path tmp_dir;
+ public final Path logs_dir;
+ public final Path plugins_dir;
+ public final Path data_dir;
public final File mail_dir;
public final File hooks_dir;
public final File static_dir;
public final File themes_dir;
public final File index_dir;
- public final File gerrit_sh;
- public final File gerrit_war;
+ public final Path gerrit_sh;
+ public final Path gerrit_war;
- public final File gerrit_config;
- public final File secure_config;
- public final File contact_information_pub;
+ public final Path gerrit_config;
+ public final Path secure_config;
+ public final Path contact_information_pub;
- public final File ssl_keystore;
- public final File ssh_key;
- public final File ssh_rsa;
- public final File ssh_dsa;
- public final File peer_keys;
+ public final Path ssl_keystore;
+ public final Path ssh_key;
+ public final Path ssh_rsa;
+ public final Path ssh_dsa;
+ public final Path 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");
- plugins_dir = new File(site_path, "plugins");
- data_dir = new File(site_path, "data");
- logs_dir = new File(site_path, "logs");
- mail_dir = new File(etc_dir, "mail");
+ bin_dir = p.resolve("bin");
+ etc_dir = p.resolve("etc");
+ lib_dir = p.resolve("lib");
+ tmp_dir = p.resolve("tmp");
+ plugins_dir = p.resolve("plugins");
+ data_dir = p.resolve("data");
+ logs_dir = p.resolve("logs");
+ mail_dir = etc_dir.resolve("mail").toFile();
hooks_dir = new File(site_path, "hooks");
static_dir = new File(site_path, "static");
themes_dir = new File(site_path, "themes");
index_dir = new File(site_path, "index");
- gerrit_sh = new File(bin_dir, "gerrit.sh");
- gerrit_war = new File(bin_dir, "gerrit.war");
+ gerrit_sh = bin_dir.resolve("gerrit.sh");
+ gerrit_war = bin_dir.resolve("gerrit.war");
- gerrit_config = new File(etc_dir, "gerrit.config");
- secure_config = new File(etc_dir, "secure.config");
- contact_information_pub = new File(etc_dir, "contact_information.pub");
+ gerrit_config = etc_dir.resolve("gerrit.config");
+ secure_config = etc_dir.resolve("secure.config");
+ contact_information_pub = etc_dir.resolve("contact_information.pub");
- ssl_keystore = new File(etc_dir, "keystore");
- ssh_key = new File(etc_dir, "ssh_host_key");
- ssh_rsa = new File(etc_dir, "ssh_host_rsa_key");
- ssh_dsa = new File(etc_dir, "ssh_host_dsa_key");
- peer_keys = new File(etc_dir, "peer_keys");
+ ssl_keystore = etc_dir.resolve("keystore");
+ ssh_key = etc_dir.resolve("ssh_host_key");
+ ssh_rsa = etc_dir.resolve("ssh_host_rsa_key");
+ ssh_dsa = etc_dir.resolve("ssh_host_dsa_key");
+ peer_keys = etc_dir.resolve("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");
+ site_css = etc_dir.resolve(CSS_FILENAME);
+ site_header = etc_dir.resolve(HEADER_FILENAME);
+ site_footer = etc_dir.resolve(FOOTER_FILENAME);
+ site_gitweb = etc_dir.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/contact/ContactStoreModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java
index 6b195de..f6e08b8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java
@@ -28,11 +28,12 @@
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.util.StringUtils;
-import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.security.Security;
/** Creates the {@link ContactStore} based on the configuration. */
@@ -46,7 +47,7 @@
public ContactStore provideContactStore(@GerritServerConfig final Config config,
final SitePaths site, final SchemaFactory<ReviewDb> schema,
final ContactStoreConnection.Factory connFactory) {
- final String url = config.getString("contactstore", null, "url");
+ String url = config.getString("contactstore", null, "url");
if (StringUtils.isEmptyOrNull(url)) {
return new NoContactStore();
}
@@ -56,18 +57,18 @@
+ " needed to encrypt contact information");
}
- final URL storeUrl;
+ URL storeUrl;
try {
storeUrl = new URL(url);
} catch (MalformedURLException e) {
throw new ProvisionException("Invalid contactstore.url: " + url, e);
}
- final String storeAPPSEC = config.getString("contactstore", null, "appsec");
- final File pubkey = site.contact_information_pub;
- if (!pubkey.exists()) {
+ String storeAPPSEC = config.getString("contactstore", null, "appsec");
+ Path pubkey = site.contact_information_pub;
+ if (!Files.exists(pubkey)) {
throw new ProvisionException("PGP public key file \""
- + pubkey.getAbsolutePath() + "\" not found");
+ + pubkey.toAbsolutePath() + "\" not found");
}
return new EncryptedContactStore(storeUrl, storeAPPSEC, pubkey, schema,
connFactory);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
index d8dbfed..e27f63d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
@@ -42,12 +42,12 @@
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
@@ -72,7 +72,7 @@
private final ContactStoreConnection.Factory connFactory;
EncryptedContactStore(final URL storeUrl, final String storeAPPSEC,
- final File pubKey, final SchemaFactory<ReviewDb> schema,
+ final Path pubKey, final SchemaFactory<ReviewDb> schema,
final ContactStoreConnection.Factory connFactory) {
this.storeUrl = storeUrl;
this.storeAPPSEC = storeAPPSEC;
@@ -104,8 +104,8 @@
return true;
}
- private static PGPPublicKeyRingCollection readPubRing(final File pub) {
- try (InputStream fin = new FileInputStream(pub);
+ private static PGPPublicKeyRingCollection readPubRing(Path pub) {
+ try (InputStream fin = Files.newInputStream(pub);
InputStream in = PGPUtil.getDecoderStream(fin)) {
return new PGPPublicKeyRingCollection(in);
} catch (IOException | PGPException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 81833fe..be584d6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -1726,18 +1726,15 @@
throws OrmException, IOException {
Submit submit = submitProvider.get();
RevisionResource rsrc = new RevisionResource(changes.parse(changeCtl), ps);
- Change c;
+ List<Change> changes;
try {
// Force submit even if submit rule evaluation fails.
- c = submit.submit(rsrc, currentUser, true);
+ changes = submit.submit(rsrc, currentUser, true);
} catch (ResourceConflictException e) {
throw new IOException(e);
}
- if (c == null) {
- addError("Submitting change " + changeCtl.getChange().getChangeId()
- + " failed.");
- } else {
- addMessage("");
+ addMessage("");
+ for (Change c : changes) {
mergeQueue.merge(c.getDest());
c = db.changes().get(c.getId());
switch (c.getStatus()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java
index 593f2c9..9827812 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java
@@ -14,17 +14,17 @@
package com.google.gerrit.server.plugins;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.jar.JarFile;
class CleanupHandle {
- private final File tmpFile;
+ private final Path tmp;
private final JarFile jarFile;
- CleanupHandle(File tmpFile,
- JarFile jarFile) {
- this.tmpFile = tmpFile;
+ CleanupHandle(Path tmp, JarFile jarFile) {
+ this.tmp = tmp;
this.jarFile = jarFile;
}
@@ -34,12 +34,13 @@
} catch (IOException err) {
PluginLoader.log.error("Cannot close " + jarFile.getName(), err);
}
- if (!tmpFile.delete() && tmpFile.exists()) {
- PluginLoader.log.warn("Cannot delete " + tmpFile.getAbsolutePath()
- + ", retrying to delete it on termination of the virtual machine");
- tmpFile.deleteOnExit();
- } else {
- PluginLoader.log.info("Cleaned plugin " + tmpFile.getName());
+ try {
+ Files.deleteIfExists(tmp);
+ PluginLoader.log.info("Cleaned plugin " + tmp.getFileName());
+ } catch (IOException e) {
+ PluginLoader.log.warn("Cannot delete " + tmp.toAbsolutePath()
+ + ", retrying to delete it on termination of the virtual machine", e);
+ tmp.toFile().deleteOnExit();
}
}
}
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 7252617..1d4233a 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 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 @@
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 53f39f1..dcfb52c 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
@@ -24,13 +24,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -43,7 +44,7 @@
static final String JAR_EXTENSION = ".jar";
static final Logger log = LoggerFactory.getLogger(JarPluginProvider.class);
- private final File tmpDir;
+ private final Path tmpDir;
@Inject
JarPluginProvider(SitePaths sitePaths) {
@@ -51,42 +52,42 @@
}
@Override
- public boolean handles(File srcFile) {
- String fileName = srcFile.getName();
+ public boolean handles(Path srcPath) {
+ String fileName = srcPath.getFileName().toString();
return fileName.endsWith(JAR_EXTENSION)
|| fileName.endsWith(JAR_EXTENSION + ".disabled");
}
@Override
- public String getPluginName(File srcFile) {
+ public String getPluginName(Path srcPath) {
try {
- return MoreObjects.firstNonNull(getJarPluginName(srcFile),
- PluginLoader.nameOf(srcFile));
+ return MoreObjects.firstNonNull(getJarPluginName(srcPath),
+ PluginLoader.nameOf(srcPath));
} catch (IOException e) {
- throw new IllegalArgumentException("Invalid plugin file " + srcFile
+ throw new IllegalArgumentException("Invalid plugin file " + srcPath
+ ": cannot get plugin name", e);
}
}
- public static String getJarPluginName(File srcFile) throws IOException {
- try (JarFile jarFile = new JarFile(srcFile)) {
+ public static String getJarPluginName(Path srcPath) throws IOException {
+ try (JarFile jarFile = new JarFile(srcPath.toFile())) {
return jarFile.getManifest().getMainAttributes()
.getValue("Gerrit-PluginName");
}
}
@Override
- public ServerPlugin get(File srcFile, FileSnapshot snapshot,
+ public ServerPlugin get(Path srcPath, FileSnapshot snapshot,
PluginDescription description) throws InvalidPluginException {
try {
- String name = getPluginName(srcFile);
- 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);
+ String name = getPluginName(srcPath);
+ String extension = getExtension(srcPath);
+ try (InputStream in = Files.newInputStream(srcPath)) {
+ Path tmp = asTemp(in, tempNameFor(name), extension, tmpDir);
+ return loadJarPlugin(name, srcPath, snapshot, tmp, description);
}
} catch (IOException e) {
- throw new InvalidPluginException("Cannot load Jar plugin " + srcFile, e);
+ throw new InvalidPluginException("Cannot load Jar plugin " + srcPath, e);
}
}
@@ -95,8 +96,8 @@
return "gerrit";
}
- private static String getExtension(File file) {
- return getExtension(file.getName());
+ private static String getExtension(Path path) {
+ return getExtension(path.getFileName().toString());
}
private static String getExtension(String name) {
@@ -109,18 +110,18 @@
return PLUGIN_TMP_PREFIX + name + "_" + fmt.format(new Date()) + "_";
}
- public static File storeInTemp(String pluginName, InputStream in,
+ public static Path 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);
}
- private ServerPlugin loadJarPlugin(String name, File srcJar,
- FileSnapshot snapshot, File tmp, PluginDescription description)
+ private ServerPlugin loadJarPlugin(String name, Path srcJar,
+ FileSnapshot snapshot, Path tmp, PluginDescription description)
throws IOException, InvalidPluginException, MalformedURLException {
- JarFile jarFile = new JarFile(tmp);
+ JarFile jarFile = new JarFile(tmp.toFile());
boolean keep = false;
try {
Manifest manifest = jarFile.getManifest();
@@ -129,24 +130,22 @@
List<URL> urls = new ArrayList<>(2);
String overlay = System.getProperty("gerrit.plugin-classes");
if (overlay != null) {
- File classes = new File(new File(new File(overlay), name), "main");
- if (classes.isDirectory()) {
- log.info(String.format("plugin %s: including %s", name,
- classes.getPath()));
- urls.add(classes.toURI().toURL());
+ Path classes = Paths.get(overlay).resolve(name).resolve("main");
+ if (Files.isDirectory(classes)) {
+ log.info(String.format("plugin %s: including %s", name, classes));
+ urls.add(classes.toUri().toURL());
}
}
- urls.add(tmp.toURI().toURL());
+ urls.add(tmp.toUri().toURL());
ClassLoader pluginLoader =
new URLClassLoader(urls.toArray(new URL[urls.size()]),
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, snapshot, jarScanner,
+ description.dataDir, pluginLoader);
plugin.setCleanupHandle(new CleanupHandle(tmp, jarFile));
keep = true;
return plugin;
@@ -157,7 +156,7 @@
}
}
- 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 a8600fe..0f4aa6c 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.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 @@
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 63f69b5..8da8cc1 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 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 @@
@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 @@
@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 54f05f0..1d717ef 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 @@
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/MultipleProvidersForPluginException.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java
index 82a6ad9..cf38310 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java
@@ -18,14 +18,14 @@
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
-import java.io.File;
+import java.nio.file.Path;
class MultipleProvidersForPluginException extends IllegalArgumentException {
private static final long serialVersionUID = 1L;
- MultipleProvidersForPluginException(File pluginSrcFile,
+ MultipleProvidersForPluginException(Path pluginSrcPath,
Iterable<ServerPluginProvider> providersHandlers) {
- super(pluginSrcFile.getAbsolutePath()
+ super(pluginSrcPath.toAbsolutePath()
+ " is claimed to be handled by more than one plugin provider: "
+ providersListToString(providersHandlers));
}
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 b227909..6b84c21 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
@@ -14,6 +14,8 @@
package com.google.gerrit.server.plugins;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.gerrit.common.Nullable;
@@ -25,7 +27,7 @@
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 +69,7 @@
}
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 +82,17 @@
private List<ReloadableRegistrationHandle<?>> reloadableHandles;
public Plugin(String name,
- File srcFile,
+ Path srcPath,
PluginUser pluginUser,
FileSnapshot snapshot,
ApiType apiType) {
this.name = name;
- this.srcFile = srcFile;
+ this.srcFile = srcPath;
this.apiType = apiType;
this.snapshot = snapshot;
this.pluginUser = pluginUser;
this.cacheKey = new Plugin.CacheKey(name);
- this.disabled = srcFile.getName().endsWith(".disabled");
+ this.disabled = srcPath.getFileName().toString().endsWith(".disabled");
}
public CleanupHandle getCleanupHandle() {
@@ -105,7 +107,7 @@
return pluginUser;
}
- public File getSrcFile() {
+ public Path getSrcFile() {
return srcFile;
}
@@ -168,7 +170,7 @@
abstract boolean canReload();
- boolean isModified(File jar) {
- return snapshot.lastModified() != jar.lastModified();
+ boolean isModified(Path jar) {
+ return snapshot.lastModified() != lastModified(jar);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java
index 0228509..1d9cd0e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java
@@ -11,14 +11,15 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+
package com.google.gerrit.server.plugins;
import com.google.common.base.Optional;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
+import java.nio.file.NoSuchFileException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
@@ -57,7 +58,7 @@
@Override
public InputStream getInputStream(PluginEntry entry) throws IOException {
- throw new FileNotFoundException("Empty plugin");
+ throw new NoSuchFileException("Empty plugin");
}
@Override
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 b51359d..17bb634 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
@@ -18,6 +18,8 @@
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
@@ -25,6 +27,7 @@
import com.google.common.collect.Multimap;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
+import com.google.common.io.ByteStreams;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.systemstatus.ServerInformation;
@@ -45,14 +48,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -71,13 +75,13 @@
static final String PLUGIN_TMP_PREFIX = "plugin_";
static final Logger log = LoggerFactory.getLogger(PluginLoader.class);
- public String getPluginName(File srcFile) {
- return MoreObjects.firstNonNull(getGerritPluginName(srcFile),
- nameOf(srcFile));
+ public String getPluginName(Path srcPath) {
+ return MoreObjects.firstNonNull(getGerritPluginName(srcPath),
+ nameOf(srcPath));
}
- private final File pluginsDir;
- private final File dataDir;
+ private final Path pluginsDir;
+ private final Path dataDir;
private final PluginGuiceEnvironment env;
private final ServerInformationImpl srvInfoImpl;
private final PluginUser.Factory pluginUserFactory;
@@ -158,7 +162,7 @@
checkRemoteInstall();
String fileName = originalName;
- File tmp = asTemp(in, ".next_" + fileName + "_", ".tmp", pluginsDir);
+ Path tmp = asTemp(in, ".next_" + fileName + "_", ".tmp", pluginsDir);
String name = MoreObjects.firstNonNull(getGerritPluginName(tmp),
nameOf(fileName));
if (!originalName.equals(name)) {
@@ -168,26 +172,26 @@
}
String fileExtension = getExtension(fileName);
- File dst = new File(pluginsDir, name + fileExtension);
+ Path dst = pluginsDir.resolve(name + fileExtension);
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);
+ Path old = pluginsDir.resolve(".last_" + fileName);
+ Files.deleteIfExists(old);
+ Files.move(active.getSrcFile(), old);
}
- new File(pluginsDir, fileName + ".disabled").delete();
- tmp.renameTo(dst);
+ Files.deleteIfExists(pluginsDir.resolve(fileName + ".disabled"));
+ Files.move(tmp, dst);
try {
Plugin plugin = runPlugin(name, dst, active);
if (active == null) {
log.info(String.format("Installed plugin %s", plugin.getName()));
}
} catch (PluginInstallException e) {
- dst.delete();
+ Files.deleteIfExists(dst);
throw e;
}
@@ -195,21 +199,17 @@
}
}
- static File asTemp(InputStream in, String prefix, String suffix, File dir)
+ static Path asTemp(InputStream in, String prefix, String suffix, Path dir)
throws IOException {
- File tmp = File.createTempFile(prefix, suffix, dir);
+ Path tmp = Files.createTempFile(dir, prefix, suffix);
boolean keep = false;
- try (FileOutputStream out = new FileOutputStream(tmp)) {
- byte[] data = new byte[8192];
- int n;
- while ((n = in.read(data)) > 0) {
- out.write(data, 0, n);
- }
+ try (OutputStream out = Files.newOutputStream(tmp)) {
+ ByteStreams.copy(in, out);
keep = true;
return tmp;
} finally {
if (!keep) {
- tmp.delete();
+ Files.delete(tmp);
}
}
}
@@ -240,12 +240,21 @@
}
log.info(String.format("Disabling plugin %s", active.getName()));
- File off = new File(active.getSrcFile() + ".disabled");
- active.getSrcFile().renameTo(off);
+ Path off = active.getSrcFile().resolveSibling(
+ active.getSrcFile().getFileName() + ".disabled");
+ try {
+ Files.move(active.getSrcFile(), off);
+ } catch (IOException e) {
+ log.error("Failed to disable plugin", e);
+ // In theory we could still unload the plugin even if the rename
+ // failed. However, it would be reloaded on the next server startup,
+ // which is probably not what the user expects.
+ continue;
+ }
unloadPlugin(active);
try {
- FileSnapshot snapshot = FileSnapshot.save(off);
+ FileSnapshot snapshot = FileSnapshot.save(off.toFile());
Plugin offPlugin = loadPlugin(name, off, snapshot);
disabled.put(name, offPlugin);
} catch (Throwable e) {
@@ -274,13 +283,17 @@
}
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);
-
+ Path on = pluginsDir.resolve(n);
+ try {
+ Files.move(off.getSrcFile(), on);
+ } catch (IOException e) {
+ log.error("Failed to move plugin " + name + " into place", e);
+ continue;
+ }
disabled.remove(name);
runPlugin(name, on, null);
}
@@ -290,7 +303,7 @@
@Override
public synchronized void start() {
- log.info("Loading plugins from " + pluginsDir.getAbsolutePath());
+ log.info("Loading plugins from " + pluginsDir.toAbsolutePath());
srvInfoImpl.state = ServerInformation.State.STARTUP;
rescan();
srvInfoImpl.state = ServerInformation.State.RUNNING;
@@ -354,30 +367,30 @@
}
public synchronized void rescan() {
- Multimap<String, File> pluginsFiles = prunePlugins(pluginsDir);
+ Multimap<String, Path> pluginsFiles = prunePlugins(pluginsDir);
if (pluginsFiles.isEmpty()) {
return;
}
syncDisabledPlugins(pluginsFiles);
- Map<String, File> activePlugins = filterDisabled(pluginsFiles);
- for (Map.Entry<String, File> entry : jarsFirstSortedPluginsSet(activePlugins)) {
+ Map<String, Path> activePlugins = filterDisabled(pluginsFiles);
+ for (Map.Entry<String, Path> entry : jarsFirstSortedPluginsSet(activePlugins)) {
String name = entry.getKey();
- File file = entry.getValue();
- String fileName = file.getName();
- if (!isJsPlugin(fileName) && !serverPluginFactory.handles(file)) {
+ Path path = entry.getValue();
+ String fileName = path.getFileName().toString();
+ if (!isJsPlugin(fileName) && !serverPluginFactory.handles(path)) {
log.warn("No Plugin provider was found that handles this file format: {}", fileName);
continue;
}
FileSnapshot brokenTime = broken.get(name);
- if (brokenTime != null && !brokenTime.isModified(file)) {
+ if (brokenTime != null && !brokenTime.isModified(path.toFile())) {
continue;
}
Plugin active = running.get(name);
- if (active != null && !active.isModified(file)) {
+ if (active != null && !active.isModified(path)) {
continue;
}
@@ -387,7 +400,7 @@
}
try {
- Plugin loadedPlugin = runPlugin(name, file, active);
+ Plugin loadedPlugin = runPlugin(name, path, active);
if (active == null && !loadedPlugin.isDisabled()) {
log.info(String.format("Loaded plugin %s, version %s",
loadedPlugin.getName(), loadedPlugin.getVersion()));
@@ -400,31 +413,28 @@
cleanInBackground();
}
- private void addAllEntries(Map<String, File> from,
- TreeSet<Entry<String, File>> to) {
- Iterator<Entry<String, File>> it = from.entrySet().iterator();
+ private void addAllEntries(Map<String, Path> from,
+ TreeSet<Entry<String, Path>> to) {
+ Iterator<Entry<String, Path>> it = from.entrySet().iterator();
while (it.hasNext()) {
- Entry<String,File> entry = it.next();
+ Entry<String,Path> entry = it.next();
to.add(new AbstractMap.SimpleImmutableEntry<>(
entry.getKey(), entry.getValue()));
}
}
- private TreeSet<Entry<String, File>> jarsFirstSortedPluginsSet(
- Map<String, File> activePlugins) {
- TreeSet<Entry<String, File>> sortedPlugins =
- Sets.newTreeSet(new Comparator<Entry<String, File>>() {
+ private TreeSet<Entry<String, Path>> jarsFirstSortedPluginsSet(
+ Map<String, Path> activePlugins) {
+ TreeSet<Entry<String, Path>> sortedPlugins =
+ Sets.newTreeSet(new Comparator<Entry<String, Path>>() {
@Override
- public int compare(Entry<String, File> entry1,
- Entry<String, File> entry2) {
- String file1 = entry1.getValue().getName();
- String file2 = entry2.getValue().getName();
- int cmp = file1.compareTo(file2);
- if (file1.endsWith(".jar")) {
- return (file2.endsWith(".jar") ? cmp : -1);
- } else {
- return (file2.endsWith(".jar") ? +1 : cmp);
- }
+ public int compare(Entry<String, Path> e1, Entry<String, Path> e2) {
+ Path n1 = e1.getValue().getFileName();
+ Path n2 = e2.getValue().getFileName();
+ return ComparisonChain.start()
+ .compareTrueFirst(n1.endsWith(".jar"), n2.endsWith(".jar"))
+ .compare(n1, n2)
+ .result();
}
});
@@ -432,14 +442,14 @@
return sortedPlugins;
}
- private void syncDisabledPlugins(Multimap<String, File> jars) {
+ private void syncDisabledPlugins(Multimap<String, Path> jars) {
stopRemovedPlugins(jars);
dropRemovedDisabledPlugins(jars);
}
- private Plugin runPlugin(String name, File plugin, Plugin oldPlugin)
+ private Plugin runPlugin(String name, Path plugin, Plugin oldPlugin)
throws PluginInstallException {
- FileSnapshot snapshot = FileSnapshot.save(plugin);
+ FileSnapshot snapshot = FileSnapshot.save(plugin.toFile());
try {
Plugin newPlugin = loadPlugin(name, plugin, snapshot);
if (newPlugin.getCleanupHandle() != null) {
@@ -479,11 +489,11 @@
}
}
- private void stopRemovedPlugins(Multimap<String, File> jars) {
+ private void stopRemovedPlugins(Multimap<String, Path> jars) {
Set<String> unload = Sets.newHashSet(running.keySet());
- for (Map.Entry<String, Collection<File>> entry : jars.asMap().entrySet()) {
- for (File file : entry.getValue()) {
- if (!file.getName().endsWith(".disabled")) {
+ for (Map.Entry<String, Collection<Path>> entry : jars.asMap().entrySet()) {
+ for (Path path : entry.getValue()) {
+ if (!path.getFileName().toString().endsWith(".disabled")) {
unload.remove(entry.getKey());
}
}
@@ -493,11 +503,11 @@
}
}
- private void dropRemovedDisabledPlugins(Multimap<String, File> jars) {
+ private void dropRemovedDisabledPlugins(Multimap<String, Path> jars) {
Set<String> unload = Sets.newHashSet(disabled.keySet());
- for (Map.Entry<String, Collection<File>> entry : jars.asMap().entrySet()) {
- for (File file : entry.getValue()) {
- if (file.getName().endsWith(".disabled")) {
+ for (Map.Entry<String, Collection<Path>> entry : jars.asMap().entrySet()) {
+ for (Path path : entry.getValue()) {
+ if (path.getFileName().toString().endsWith(".disabled")) {
unload.remove(entry.getKey());
}
}
@@ -528,8 +538,8 @@
}
}
- public static String nameOf(File plugin) {
- return nameOf(plugin.getName());
+ public static String nameOf(Path plugin) {
+ return nameOf(plugin.getFileName().toString());
}
private static String nameOf(String name) {
@@ -545,21 +555,21 @@
return 0 < ext ? name.substring(ext) : "";
}
- private Plugin loadPlugin(String name, File srcPlugin, FileSnapshot snapshot)
+ private Plugin loadPlugin(String name, Path srcPlugin, FileSnapshot snapshot)
throws InvalidPluginException {
- String pluginName = srcPlugin.getName();
+ String pluginName = srcPlugin.getFileName().toString();
if (isJsPlugin(pluginName)) {
return loadJsPlugin(name, srcPlugin, snapshot);
} else if (serverPluginFactory.handles(srcPlugin)) {
return loadServerPlugin(srcPlugin, snapshot);
} else {
throw new InvalidPluginException(String.format(
- "Unsupported plugin type: %s", srcPlugin.getName()));
+ "Unsupported plugin type: %s", srcPlugin.getFileName()));
}
}
- private File getPluginDataDir(String name) {
- return new File(dataDir, name);
+ private Path getPluginDataDir(String name) {
+ return dataDir.resolve(name);
}
private String getPluginCanonicalWebUrl(String name) {
@@ -569,11 +579,11 @@
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);
}
- private ServerPlugin loadServerPlugin(File scriptFile,
+ private ServerPlugin loadServerPlugin(Path scriptFile,
FileSnapshot snapshot) throws InvalidPluginException {
String name = serverPluginFactory.getPluginName(scriptFile);
return serverPluginFactory.get(scriptFile, snapshot, new PluginDescription(
@@ -597,15 +607,15 @@
// Only one active plugin per plugin name can exist for each plugin name.
// Filter out disabled plugins and transform the multimap to a map
- private static Map<String, File> filterDisabled(
- Multimap<String, File> pluginFiles) {
- Map<String, File> activePlugins = Maps.newHashMapWithExpectedSize(
- pluginFiles.keys().size());
- for (String name : pluginFiles.keys()) {
- for (File pluginFile : pluginFiles.asMap().get(name)) {
- if (!pluginFile.getName().endsWith(".disabled")) {
+ private static Map<String, Path> filterDisabled(
+ Multimap<String, Path> pluginPaths) {
+ Map<String, Path> activePlugins = Maps.newHashMapWithExpectedSize(
+ pluginPaths.keys().size());
+ for (String name : pluginPaths.keys()) {
+ for (Path pluginPath : pluginPaths.asMap().get(name)) {
+ if (!pluginPath.getFileName().toString().endsWith(".disabled")) {
assert(!activePlugins.containsKey(name));
- activePlugins.put(name, pluginFile);
+ activePlugins.put(name, pluginPath);
}
}
}
@@ -621,37 +631,40 @@
//
// NOTE: Bear in mind that the plugin name can be reassigned after load by the
// Server plugin provider.
- public Multimap<String, File> prunePlugins(File pluginsDir) {
- List<File> pluginFiles = scanFilesInPluginsDirectory(pluginsDir);
- Multimap<String, File> map;
- map = asMultimap(pluginFiles);
+ public Multimap<String, Path> prunePlugins(Path pluginsDir) {
+ List<Path> pluginPaths = scanPathsInPluginsDirectory(pluginsDir);
+ Multimap<String, Path> map;
+ map = asMultimap(pluginPaths);
for (String plugin : map.keySet()) {
- Collection<File> files = map.asMap().get(plugin);
+ Collection<Path> files = map.asMap().get(plugin);
if (files.size() == 1) {
continue;
}
// retrieve enabled plugins
- Iterable<File> enabled = filterDisabledPlugins(
- files);
+ Iterable<Path> enabled = filterDisabledPlugins(files);
// If we have only one (the winner) plugin, nothing to do
if (!Iterables.skip(enabled, 1).iterator().hasNext()) {
continue;
}
- File winner = Iterables.getFirst(enabled, null);
+ Path winner = Iterables.getFirst(enabled, null);
assert(winner != null);
// Disable all loser plugins by renaming their file names to
// "file.disabled" and replace the disabled files in the multimap.
- Collection<File> elementsToRemove = Lists.newArrayList();
- Collection<File> elementsToAdd = Lists.newArrayList();
- for (File loser : Iterables.skip(enabled, 1)) {
+ Collection<Path> elementsToRemove = Lists.newArrayList();
+ Collection<Path> elementsToAdd = Lists.newArrayList();
+ for (Path loser : Iterables.skip(enabled, 1)) {
log.warn(String.format("Plugin <%s> was disabled, because"
+ " another plugin <%s>"
+ " with the same name <%s> already exists",
loser, winner, plugin));
- File disabledPlugin = new File(loser + ".disabled");
+ Path disabledPlugin = Paths.get(loser + ".disabled");
elementsToAdd.add(disabledPlugin);
elementsToRemove.add(loser);
- loser.renameTo(disabledPlugin);
+ try {
+ Files.move(loser, disabledPlugin);
+ } catch (IOException e) {
+ log.warn("Failed to fully disable plugin " + loser, e);
+ }
}
Iterables.removeAll(files, elementsToRemove);
Iterables.addAll(files, elementsToAdd);
@@ -659,50 +672,52 @@
return map;
}
- private List<File> scanFilesInPluginsDirectory(File pluginsDir) {
- if (pluginsDir == null || !pluginsDir.exists()) {
+ private List<Path> scanPathsInPluginsDirectory(Path pluginsDir) {
+ if (pluginsDir == null || !Files.exists(pluginsDir)) {
return Collections.emptyList();
}
- File[] matches = pluginsDir.listFiles(new FileFilter() {
+ DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
- public boolean accept(File pathname) {
- String n = pathname.getName();
+ public boolean accept(Path entry) throws IOException {
+ String n = entry.getFileName().toString();
return !n.startsWith(".last_")
&& !n.startsWith(".next_");
}
- });
- if (matches == null) {
- log.error("Cannot list " + pluginsDir.getAbsolutePath());
- return Collections.emptyList();
+ };
+ try (DirectoryStream<Path> files
+ = Files.newDirectoryStream(pluginsDir, filter)) {
+ return ImmutableList.copyOf(files);
+ } catch (IOException e) {
+ log.error("Cannot list " + pluginsDir.toAbsolutePath(), e);
+ return ImmutableList.of();
}
- return Arrays.asList(matches);
}
- private static Iterable<File> filterDisabledPlugins(
- Collection<File> files) {
- return Iterables.filter(files, new Predicate<File>() {
+ private static Iterable<Path> filterDisabledPlugins(
+ Collection<Path> paths) {
+ return Iterables.filter(paths, new Predicate<Path>() {
@Override
- public boolean apply(File file) {
- return !file.getName().endsWith(".disabled");
+ public boolean apply(Path p) {
+ return !p.getFileName().toString().endsWith(".disabled");
}
});
}
- public String getGerritPluginName(File srcFile) {
- String fileName = srcFile.getName();
+ public String getGerritPluginName(Path srcPath) {
+ String fileName = srcPath.getFileName().toString();
if (isJsPlugin(fileName)) {
return fileName.substring(0, fileName.length() - 3);
}
- if (serverPluginFactory.handles(srcFile)) {
- return serverPluginFactory.getPluginName(srcFile);
+ if (serverPluginFactory.handles(srcPath)) {
+ return serverPluginFactory.getPluginName(srcPath);
}
return null;
}
- private Multimap<String, File> asMultimap(List<File> plugins) {
- Multimap<String, File> map = LinkedHashMultimap.create();
- for (File srcFile : plugins) {
- map.put(getPluginName(srcFile), srcFile);
+ private Multimap<String, Path> asMultimap(List<Path> plugins) {
+ Multimap<String, Path> map = LinkedHashMultimap.create();
+ for (Path srcPath : plugins) {
+ map.put(getPluginName(srcPath), srcPath);
}
return map;
}
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 0b037fb..28d57b2 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
@@ -17,25 +17,19 @@
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
-import com.google.gerrit.extensions.annotations.PluginData;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.util.RequestContext;
-import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
-import com.google.inject.Provider;
-import com.google.inject.ProvisionException;
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
@@ -59,7 +53,7 @@
private final Manifest manifest;
private final PluginContentScanner scanner;
- private final File dataDir;
+ private final Path dataDir;
private final String pluginCanonicalWebUrl;
private final ClassLoader classLoader;
private Class<? extends Module> sysModule;
@@ -75,12 +69,13 @@
public ServerPlugin(String name,
String pluginCanonicalWebUrl,
PluginUser pluginUser,
- File srcJar,
+ Path srcJar,
FileSnapshot snapshot,
PluginContentScanner scanner,
- File dataDir,
+ Path dataDir,
ClassLoader classLoader) throws InvalidPluginException {
- super(name, srcJar, pluginUser, snapshot, Plugin.getApiType(getPluginManifest(scanner)));
+ super(name, srcJar, pluginUser, snapshot,
+ Plugin.getApiType(getPluginManifest(scanner)));
this.pluginCanonicalWebUrl = pluginCanonicalWebUrl;
this.scanner = scanner;
this.dataDir = dataDir;
@@ -127,10 +122,18 @@
return (Class<? extends Module>) clazz;
}
- File getSrcJar() {
+ Path getSrcJar() {
return getSrcFile();
}
+ Path getDataDir() {
+ return dataDir;
+ }
+
+ String getPluginCanonicalWebUrl() {
+ return pluginCanonicalWebUrl;
+ }
+
private static Manifest getPluginManifest(PluginContentScanner scanner)
throws InvalidPluginException {
try {
@@ -229,45 +232,11 @@
}
private Injector newRootInjector(final PluginGuiceEnvironment env) {
- List<Module> modules = Lists.newArrayListWithCapacity(4);
+ List<Module> modules = Lists.newArrayListWithCapacity(2);
if (getApiType() == ApiType.PLUGIN) {
modules.add(env.getSysModule());
}
- modules.add(new AbstractModule() {
- @Override
- protected void configure() {
- bind(PluginUser.class).toInstance(getPluginUser());
- bind(String.class)
- .annotatedWith(PluginName.class)
- .toInstance(getName());
- bind(String.class)
- .annotatedWith(PluginCanonicalWebUrl.class)
- .toInstance(pluginCanonicalWebUrl);
-
- bind(File.class)
- .annotatedWith(PluginData.class)
- .toProvider(new Provider<File>() {
- private volatile boolean ready;
-
- @Override
- public File get() {
- if (!ready) {
- synchronized (dataDir) {
- if (!ready) {
- if (!dataDir.exists() && !dataDir.mkdirs()) {
- throw new ProvisionException(String.format(
- "Cannot create %s for plugin %s",
- dataDir.getAbsolutePath(), getName()));
- }
- ready = true;
- }
- }
- }
- return dataDir;
- }
- });
- }
- });
+ modules.add(new ServerPluginInfoModule(this));
return Guice.createInjector(modules);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java
new file mode 100644
index 0000000..b0e9453
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java
@@ -0,0 +1,77 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.plugins;
+
+import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
+import com.google.gerrit.extensions.annotations.PluginData;
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.server.PluginUser;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+class ServerPluginInfoModule extends AbstractModule {
+ private final ServerPlugin plugin;
+ private final Path dataDir;
+
+ private volatile boolean ready;
+
+ ServerPluginInfoModule(ServerPlugin plugin) {
+ this.plugin = plugin;
+ this.dataDir = plugin.getDataDir();
+ }
+
+ @Override
+ protected void configure() {
+ bind(PluginUser.class).toInstance(plugin.getPluginUser());
+ bind(String.class)
+ .annotatedWith(PluginName.class)
+ .toInstance(plugin.getName());
+ bind(String.class)
+ .annotatedWith(PluginCanonicalWebUrl.class)
+ .toInstance(plugin.getPluginCanonicalWebUrl());
+ }
+
+ @Provides
+ @PluginData
+ Path getPluginData() {
+ if (!ready) {
+ synchronized (dataDir) {
+ if (!ready) {
+ try {
+ Files.createDirectories(dataDir);
+ } catch (IOException e) {
+ throw new ProvisionException(String.format(
+ "Cannot create %s for plugin %s",
+ dataDir.toAbsolutePath(), plugin.getName()), e);
+ }
+ ready = true;
+ }
+ }
+ }
+ return dataDir;
+ }
+
+ @Provides
+ @PluginData
+ File getPluginDataAsFile(@PluginData Path pluginData) {
+ return pluginData.toFile();
+ }
+}
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 37fed9b..bc2432b 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
@@ -19,7 +19,7 @@
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
-import java.io.File;
+import java.nio.file.Path;
/**
* Provider of one Server plugin from one external file
@@ -40,7 +40,7 @@
public class PluginDescription {
public final PluginUser user;
public final String canonicalUrl;
- public final File dataDir;
+ public final Path dataDir;
/**
* Creates a new PluginDescription for ServerPluginProvider.
@@ -49,7 +49,7 @@
* @param canonicalUrl plugin root Web URL
* @param dataDir directory for plugin data
*/
- public PluginDescription(PluginUser user, String canonicalUrl, File dataDir) {
+ public PluginDescription(PluginUser user, String canonicalUrl, Path dataDir) {
this.user = user;
this.canonicalUrl = canonicalUrl;
this.dataDir = dataDir;
@@ -59,39 +59,39 @@
/**
* Declares the availability to manage an external file or directory
*
- * @param srcFile the external file or directory
+ * @param srcPath the external file or directory
* @return true if file or directory can be loaded into a Server Plugin
*/
- boolean handles(File srcFile);
+ boolean handles(Path srcPath);
/**
* Returns the plugin name of an external file or directory
*
- * Should be called only if {@link #handles(File) handles(srcFile)}
+ * Should be called only if {@link #handles(Path) handles(srcFile)}
* returns true and thus srcFile is a supported plugin format.
* An IllegalArgumentException is thrown otherwise as srcFile
* is not a valid file format for extracting its plugin name.
*
- * @param srcFile external file or directory
+ * @param srcPath external file or directory
* @return plugin name
*/
- String getPluginName(File srcFile);
+ String getPluginName(Path srcPath);
/**
* Loads an external file or directory into a Server plugin.
*
- * Should be called only if {@link #handles(File) handles(srcFile)}
+ * Should be called only if {@link #handles(Path) handles(srcFile)}
* returns true and thus srcFile is a supported plugin format.
* An IllegalArgumentException is thrown otherwise as srcFile
* is not a valid file format for extracting its plugin name.
*
- * @param srcFile external file or directory
+ * @param srcPath external file or directory
* @param snapshot snapshot of the external file
* @param pluginDescriptor descriptor of the ServerPlugin to load
* @throws InvalidPluginException if plugin is supposed to be handled
* but cannot be loaded for any other reason
*/
- ServerPlugin get(File srcFile, FileSnapshot snapshot,
+ ServerPlugin get(Path srcPath, FileSnapshot snapshot,
PluginDescription pluginDescriptor) throws InvalidPluginException;
/**
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java
index 0e8bd87..afdc5b3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java
@@ -22,7 +22,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@@ -38,27 +38,26 @@
}
@Override
- public ServerPlugin get(File srcFile, FileSnapshot snapshot,
+ public ServerPlugin get(Path srcPath, FileSnapshot snapshot,
PluginDescription pluginDescription) throws InvalidPluginException {
- return providerOf(srcFile).get(srcFile, snapshot, pluginDescription);
+ return providerOf(srcPath).get(srcPath, snapshot, pluginDescription);
}
@Override
- public String getPluginName(File srcFile) {
- return providerOf(srcFile).getPluginName(srcFile);
+ public String getPluginName(Path srcPath) {
+ return providerOf(srcPath).getPluginName(srcPath);
}
@Override
- public boolean handles(File srcFile) {
- List<ServerPluginProvider> providers =
- providersForHandlingPlugin(srcFile);
+ public boolean handles(Path srcPath) {
+ List<ServerPluginProvider> providers = providersForHandlingPlugin(srcPath);
switch (providers.size()) {
case 1:
return true;
case 0:
return false;
default:
- throw new MultipleProvidersForPluginException(srcFile, providers);
+ throw new MultipleProvidersForPluginException(srcPath, providers);
}
}
@@ -67,27 +66,27 @@
return "gerrit";
}
- private ServerPluginProvider providerOf(File srcFile) {
+ private ServerPluginProvider providerOf(Path srcPath) {
List<ServerPluginProvider> providers =
- providersForHandlingPlugin(srcFile);
+ providersForHandlingPlugin(srcPath);
switch (providers.size()) {
case 1:
return providers.get(0);
case 0:
throw new IllegalArgumentException(
"No ServerPluginProvider found/loaded to handle plugin file "
- + srcFile.getAbsolutePath());
+ + srcPath.toAbsolutePath());
default:
- throw new MultipleProvidersForPluginException(srcFile, providers);
+ throw new MultipleProvidersForPluginException(srcPath, providers);
}
}
private List<ServerPluginProvider> providersForHandlingPlugin(
- final File srcFile) {
+ final Path srcPath) {
List<ServerPluginProvider> providers = new ArrayList<>();
for (ServerPluginProvider serverPluginProvider : serverPluginProviders) {
- boolean handles = serverPluginProvider.handles(srcFile);
- log.debug("File {} handled by {} ? => {}", srcFile,
+ boolean handles = serverPluginProvider.handles(srcPath);
+ log.debug("File {} handled by {} ? => {}", srcPath,
serverPluginProvider.getProviderPluginName(), handles);
if (handles) {
providers.add(serverPluginProvider);
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 daf1d4d..8829ac3 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 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 @@
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 @@
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/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
index 591601d..acfbba2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
@@ -64,7 +64,7 @@
throw new ProvisionException("Unsupported schema version "
+ currentVer.versionNbr + "; expected schema version " + expectedVer
+ ". Run init to upgrade:\n"
- + "$ java -jar " + site.gerrit_war.getAbsolutePath() + " init -d "
+ + "$ java -jar " + site.gerrit_war.toAbsolutePath() + " init -d "
+ site.site_path.getAbsolutePath());
} else if (currentVer.versionNbr > expectedVer) {
throw new ProvisionException("Unsupported schema version "
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java
index b852217..7665c64 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java
@@ -26,6 +26,7 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@@ -35,8 +36,8 @@
@Inject
DefaultSecureStore(SitePaths site) {
- File secureConfig = new File(site.etc_dir, "secure.config");
- sec = new FileBasedConfig(secureConfig, FS.DETECTED);
+ Path secureConfig = site.etc_dir.resolve("secure.config");
+ sec = new FileBasedConfig(secureConfig.toFile(), FS.DETECTED);
try {
sec.load();
} catch (Exception e) {
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 e830590..99127d8 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
+import java.nio.file.Path;
@Singleton
public class SecureStoreProvider implements Provider<SecureStore> {
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;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java
index ba31f56..d4b8457 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java
@@ -33,8 +33,8 @@
import org.eclipse.jgit.lib.Config;
import org.slf4j.LoggerFactory;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
@Singleton
public class SystemLog {
@@ -55,12 +55,12 @@
return Strings.isNullOrEmpty(System.getProperty(LOG4J_CONFIGURATION));
}
- public static Appender createAppender(File logdir, String name, Layout layout) {
+ public static Appender createAppender(Path logdir, String name, Layout layout) {
final DailyRollingFileAppender dst = new DailyRollingFileAppender();
dst.setName(name);
dst.setLayout(layout);
dst.setEncoding("UTF-8");
- dst.setFile(new File(resolve(logdir), name).getPath());
+ dst.setFile(resolve(logdir).resolve(name).toString());
dst.setImmediateFlush(true);
dst.setAppend(true);
dst.setErrorHandler(new DieErrorHandler());
@@ -90,11 +90,11 @@
return async;
}
- private static File resolve(final File logs_dir) {
+ private static Path resolve(Path p) {
try {
- return logs_dir.getCanonicalFile();
+ return p.toRealPath().normalize();
} catch (IOException e) {
- return logs_dir.getAbsoluteFile();
+ return p.toAbsolutePath().normalize();
}
}
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 5fdecf0..4808091 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 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"), 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 8686fe6..141c8e3 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.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 @@
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 72495b3..f33cfb2 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 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 @@
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-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
index 93d2e5b..ab3b446 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
@@ -14,6 +14,9 @@
package com.google.gerrit.sshd;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.gerrit.common.FileUtil;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PeerDaemonUser;
@@ -33,10 +36,10 @@
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.Collection;
@@ -170,56 +173,50 @@
}
private static class PeerKeyCache {
- private final File path;
+ private final Path path;
private final long modified;
final Set<PublicKey> keys;
- PeerKeyCache(final File path) {
+ PeerKeyCache(Path path) {
this.path = path;
- this.modified = path.lastModified();
+ this.modified = FileUtil.lastModified(path);
this.keys = read(path);
}
- private static Set<PublicKey> read(File path) {
- try {
- final BufferedReader br = new BufferedReader(new FileReader(path));
- try {
- final Set<PublicKey> keys = new HashSet<>();
- String line;
- while ((line = br.readLine()) != null) {
- line = line.trim();
- if (line.startsWith("#") || line.isEmpty()) {
- continue;
- }
-
- try {
- byte[] bin = Base64.decodeBase64(line.getBytes("ISO-8859-1"));
- keys.add(new Buffer(bin).getRawPublicKey());
- } catch (RuntimeException e) {
- logBadKey(path, line, e);
- } catch (SshException e) {
- logBadKey(path, line, e);
- }
+ private static Set<PublicKey> read(Path path) {
+ try (BufferedReader br = Files.newBufferedReader(path, UTF_8)) {
+ final Set<PublicKey> keys = new HashSet<>();
+ String line;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("#") || line.isEmpty()) {
+ continue;
}
- return Collections.unmodifiableSet(keys);
- } finally {
- br.close();
- }
- } catch (FileNotFoundException noFile) {
- return Collections.emptySet();
+ try {
+ byte[] bin = Base64.decodeBase64(line.getBytes("ISO-8859-1"));
+ keys.add(new Buffer(bin).getRawPublicKey());
+ } catch (RuntimeException e) {
+ logBadKey(path, line, e);
+ } catch (SshException e) {
+ logBadKey(path, line, e);
+ }
+ }
+ return Collections.unmodifiableSet(keys);
+ } catch (NoSuchFileException noFile) {
+ return Collections.emptySet();
} catch (IOException err) {
log.error("Cannot read " + path, err);
return Collections.emptySet();
}
}
- private static void logBadKey(File path, String line, Exception e) {
+ private static void logBadKey(Path path, String line, Exception e) {
log.warn("Invalid key in " + path + ":\n " + line, e);
}
boolean isCurrent() {
- return path.lastModified() == modified;
+ return modified == FileUtil.lastModified(path);
}
PeerKeyCache reload() {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java
index 241f853..3e6e2f5 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java
@@ -24,7 +24,8 @@
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
-import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@@ -38,29 +39,29 @@
@Override
public KeyPairProvider get() {
- final File objKey = site.ssh_key;
- final File rsaKey = site.ssh_rsa;
- final File dsaKey = site.ssh_dsa;
+ Path objKey = site.ssh_key;
+ Path rsaKey = site.ssh_rsa;
+ Path dsaKey = site.ssh_dsa;
final List<String> stdKeys = new ArrayList<>(2);
- if (rsaKey.exists()) {
- stdKeys.add(rsaKey.getAbsolutePath());
+ if (Files.exists(rsaKey)) {
+ stdKeys.add(rsaKey.toAbsolutePath().toString());
}
- if (dsaKey.exists()) {
- stdKeys.add(dsaKey.getAbsolutePath());
+ if (Files.exists(dsaKey)) {
+ stdKeys.add(dsaKey.toAbsolutePath().toString());
}
- if (objKey.exists()) {
+ if (Files.exists(objKey)) {
if (stdKeys.isEmpty()) {
SimpleGeneratorHostKeyProvider p = new SimpleGeneratorHostKeyProvider();
- p.setPath(objKey.getAbsolutePath());
+ p.setPath(objKey.toAbsolutePath().toString());
return p;
} else {
// Both formats of host key exist, we don't know which format
// should be authoritative. Complain and abort.
//
- stdKeys.add(objKey.getAbsolutePath());
+ stdKeys.add(objKey.toAbsolutePath().toString());
throw new ProvisionException("Multiple host keys exist: " + stdKeys);
}
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml
index 81d8498..17e8286 100644
--- a/gerrit-war/pom.xml
+++ b/gerrit-war/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-war</artifactId>
- <version>2.11-SNAPSHOT</version>
+ <version>2.12-SNAPSHOT</version>
<packaging>war</packaging>
<name>Gerrit Code Review - WAR</name>
<description>Gerrit WAR</description>
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 6bbbd8f..ea4a3ea 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 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 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 @@
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 b97df3f..60f389e 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.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<File> {
- private final File path;
+/** Provides {@link Path} annotated with {@link SitePath}. */
+class SitePathFromSystemConfigProvider implements Provider<Path> {
+ private final Path path;
@Inject
SitePathFromSystemConfigProvider(SchemaFactory<ReviewDb> schemaFactory)
@@ -36,18 +37,18 @@
}
@Override
- public File get() {
+ public Path get() {
return path;
}
- private static File read(SchemaFactory<ReviewDb> schemaFactory)
+ private static Path read(SchemaFactory<ReviewDb> schemaFactory)
throws OrmException {
ReviewDb db = schemaFactory.open();
try {
List<SystemConfig> 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 15e2daa..eb4c792 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.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 @@
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 @@
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 @@
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 @@
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);
}
});
diff --git a/plugins/cookbook-plugin b/plugins/cookbook-plugin
index 4c295fd..cbcc3ca 160000
--- a/plugins/cookbook-plugin
+++ b/plugins/cookbook-plugin
@@ -1 +1 @@
-Subproject commit 4c295fd3829725af769dc3c37db9df1c562e24a3
+Subproject commit cbcc3cac14604ff2194473b38d268dbcfa8f1dcc
diff --git a/plugins/replication b/plugins/replication
index 3973b31..2b86260 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 3973b31f3c86cc5401ef2dfac5ac82f25d79e432
+Subproject commit 2b862605ef89a3c6858ace37ee048b526f8dcd35