Merge branch 'stable-2.15' into stable-2.16

* stable-2.15:
  Upgrade mockito-core to 2.27.0

Change-Id: I88885d93424a9f9648feaf43907453d1f529a2b6
diff --git a/WORKSPACE b/WORKSPACE
index 6a25731..033eec2 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "8386b3fbf80e375f0a10c8386c0a8dfe260c5c1b",
+    commit = "c827ba79413585ab9dfc1bbd0d7f609eedd6aa80",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/AccountLimitsFinder.java b/src/main/java/com/googlesource/gerrit/plugins/quota/AccountLimitsFinder.java
index 43d3a19..369f7bf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/AccountLimitsFinder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/quota/AccountLimitsFinder.java
@@ -16,10 +16,15 @@
 import static com.googlesource.gerrit.plugins.quota.AccountLimitsConfig.KEY;
 
 import com.google.gerrit.common.data.GroupDescription;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.GroupMembership;
-import com.google.gerrit.server.group.GroupsCollection;
+import com.google.gerrit.server.group.GroupResource;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.restapi.group.GroupsCollection;
 import com.google.inject.Inject;
 import com.googlesource.gerrit.plugins.quota.AccountLimitsConfig.RateLimit;
 import com.googlesource.gerrit.plugins.quota.AccountLimitsConfig.Type;
@@ -51,11 +56,19 @@
     if (limits.isPresent()) {
       GroupMembership memberShip = user.getEffectiveGroups();
       for (String groupName : limits.get().keySet()) {
-        GroupDescription.Basic d = groupsCollection.parseId(groupName);
-        if (d == null) {
+        try {
+          GroupResource group =
+              groupsCollection.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(groupName));
+          Optional<GroupDescription.Internal> maybeInternalGroup = group.asInternalGroup();
+          if (!maybeInternalGroup.isPresent()) {
+            log.debug("Ignoring limits for non-internal group ''{}'' in quota.config", groupName);
+          } else if (memberShip.contains(maybeInternalGroup.get().getGroupUUID())) {
+            return Optional.ofNullable(limits.get().get(groupName));
+          }
+        } catch (ResourceNotFoundException e) {
           log.debug("Ignoring limits for unknown group ''{}'' in quota.config", groupName);
-        } else if (memberShip.contains(d.getGroupUUID())) {
-          return Optional.ofNullable(limits.get().get(groupName));
+        } catch (AuthException e) {
+          log.debug("Ignoring limits for non-visible group ''{}'' in quota.config", groupName);
         }
       }
     }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/ListQuotas.java b/src/main/java/com/googlesource/gerrit/plugins/quota/ListQuotas.java
index 1d8061c..d683de9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/ListQuotas.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/quota/ListQuotas.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.ConfigResource;
-import com.google.gerrit.server.project.ListProjects;
+import com.google.gerrit.server.restapi.project.ListProjects;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.googlesource.gerrit.plugins.quota.GetQuota.QuotaInfo;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java b/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java
index d1f1505..d6b8d87 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java
@@ -35,10 +35,10 @@
 import java.nio.file.Path;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.time.Duration;
 import java.util.Collection;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import org.apache.commons.lang.mutable.MutableLong;
 import org.eclipse.jgit.internal.storage.file.FileRepository;
@@ -64,7 +64,7 @@
       protected void configure() {
         persist(REPO_SIZE_CACHE, Project.NameKey.class, AtomicLong.class)
             .loader(Loader.class)
-            .expireAfterWrite(1, TimeUnit.DAYS);
+            .expireAfterWrite(Duration.ofDays(1));
         bind(RepoSizeCache.class).to(MaxRepositorySizeQuota.class);
       }
     };
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/PublisherScheduler.java b/src/main/java/com/googlesource/gerrit/plugins/quota/PublisherScheduler.java
index bfa95f3..c253c5f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/PublisherScheduler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/quota/PublisherScheduler.java
@@ -14,13 +14,12 @@
 
 package com.googlesource.gerrit.plugins.quota;
 
-import static com.google.gerrit.server.config.ScheduleConfig.MISSING_CONFIG;
-
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.ScheduleConfig;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.inject.Inject;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.lib.Config;
 import org.slf4j.Logger;
@@ -31,28 +30,30 @@
   private static final Logger log = LoggerFactory.getLogger(PublisherScheduler.class);
   private final WorkQueue workQueue;
   private final Publisher publisher;
