Merge branch 'stable-3.0' into stable-3.1

* stable-3.0:
  Clarify OWNERS use with both directory and matchers
  Upgrade bazlets to latest stable-3.0
  Upgrade bazlets to latest stable-2.16
  Add reviewers from OWNERS all at once
  Implement visibility using permission backend
  Do not assign reviewers that cannot see the change
  Fix NPE when target branch doesn't exist
  Make transitive starlark loads explicit
  Format java files with google-java-format
  Create a user-context if not propagated by Gerrit

Change-Id: If2157c1b867c24f683fa90f4a7bd2b7e5d778794
diff --git a/BUILD b/BUILD
index b52c2c1..548e6a8 100644
--- a/BUILD
+++ b/BUILD
@@ -1,6 +1,6 @@
 load("//tools:genrule2.bzl", "genrule2")
 load("//tools/bzl:plugin.bzl", "PLUGIN_TEST_DEPS")
-load("//owners-common:common.bzl", "EXTERNAL_DEPS")
+load("//owners-common:common.bzl", "EXTERNAL_DEPS", "EXTERNAL_TEST_DEPS")
 
 genrule2(
     name = "all",
@@ -21,7 +21,7 @@
     name = "owners_classpath_deps",
     testonly = 1,
     visibility = ["//visibility:public"],
-    exports = EXTERNAL_DEPS + PLUGIN_TEST_DEPS + [
+    exports = EXTERNAL_DEPS + EXTERNAL_TEST_DEPS + PLUGIN_TEST_DEPS + [
         "//owners:owners__plugin",
         "//owners-autoassign:owners-autoassign__plugin",
         "//owners-common:owners-common__plugin",
diff --git a/README.md b/README.md
index aee2d8e..4c9519f 100644
--- a/README.md
+++ b/README.md
@@ -55,8 +55,8 @@
 The output is created in
 
 ```
-  bazel-genfiles/owners/owners.jar
-  bazel-genfiles/owners-autoassign/owners-autoassign.jar
+  bazel-bin/owners/owners.jar
+  bazel-bin/owners-autoassign/owners-autoassign.jar
 
 ```
 
@@ -104,8 +104,8 @@
 The output is created in
 
 ```
-  bazel-genfiles/plugins/owners/owners.jar
-  bazel-genfiles/plugins/owners-autoassign/owners-autoassign.jar
+  bazel-bin/plugins/owners/owners.jar
+  bazel-bin/plugins/owners-autoassign/owners-autoassign.jar
 ```
 
 To execute the tests run:
diff --git a/WORKSPACE b/WORKSPACE
index 5c0cb74..96a6228 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "7472a1104a37d514799100d6556445836e8efe4c",
+    commit = "56aafc4c0bb1b72fba34f5bdfb29ddb1e1a17801",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 7c6aa5c..bca48e4 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -33,3 +33,68 @@
         artifact = "org.yaml:snakeyaml:1.23",
         sha1 = "ec62d74fe50689c28c0ff5b35d3aebcaa8b5be68",
     )
+
+    maven_jar(
+        name = "easymock",
+        artifact = "org.easymock:easymock:3.1",
+        sha1 = "3e127311a86fc2e8f550ef8ee4abe094bbcf7e7e",
+        deps = [
+            "@cglib//jar",
+            "@objenesis//jar",
+        ],
+    )
+
+    maven_jar(
+        name = "cglib",
+        artifact = "cglib:cglib-nodep:3.2.6",
+        sha1 = "92bf48723d277d6efd1150b2f7e9e1e92cb56caf",
+    )
+
+    maven_jar(
+        name = "objenesis",
+        artifact = "org.objenesis:objenesis:2.6",
+        sha1 = "639033469776fd37c08358c6b92a4761feb2af4b",
+    )
+
+    POWERM_VERS = "1.6.1"
+    maven_jar(
+        name = "powermock-module-junit4",
+        artifact = "org.powermock:powermock-module-junit4:" + POWERM_VERS,
+        sha1 = "ea8530b2848542624f110a393513af397b37b9cf",
+    )
+
+    maven_jar(
+        name = "powermock-module-junit4-common",
+        artifact = "org.powermock:powermock-module-junit4-common:" + POWERM_VERS,
+        sha1 = "7222ced54dabc310895d02e45c5428ca05193cda",
+    )
+
+    maven_jar(
+        name = "powermock-reflect",
+        artifact = "org.powermock:powermock-reflect:" + POWERM_VERS,
+        sha1 = "97d25eda8275c11161bcddda6ef8beabd534c878",
+    )
+
+    maven_jar(
+        name = "powermock-api-easymock",
+        artifact = "org.powermock:powermock-api-easymock:" + POWERM_VERS,
+        sha1 = "aa740ecf89a2f64d410b3d93ef8cd6833009ef00",
+    )
+
+    maven_jar(
+        name = "powermock-api-support",
+        artifact = "org.powermock:powermock-api-support:" + POWERM_VERS,
+        sha1 = "592ee6d929c324109d3469501222e0c76ccf0869",
+    )
+
+    maven_jar(
+        name = "powermock-core",
+        artifact = "org.powermock:powermock-core:" + POWERM_VERS,
+        sha1 = "5afc1efce8d44ed76b30af939657bd598e45d962",
+    )
+
+    maven_jar(
+        name = "javassist",
+        artifact = "org.javassist:javassist:3.22.0-GA",
+        sha1 = "3e83394258ae2089be7219b971ec21a8288528ad",
+    )
diff --git a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java
index 4a34958..ac101df 100644
--- a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java
+++ b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java
@@ -19,6 +19,10 @@
 import static com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace.IGNORE_NONE;
 
 import com.google.common.collect.Sets;
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.extensions.annotations.Listen;
 import com.google.gerrit.extensions.api.GerritApi;
@@ -28,10 +32,6 @@
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
 import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.patch.PatchList;
@@ -89,7 +89,7 @@
     if (currentUser.isIdentifiedUser()) {
       handleGitReferenceUpdated(event);
     } else if (updaterAccountInfo != null) {
-      handleGitReferenceUpdatedAsUser(event, new Account.Id(updaterAccountInfo._accountId));
+      handleGitReferenceUpdatedAsUser(event, Account.id(updaterAccountInfo._accountId));
     } else {
       handleGitReferenceUpdatedAsServer(event);
     }
@@ -135,7 +135,7 @@
     // The provider injected by Gerrit is shared with other workers on the
     // same local thread and thus cannot be closed in this event listener.
     try {
-      ChangeApi cApi = changes.id(cId.id);
+      ChangeApi cApi = changes.id(cId.get());
       ChangeInfo change = cApi.get();
       if (change == null) {
         return;
@@ -166,7 +166,7 @@
 
     PatchListKey plKey = PatchListKey.againstCommit(null, newId, IGNORE_NONE);
     try {
-      return patchListCache.get(plKey, new Project.NameKey(change.project));
+      return patchListCache.get(plKey, Project.nameKey(change.project));
     } catch (PatchListNotAvailableException e) {
       logger.warn("Could not load patch list: {}", plKey, e);
     }
diff --git a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java
index 3634cbe..c3708b5 100644
--- a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java
+++ b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java
@@ -16,17 +16,15 @@
 
 package com.googlesource.gerrit.owners.common;
 
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.api.GerritApi;
 import com.google.gerrit.extensions.api.changes.AddReviewerInput;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Account.Id;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.permissions.ChangePermission;
 import com.google.gerrit.server.permissions.PermissionBackend;
@@ -69,13 +67,13 @@
     try {
       ChangeInfo changeInfo = cApi.get();
       try (ManualRequestContext ctx =
-          requestContext.openAs(new Account.Id(changeInfo.owner._accountId))) {
+          requestContext.openAs(Account.id(changeInfo.owner._accountId))) {
         // TODO(davido): Switch back to using changes API again,
         // when it supports batch mode for adding reviewers
         ReviewInput in = new ReviewInput();
         in.reviewers = new ArrayList<>(reviewers.size());
         for (Account.Id account : reviewers) {
-          if (isVisibleTo(ctx.getReviewDbProvider().get(), changeInfo, account)) {
+          if (isVisibleTo(changeInfo, account)) {
             AddReviewerInput addReviewerInput = new AddReviewerInput();
             addReviewerInput.reviewer = account.toString();
             in.reviewers.add(addReviewerInput);
@@ -94,10 +92,10 @@
     }
   }
 
-  private boolean isVisibleTo(ReviewDb reviewDb, ChangeInfo changeInfo, Id account) {
+  private boolean isVisibleTo(ChangeInfo changeInfo, Account.Id account) {
     ChangeData changeData =
         changeDataFactory.create(
-            reviewDb, new Project.NameKey(changeInfo.project), new Change.Id(changeInfo._number));
+            Project.nameKey(changeInfo.project), Change.id(changeInfo._number));
     return permissionBackend
         .user(userFactory.create(account))
         .change(changeData)
diff --git a/owners-autoassign/src/main/resources/Documentation/config.md b/owners-autoassign/src/main/resources/Documentation/config.md
deleted file mode 120000
index beb6012..0000000
--- a/owners-autoassign/src/main/resources/Documentation/config.md
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../config.md
\ No newline at end of file
diff --git a/owners-autoassign/src/main/resources/Documentation/config.md b/owners-autoassign/src/main/resources/Documentation/config.md
new file mode 100644
index 0000000..b294ae8
--- /dev/null
+++ b/owners-autoassign/src/main/resources/Documentation/config.md
@@ -0,0 +1,270 @@
+## Configuration
+
+Owner approval is determined based on OWNERS files located in the same
+repository on the target branch of the changes uploaded for review.
+
+The `OWNERS` file has the following YAML structure:
+
+```yaml
+inherited: true
+owners:
+- some.email@example.com
+- User Name
+- group/Group of Users
+matchers:
+- suffix: .java
+  owners:
+      [...]
+- regex: .*/README.*
+  owners:
+      [...]
+- partial_regex: example
+  owners:
+      [...]
+- exact: path/to/file.txt
+      [...]
+```
+
+_NOTE: Be aware to double check that emails and full user names correspond to
+valid registered Gerrit users. When owner user full name or e-mail cannot be
+resolved, a corresponding WARN message is logged on Gerrit error_log and the
+user entry dropped._
+
+That translates to inheriting owner email address from any parent OWNER files
+and to define 'some.email@example.com' or 'User Name' users as the mandatory
+reviewers for all changes that include modification to those files.
+
+To specify a group of people instead of naming individual owners, prefix the
+group name or UUID with 'group/'.
+
+Additional owners can be specified for files selected by other matching
+conditions (matchers section). Matching can be done by file suffix, regex
+(partial or full) and exact string comparison. For exact match, path is
+relative to the root of the repo.
+
+The plugin analyzes the latest patch set by looking at each file directory and
+building an OWNERS hierarchy. It stops once it finds an OWNERS file that has
+“inherited” set to false (by default it’s true.)
+
+For example, imagine the following tree:
+
+```
+/OWNERS
+/example/src/main/OWNERS
+/example/src/main/java/com/example/foo/Foo.java
+/example/src/main/resources/config.properties
+/example/src/test/OWNERS
+/example/src/test/java/com/example/foo/FooTest.java
+```
+
+If you submit a patch set that changes /example/src/main/java/com/example/foo/Foo.java
+then the plugin will first open /example/src/main/OWNERS and if inherited is set
+to true combine it with the owners listed in /OWNERS.
+
+If for each patch there is a reviewer who gave a Code-Review +2 then the plugin
+will not add any labels, otherwise, it will add ```label('Code-Review from owners', need(_)).```
+
+## Global project OWNERS
+
+Set a OWNERS file into the project refs/meta/config to define a global set of
+rules applied to every change pushed, regardless of the folder or target branch.
+
+Example of assigning every configuration files to a specific owner group:
+
+```yaml
+matchers:
+- suffix: .config
+  owners:
+  - Configuration Managers
+```
+
+Global refs/meta/config OWNERS configuration is inherited only when the OWNERS file
+contain the 'inherited: true' condition at the top of the file or if they are absent.
+
+That means that in the absence of any OWNERS file in the target branch, the refs/meta/config
+OWNERS is used as global default.
+
+
+## Example 1 - OWNERS file without matchers and default Gerrit submit rules
+
+Given an OWNERS configuration of:
+
+```yaml
+inherited: true
+owners:
+- John Doe
+- Doug Smith
+```
+
+And sample rules.pl that uses this predicate to enable the submit rule if
+one of the owners has given a Code Review +2
+
+```prolog
+submit_rule(S) :-
+  gerrit:default_submit(D),
+  D =.. [submit | Ds],
+  findall(U, gerrit:commit_label(label('Code-Review', 2), U), Approvers),
+  gerrit_owners:add_owner_approval(Approvers, Ds, A),
+  S =.. [submit | A].
+```
+
+Then Gerrit would evaluate the Prolog rule as follows:
+
+It first gets the current default on rule which gives ok() if no Code-Review -2
+and at least a Code-Review +2 is being provided.
+
+Then it accumulates in Approvers the list of users who had given Code-Review +2
+and then checks if this list contains either 'John Doe' or 'Doug Smith'.
+
+If Approvers list does not include one of the owners, then Owner-Approval need()
+is added thus making the change not submittable.
+
+## Example 2 - OWNERS file without matchers and no default Gerrit rules
+
+Given an OWNERS configuration of:
+
+```yaml
+inherited: true
+owners:
+- John Doe
+- Doug Smith
+```
+
+And a rule which makes submittable a change if at least one of the owners has
+given a +1 without taking into consideration any other label:
+
+```prolog
+submit_rule(S) :-
+     Ds = [ label(‘owners_plugin_default’,ok(user(100000))) ],
+     findall(U, gerrit:commit_label(label('Code-Review', 1), U), Approvers),
+     gerrit_owners:add_owner_approval(Approvers, Ds, A),
+     S =.. [submit | A].
+```
+
+Then Gerrit would make the change Submittable only if 'John Doe' or 'Doug Smith'
+have provided at least a Code-Review +1.
+
+## Example 3 - OWNERS file without matchers and custom _Owner-Approves_ label
+
+Sometimes to differentiate the _owners approval_ on a change from the code
+review on the entire project. The scenario could be for instance the sign-off of
+the project's build dependencies based on the Company roles-and-responsibilities
+matrix and governance process.
+
+In this case, we need to grant specific people with the _Owner-Approved_ label
+without necessarily having to give Code-Review +2 rights on the entire project.
+
+Amend the project.config as shown in (1) and add a new label; then give
+permissions to any registered user. Finally, define a small variant of the
+Prolog rules as shown in (2).
+
+(1) Example fo the project config changes with the new label with values
+(label name and values are arbitrary)
+
+```
+[label "Owner-Approved"]
+     function = NoOp
+     defaultValue = 0
+     copyMinScore = true
+     copyAllScoresOnTrivialRebase = true
+     value = -1 I don't want this to be merged
+     value =  0 No score
+     value = +1 Approved
+[access "refs/heads/*"]
+     label-Owner-Approved = -1..+1 group Registered Users
+```
+
+(2) Define the project's rules.pl with an amended version of Example 1:
+
+```prolog
+submit_rule(S) :-
+  gerrit:default_submit(D),
+  D =.. [submit | Ds],
+  findall(U, gerrit:commit_label(label('Owner-Approved', 1), U), Approvers),
+  gerrit_owners:add_owner_approval(Approvers, Ds, A),
+  S =.. [submit | A].
+```
+
+Given now an OWNERS configuration of:
+
+```yaml
+inherited: true
+owners:
+- John Doe
+- Doug Smith
+```
+
+A change cannot be submitted until John Doe or Doug Smith add a label
+"Owner-Approved", independently from being able to provide any Code-Review.
+
+## Example 4 - Owners based on matchers
+
+Often the ownership comes from the developer's skills and competencies and
+cannot be purely defined by the project's directory structure.
+For instance, all the files ending with .sql should be owned and signed-off by
+the DBA while all the ones ending with .css by approved by the UX Team.
+
+Given an OWNERS configuration of:
+
+```yaml
+inherited: true
+matchers:
+- suffix: .sql
+  owners:
+  - Mister Dba
+- suffix: .css
+  owners:
+  - John Creative
+  - Matt Designer
+```
+
+And a rules.pl of:
+
+```prolog
+submit_rule(S) :-
+  gerrit:default_submit(L),
+  L =.. [submit | Sr ],
+  gerrit_owners:add_match_owner_approval(Sr,A),
+  S =.. [submit | A ].
+```
+
+Then for any change that contains files with .sql or .css extensions, besides
+to the default Gerrit submit rules, the extra constraints on the additional
+owners of the modified files will be added. The final submit is enabled if both
+Gerrit default rules are satisfied and all the owners of the .sql files
+(Mister Dba) and the .css files (either John Creative or Matt Designer) have
+provided their Code-Review +2 feedback.
+
+## Example 5 - Owners details on a per-file basis
+
+When using the owners with a series of matchers associated to different set of
+owners, it may not be trivial to understand exactly *why* change is not approved
+yet.
+
+We need to define one extra submit rule to scan the entire list of files in the
+change and their associated owners and cross-check with the existing Code-Review
+feedback received.
+
+Given the same OWNERS and rules.pl configuration of Example 4 with the following
+extra rule:
+
+```prolog
+submit_rule(submit(W)) :-
+  gerrit_owners:findall_match_file_user(W).
+```
+
+For every change that would include any .sql or .css file (e.g. my-update.sql
+and styles.css) Gerrit will display as additional description on the "need" code
+review labels section of the change screen:
+
+```
+Code-Review from owners
+Mister Dba owns my-update.sql
+John Creative, Matt Designer own styles.css
+```
+
+As soon as the owners reviews are provided, the corresponding entry will be
+removed from the "need" section of the change.
+
+In this way, it is always clear which owner needs to provide their feedback on
+which file of the change.
diff --git a/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java b/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java
index 24c07a3..5c9f1a7 100644
--- a/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java
+++ b/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java
@@ -19,8 +19,8 @@
 
 import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
 import com.google.gerrit.acceptance.TestPlugin;
+import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
-import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
diff --git a/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/ReferenceUpdatedEventTest.java b/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/ReferenceUpdatedEventTest.java
index 9946502..7024543 100644
--- a/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/ReferenceUpdatedEventTest.java
+++ b/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/ReferenceUpdatedEventTest.java
@@ -15,12 +15,11 @@
 
 package com.vmware.gerrit.owners.common;
 
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.api.changes.NotifyHandling;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Account.Id;
-import com.google.gerrit.reviewdb.client.Project;
 import org.eclipse.jgit.transport.ReceiveCommand;
 import org.junit.Ignore;
 
@@ -32,7 +31,7 @@
   private final String oldObjectId;
   private final String newObjectId;
   private final ReceiveCommand.Type type;
-  private final Id eventAccountId;
+  private final Account.Id eventAccountId;
 
   public ReferenceUpdatedEventTest(
       Project.NameKey project,
diff --git a/owners-common/BUILD b/owners-common/BUILD
index e2825d5..0f12783 100644
--- a/owners-common/BUILD
+++ b/owners-common/BUILD
@@ -1,6 +1,6 @@
 load("//tools/bzl:junit.bzl", "junit_tests")
 load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_DEPS_NEVERLINK", "PLUGIN_TEST_DEPS", "gerrit_plugin")
-load("//owners-common:common.bzl", "EXTERNAL_DEPS")
+load("//owners-common:common.bzl", "EXTERNAL_DEPS", "EXTERNAL_TEST_DEPS")
 
 java_library(
     name = "owners-common",
@@ -21,7 +21,7 @@
     name = "test",
     testonly = 1,
     srcs = glob(["src/test/java/**/*.java"]),
-    deps = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
+    deps = EXTERNAL_TEST_DEPS + PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
         ":owners-common",
     ],
 )
diff --git a/owners-common/common.bzl b/owners-common/common.bzl
index f766ff2..c571145 100644
--- a/owners-common/common.bzl
+++ b/owners-common/common.bzl
@@ -5,3 +5,14 @@
     "@jackson-dataformat-yaml//jar",
     "@snakeyaml//jar",
 ]
+
+EXTERNAL_TEST_DEPS = [
+    "@easymock//jar",
+    "@powermock-module-junit4//jar",
+    "@powermock-module-junit4-common//jar",
+    "@powermock-reflect//jar",
+    "@powermock-api-easymock//jar",
+    "@powermock-api-support//jar",
+    "@powermock-core//jar",
+    "@javassist//jar",
+]
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Accounts.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Accounts.java
index 0fdf717..9a27d36 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Accounts.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Accounts.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import com.google.inject.ImplementedBy;
 import java.util.Set;
 
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/AccountsImpl.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/AccountsImpl.java
index b5c1f90..52e2b58 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/AccountsImpl.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/AccountsImpl.java
@@ -18,9 +18,9 @@
 import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAILTO;
 import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME;
 
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Account.Id;
-import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Account.Id;
+import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountResolver;
@@ -64,7 +64,7 @@
     this.byId = byId;
     this.groupCache = groupCache;
     this.groupMembers = groupMembers;
-    this.adminUser = userFactory.create(new Account.Id(1000000));
+    this.adminUser = userFactory.create(Account.id(1000000));
     this.oneOffRequestContext = oneOffRequestContext;
   }
 
@@ -79,9 +79,9 @@
   private Set<Id> findAccountsInGroup(String groupNameOrUUID) {
     Optional<InternalGroup> group =
         groupCache
-            .get(new AccountGroup.NameKey(groupNameOrUUID))
+            .get(AccountGroup.nameKey(groupNameOrUUID))
             .map(Optional::of)
-            .orElse(groupCache.get(new AccountGroup.UUID(groupNameOrUUID)));
+            .orElse(groupCache.get(AccountGroup.uuid(groupNameOrUUID)));
 
     if (!group.isPresent()) {
       log.warn("Group {} was not found", groupNameOrUUID);
@@ -91,7 +91,7 @@
     try (ManualRequestContext ctx = oneOffRequestContext.openAs(adminUser.getAccountId())) {
 
       return groupMembers.listAccounts(group.get().getGroupUUID(), null).stream()
-          .map(Account::getId)
+          .map(Account::id)
           .collect(Collectors.toSet());
     } catch (NoSuchProjectException | IOException e) {
       log.error("Unable to list accounts in group " + group, e);
@@ -144,15 +144,15 @@
       return false;
     }
 
-    Account account = accountState.get().getAccount();
+    Account account = accountState.get().account();
     return isFullNameMatch(account, nameOrEmail)
-        || nameOrEmail.equalsIgnoreCase(account.getPreferredEmail())
-        || accountState.get().getExternalIds().stream()
+        || nameOrEmail.equalsIgnoreCase(account.preferredEmail())
+        || accountState.get().externalIds().stream()
             .anyMatch(eid -> isEMailMatch(eid, nameOrEmail) || isUsernameMatch(eid, nameOrEmail));
   }
 
   private boolean isFullNameMatch(Account account, String fullName) {
-    return Optional.ofNullable(account.getFullName())
+    return Optional.ofNullable(account.fullName())
         .filter(n -> n.trim().equalsIgnoreCase(fullName))
         .isPresent();
   }
@@ -174,7 +174,7 @@
   }
 
   private boolean isActive(Account.Id accountId) {
-    return byId.get(accountId).map(AccountState::getAccount).map(Account::isActive).orElse(false);
+    return byId.get(accountId).map(AccountState::account).map(Account::isActive).orElse(false);
   }
 
   private Optional<String> keySchemeRest(String scheme, ExternalId.Key key) {
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ConfigurationParser.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ConfigurationParser.java
index dcdd9f7..5b1049d 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ConfigurationParser.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ConfigurationParser.java
@@ -20,7 +20,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
-import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.entities.Account.Id;
 import java.io.IOException;
 import java.util.Optional;
 import java.util.Set;
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ExactMatcher.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ExactMatcher.java
index f638a32..07dadbe 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ExactMatcher.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/ExactMatcher.java
@@ -15,7 +15,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Set;
 
 public class ExactMatcher extends Matcher {
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Matcher.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Matcher.java
index d57116b..412fa79 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Matcher.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/Matcher.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Set;
 
 public abstract class Matcher {
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OwnersMap.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OwnersMap.java
index 8af46e3..06d9d12 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OwnersMap.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OwnersMap.java
@@ -18,8 +18,8 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Account.Id;
 import java.util.Map;
 import java.util.Set;
 
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PartialRegExMatcher.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PartialRegExMatcher.java
index 759170f..c046c13 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PartialRegExMatcher.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PartialRegExMatcher.java
@@ -15,7 +15,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Set;
 import java.util.regex.Pattern;
 
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java
index bb53419..77289a3 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java
@@ -16,18 +16,18 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
-import static com.google.gerrit.reviewdb.client.Patch.MERGE_LIST;
+import static com.google.gerrit.entities.Patch.COMMIT_MSG;
+import static com.google.gerrit.entities.Patch.MERGE_LIST;
 import static com.googlesource.gerrit.owners.common.JgitWrapper.getBlobAsBytes;
 
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Account.Id;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Account.Id;
+import com.google.gerrit.entities.Patch;
+import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListEntry;
 import java.io.IOException;
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntry.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntry.java
index 3a7111d..d2c73ec 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntry.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntry.java
@@ -18,7 +18,7 @@
 
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/RegExMatcher.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/RegExMatcher.java
index 2f1c23d..45fd615 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/RegExMatcher.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/RegExMatcher.java
@@ -15,7 +15,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Set;
 import java.util.regex.Pattern;
 
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/SuffixMatcher.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/SuffixMatcher.java
index 4c72b7a..39e8b32 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/SuffixMatcher.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/SuffixMatcher.java
@@ -15,7 +15,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Set;
 
 public class SuffixMatcher extends Matcher {
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/ClassicConfig.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/ClassicConfig.java
index e388125..a62ee5b 100644
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/ClassicConfig.java
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/ClassicConfig.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import org.junit.Ignore;
 
 @Ignore
@@ -22,9 +22,9 @@
   public static final String USER_A_EMAIL_COM = "user-a@email.com";
   public static final String USER_B_EMAIL_COM = "user-b@email.com";
   public static final String USER_C_EMAIL_COM = "user-c@email.com";
-  public static final Account.Id USER_A_ID = new Account.Id(1);
-  public static final Account.Id USER_B_ID = new Account.Id(2);
-  public static final Account.Id USER_C_ID = new Account.Id(3);
+  public static final Account.Id USER_A_ID = Account.id(1);
+  public static final Account.Id USER_B_ID = Account.id(2);
+  public static final Account.Id USER_C_ID = Account.id(3);
 
   @Override
   public void setup() throws Exception {
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/Config.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/Config.java
index a5df462..ea00372 100644
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/Config.java
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/Config.java
@@ -19,7 +19,7 @@
 import static org.easymock.EasyMock.expect;
 
 import com.google.common.base.Charsets;
-import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.entities.Patch;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListEntry;
 import java.io.IOException;
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/PathOwnersTest.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/PathOwnersTest.java
index 42a1796..df2b891 100644
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/PathOwnersTest.java
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/PathOwnersTest.java
@@ -18,7 +18,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.powermock.api.easymock.PowerMock.replayAll;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Arrays;
 import java.util.Optional;
 import java.util.Set;
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexTest.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexTest.java
index 47f9381..b68ec99 100644
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexTest.java
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexTest.java
@@ -15,6 +15,7 @@
 package com.googlesource.gerrit.owners.common;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth8.assertThat;
 import static com.googlesource.gerrit.owners.common.MatcherConfig.exactMatcher;
 import static com.googlesource.gerrit.owners.common.MatcherConfig.partialRegexMatcher;
 import static com.googlesource.gerrit.owners.common.MatcherConfig.regexMatcher;
@@ -24,7 +25,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.powermock.api.easymock.PowerMock.replayAll;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -48,12 +49,12 @@
   private static final String ACCOUNT_D = "d";
   private static final String ACCOUNT_E = "e";
   private static final String ACCOUNT_F = "f";
-  private static final Account.Id ACCOUNT_A_ID = new Account.Id(1);
-  private static final Account.Id ACCOUNT_B_ID = new Account.Id(2);
-  private static final Account.Id ACCOUNT_C_ID = new Account.Id(3);
-  private static final Account.Id ACCOUNT_D_ID = new Account.Id(4);
-  private static final Account.Id ACCOUNT_E_ID = new Account.Id(5);
-  private static final Account.Id ACCOUNT_F_ID = new Account.Id(6);
+  private static final Account.Id ACCOUNT_A_ID = Account.id(1);
+  private static final Account.Id ACCOUNT_B_ID = Account.id(2);
+  private static final Account.Id ACCOUNT_C_ID = Account.id(3);
+  private static final Account.Id ACCOUNT_D_ID = Account.id(4);
+  private static final Account.Id ACCOUNT_E_ID = Account.id(5);
+  private static final Account.Id ACCOUNT_F_ID = Account.id(6);
 
   @Override
   @Before
@@ -82,7 +83,7 @@
     // the function to test
     Optional<OwnersConfig> configNullable = getOwnersConfig(fullConfig);
     // check classical configuration
-    assertTrue(configNullable.isPresent());
+    assertThat(configNullable).isPresent();
 
     OwnersConfig config = configNullable.get();
     assertTrue(config.isInherited());
@@ -227,7 +228,7 @@
     Optional<OwnersConfig> ownersConfigOpt =
         getOwnersConfig(createConfig(false, new String[0], suffixMatcher(".txt", ACCOUNT_B)));
 
-    assertThat(ownersConfigOpt.isPresent()).named("ownersConfig").isTrue();
+    assertThat(ownersConfigOpt).isPresent();
     OwnersConfig ownersConfig = ownersConfigOpt.get();
 
     assertThat(ownersConfig.getOwners()).isEmpty();
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/TestAccounts.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/TestAccounts.java
index ba48011..c450f01 100644
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/TestAccounts.java
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/TestAccounts.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
diff --git a/owners/BUILD b/owners/BUILD
index 05c1fa7..3acc05b 100644
--- a/owners/BUILD
+++ b/owners/BUILD
@@ -1,5 +1,6 @@
-load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS_NEVERLINK", "gerrit_plugin")
+load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS_NEVERLINK", "PLUGIN_TEST_DEPS", "gerrit_plugin")
 load("//lib/prolog:prolog.bzl", "prolog_cafe_library")
+load("//owners-common:common.bzl", "EXTERNAL_DEPS", "EXTERNAL_TEST_DEPS")
 
 PROLOG_PREDICATES = glob(["src/main/java/gerrit_owners/**/*.java"]) + [
     "src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java",
@@ -44,3 +45,10 @@
         "//owners-common",
     ],
 )
+
+java_library(
+    name = "owners__plugin_test_deps",
+    testonly = 1,
+    visibility = ["//visibility:public"],
+    exports = EXTERNAL_DEPS + EXTERNAL_TEST_DEPS + PLUGIN_TEST_DEPS,
+)
diff --git a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java
index 18abe29..f721539 100644
--- a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java
+++ b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java
@@ -43,7 +43,7 @@
           protected PathOwners createValue(Prolog engine) {
             PatchList patchList = StoredValues.PATCH_LIST.get(engine);
             Repository repository = StoredValues.REPOSITORY.get(engine);
-            String branch = StoredValues.getChange(engine).getDest().get();
+            String branch = StoredValues.getChange(engine).getDest().branch();
             return new PathOwners(accounts, repository, branch, patchList);
           }
         };
diff --git a/owners/src/main/java/gerrit_owners/PRED_file_owners_2.java b/owners/src/main/java/gerrit_owners/PRED_file_owners_2.java
index 4e7263a..fd87eb3 100644
--- a/owners/src/main/java/gerrit_owners/PRED_file_owners_2.java
+++ b/owners/src/main/java/gerrit_owners/PRED_file_owners_2.java
@@ -16,7 +16,7 @@
 
 import static com.googlesource.gerrit.owners.common.StreamUtils.iteratorStream;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.rules.PrologEnvironment;
 import com.google.gerrit.server.rules.StoredValues;
@@ -74,8 +74,8 @@
       cache.put(accountId, who);
       user = who;
     }
-    Account account = user.asIdentifiedUser().state().getAccount();
-    String userName = account.getFullName();
+    Account account = user.asIdentifiedUser().state().account();
+    String userName = account.fullName();
     return sanitizeAsSubmitLabel(userName);
   }
 
diff --git a/owners/src/main/java/gerrit_owners/PRED_matcher_owner_2.java b/owners/src/main/java/gerrit_owners/PRED_matcher_owner_2.java
index 5abf7ad..d056a9f 100644
--- a/owners/src/main/java/gerrit_owners/PRED_matcher_owner_2.java
+++ b/owners/src/main/java/gerrit_owners/PRED_matcher_owner_2.java
@@ -16,7 +16,7 @@
 
 package gerrit_owners;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import com.googlecode.prolog_cafe.exceptions.PrologException;
 import com.googlecode.prolog_cafe.lang.IntegerTerm;
 import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
diff --git a/owners/src/main/java/gerrit_owners/PRED_owner_2.java b/owners/src/main/java/gerrit_owners/PRED_owner_2.java
index 5697a32..9748934 100644
--- a/owners/src/main/java/gerrit_owners/PRED_owner_2.java
+++ b/owners/src/main/java/gerrit_owners/PRED_owner_2.java
@@ -16,7 +16,7 @@
 
 package gerrit_owners;
 
-import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.entities.Account;
 import com.googlecode.prolog_cafe.exceptions.PrologException;
 import com.googlecode.prolog_cafe.lang.IntegerTerm;
 import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
diff --git a/owners/src/main/resources/Documentation/config.md b/owners/src/main/resources/Documentation/config.md
deleted file mode 120000
index beb6012..0000000
--- a/owners/src/main/resources/Documentation/config.md
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../config.md
\ No newline at end of file
diff --git a/owners/src/main/resources/Documentation/config.md b/owners/src/main/resources/Documentation/config.md
new file mode 100644
index 0000000..b294ae8
--- /dev/null
+++ b/owners/src/main/resources/Documentation/config.md
@@ -0,0 +1,270 @@
+## Configuration
+
+Owner approval is determined based on OWNERS files located in the same
+repository on the target branch of the changes uploaded for review.
+
+The `OWNERS` file has the following YAML structure:
+
+```yaml
+inherited: true
+owners:
+- some.email@example.com
+- User Name
+- group/Group of Users
+matchers:
+- suffix: .java
+  owners:
+      [...]
+- regex: .*/README.*
+  owners:
+      [...]
+- partial_regex: example
+  owners:
+      [...]
+- exact: path/to/file.txt
+      [...]
+```
+
+_NOTE: Be aware to double check that emails and full user names correspond to
+valid registered Gerrit users. When owner user full name or e-mail cannot be
+resolved, a corresponding WARN message is logged on Gerrit error_log and the
+user entry dropped._
+
+That translates to inheriting owner email address from any parent OWNER files
+and to define 'some.email@example.com' or 'User Name' users as the mandatory
+reviewers for all changes that include modification to those files.
+
+To specify a group of people instead of naming individual owners, prefix the
+group name or UUID with 'group/'.
+
+Additional owners can be specified for files selected by other matching
+conditions (matchers section). Matching can be done by file suffix, regex
+(partial or full) and exact string comparison. For exact match, path is
+relative to the root of the repo.
+
+The plugin analyzes the latest patch set by looking at each file directory and
+building an OWNERS hierarchy. It stops once it finds an OWNERS file that has
+“inherited” set to false (by default it’s true.)
+
+For example, imagine the following tree:
+
+```
+/OWNERS
+/example/src/main/OWNERS
+/example/src/main/java/com/example/foo/Foo.java
+/example/src/main/resources/config.properties
+/example/src/test/OWNERS
+/example/src/test/java/com/example/foo/FooTest.java
+```
+
+If you submit a patch set that changes /example/src/main/java/com/example/foo/Foo.java
+then the plugin will first open /example/src/main/OWNERS and if inherited is set
+to true combine it with the owners listed in /OWNERS.
+
+If for each patch there is a reviewer who gave a Code-Review +2 then the plugin
+will not add any labels, otherwise, it will add ```label('Code-Review from owners', need(_)).```
+
+## Global project OWNERS
+
+Set a OWNERS file into the project refs/meta/config to define a global set of
+rules applied to every change pushed, regardless of the folder or target branch.
+
+Example of assigning every configuration files to a specific owner group:
+
+```yaml
+matchers:
+- suffix: .config
+  owners:
+  - Configuration Managers
+```
+
+Global refs/meta/config OWNERS configuration is inherited only when the OWNERS file
+contain the 'inherited: true' condition at the top of the file or if they are absent.
+
+That means that in the absence of any OWNERS file in the target branch, the refs/meta/config
+OWNERS is used as global default.
+
+
+## Example 1 - OWNERS file without matchers and default Gerrit submit rules
+
+Given an OWNERS configuration of:
+
+```yaml
+inherited: true
+owners:
+- John Doe
+- Doug Smith
+```
+
+And sample rules.pl that uses this predicate to enable the submit rule if
+one of the owners has given a Code Review +2
+
+```prolog
+submit_rule(S) :-
+  gerrit:default_submit(D),
+  D =.. [submit | Ds],
+  findall(U, gerrit:commit_label(label('Code-Review', 2), U), Approvers),
+  gerrit_owners:add_owner_approval(Approvers, Ds, A),
+  S =.. [submit | A].
+```
+
+Then Gerrit would evaluate the Prolog rule as follows:
+
+It first gets the current default on rule which gives ok() if no Code-Review -2
+and at least a Code-Review +2 is being provided.
+
+Then it accumulates in Approvers the list of users who had given Code-Review +2
+and then checks if this list contains either 'John Doe' or 'Doug Smith'.
+
+If Approvers list does not include one of the owners, then Owner-Approval need()
+is added thus making the change not submittable.
+
+## Example 2 - OWNERS file without matchers and no default Gerrit rules
+
+Given an OWNERS configuration of:
+
+```yaml
+inherited: true
+owners:
+- John Doe
+- Doug Smith
+```
+
+And a rule which makes submittable a change if at least one of the owners has
+given a +1 without taking into consideration any other label:
+
+```prolog
+submit_rule(S) :-
+     Ds = [ label(‘owners_plugin_default’,ok(user(100000))) ],
+     findall(U, gerrit:commit_label(label('Code-Review', 1), U), Approvers),
+     gerrit_owners:add_owner_approval(Approvers, Ds, A),
+     S =.. [submit | A].
+```
+
+Then Gerrit would make the change Submittable only if 'John Doe' or 'Doug Smith'
+have provided at least a Code-Review +1.
+
+## Example 3 - OWNERS file without matchers and custom _Owner-Approves_ label
+
+Sometimes to differentiate the _owners approval_ on a change from the code
+review on the entire project. The scenario could be for instance the sign-off of
+the project's build dependencies based on the Company roles-and-responsibilities
+matrix and governance process.
+
+In this case, we need to grant specific people with the _Owner-Approved_ label
+without necessarily having to give Code-Review +2 rights on the entire project.
+
+Amend the project.config as shown in (1) and add a new label; then give
+permissions to any registered user. Finally, define a small variant of the
+Prolog rules as shown in (2).
+
+(1) Example fo the project config changes with the new label with values
+(label name and values are arbitrary)
+
+```
+[label "Owner-Approved"]
+     function = NoOp
+     defaultValue = 0
+     copyMinScore = true
+     copyAllScoresOnTrivialRebase = true
+     value = -1 I don't want this to be merged
+     value =  0 No score
+     value = +1 Approved
+[access "refs/heads/*"]
+     label-Owner-Approved = -1..+1 group Registered Users
+```
+
+(2) Define the project's rules.pl with an amended version of Example 1:
+
+```prolog
+submit_rule(S) :-
+  gerrit:default_submit(D),
+  D =.. [submit | Ds],
+  findall(U, gerrit:commit_label(label('Owner-Approved', 1), U), Approvers),
+  gerrit_owners:add_owner_approval(Approvers, Ds, A),
+  S =.. [submit | A].
+```
+
+Given now an OWNERS configuration of:
+
+```yaml
+inherited: true
+owners:
+- John Doe
+- Doug Smith
+```
+
+A change cannot be submitted until John Doe or Doug Smith add a label
+"Owner-Approved", independently from being able to provide any Code-Review.
+
+## Example 4 - Owners based on matchers
+
+Often the ownership comes from the developer's skills and competencies and
+cannot be purely defined by the project's directory structure.
+For instance, all the files ending with .sql should be owned and signed-off by
+the DBA while all the ones ending with .css by approved by the UX Team.
+
+Given an OWNERS configuration of:
+
+```yaml
+inherited: true
+matchers:
+- suffix: .sql
+  owners:
+  - Mister Dba
+- suffix: .css
+  owners:
+  - John Creative
+  - Matt Designer
+```
+
+And a rules.pl of:
+
+```prolog
+submit_rule(S) :-
+  gerrit:default_submit(L),
+  L =.. [submit | Sr ],
+  gerrit_owners:add_match_owner_approval(Sr,A),
+  S =.. [submit | A ].
+```
+
+Then for any change that contains files with .sql or .css extensions, besides
+to the default Gerrit submit rules, the extra constraints on the additional
+owners of the modified files will be added. The final submit is enabled if both
+Gerrit default rules are satisfied and all the owners of the .sql files
+(Mister Dba) and the .css files (either John Creative or Matt Designer) have
+provided their Code-Review +2 feedback.
+
+## Example 5 - Owners details on a per-file basis
+
+When using the owners with a series of matchers associated to different set of
+owners, it may not be trivial to understand exactly *why* change is not approved
+yet.
+
+We need to define one extra submit rule to scan the entire list of files in the
+change and their associated owners and cross-check with the existing Code-Review
+feedback received.
+
+Given the same OWNERS and rules.pl configuration of Example 4 with the following
+extra rule:
+
+```prolog
+submit_rule(submit(W)) :-
+  gerrit_owners:findall_match_file_user(W).
+```
+
+For every change that would include any .sql or .css file (e.g. my-update.sql
+and styles.css) Gerrit will display as additional description on the "need" code
+review labels section of the change screen:
+
+```
+Code-Review from owners
+Mister Dba owns my-update.sql
+John Creative, Matt Designer own styles.css
+```
+
+As soon as the owners reviews are provided, the corresponding entry will be
+removed from the "need" section of the change.
+
+In this way, it is always clear which owner needs to provide their feedback on
+which file of the change.
diff --git a/tools/bzl/maven_jar.bzl b/tools/bzl/maven_jar.bzl
index ce4730f..ed1504d 100644
--- a/tools/bzl/maven_jar.bzl
+++ b/tools/bzl/maven_jar.bzl
@@ -1,4 +1,4 @@
-load("@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl", _GERRIT = "GERRIT", _maven_jar = "maven_jar")
+load("@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl", _gerrit = "GERRIT", _maven_jar = "maven_jar")
 
-GERRIT = _GERRIT
 maven_jar = _maven_jar
+GERRIT = _gerrit