Merge branch 'stable-2.15'

* stable-2.15:
  Format Configuration class with google-java-format
  Extract configuration to a separate class
  Compile against Gerrit 2.15.1
  Update bazlets to latest stable-2.15 to use 2.15.1 API
  Format Java files with google-java-format 1.5
  Update bazlets to latest stable-2.14 to use 2.14.8 API
  Use log built-in string formatting

Change-Id: Ifc891a1dfa31d8b5918b6f887fef38c1b36565d0
diff --git a/WORKSPACE b/WORKSPACE
index f8451b4..9261d31 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,27 +3,27 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "df6622a4e725b4d0bad99377f05749171a8c94b9",
+    commit = "2c89b78092943e040377db8aad4568f426ac785a",
     #    local_path = "/home/<user>/projects/bazlets",
 )
 
 #Snapshot Plugin API
-#load(
-#    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
-#    "gerrit_api_maven_local",
-#)
-
-# Load snapshot Plugin API
-#gerrit_api_maven_local()
-
-# Release Plugin API
 load(
-    "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
-    "gerrit_api",
+    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
+    "gerrit_api_maven_local",
 )
 
+# Load snapshot Plugin API
+gerrit_api_maven_local()
+
+# Release Plugin API
+#load(
+#    "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
+#    "gerrit_api",
+#)
+
 # Load release Plugin API
-gerrit_api()
+#gerrit_api()
 
 load("//:external_plugin_deps.bzl", "external_plugin_deps")
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteAction.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteAction.java
index 9ebfd34..a6e0556 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteAction.java
@@ -71,6 +71,6 @@
   }
 
   private boolean isAllProjects(ProjectResource rsrc) {
-    return (rsrc.getControl().getProject().getNameKey().equals(allProjectsName));
+    return (rsrc.getProjectState().getProject().getNameKey().equals(allProjectsName));
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java
index f7124e4..a804b3f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java
@@ -14,11 +14,9 @@
 
 package com.googlesource.gerrit.plugins.deleteproject;
 
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.sshd.CommandMetaData;
 import com.google.gerrit.sshd.SshCommand;
 import com.google.gwtorm.server.OrmException;
@@ -31,7 +29,7 @@
 @CommandMetaData(name = "delete", description = "Delete specific project")
 public final class DeleteCommand extends SshCommand {
   @Argument(index = 0, required = true, metaVar = "NAME", usage = "project to delete")
-  private ProjectControl projectControl;
+  private ProjectState projectState;
 
   @Option(name = "--yes-really-delete", usage = "confirmation to delete the project")
   private boolean yesReallyDelete;
@@ -56,7 +54,7 @@
       input.force = force;
       input.preserve = preserveGitRepository;
 
-      ProjectResource rsrc = new ProjectResource(projectControl);
+      ProjectResource rsrc = new ProjectResource(projectState, user);
       deleteProject.assertDeletePermission(rsrc);
       deleteProject.assertCanDelete(rsrc, input);
 
@@ -93,11 +91,7 @@
       }
 
       deleteProject.doDelete(rsrc, input);
-    } catch (AuthException
-        | ResourceNotFoundException
-        | ResourceConflictException
-        | OrmException
-        | IOException e) {
+    } catch (RestApiException | OrmException | IOException e) {
       throw die(e);
     }
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java
index 292d8bd..c3aefbc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java
@@ -16,13 +16,13 @@
 
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.MultimapBuilder;
-import com.google.gerrit.audit.AuditEvent;
-import com.google.gerrit.audit.AuditService;
 import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.extensions.systemstatus.ServerInformation;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.OutputFormat;
+import com.google.gerrit.server.audit.AuditEvent;
+import com.google.gerrit.server.audit.AuditService;
 import com.google.gerrit.server.util.PluginLogFile;
 import com.google.gerrit.server.util.SystemLog;
 import com.google.inject.Inject;
@@ -73,7 +73,9 @@
             );
 
     event.setProperty(ACCOUNT_ID, user.getAccountId().toString());
-    event.setProperty(USER_NAME, user.getUserName());
+    if (user.getUserName().isPresent()) {
+      event.setProperty(USER_NAME, user.getUserName().get());
+    }
     event.setProperty(PROJECT_NAME, project.get());
 
     if (options != null) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java
index 97c3726..36fb12f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.Response;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
@@ -32,6 +33,7 @@
 import com.google.gerrit.server.notedb.NotesMigration;
 import com.google.gerrit.server.permissions.GlobalPermission;
 import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.ProjectPermission;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
