Merge branch 'stable-2.15'

* stable-2.15:
  Upgrade bazlets to latest stable-2.15 to build with 2.15.7 API
  Remove tools/bazel.rc
  Bazel: Fix standalone build
  Add "Empty file" comments in empty BUILD files
  ConfigurationParser: Format with google-java-format
  Fix owners e-mail matching on LDAP
  Allow OWNERS file with single owner
  Revert "Fix label name generated by workskace-status.sh"
  Bazel: Add standalone build mode
  Fix label name generated by workskace-status.sh
  Ignore /MERGE_LIST when looking for owners
  Upgrade bazlets to latest stable-2.14 to build with 2.14.16 API
  Align Eclipse compiler settings with core Gerrit's
  Replace wildcard imports with explicit imports
  Upgrade jackson to 2.9.7
  bazlets: Replace native.git_repository with skylark rule
  Upgrade bazlets to latest stable-2.14 to build with 2.14.15 API
  Format all Bazel build files with buildifier
  Migrate (i.e. move) `tools/bazel.rc` to `.bazelrc`
  Update bazlets to latest stable-2.14 to build with 2.14.14 API
  Update bazlets to latest stable-2.14 to build with 2.14.13 API
  Don't include jackson-core in shaded JAR
  Align jackson version with core Gerrit
  Check null account full name
  Format all BUILD files with buildifier 0.12.0
  Fix in-tree build
  Adjust to renamed dependencies in core
  Fix names of build output jar files in README
  Adjust to renamed dependencies in core
  Update bazlets to latest revision on stable-2.14
  Filter out inactive accounts in OWNERS
  Bazel: Add standalone build mode
  Does not include jackson-core in the final artifacts
  Sync Jackson lib version with Gerrit
  Fix owners dependencies
  Remove duplicated build dependencies
  Reformat build files
  Remove Buck build
  Fix config documentation
  Fix Eclipse warnings
  Cleanup .gitignore file
  Eager initialize Owners Prolog Predicates
  Consider name and e-mail matching edge cases
  Batch sending mail when multiple reviewers added

Also update WORKSPACE to build with the 2.16-rc3 API.

Change-Id: Iff88759f91d630964ce5f3ec92ad6495adbd836b
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..4ed16cf
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,2 @@
+build --workspace_status_command=./tools/workspace-status.sh
+test --build_tests_only
diff --git a/.buckconfig b/.buckconfig
deleted file mode 100644
index bd040e3..0000000
--- a/.buckconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-[java]
-  source_level = 8
-  target_level = 8
diff --git a/.gitignore b/.gitignore
index 560ddee..6042b9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,9 @@
-target
-
 # IntelliJ
 *.iml
 *.ipr
 .idea
