ProjectCacheImpl: Harden against null UUIDs

Since Ie51b350d GroupList#uuids may include null UUIDs. Regardless of
whether or not this is a good idea, these UUIDs are never relevant as
defined by ProjectCache#guessRelevantGroupUUIDs. Harden
ProjectCacheImpl against this state of affairs as well as future bugs.

This is a backport of I74c62a500 from master, which cannot be directly
cherry-picked to stable-2.13 due to using Java 8 specific syntax. This
is re-implemented in a Java 7 compatible way.

Change-Id: I448e3f30374ebf25c44f3b3a6911db5725173a28
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index d27d4f9..1753300 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -14,9 +14,11 @@
 
 package com.google.gerrit.server.project;
 
+import com.google.common.base.Predicate;
 import com.google.common.base.Throwables;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Sets;
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -58,6 +60,14 @@
   private static final String CACHE_NAME = "projects";
   private static final String CACHE_LIST = "project_list";
 
+  private static final Predicate<AccountGroup.UUID> NON_NULL_UUID =
+      new Predicate<AccountGroup.UUID>() {
+        @Override
+        public boolean apply(AccountGroup.UUID uuid) {
+          return uuid != null && uuid.get() != null;
+        }
+      };
+
   public static Module module() {
     return new CacheModule() {
       @Override
@@ -200,12 +210,12 @@
   }
 
   @Override
-  public Iterable<Project.NameKey> all() {
+  public SortedSet<Project.NameKey> all() {
     try {
       return list.get(ListKey.ALL);
     } catch (ExecutionException e) {
       log.warn("Cannot list available projects", e);
-      return Collections.emptyList();
+      return Collections.emptySortedSet();
     }
   }
 
@@ -215,7 +225,10 @@
     for (Project.NameKey n : all()) {
       ProjectState p = byName.getIfPresent(n.get());
       if (p != null) {
-        groups.addAll(p.getConfig().getAllGroupUUIDs());
+        groups.addAll(FluentIterable
+            .from(p.getConfig().getAllGroupUUIDs())
+            .filter(NON_NULL_UUID)
+            .toSet());
       }
     }
     return groups;