Replace anonymous Account.Id serializer with named class
CacheSerializer.convert constructs a CacheSerializer class which, being
created as return value, does not have a well-defined class name, but
rather an anonymous class name.
This can break some cache implementations that try to parse the
serializer and expect a well-defined class name.
Specifically this issue has been observed in an implementation of
chronicle-map cache. More information can be found in the relevant issue
ticket.
Bug: Issue 13410
Change-Id: I15cdfb4bcb0d3f2bb92bacf5d9ce9a5e270f5680
diff --git a/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java b/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java
index 3bb88e5..03ecd91 100644
--- a/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java
+++ b/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java
@@ -40,15 +40,32 @@
private final DynamicItem<OAuthTokenEncrypter> encrypter;
+ public enum AccountIdSerializer implements CacheSerializer<Account.Id> {
+ INSTANCE;
+
+ private final Converter<Account.Id, Integer> converter =
+ Converter.from(Account.Id::get, Account::id);
+
+ private final Converter<Integer, Account.Id> reverse = converter.reverse();
+
+ @Override
+ public byte[] serialize(Account.Id object) {
+ return IntegerCacheSerializer.INSTANCE.serialize(converter.convert(object));
+ }
+
+ @Override
+ public Account.Id deserialize(byte[] in) {
+ return reverse.convert(IntegerCacheSerializer.INSTANCE.deserialize(in));
+ }
+ }
+
public static Module module() {
return new CacheModule() {
@Override
protected void configure() {
persist(OAUTH_TOKENS, Account.Id.class, OAuthToken.class)
.version(1)
- .keySerializer(
- CacheSerializer.convert(
- IntegerCacheSerializer.INSTANCE, Converter.from(Account.Id::get, Account::id)))
+ .keySerializer(AccountIdSerializer.INSTANCE)
.valueSerializer(new Serializer());
}
};
diff --git a/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java b/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java
index 586f1bc..64fa74f 100644
--- a/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java
+++ b/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java
@@ -19,6 +19,7 @@
import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.auth.oauth.OAuthToken;
import com.google.gerrit.proto.testing.SerializedClassSubject;
import com.google.gerrit.server.cache.proto.Cache.OAuthTokenProto;
@@ -71,6 +72,23 @@
assertThat(s.deserialize(serializedWithEmptyString)).isEqualTo(tokenWithNull);
}
+ @Test
+ public void serializeAndDeserializeBackAccountId() {
+ OAuthTokenCache.AccountIdSerializer serializer = OAuthTokenCache.AccountIdSerializer.INSTANCE;
+
+ Account.Id id = Account.id(1234);
+ assertThat(serializer.deserialize(serializer.serialize(id))).isEqualTo(id);
+ }
+
+ // Anonymous classes can break some cache implementations that try to parse the
+ // serializer class name and expect a well-defined class name: test that
+ // OAuthTokenCache.AccountIdSerializer is not an anonymous class.
+ @Test
+ public void accountIdSerializerIsNotAnAnonymousClass() {
+ assertThat(OAuthTokenCache.AccountIdSerializer.INSTANCE.getDeclaringClass().getSimpleName())
+ .isNotEmpty();
+ }
+
/** See {@link SerializedClassSubject} for background and what to do if this test fails. */
@Test
public void oAuthTokenFields() throws Exception {