-  private final ScheduleConfig scheduleConfig;
+  private final Optional<ScheduleConfig.Schedule> scheduleConfig;
 
   @Inject
   PublisherScheduler(WorkQueue workQueue, Publisher publisher, @GerritServerConfig Config cfg) {
     this.workQueue = workQueue;
     this.publisher = publisher;
     scheduleConfig =
-        new ScheduleConfig(cfg, "plugin", "quota", "publicationInterval", "publicationStartTime");
+        ScheduleConfig.builder(cfg, "plugin")
+            .setSubsection("quota")
+            .setKeyInterval("publicationInterval")
+            .setKeyStartTime("publicationStartTime")
+            .buildSchedule();
   }
 
   @Override
   public void start() {
-    long interval = scheduleConfig.getInterval();
-    long delay = scheduleConfig.getInitialDelay();
-    if (delay == MISSING_CONFIG && interval == MISSING_CONFIG) {
+    if (!scheduleConfig.isPresent()) {
       log.info("Ignoring missing schedule configuration");
-    } else if (delay < 0 || interval <= 0) {
-      log.warn("Ignoring invalid schedule configuration");
     } else {
+      ScheduleConfig.Schedule schedule = scheduleConfig.get();
       workQueue
           .getDefaultQueue()
-          .scheduleAtFixedRate(publisher, delay, interval, TimeUnit.MILLISECONDS);
+          .scheduleAtFixedRate(
+              publisher, schedule.initialDelay(), schedule.interval(), TimeUnit.MILLISECONDS);
     }
   }
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherExceptionTest.java b/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherExceptionTest.java
index f2d84c5..fa7351e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherExceptionTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherExceptionTest.java
@@ -43,12 +43,12 @@
   public void setupClassUnderTest() {
     listener = createMock(UsageDataPublishedListener.class);
     listeners = DynamicSet.emptySet();
-    listeners.add(listener);
+    listeners.add("quota", listener);
 
     creator = createMock(UsageDataEventCreator.class);
     expect(creator.getName()).andStubReturn(CREATOR_NAME);
     creators = DynamicSet.emptySet();
-    creators.add(creator);
+    creators.add("quota", creator);
 
     classUnderTest = new Publisher(listeners, creators);
   }
@@ -87,7 +87,7 @@
     UsageDataEventCreator good = createMock(UsageDataEventCreator.class);
     Event data = new UsageDataEvent(null);
     expect(good.create()).andStubReturn(data);
-    creators.add(good);
+    creators.add("quota", good);
 
     listener.onUsageDataPublished(data);
     expectLastCall();
@@ -130,7 +130,7 @@
 
     UsageDataPublishedListener good = createMock(UsageDataPublishedListener.class);
     good.onUsageDataPublished(data);
-    listeners.add(good);
+    listeners.add("quota", good);
 
     replay(listener, good, creator, appender);
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherTest.java b/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherTest.java
index b86e87d..d78b7e1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/quota/PublisherTest.java
@@ -38,8 +38,8 @@
     expect(c2.create()).andStubReturn(e2);
 
     DynamicSet<UsageDataEventCreator> creators = DynamicSet.emptySet();
-    creators.add(c1);
-    creators.add(c2);
+    creators.add("quota", c1);
+    creators.add("quota", c2);
 
     UsageDataPublishedListener listener = createMock(UsageDataPublishedListener.class);
     listener.onUsageDataPublished(e1);
@@ -49,7 +49,7 @@
 
     replay(c1, c2, listener);
     DynamicSet<UsageDataPublishedListener> listeners = DynamicSet.emptySet();
-    listeners.add(listener);
+    listeners.add("quota", listener);
 
     Publisher classUnderTest = new Publisher(listeners, creators);
     classUnderTest.run();
@@ -63,7 +63,7 @@
     UsageDataEventCreator creator = createMock(UsageDataEventCreator.class);
     expect(creator.create()).andStubReturn(event);
     DynamicSet<UsageDataEventCreator> creators = DynamicSet.emptySet();
-    creators.add(creator);
+    creators.add("quota", creator);
 
     UsageDataPublishedListener l1 = createMock(UsageDataPublishedListener.class);
     l1.onUsageDataPublished(event);
@@ -76,8 +76,8 @@
     replay(creator, l1, l2);
 
     DynamicSet<UsageDataPublishedListener> listeners = DynamicSet.emptySet();
-    listeners.add(l1);
-    listeners.add(l2);
+    listeners.add("quota", l1);
+    listeners.add("quota", l2);
 
     Publisher classUnderTest = new Publisher(listeners, creators);
     classUnderTest.run();
@@ -90,7 +90,7 @@
     UsageDataEventCreator creator = createMock(UsageDataEventCreator.class);
     replay(creator);
     DynamicSet<UsageDataEventCreator> creators = DynamicSet.emptySet();
-    creators.add(creator);
+    creators.add("quota", creator);
 
     DynamicSet<UsageDataPublishedListener> listeners = DynamicSet.emptySet();
     Publisher classUnderTest = new Publisher(listeners, creators);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/quota/RepoSizeEventCreatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/quota/RepoSizeEventCreatorTest.java
index 1da13f1..0028a04 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/quota/RepoSizeEventCreatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/quota/RepoSizeEventCreatorTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.google.common.collect.ImmutableSortedSet;
 import com.google.gerrit.extensions.events.UsageDataPublishedListener.Data;
 import com.google.gerrit.extensions.events.UsageDataPublishedListener.Event;
 import com.google.gerrit.reviewdb.client.Project;
@@ -29,7 +30,6 @@
 import com.google.gwtorm.server.StandardKeyEncoder;
 import java.io.File;
 import java.io.IOException;
-import java.util.Arrays;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -53,7 +53,7 @@
     tmp.delete();
     tmp.mkdir();
     projectCache = createMock(ProjectCache.class);
-    Iterable<Project.NameKey> projects = Arrays.asList(p1, p2, p3);
+    ImmutableSortedSet<Project.NameKey> projects = ImmutableSortedSet.of(p1, p2, p3);
     expect(projectCache.all()).andStubReturn(projects);
     repoSizeCache = createNiceMock(RepoSizeCache.class);
     replay(projectCache);