Fix caching of configs in ProjectState

ProjectState is caching project config files, but it only used the
file name as key and not the ref, which is an issue if the same config
file appears in different refs. This is e.g. the case for the
preference.config file in which the user preferences are stored as it
exists in each user ref. As result most users were getting the wrong
preferences for the 'My' menu entries.

Change-Id: Ib557ff3520bae1a8ee40e3ba6f1b3a8fdd3f880a
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
index 95386afb..88f4d1f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
@@ -87,7 +87,7 @@
   private final List<CommentLinkInfo> commentLinks;
 
   private final ProjectConfig config;
-  private final Map<String, ProjectLevelConfig> configs;
+  private final Map<ConfigKey, ProjectLevelConfig> configs;
   private final Set<AccountGroup.UUID> localOwners;
 
   /** Prolog rule state. */
@@ -227,8 +227,9 @@
   }
 
   public ProjectLevelConfig getConfig(String fileName, String ref) {
-    if (configs.containsKey(fileName)) {
-      return configs.get(fileName);
+    ConfigKey cfgKey = new ConfigKey(fileName, ref);
+    if (configs.containsKey(cfgKey)) {
+      return configs.get(cfgKey);
     }
 
     ProjectLevelConfig cfg = new ProjectLevelConfig(fileName, ref, this);
@@ -245,7 +246,7 @@
       log.warn("Failed to load " + fileName + " for " + getProject().getName(), e);
     }
 
-    configs.put(fileName, cfg);
+    configs.put(cfgKey, cfg);
     return cfg;
   }
 
@@ -504,4 +505,26 @@
     }
     return false;
   }
+
+  private static class ConfigKey {
+    final String file;
+    final String ref;
+
+    ConfigKey(String file, String ref) {
+      this.file = file;
+      this.ref = ref;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+      return other instanceof ConfigKey
+          && file.equals(((ConfigKey) other).file)
+          && ref.equals(((ConfigKey) other).ref);
+    }
+
+    @Override
+    public int hashCode() {
+      return file.hashCode() * 31 + ref.hashCode();
+    }
+  }
 }