Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ target/
.classpath
.project
.settings
.idea
*.iml
3 changes: 1 addition & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

Expand Down Expand Up @@ -127,4 +126,4 @@
<url>[email protected]:HubSpot/jackson-datatype-protobuf.git</url>
<tag>HEAD</tag>
</scm>
</project>
</project>
Original file line number Diff line number Diff line change
@@ -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<Descriptor, Set<ExtensionInfo>> extensionFunction;

private ExtensionRegistryWrapper() {
this.extensionFunction = new Function<Descriptor, Set<ExtensionInfo>>() {

@Override
public Set<ExtensionInfo> apply(Descriptor descriptor) {
return Collections.emptySet();
}
};
this.extensionFunction = descriptor -> Collections.emptySet();
}

private ExtensionRegistryWrapper(final ExtensionRegistry extensionRegistry) {
Expand All @@ -30,20 +26,13 @@ private ExtensionRegistryWrapper(final ExtensionRegistry extensionRegistry) {

@Override
public Set<ExtensionInfo> apply(Descriptor descriptor) {
Set<ExtensionInfo> cached = extensionCache.get(descriptor);
if (cached != null) {
return cached;
}

Set<ExtensionInfo> 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);
}

Expand All @@ -62,8 +51,4 @@ public List<ExtensionInfo> findExtensionsByDescriptor(Descriptor descriptor) {
public Set<ExtensionInfo> getExtensionsByDescriptor(Descriptor descriptor) {
return extensionFunction.apply(descriptor);
}

private interface Function<T, V> {
V apply(T t);
}
}
Original file line number Diff line number Diff line change
@@ -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();
Expand Down Expand Up @@ -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;

Expand All @@ -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);
}
}
Expand All @@ -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);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,53 @@
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<PropertyNamingStrategy, Function<FieldDescriptor, String>> serializationCache;
private final Map<PropertyNamingStrategy, Function<String, FieldDescriptor>> deserializationCache;

private static <K, V> ConcurrentMap<K, V> 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) {
return new PropertyNamingCache(descriptor, config);
}

public Function<FieldDescriptor, String> forSerialization(PropertyNamingStrategy propertyNamingStrategy) {
Function<FieldDescriptor, String> cached = serializationCache.get(propertyNamingStrategy);
if (cached != null) {
return cached;
} else {
Function<FieldDescriptor, String> function = buildSerializationFunction(descriptor, propertyNamingStrategy);
serializationCache.put(propertyNamingStrategy, function);

return function;
}
return serializationCache.computeIfAbsent(propertyNamingStrategy, this::buildSerializationFunction);
}

public Function<String, FieldDescriptor> forDeserialization(PropertyNamingStrategy propertyNamingStrategy) {
Function<String, FieldDescriptor> cached = deserializationCache.get(propertyNamingStrategy);
if (cached != null) {
return cached;
} else {
Function<String, FieldDescriptor> function = buildDeserializationFunction(descriptor, propertyNamingStrategy);
deserializationCache.put(propertyNamingStrategy, function);

return function;
}
return deserializationCache.computeIfAbsent(propertyNamingStrategy,this::buildDeserializationFunction);
}

private Function<FieldDescriptor, String> buildSerializationFunction(
Descriptor descriptor,
PropertyNamingStrategy originalNamingStrategy
) {
PropertyNamingStrategyBase namingStrategy =
Expand All @@ -75,7 +66,6 @@ private Function<FieldDescriptor, String> buildSerializationFunction(
}

private Function<String, FieldDescriptor> buildDeserializationFunction(
Descriptor descriptor,
PropertyNamingStrategy originalNamingStrategy
) {
PropertyNamingStrategyBase namingStrategy =
Expand Down