|
|
|
|
@@ -1,5 +1,5 @@
|
|
|
|
|
/*
|
|
|
|
|
* Copyright 2002-2022 the original author or authors.
|
|
|
|
|
* Copyright 2002-2023 the original author or authors.
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
@@ -32,8 +32,6 @@ import com.google.protobuf.ExtensionRegistry;
|
|
|
|
|
import com.google.protobuf.Message;
|
|
|
|
|
import com.google.protobuf.TextFormat;
|
|
|
|
|
import com.google.protobuf.util.JsonFormat;
|
|
|
|
|
import com.googlecode.protobuf.format.FormatFactory;
|
|
|
|
|
import com.googlecode.protobuf.format.ProtobufFormatter;
|
|
|
|
|
|
|
|
|
|
import org.springframework.http.HttpInputMessage;
|
|
|
|
|
import org.springframework.http.HttpOutputMessage;
|
|
|
|
|
@@ -48,8 +46,6 @@ import org.springframework.util.ClassUtils;
|
|
|
|
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
|
|
|
|
|
|
|
|
|
import static org.springframework.http.MediaType.APPLICATION_JSON;
|
|
|
|
|
import static org.springframework.http.MediaType.APPLICATION_XML;
|
|
|
|
|
import static org.springframework.http.MediaType.TEXT_HTML;
|
|
|
|
|
import static org.springframework.http.MediaType.TEXT_PLAIN;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -60,26 +56,17 @@ import static org.springframework.http.MediaType.TEXT_PLAIN;
|
|
|
|
|
* <p>To generate {@code Message} Java classes, you need to install the {@code protoc} binary.
|
|
|
|
|
*
|
|
|
|
|
* <p>This converter supports by default {@code "application/x-protobuf"} and {@code "text/plain"}
|
|
|
|
|
* with the official {@code "com.google.protobuf:protobuf-java"} library. Other formats can be
|
|
|
|
|
* supported with one of the following additional libraries on the classpath:
|
|
|
|
|
* <ul>
|
|
|
|
|
* <li>{@code "application/json"}, {@code "application/xml"}, and {@code "text/html"} (write-only)
|
|
|
|
|
* with the {@code "com.googlecode.protobuf-java-format:protobuf-java-format"} third-party library
|
|
|
|
|
* <li>{@code "application/json"} with the official {@code "com.google.protobuf:protobuf-java-util"}
|
|
|
|
|
* for Protobuf 3 (see {@link ProtobufJsonFormatHttpMessageConverter} for a configurable variant)
|
|
|
|
|
* </ul>
|
|
|
|
|
* with the official {@code "com.google.protobuf:protobuf-java"} library.
|
|
|
|
|
* The {@code "application/json"} format is also supported with the {@code "com.google.protobuf:protobuf-java-util"}
|
|
|
|
|
* dependency. See {@link ProtobufJsonFormatHttpMessageConverter} for a configurable variant.
|
|
|
|
|
*
|
|
|
|
|
* <p>Requires Protobuf 2.6 or higher (and Protobuf Java Format 1.4 or higher for formatting).
|
|
|
|
|
* This converter will auto-adapt to Protobuf 3 and its default {@code protobuf-java-util} JSON
|
|
|
|
|
* format if the Protobuf 2 based {@code protobuf-java-format} isn't present; however, for more
|
|
|
|
|
* explicit JSON setup on Protobuf 3, consider {@link ProtobufJsonFormatHttpMessageConverter}.
|
|
|
|
|
* <p>This converter requires Protobuf 3 or higher as of Spring Framework 6.1.
|
|
|
|
|
*
|
|
|
|
|
* @author Alex Antonov
|
|
|
|
|
* @author Brian Clozel
|
|
|
|
|
* @author Juergen Hoeller
|
|
|
|
|
* @author Sebastien Deleuze
|
|
|
|
|
* @since 4.1
|
|
|
|
|
* @see FormatFactory
|
|
|
|
|
* @see JsonFormat
|
|
|
|
|
* @see ProtobufJsonFormatHttpMessageConverter
|
|
|
|
|
*/
|
|
|
|
|
@@ -105,18 +92,10 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
|
|
|
|
*/
|
|
|
|
|
public static final String X_PROTOBUF_MESSAGE_HEADER = "X-Protobuf-Message";
|
|
|
|
|
|
|
|
|
|
private static final boolean protobufFormatFactoryPresent;
|
|
|
|
|
|
|
|
|
|
private static final boolean protobufJsonFormatPresent;
|
|
|
|
|
private static final boolean protobufJsonFormatPresent = ClassUtils.isPresent("com.google.protobuf.util.JsonFormat", ProtobufHttpMessageConverter.class.getClassLoader());
|
|
|
|
|
|
|
|
|
|
private static final Map<Class<?>, Method> methodCache = new ConcurrentReferenceHashMap<>();
|
|
|
|
|
|
|
|
|
|
static {
|
|
|
|
|
ClassLoader classLoader = ProtobufHttpMessageConverter.class.getClassLoader();
|
|
|
|
|
protobufFormatFactoryPresent = ClassUtils.isPresent("com.googlecode.protobuf.format.FormatFactory", classLoader);
|
|
|
|
|
protobufJsonFormatPresent = ClassUtils.isPresent("com.google.protobuf.util.JsonFormat", classLoader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final ExtensionRegistry extensionRegistry;
|
|
|
|
|
|
|
|
|
|
@@ -146,9 +125,6 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
|
|
|
|
if (formatSupport != null) {
|
|
|
|
|
this.protobufFormatSupport = formatSupport;
|
|
|
|
|
}
|
|
|
|
|
else if (protobufFormatFactoryPresent) {
|
|
|
|
|
this.protobufFormatSupport = new ProtobufJavaFormatSupport();
|
|
|
|
|
}
|
|
|
|
|
else if (protobufJsonFormatPresent) {
|
|
|
|
|
this.protobufFormatSupport = new ProtobufJavaUtilSupport(null, null);
|
|
|
|
|
}
|
|
|
|
|
@@ -290,73 +266,6 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@link ProtobufFormatSupport} implementation used when
|
|
|
|
|
* {@code com.googlecode.protobuf.format.FormatFactory} is available.
|
|
|
|
|
*/
|
|
|
|
|
static class ProtobufJavaFormatSupport implements ProtobufFormatSupport {
|
|
|
|
|
|
|
|
|
|
private final ProtobufFormatter jsonFormatter;
|
|
|
|
|
|
|
|
|
|
private final ProtobufFormatter xmlFormatter;
|
|
|
|
|
|
|
|
|
|
private final ProtobufFormatter htmlFormatter;
|
|
|
|
|
|
|
|
|
|
public ProtobufJavaFormatSupport() {
|
|
|
|
|
FormatFactory formatFactory = new FormatFactory();
|
|
|
|
|
this.jsonFormatter = formatFactory.createFormatter(FormatFactory.Formatter.JSON);
|
|
|
|
|
this.xmlFormatter = formatFactory.createFormatter(FormatFactory.Formatter.XML);
|
|
|
|
|
this.htmlFormatter = formatFactory.createFormatter(FormatFactory.Formatter.HTML);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public MediaType[] supportedMediaTypes() {
|
|
|
|
|
return new MediaType[] {PROTOBUF, TEXT_PLAIN, APPLICATION_XML, APPLICATION_JSON};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean supportsWriteOnly(@Nullable MediaType mediaType) {
|
|
|
|
|
return TEXT_HTML.isCompatibleWith(mediaType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void merge(InputStream input, Charset charset, MediaType contentType,
|
|
|
|
|
ExtensionRegistry extensionRegistry, Message.Builder builder)
|
|
|
|
|
throws IOException, HttpMessageConversionException {
|
|
|
|
|
|
|
|
|
|
if (contentType.isCompatibleWith(APPLICATION_JSON)) {
|
|
|
|
|
this.jsonFormatter.merge(input, charset, extensionRegistry, builder);
|
|
|
|
|
}
|
|
|
|
|
else if (contentType.isCompatibleWith(APPLICATION_XML)) {
|
|
|
|
|
this.xmlFormatter.merge(input, charset, extensionRegistry, builder);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
throw new HttpMessageConversionException(
|
|
|
|
|
"protobuf-java-format does not support parsing " + contentType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void print(Message message, OutputStream output, MediaType contentType, Charset charset)
|
|
|
|
|
throws IOException, HttpMessageConversionException {
|
|
|
|
|
|
|
|
|
|
if (contentType.isCompatibleWith(APPLICATION_JSON)) {
|
|
|
|
|
this.jsonFormatter.print(message, output, charset);
|
|
|
|
|
}
|
|
|
|
|
else if (contentType.isCompatibleWith(APPLICATION_XML)) {
|
|
|
|
|
this.xmlFormatter.print(message, output, charset);
|
|
|
|
|
}
|
|
|
|
|
else if (contentType.isCompatibleWith(TEXT_HTML)) {
|
|
|
|
|
this.htmlFormatter.print(message, output, charset);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
throw new HttpMessageConversionException(
|
|
|
|
|
"protobuf-java-format does not support printing " + contentType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@link ProtobufFormatSupport} implementation used when
|
|
|
|
|
* {@code com.google.protobuf.util.JsonFormat} is available.
|
|
|
|
|
|