-
-# Maven Relase
-pom.xml.*
-release.properties
+/.classpath
+/.project
+/.settings/
+/bazel-*
+/eclipse-out/
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..40e022d
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,126 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=enabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..b52c2c1
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,29 @@
+load("//tools:genrule2.bzl", "genrule2")
+load("//tools/bzl:plugin.bzl", "PLUGIN_TEST_DEPS")
+load("//owners-common:common.bzl", "EXTERNAL_DEPS")
+
+genrule2(
+    name = "all",
+    srcs = [
+        "//owners",
+        "//owners-autoassign",
+        "//owners-common",
+    ],
+    outs = ["all.zip"],
+    cmd = " && ".join([
+        "cp $(SRCS) $$TMP",
+        "cd $$TMP",
+        "zip -qr $$ROOT/$@ .",
+    ]),
+)
+
+java_library(
+    name = "owners_classpath_deps",
+    testonly = 1,
+    visibility = ["//visibility:public"],
+    exports = EXTERNAL_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 7c0340a..aee2d8e 100644
--- a/README.md
+++ b/README.md
@@ -39,8 +39,46 @@
 
 ## How to build
 
-Create three symbolic links of the owners-owners, owners-common and owners-autoassign
-from the Gerrit source code /plugins directory to the subdirectories of this project.
+This plugin is built with Bazel and two build modes are supported:
+
+ * Standalone
+ * In Gerrit tree
+
+### Build standalone
+
+To build the plugin, issue the following command:
+
+```
+  bazel build :all
+```
+
+The output is created in
+
+```
+  bazel-genfiles/owners/owners.jar
+  bazel-genfiles/owners-autoassign/owners-autoassign.jar
+
+```
+
+To execute the tests run:
+
+```
+  bazel test //...
+```
+
+This project can be imported into the Eclipse IDE:
+
+```
+  ./tools/eclipse/project.sh
+```
+
+## Build in Gerrit tree
+
+Create symbolic links of the owners and owners-autoassign folders and of the
+external_plugin_deps.bzl file to the Gerrit source code /plugins directory.
+
+Create a symbolic link of the owners-common plugin to the Gerrit source code
+directory.
 
 Then build the owners and owners-autoassign plugins with the usual Gerrit
 plugin compile command.
@@ -51,10 +89,11 @@
    $ git clone https://gerrit.googlesource.com/plugins/owners
    $ git clone https://gerrit.googlesource.com/gerrit
    $ cd gerrit/plugins
-   $ ln -s ../../owners/owners* .
+   $ ln -s ../../owners/owners .
+   $ ln -s ../../owners/owners-autoassign .
    $ ln -sf ../../owners/external_plugin_deps.bzl .
    $ cd ..
-   $ bazel test plugins/owners-common:test
+   $ ln -s ../owners/owners-common .
    $ bazel build plugins/owners plugins/owners-autoassign
 ```
 
@@ -62,3 +101,25 @@
 and does not need to be built separately being a direct dependency of the build
 process. Its resulting .jar must not be installed in gerrit plugins directory.
 
+The output is created in
+
+```
+  bazel-genfiles/plugins/owners/owners.jar
+  bazel-genfiles/plugins/owners-autoassign/owners-autoassign.jar
+```
+
+To execute the tests run:
+
+```
+  bazel test owners-common:test
+```
+
+This project can be imported into the Eclipse IDE:
+
+Add the plugin name to the `CUSTOM_PLUGINS` in Gerrit core in
+`tools/bzl/plugins.bzl` file and run:
+
+```
+  ./tools/eclipse/project.py
+```
+
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..f8ee819
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,29 @@
+workspace(name = "owners")
+
+load("//:bazlets.bzl", "load_bazlets")
+
+load_bazlets(
+    commit = "d044cd60d37e302d9ac324f7a2c4e48b4011d4e6",
+    #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",
+)
+
+gerrit_api()
+
+load(":external_plugin_deps_standalone.bzl", "external_plugin_deps_standalone")
+
+external_plugin_deps_standalone()
diff --git a/bazlets.bzl b/bazlets.bzl
new file mode 100644
index 0000000..f089af4
--- /dev/null
+++ b/bazlets.bzl
@@ -0,0 +1,18 @@
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+NAME = "com_googlesource_gerrit_bazlets"
+
+def load_bazlets(
+        commit,
+        local_path = None):
+    if not local_path:
+        git_repository(
+            name = NAME,
+            remote = "https://gerrit.googlesource.com/bazlets",
+            commit = commit,
+        )
+    else:
+        native.local_repository(
+            name = NAME,
+            path = local_path,
+        )
diff --git a/config.md b/config.md
index 2d63581..b294ae8 100644
--- a/config.md
+++ b/config.md
@@ -70,6 +70,7 @@
 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
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 4e76496..7c6aa5c 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -1,29 +1,35 @@
 load("//tools/bzl:maven_jar.bzl", "maven_jar")
 
-JACKSON_REV = "2.1.1"
+JACKSON_VER = "2.9.7"
 
-def external_plugin_deps():
+def external_plugin_deps(omit_jackson_core = True):
+    if not omit_jackson_core:
         maven_jar(
-          name = "jackson_core",
-          artifact = "com.fasterxml.jackson.core:jackson-core:%s" % JACKSON_REV,
-          sha1 = "82ad1c5f92f6dcc6291f5c46ebacb975eaa844de",
+            name = "jackson-core",
+            artifact = "com.fasterxml.jackson.core:jackson-core:" + JACKSON_VER,
+            sha1 = "4b7f0e0dc527fab032e9800ed231080fdc3ac015",
         )
 
-        maven_jar(
-          name = "jackson_databind",
-          artifact = "com.fasterxml.jackson.core:jackson-databind:%s" % JACKSON_REV,
-          sha1 = "38d2b3c0c89af5b937fd98c3e558bf6b58c14aa2",
-        )
+    maven_jar(
+        name = "jackson-databind",
+        artifact = "com.fasterxml.jackson.core:jackson-databind:" + JACKSON_VER,
+        sha1 = "e6faad47abd3179666e89068485a1b88a195ceb7",
+    )
 
-        maven_jar(
-          name = "jackson_annotations",
-          artifact = "com.fasterxml.jackson.core:jackson-annotations:%s" % JACKSON_REV,
-          sha1 = "0b01cc83e745fc4425a3968fafbf8e5b8254a6dd",
+    maven_jar(
+        name = "jackson-annotations",
+        artifact = "com.fasterxml.jackson.core:jackson-annotations:" + JACKSON_VER,
+        sha1 = "4b838e5c4fc17ac02f3293e9a558bb781a51c46d",
+    )
 
-        )
+    maven_jar(
+        name = "jackson-dataformat-yaml",
+        artifact = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:" + JACKSON_VER,
+        sha1 = "a428edc4bb34a2da98a50eb759c26941d4e85960",
+    )
 
-        maven_jar(
-          name = "jackson_dataformat_yaml",
-          artifact = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:%s" % JACKSON_REV,
-          sha1 = "3922d45de7f3ccabe8f16aad4060a6394373c6cb",
-        )
+    maven_jar(
+        name = "snakeyaml",
+        artifact = "org.yaml:snakeyaml:1.23",
+        sha1 = "ec62d74fe50689c28c0ff5b35d3aebcaa8b5be68",
+    )
diff --git a/external_plugin_deps_standalone.bzl b/external_plugin_deps_standalone.bzl
new file mode 100644
index 0000000..b2964a5
--- /dev/null
+++ b/external_plugin_deps_standalone.bzl
@@ -0,0 +1,32 @@
+load("//tools/bzl:maven_jar.bzl", "GERRIT", "maven_jar")
+load("//:external_plugin_deps.bzl", "external_plugin_deps")
+
+PROLOG_VERS = "1.4.3"
+PROLOG_REPO = GERRIT
+
+def external_plugin_deps_standalone():
+    external_plugin_deps(omit_jackson_core = False)
+
+    maven_jar(
+        name = "prolog-runtime",
+        artifact = "com.googlecode.prolog-cafe:prolog-runtime:" + PROLOG_VERS,
+        attach_source = False,
+        repository = PROLOG_REPO,
+        sha1 = "d5206556cbc76ffeab21313ffc47b586a1efbcbb",
+    )
+
+    maven_jar(
+        name = "prolog-compiler",
+        artifact = "com.googlecode.prolog-cafe:prolog-compiler:" + PROLOG_VERS,
+        attach_source = False,
+        repository = PROLOG_REPO,
+        sha1 = "f37032cf1dec3e064427745bc59da5a12757a3b2",
+    )
+
+    maven_jar(
+        name = "prolog-io",
+        artifact = "com.googlecode.prolog-cafe:prolog-io:" + PROLOG_VERS,
+        attach_source = False,
+        repository = PROLOG_REPO,
+        sha1 = "d02b2640b26f64036b6ba2b45e4acc79281cea17",
+    )
diff --git a/lib/prolog/BUILD b/lib/prolog/BUILD
new file mode 100644
index 0000000..c5ed0b7
--- /dev/null
+++ b/lib/prolog/BUILD
@@ -0,0 +1 @@
+# Empty file required by Bazel
diff --git a/lib/prolog/prolog.bzl b/lib/prolog/prolog.bzl
new file mode 100644
index 0000000..ae46601
--- /dev/null
+++ b/lib/prolog/prolog.bzl
@@ -0,0 +1 @@
+load("@com_googlesource_gerrit_bazlets//lib/prolog:prolog.bzl", "prolog_cafe_library")
diff --git a/owners-autoassign/BUILD b/owners-autoassign/BUILD
index 1f05c0c..e874bc5 100644
--- a/owners-autoassign/BUILD
+++ b/owners-autoassign/BUILD
@@ -1,7 +1,4 @@
-load("//tools/bzl:junit.bzl", "junit_tests")
-load("//tools/bzl:plugin.bzl", "gerrit_plugin", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS")
-load("//lib/prolog:prolog.bzl", "prolog_cafe_library")
-load("//plugins/owners-common:common.bzl", "EXTERNAL_DEPS")
+load("//tools/bzl:plugin.bzl", "gerrit_plugin")
 
 gerrit_plugin(
     name = "owners-autoassign",
@@ -15,8 +12,8 @@
         "Gerrit-Module: com.googlesource.gerrit.owners.common.AutoassignModule",
         "Gerrit-ApiVersion: 2.14-SNAPSHOT",
     ],
-    deps = [
-        "//plugins/owners-common",
-    ],
     resources = glob(["src/main/**/*"]),
+    deps = [
+        "//owners-common",
+    ],
 )
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 f69c429..f62b8c7 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
@@ -17,7 +17,8 @@
 package com.googlesource.gerrit.owners.common;
 
 import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.api.changes.AddReviewerInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Change;
@@ -26,6 +27,7 @@
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import java.util.ArrayList;
 import java.util.Collection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,12 +48,16 @@
   public void addReviewers(Change change, Collection<Account.Id> reviewers)
       throws ReviewerManagerException {
     try (ManualRequestContext ctx = requestContext.openAs(change.getOwner())) {
-
-      ChangeApi cApi = gApi.changes().id(change.getId().get());
+      // 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) {
-        cApi.addReviewer(account.toString());
+        AddReviewerInput addReviewerInput = new AddReviewerInput();
+        addReviewerInput.reviewer = account.toString();
+        in.reviewers.add(addReviewerInput);
       }
-
+      gApi.changes().id(change.getId().get()).current().review(in);
     } catch (RestApiException | OrmException e) {
       log.error("Couldn't add reviewers to the change", e);
       throw new ReviewerManagerException(e);
diff --git a/owners-common/BUILD b/owners-common/BUILD
index 8a4ea42..e2825d5 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", "gerrit_plugin", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "PLUGIN_DEPS_NEVERLINK")
-load("//plugins/owners-common:common.bzl", "EXTERNAL_DEPS")
+load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_DEPS_NEVERLINK", "PLUGIN_TEST_DEPS", "gerrit_plugin")
+load("//owners-common:common.bzl", "EXTERNAL_DEPS")
 
 java_library(
     name = "owners-common",
diff --git a/owners-common/common.bzl b/owners-common/common.bzl
index e9a7931..f766ff2 100644
--- a/owners-common/common.bzl
+++ b/owners-common/common.bzl
@@ -1,6 +1,7 @@
-EXTERNAL_DEPS = [ 
-    '@jackson_core//jar',
-    '@jackson_databind//jar',
-    '@jackson_annotations//jar',
-    '@jackson_dataformat_yaml//jar'
-  ]
+EXTERNAL_DEPS = [
+    "@jackson-core//jar:neverlink",
+    "@jackson-databind//jar",
+    "@jackson-annotations//jar",
+    "@jackson-dataformat-yaml//jar",
+    "@snakeyaml//jar",
+]
diff --git a/owners-common/common.defs b/owners-common/common.defs
deleted file mode 100644
index 26452a1..0000000
--- a/owners-common/common.defs
+++ /dev/null
@@ -1,7 +0,0 @@
-EXTERNAL_DEPS = [
-  '//plugins/owners-common' + i for i in [
-    ':jackson-core',
-    ':jackson-databind',
-    ':jackson-annotations',
-    ':jackson-dataformat-yaml',
-]]
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 600cb67..d427ef9 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
@@ -14,6 +14,9 @@
 
 package com.googlesource.gerrit.owners.common;
 
+import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GERRIT;
+import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAILTO;
+
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Account.Id;
 import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -22,13 +25,15 @@
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.account.GroupMembers;
+import com.google.gerrit.server.account.externalids.ExternalId;
 import com.google.gerrit.server.group.InternalGroup;
 import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.gerrit.server.util.ManualRequestContext;
+import com.google.gerrit.server.util.OneOffRequestContext;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import java.io.IOException;
 import java.util.Collections;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -43,17 +48,20 @@
   private final AccountCache byId;
   private final GroupCache groupCache;
   private final GroupMembers groupMembers;
+  private final OneOffRequestContext oneOffRequestContext;
 
   @Inject
   public AccountsImpl(
       AccountResolver resolver,
       AccountCache byId,
       GroupCache groupCache,
-      GroupMembers groupMembers) {
+      GroupMembers groupMembers,
+      OneOffRequestContext oneOffRequestContext) {
     this.resolver = resolver;
     this.byId = byId;
     this.groupCache = groupCache;
     this.groupMembers = groupMembers;
+    this.oneOffRequestContext = oneOffRequestContext;
   }
 
   @Override
@@ -89,15 +97,26 @@
   }
 
   private Set<Account.Id> findUserOrEmail(String nameOrEmail) {
-    try {
+    try (ManualRequestContext ctx = oneOffRequestContext.open()) {
       Set<Id> accountIds = resolver.findAll(nameOrEmail);
       if (accountIds.isEmpty()) {
         log.warn("User '{}' does not resolve to any account.", nameOrEmail);
         return accountIds;
       }
 
+      Set<Id> activeAccountIds =
+          accountIds.stream().filter(this::isActive).collect(Collectors.toSet());
+      if (activeAccountIds.isEmpty()) {
+        log.warn(
+            "User '{}' resolves to {} accounts {}, but none of them are active",
+            nameOrEmail,
+            accountIds.size(),
+            accountIds);
+        return activeAccountIds;
+      }
+
       Set<Id> fulllyMatchedAccountIds =
-          accountIds
+          activeAccountIds
               .stream()
               .filter(id -> isFullMatch(id, nameOrEmail))
               .collect(Collectors.toSet());
@@ -118,22 +137,49 @@
   }
 
   private boolean isFullMatch(Account.Id id, String nameOrEmail) {
-    Optional<AccountState> account = byId.get(id);
-    return account.isPresent() && Objects.toString(account.get().getAccount().getFullName(), "")
-            .trim()
-            .equalsIgnoreCase(nameOrEmail)
-        || account
+    Optional<AccountState> accountState = byId.get(id);
+    if (!accountState.isPresent()) {
+      return false;
+    }
+
+    Account account = accountState.get().getAccount();
+    return isFullNameMatch(account, nameOrEmail)
+        || nameOrEmail.equalsIgnoreCase(account.getPreferredEmail())
+        || accountState
             .get()
             .getExternalIds()
             .stream()
-            .anyMatch(
-                extId ->
-                    getSchemeRest(extId.key().scheme(), extId.key().get())
-                        .trim()
-                        .equalsIgnoreCase(nameOrEmail));
+            .anyMatch(eid -> isEMailMatch(eid, nameOrEmail) || isUsernameMatch(eid, nameOrEmail));
   }
 
-  private String getSchemeRest(String scheme, String key) {
-    return null != scheme ? key.substring(scheme.length() + 1) : key;
+  private boolean isFullNameMatch(Account account, String fullName) {
+    return Optional.ofNullable(account.getFullName())
+        .filter(n -> n.trim().equalsIgnoreCase(fullName))
+        .isPresent();
+  }
+
+  private boolean isUsernameMatch(ExternalId externalId, String username) {
+    return keySchemeRest(SCHEME_GERRIT, externalId.key())
+        .filter(name -> name.equals(username))
+        .isPresent();
+  }
+
+  private boolean isEMailMatch(ExternalId externalId, String email) {
+    ExternalId.Key externalKey = externalId.key();
+    return OptionalUtils.combine(
+            Optional.ofNullable(externalId.email()).filter(mail -> mail.equalsIgnoreCase(email)),
+            keySchemeRest(SCHEME_MAILTO, externalKey).filter(mail -> mail.equalsIgnoreCase(email)))
+        .isPresent();
+  }
+
+  private boolean isActive(Account.Id accountId) {
+    return byId.get(accountId).map(AccountState::getAccount).map(Account::isActive).orElse(false);
+  }
+
+  private Optional<String> keySchemeRest(String scheme, ExternalId.Key key) {
+    if (scheme != null && key.isScheme(scheme)) {
+      return Optional.of(key.get().substring(scheme.length() + 1));
+    }
+    return Optional.empty();
   }
 }
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 26c62eb..2f5c5c0 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
@@ -80,6 +80,9 @@
   }
 
   private static Stream<String> extractOwners(JsonNode node) {
+    if (node.isTextual()) {
+      return Stream.of(node.asText());
+    }
     return iteratorStream(node.iterator()).map(JsonNode::asText);
   }
 
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OptionalUtils.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OptionalUtils.java
new file mode 100644
index 0000000..f35941d
--- /dev/null
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/OptionalUtils.java
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 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.googlesource.gerrit.owners.common;
+
+import java.util.Optional;
+
+public class OptionalUtils {
+
+  public static <T> Optional<T> combine(Optional<T> firstChoice, Optional<T> secondChoice) {
+    return Optional.ofNullable(firstChoice.orElse(secondChoice.orElse(null)));
+  }
+}
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 6e73bc8..bb53419 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,6 +16,8 @@
 
 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.googlesource.gerrit.owners.common.JgitWrapper.getBlobAsBytes;
 
 import com.google.common.collect.Maps;
@@ -220,9 +222,10 @@
   private Set<String> getModifiedPaths() {
     Set<String> paths = Sets.newHashSet();
     for (PatchListEntry patch : patchList.getPatches()) {
-      // Ignore commit message
-      if (!patch.getNewName().equals("/COMMIT_MSG")) {
-        paths.add(patch.getNewName());
+      // Ignore commit message and Merge List
+      String newName = patch.getNewName();
+      if (!COMMIT_MSG.equals(newName) && !MERGE_LIST.equals(newName)) {
+        paths.add(newName);
 
         // If a file was moved then we need approvals for old and new
         // path
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexMatcherTest.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexMatcherTest.java
index 8f6f3d0..1fd557b 100644
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexMatcherTest.java
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/RegexMatcherTest.java
@@ -15,7 +15,8 @@
 
 package com.googlesource.gerrit.owners.common;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
 
diff --git a/owners/BUILD b/owners/BUILD
index 79aebaf..1c56104 100644
--- a/owners/BUILD
+++ b/owners/BUILD
@@ -1,30 +1,35 @@
-load("//tools/bzl:junit.bzl", "junit_tests")
-load("//tools/bzl:plugin.bzl", "gerrit_plugin", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "PLUGIN_DEPS_NEVERLINK")
+load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS_NEVERLINK", "gerrit_plugin")
 load("//lib/prolog:prolog.bzl", "prolog_cafe_library")
-load("//plugins/owners-common:common.bzl", "EXTERNAL_DEPS")
+
+PROLOG_PREDICATES = glob(["src/main/java/gerrit_owners/**/*.java"]) + [
+    "src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java",
+]
 
 java_library(
-    name = "gerrit-owners-lib",
-    srcs = glob([
-        "src/main/java/**/*.java",
-    ]),
+    name = "gerrit-owners-predicates",
+    srcs = PROLOG_PREDICATES,
     deps = [
-        "@prolog_runtime//jar:neverlink",
-        "//plugins/owners-common:owners-common",
-    ] + PLUGIN_DEPS_NEVERLINK + EXTERNAL_DEPS,
+        "@prolog-runtime//jar:neverlink",
+        "//owners-common:owners-common",
+    ] + PLUGIN_DEPS_NEVERLINK,
 )
 
 prolog_cafe_library(
     name = "gerrit-owners-prolog-rules",
     srcs = glob(["src/main/prolog/*.pl"]),
     deps = PLUGIN_DEPS_NEVERLINK + [
-        ":gerrit-owners-lib",
+        ":gerrit-owners-predicates",
     ],
 )
 
 gerrit_plugin(
     name = "owners",
-    srcs = ["src/main/java/com/googlesource/gerrit/owners/CompileStub.java"],
+    srcs = glob(
+        [
+            "src/main/java/**/*.java",
+        ],
+        exclude = PROLOG_PREDICATES,
+    ),
     manifest_entries = [
         "Implementation-Title: Gerrit OWNERS plugin",
         "Implementation-URL: https://gerrit.googlesource.com/plugins/owners",
@@ -32,9 +37,10 @@
         "Gerrit-Module: com.googlesource.gerrit.owners.OwnersModule",
         "Gerrit-ApiVersion: 2.14-SNAPSHOT",
     ],
-    resources = glob(["src/main/**/*"]),
+    resources = glob(["src/main/resources/**/*"]),
     deps = [
-        ":gerrit-owners-lib",
+        ":gerrit-owners-predicates",
         ":gerrit-owners-prolog-rules",
-    ] + EXTERNAL_DEPS,
+        "//owners-common",
+    ],
 )
diff --git a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersModule.java b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersModule.java
index 5fbb720..750c58e 100644
--- a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersModule.java
+++ b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersModule.java
@@ -22,6 +22,8 @@
 public class OwnersModule extends AbstractModule {
   @Override
   protected void configure() {
-    DynamicSet.bind(binder(), PredicateProvider.class).to(OwnerPredicateProvider.class);
+    DynamicSet.bind(binder(), PredicateProvider.class)
+        .to(OwnerPredicateProvider.class)
+        .asEagerSingleton();
   }
 }
diff --git a/tools/BUILD b/tools/BUILD
new file mode 100644
index 0000000..c5ed0b7
--- /dev/null
+++ b/tools/BUILD
@@ -0,0 +1 @@
+# Empty file required by Bazel
diff --git a/tools/bzl/BUILD b/tools/bzl/BUILD
new file mode 100644
index 0000000..c5ed0b7
--- /dev/null
+++ b/tools/bzl/BUILD
@@ -0,0 +1 @@
+# Empty file required by Bazel
diff --git a/tools/bzl/classpath.bzl b/tools/bzl/classpath.bzl
new file mode 100644
index 0000000..d5764f7
--- /dev/null
+++ b/tools/bzl/classpath.bzl
@@ -0,0 +1,4 @@
+load(
+    "@com_googlesource_gerrit_bazlets//tools:classpath.bzl",
+    "classpath_collector",
+)
diff --git a/tools/bzl/junit.bzl b/tools/bzl/junit.bzl
new file mode 100644
index 0000000..3af7e58
--- /dev/null
+++ b/tools/bzl/junit.bzl
@@ -0,0 +1,4 @@
+load(
+    "@com_googlesource_gerrit_bazlets//tools:junit.bzl",
+    "junit_tests",
+)
diff --git a/tools/bzl/maven_jar.bzl b/tools/bzl/maven_jar.bzl
new file mode 100644
index 0000000..43393b9
--- /dev/null
+++ b/tools/bzl/maven_jar.bzl
@@ -0,0 +1 @@
+load("@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl", "GERRIT", "maven_jar")
diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl
new file mode 100644
index 0000000..d21bdf4
--- /dev/null
+++ b/tools/bzl/plugin.bzl
@@ -0,0 +1,7 @@
+load(
+    "@com_googlesource_gerrit_bazlets//:gerrit_plugin.bzl",
+    "PLUGIN_DEPS",
+    "PLUGIN_DEPS_NEVERLINK",
+    "PLUGIN_TEST_DEPS",
+    "gerrit_plugin",
+)
diff --git a/tools/eclipse/BUILD b/tools/eclipse/BUILD
new file mode 100644
index 0000000..a53253f
--- /dev/null
+++ b/tools/eclipse/BUILD
@@ -0,0 +1,9 @@
+load("//tools/bzl:classpath.bzl", "classpath_collector")
+
+classpath_collector(
+    name = "main_classpath_collect",
+    testonly = 1,
+    deps = [
+        "//:owners_classpath_deps",
+    ],
+)
diff --git a/tools/eclipse/project.sh b/tools/eclipse/project.sh
new file mode 100755
index 0000000..100cc75
--- /dev/null
+++ b/tools/eclipse/project.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+#Copyright (C) 2017 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.
+
+`bazel query @com_googlesource_gerrit_bazlets//tools/eclipse:project --output location | sed s/BUILD:.*//`project.py -n owners -r .
+
+
diff --git a/tools/genrule2.bzl b/tools/genrule2.bzl
new file mode 100644
index 0000000..de66f32
--- /dev/null
+++ b/tools/genrule2.bzl
@@ -0,0 +1 @@
+load("@com_googlesource_gerrit_bazlets//tools:genrule2.bzl", "genrule2")
diff --git a/tools/workspace-status.sh b/tools/workspace-status.sh
new file mode 100755
index 0000000..3daa1b2
--- /dev/null
+++ b/tools/workspace-status.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# This script will be run by bazel when the build process starts to
+# generate key-value information that represents the status of the
+# workspace. The output should be like
+#
+# KEY1 VALUE1
+# KEY2 VALUE2
+#
+# If the script exits with non-zero code, it's considered as a failure
+# and the output will be discarded.
+
+function rev() {
+  cd $1; git describe --always --match "v[0-9].*" --dirty
+}
+
+echo STABLE_BUILD_OWNERS-AUTOASSIGN_LABEL $(rev .)
+echo STABLE_BUILD_OWNERS_LABEL $(rev .)