diff --git a/.gitignore b/.gitignore index b6cd1d6..ca92ae7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ target/ .classpath .project .settings +.idea +*.iml diff --git a/pom.xml b/pom.xml index fcfba55..3f161e3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,3 @@ - 4.0.0 @@ -127,4 +126,4 @@ git@github.com:HubSpot/jackson-datatype-protobuf.git HEAD - + \ No newline at end of file diff --git a/src/main/java/com/hubspot/jackson/datatype/protobuf/ExtensionRegistryWrapper.java b/src/main/java/com/hubspot/jackson/datatype/protobuf/ExtensionRegistryWrapper.java index 154b634..a1014de 100644 --- a/src/main/java/com/hubspot/jackson/datatype/protobuf/ExtensionRegistryWrapper.java +++ b/src/main/java/com/hubspot/jackson/datatype/protobuf/ExtensionRegistryWrapper.java @@ -1,27 +1,23 @@ package com.hubspot.jackson.datatype.protobuf; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.ExtensionRegistry.ExtensionInfo; + import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; - -import com.google.protobuf.Descriptors.Descriptor; -import com.google.protobuf.ExtensionRegistry; -import com.google.protobuf.ExtensionRegistry.ExtensionInfo; +import java.util.function.Function; public class ExtensionRegistryWrapper { private final Function> extensionFunction; private ExtensionRegistryWrapper() { - this.extensionFunction = new Function>() { - - @Override - public Set apply(Descriptor descriptor) { - return Collections.emptySet(); - } - }; + this.extensionFunction = descriptor -> Collections.emptySet(); } private ExtensionRegistryWrapper(final ExtensionRegistry extensionRegistry) { @@ -30,20 +26,13 @@ private ExtensionRegistryWrapper(final ExtensionRegistry extensionRegistry) { @Override public Set apply(Descriptor descriptor) { - Set cached = extensionCache.get(descriptor); - if (cached != null) { - return cached; - } - - Set extensions = - extensionRegistry.getAllImmutableExtensionsByExtendedType(descriptor.getFullName()); - extensionCache.put(descriptor, extensions); - return extensions; + return extensionCache.computeIfAbsent(descriptor, key -> extensionRegistry.getAllImmutableExtensionsByExtendedType(descriptor.getFullName())); } }; } public static ExtensionRegistryWrapper wrap(ExtensionRegistry extensionRegistry) { + Objects.requireNonNull(extensionRegistry, "extensionRegistry should not be null!"); return new ExtensionRegistryWrapper(extensionRegistry); } @@ -62,8 +51,4 @@ public List findExtensionsByDescriptor(Descriptor descriptor) { public Set getExtensionsByDescriptor(Descriptor descriptor) { return extensionFunction.apply(descriptor); } - - private interface Function { - V apply(T t); - } } diff --git a/src/main/java/com/hubspot/jackson/datatype/protobuf/PropertyNamingStrategyWrapper.java b/src/main/java/com/hubspot/jackson/datatype/protobuf/PropertyNamingStrategyWrapper.java index 2292f33..acedc8d 100644 --- a/src/main/java/com/hubspot/jackson/datatype/protobuf/PropertyNamingStrategyWrapper.java +++ b/src/main/java/com/hubspot/jackson/datatype/protobuf/PropertyNamingStrategyWrapper.java @@ -1,12 +1,14 @@ package com.hubspot.jackson.datatype.protobuf; -import java.lang.reflect.Method; - import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.PropertyNamingStrategy.PropertyNamingStrategyBase; import com.google.common.base.CaseFormat; -@SuppressWarnings("serial") +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +@SuppressWarnings("deprecation") public class PropertyNamingStrategyWrapper extends PropertyNamingStrategyBase { private static final PropertyNamingStrategyBase SNAKE_TO_CAMEL = new SnakeToCamelNamingStrategy(); private static final PropertyNamingStrategyBase NO_OP = new NoOpNamingStrategy(); @@ -49,7 +51,7 @@ public String translate(String fieldName) { private static class NamingBaseAdapter extends PropertyNamingStrategyBase { private static final Class NAMING_BASE = tryToLoadNamingBase(); - private static final Method TRANSLATE_METHOD = tryToLoadTranslateMethod(NAMING_BASE); + private static final MethodHandle TRANSLATE_METHOD = tryToLoadTranslateMethod(NAMING_BASE); private final PropertyNamingStrategy delegate; @@ -65,7 +67,7 @@ public static boolean extendsNamingBase(PropertyNamingStrategy namingStrategy) { public String translate(String fieldName) { try { return (String) TRANSLATE_METHOD.invoke(delegate, fieldName); - } catch (ReflectiveOperationException e) { + } catch (Throwable e) { throw new RuntimeException("Unable to invoke translate method", e); } } @@ -78,13 +80,13 @@ private static Class tryToLoadNamingBase() { } } - private static Method tryToLoadTranslateMethod(Class namingBase) { + private static MethodHandle tryToLoadTranslateMethod(Class namingBase) { if (namingBase == null) { return null; } else { try { - return namingBase.getMethod("translate", String.class); - } catch (NoSuchMethodException e) { + return MethodHandles.publicLookup().findVirtual(namingBase, "translate", MethodType.methodType(String.class, String.class)); + } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException("Unable to find translate method on class: " + namingBase); } } diff --git a/src/main/java/com/hubspot/jackson/datatype/protobuf/internal/PropertyNamingCache.java b/src/main/java/com/hubspot/jackson/datatype/protobuf/internal/PropertyNamingCache.java index 1b975a9..5fbc537 100644 --- a/src/main/java/com/hubspot/jackson/datatype/protobuf/internal/PropertyNamingCache.java +++ b/src/main/java/com/hubspot/jackson/datatype/protobuf/internal/PropertyNamingCache.java @@ -1,30 +1,38 @@ package com.hubspot.jackson.datatype.protobuf.internal; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.function.Function; - import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.PropertyNamingStrategy.PropertyNamingStrategyBase; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.MapMaker; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.hubspot.jackson.datatype.protobuf.PropertyNamingStrategyWrapper; import com.hubspot.jackson.datatype.protobuf.ProtobufJacksonConfig; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + public class PropertyNamingCache { + + private static final int DEFAULT_CONCURRENCY_LEVEL = Math.min(Runtime.getRuntime().availableProcessors(), 16); private final Descriptor descriptor; private final ProtobufJacksonConfig config; private final Map> serializationCache; private final Map> deserializationCache; + private static ConcurrentMap buildWeakMap() { + return new MapMaker().concurrencyLevel(DEFAULT_CONCURRENCY_LEVEL).weakKeys().makeMap(); + } + private PropertyNamingCache(Descriptor descriptor, ProtobufJacksonConfig config) { this.descriptor = descriptor; this.config = config; - this.serializationCache = Collections.synchronizedMap(new WeakHashMap<>()); - this.deserializationCache = Collections.synchronizedMap(new WeakHashMap<>()); + this.serializationCache = buildWeakMap(); + this.deserializationCache = buildWeakMap(); } public static PropertyNamingCache forDescriptor(Descriptor descriptor, ProtobufJacksonConfig config) { @@ -32,31 +40,14 @@ public static PropertyNamingCache forDescriptor(Descriptor descriptor, ProtobufJ } public Function forSerialization(PropertyNamingStrategy propertyNamingStrategy) { - Function cached = serializationCache.get(propertyNamingStrategy); - if (cached != null) { - return cached; - } else { - Function function = buildSerializationFunction(descriptor, propertyNamingStrategy); - serializationCache.put(propertyNamingStrategy, function); - - return function; - } + return serializationCache.computeIfAbsent(propertyNamingStrategy, this::buildSerializationFunction); } public Function forDeserialization(PropertyNamingStrategy propertyNamingStrategy) { - Function cached = deserializationCache.get(propertyNamingStrategy); - if (cached != null) { - return cached; - } else { - Function function = buildDeserializationFunction(descriptor, propertyNamingStrategy); - deserializationCache.put(propertyNamingStrategy, function); - - return function; - } + return deserializationCache.computeIfAbsent(propertyNamingStrategy,this::buildDeserializationFunction); } private Function buildSerializationFunction( - Descriptor descriptor, PropertyNamingStrategy originalNamingStrategy ) { PropertyNamingStrategyBase namingStrategy = @@ -75,7 +66,6 @@ private Function buildSerializationFunction( } private Function buildDeserializationFunction( - Descriptor descriptor, PropertyNamingStrategy originalNamingStrategy ) { PropertyNamingStrategyBase namingStrategy =