Fix cache eviction for projects cache

When the project name contains a slash, the cache eviction router
throws a MalformedJsonException.

Detect key values that are string already and just pass them through
without JSON transcoding, preventing the problem of breakage when
the string value is not a valid JSON element.

Bug: Issue 12315
Change-Id: I31342cf14c64f2f3fdfcae985e99228ceb60c71a
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/GsonParser.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/GsonParser.java
index 7930207..cd14b93 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/GsonParser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/GsonParser.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.plugins.multisite.forwarder;
 
-import com.google.common.base.Strings;
+import com.google.common.base.MoreObjects;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gson.Gson;
@@ -25,29 +25,34 @@
 
   private GsonParser() {}
 
-  public static Object fromJson(String cacheName, String json) {
+  @SuppressWarnings("cast")
+  public static Object fromJson(String cacheName, Object json) {
     Gson gson = new GsonBuilder().create();
     Object key;
     // Need to add a case for 'adv_bases'
     switch (cacheName) {
       case Constants.ACCOUNTS:
-        key = gson.fromJson(Strings.nullToEmpty(json).trim(), Account.Id.class);
+        key = gson.fromJson(nullToEmpty(json).toString().trim(), Account.Id.class);
         break;
       case Constants.GROUPS:
-        key = gson.fromJson(Strings.nullToEmpty(json).trim(), AccountGroup.Id.class);
+        key = gson.fromJson(nullToEmpty(json).toString().trim(), AccountGroup.Id.class);
         break;
       case Constants.GROUPS_BYINCLUDE:
       case Constants.GROUPS_MEMBERS:
-        key = gson.fromJson(Strings.nullToEmpty(json).trim(), AccountGroup.UUID.class);
+        key = gson.fromJson(nullToEmpty(json).toString().trim(), AccountGroup.UUID.class);
         break;
       case Constants.PROJECT_LIST:
-        key = gson.fromJson(Strings.nullToEmpty(json), Object.class);
+        key = gson.fromJson(nullToEmpty(json).toString(), Object.class);
         break;
       default:
-        try {
-          key = gson.fromJson(Strings.nullToEmpty(json).trim(), String.class);
-        } catch (Exception e) {
-          key = gson.fromJson(Strings.nullToEmpty(json), Object.class);
+        if (json instanceof String) {
+          key = (String) json;
+        } else {
+          try {
+            key = gson.fromJson(nullToEmpty(json).toString().trim(), String.class);
+          } catch (Exception e) {
+            key = gson.fromJson(nullToEmpty(json).toString(), Object.class);
+          }
         }
     }
     return key;
@@ -74,4 +79,8 @@
     }
     return json;
   }
+
+  private static Object nullToEmpty(Object value) {
+    return MoreObjects.firstNonNull(value, "");
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java
index 4c17a95..a6cd8c4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java
@@ -31,8 +31,7 @@
 
   @Override
   public void route(CacheEvictionEvent cacheEvictionEvent) throws CacheNotFoundException {
-    Object parsedKey =
-        GsonParser.fromJson(cacheEvictionEvent.cacheName, cacheEvictionEvent.key.toString());
+    Object parsedKey = GsonParser.fromJson(cacheEvictionEvent.cacheName, cacheEvictionEvent.key);
     cacheEvictionHanlder.evict(CacheEntry.from(cacheEvictionEvent.cacheName, parsedKey));
   }
 }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java
index ec03a40..23cbd4d 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java
@@ -44,4 +44,13 @@
 
     verify(cacheEvictionHandler).evict(CacheEntry.from(event.cacheName, event.key));
   }
+
+  @Test
+  public void routerShouldSendEventsToTheAppropriateHandler_ProjectCacheEvictionWithSlash()
+      throws Exception {
+    final CacheEvictionEvent event = new CacheEvictionEvent("cache", "some/project");
+    router.route(event);
+
+    verify(cacheEvictionHandler).evict(CacheEntry.from(event.cacheName, event.key));
+  }
 }