@@ -94,8 +96,7 @@
 
   @Override
   public Object apply(ProjectResource rsrc, Input input)
-      throws ResourceNotFoundException, ResourceConflictException, OrmException, IOException,
-          AuthException {
+      throws OrmException, IOException, RestApiException {
     assertDeletePermission(rsrc);
     assertCanDelete(rsrc, input);
 
@@ -118,17 +119,18 @@
   }
 
   protected boolean canDelete(ProjectResource rsrc) {
-    PermissionBackend.WithUser userPermission = permissionBackend.user(userProvider);
+    PermissionBackend.WithUser userPermission = permissionBackend.currentUser();
+    PermissionBackend.ForProject projectPermission = userPermission.project(rsrc.getNameKey());
     return userPermission.testOrFalse(GlobalPermission.ADMINISTRATE_SERVER)
         || userPermission.testOrFalse(new PluginPermission(pluginName, DELETE_PROJECT))
         || (userPermission.testOrFalse(new PluginPermission(pluginName, DELETE_OWN_PROJECT))
-            && rsrc.getControl().isOwner());
+            && projectPermission.testOrFalse(ProjectPermission.WRITE_CONFIG));
   }
 
   public void assertCanDelete(ProjectResource rsrc, Input input) throws ResourceConflictException {
     try {
       pcHandler.assertCanDelete(rsrc);
-      dbHandler.assertCanDelete(rsrc.getControl().getProject());
+      dbHandler.assertCanDelete(rsrc.getProjectState().getProject());
       fsHandler.assertCanDelete(rsrc, input == null ? false : input.preserve);
     } catch (CannotDeleteProjectException e) {
       throw new ResourceConflictException(e.getMessage());
@@ -136,12 +138,12 @@
   }
 
   public Collection<String> getWarnings(ProjectResource rsrc) throws OrmException {
-    return dbHandler.getWarnings(rsrc.getControl().getProject());
+    return dbHandler.getWarnings(rsrc.getProjectState().getProject());
   }
 
   public void doDelete(ProjectResource rsrc, Input input)
-      throws OrmException, IOException, ResourceNotFoundException, ResourceConflictException {
-    Project project = rsrc.getControl().getProject();
+      throws OrmException, IOException, RestApiException {
+    Project project = rsrc.getProjectState().getProject();
     boolean preserve = input != null && input.preserve;
     Exception ex = null;
     try {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java
index 8b60ae3..6030e94 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java
@@ -16,18 +16,17 @@
 
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.CreateProject;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.restapi.project.CreateProject;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
@@ -54,8 +53,7 @@
     this.cfg = cfg;
   }
 
-  public void apply(ProjectResource rsrc)
-      throws ResourceNotFoundException, ResourceConflictException, IOException {
+  public void apply(ProjectResource rsrc) throws IOException, RestApiException {
     try {
       MetaDataUpdate md = metaDataUpdateFactory.create(rsrc.getNameKey());
 
@@ -81,16 +79,11 @@
     }
   }
 
-  private void createProjectIfMissing(String projectName)
-      throws ResourceConflictException, IOException {
+  private void createProjectIfMissing(String projectName) throws IOException, RestApiException {
     if (projectCache.get(new Project.NameKey(projectName)) == null) {
       try {
         createProjectFactory.create(projectName).apply(TopLevelResource.INSTANCE, null);
-      } catch (BadRequestException
-          | UnprocessableEntityException
-          | ResourceNotFoundException
-          | ConfigInvalidException
-          | PermissionBackendException e) {
+      } catch (RestApiException | ConfigInvalidException | PermissionBackendException e) {
         throw new ResourceConflictException(
             String.format("Failed to create project %s", projectName));
       }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java
index bdf3ff5..c453478 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java
@@ -17,6 +17,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
+import java.io.IOException;
 
 public class CacheDeleteHandler {
 
@@ -27,7 +28,7 @@
     this.projectCache = projectCache;
   }
 
-  public void delete(Project project) {
+  public void delete(Project project) throws IOException {
     projectCache.remove(project);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java
index 5eecef6..b2daea2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java
@@ -27,20 +27,20 @@
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.reviewdb.server.ReviewDbUtil;
 import com.google.gerrit.server.StarredChangesUtil;
+import com.google.gerrit.server.UserInitiated;
 import com.google.gerrit.server.account.AccountState;
-import com.google.gerrit.server.account.WatchConfig;
-import com.google.gerrit.server.account.WatchConfig.Accessor;
-import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
+import com.google.gerrit.server.account.AccountsUpdate;
+import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
 import com.google.gerrit.server.change.AccountPatchReviewStore;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.MergeOpRepoManager;
-import com.google.gerrit.server.git.SubmoduleException;
-import com.google.gerrit.server.git.SubmoduleOp;
 import com.google.gerrit.server.index.change.ChangeIndexer;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gerrit.server.submit.MergeOpRepoManager;
+import com.google.gerrit.server.submit.SubmoduleException;
+import com.google.gerrit.server.submit.SubmoduleOp;
 import com.google.gwtorm.jdbc.JdbcSchema;
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.ResultSet;
@@ -74,7 +74,7 @@
   private final DynamicItem<AccountPatchReviewStore> accountPatchReviewStore;
   private final ChangeIndexer indexer;
   private final Provider<InternalAccountQuery> accountQueryProvider;
-  private final Provider<Accessor> watchConfig;
+  private final Provider<AccountsUpdate> accountsUpdateProvider;
 
   @Inject
   public DatabaseDeleteHandler(
@@ -87,9 +87,7 @@
       DynamicItem<AccountPatchReviewStore> accountPatchReviewStore,
       ChangeIndexer indexer,
       Provider<InternalAccountQuery> accountQueryProvider,
-      Provider<WatchConfig.Accessor> watchConfig) {
-    this.accountQueryProvider = accountQueryProvider;
-    this.watchConfig = watchConfig;
+      @UserInitiated Provider<AccountsUpdate> accountsUpdateProvider) {
     this.db = ReviewDbUtil.unwrapDb(db);
     this.queryProvider = queryProvider;
     this.repoManager = repoManager;
@@ -98,6 +96,8 @@
     this.starredChangesUtil = starredChangesUtil;
     this.accountPatchReviewStore = accountPatchReviewStore;
     this.indexer = indexer;
+    this.accountQueryProvider = accountQueryProvider;
+    this.accountsUpdateProvider = accountsUpdateProvider;
   }
 
   public Collection<String> getWarnings(Project project) throws OrmException {
@@ -205,7 +205,12 @@
       for (ProjectWatchKey watchKey : a.getProjectWatches().keySet()) {
         if (project.getNameKey().equals(watchKey.project())) {
           try {
-            watchConfig.get().deleteProjectWatches(accountId, singleton(watchKey));
+            accountsUpdateProvider
+                .get()
+                .update(
+                    "Delete Project Watches via API",
+                    accountId,
+                    u -> u.deleteProjectWatches(singleton(watchKey)));
           } catch (IOException | ConfigInvalidException e) {
             log.error(
                 "Removing watch entry for user {} in project {} failed.",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java
index 30486da..12fe3e9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java
@@ -18,13 +18,14 @@
 import com.google.common.base.Joiner;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.extensions.common.ProjectInfo;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.AllProjectsNameProvider;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.ListChildProjects;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.restapi.project.ListChildProjects;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.googlesource.gerrit.plugins.deleteproject.CannotDeleteProjectException;
@@ -47,19 +48,22 @@
     this.listChildProjectsProvider = listChildProjectsProvider;
   }
 
-  public void assertCanDelete(ProjectResource rsrc) throws CannotDeleteProjectException {
+  public void assertCanDelete(ProjectResource rsrc)
+      throws CannotDeleteProjectException, ResourceConflictException {
     assertIsNotAllProjects(rsrc);
     assertHasNoChildProjects(rsrc);
   }
 
-  private void assertIsNotAllProjects(ProjectResource rsrc) throws CannotDeleteProjectException {
-    Project project = rsrc.getControl().getProject();
+  private void assertIsNotAllProjects(ProjectResource rsrc)
+      throws CannotDeleteProjectException, ResourceConflictException {
+    Project project = rsrc.getProjectState().getProject();
     if (project.getNameKey().equals(allProjectsName)) {
       throw new CannotDeleteProjectException("Perhaps you meant to rm -fR " + site.site_path);
     }
   }
 
-  private void assertHasNoChildProjects(ProjectResource rsrc) throws CannotDeleteProjectException {
+  private void assertHasNoChildProjects(ProjectResource rsrc)
+      throws CannotDeleteProjectException, ResourceConflictException {
     try {
       List<ProjectInfo> children = listChildProjectsProvider.get().apply(rsrc);
       if (!children.isEmpty()) {