Polishing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -194,7 +194,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
* @see <a href="https://tools.ietf.org/html/rfc2616#section-2.2">HTTP 1.1, section 2.2</a>
|
||||
*/
|
||||
private void checkToken(String token) {
|
||||
for (int i = 0; i < token.length(); i++ ) {
|
||||
for (int i = 0; i < token.length(); i++) {
|
||||
char ch = token.charAt(i);
|
||||
if (!TOKEN.get(ch)) {
|
||||
throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + token + "\"");
|
||||
@@ -207,8 +207,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
Assert.hasLength(value, "'value' must not be empty");
|
||||
checkToken(attribute);
|
||||
if (PARAM_CHARSET.equals(attribute)) {
|
||||
value = unquote(value);
|
||||
Charset.forName(value);
|
||||
Charset.forName(unquote(value));
|
||||
}
|
||||
else if (!isQuotedString(value)) {
|
||||
checkToken(value);
|
||||
|
||||
@@ -123,7 +123,7 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
|
||||
/**
|
||||
* Specify the encoding to use when converting to and from text-based
|
||||
* message body content. The default encoding will be "UTF-8".
|
||||
* <p>When reading from a a text-based message, an encoding may have been
|
||||
* <p>When reading from a text-based message, an encoding may have been
|
||||
* suggested through a special JMS property which will then be preferred
|
||||
* over the encoding set on this MessageConverter instance.
|
||||
* @see #setEncodingPropertyName
|
||||
@@ -457,11 +457,11 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
|
||||
}
|
||||
Class<?> mappedClass = this.idClassMappings.get(typeId);
|
||||
if (mappedClass != null) {
|
||||
return this.objectMapper.getTypeFactory().constructType(mappedClass);
|
||||
return this.objectMapper.constructType(mappedClass);
|
||||
}
|
||||
try {
|
||||
Class<?> typeClass = ClassUtils.forName(typeId, this.beanClassLoader);
|
||||
return this.objectMapper.getTypeFactory().constructType(typeClass);
|
||||
return this.objectMapper.constructType(typeClass);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new MessageConversionException("Failed to resolve type id [" + typeId + "]", ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -151,21 +151,6 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the default content type for the payload. Called when
|
||||
* {@link #toMessage(Object, MessageHeaders)} is invoked without message headers or
|
||||
* without a content type header.
|
||||
* <p>By default, this returns the first element of the {@link #getSupportedMimeTypes()
|
||||
* supportedMimeTypes}, if any. Can be overridden in sub-classes.
|
||||
* @param payload the payload being converted to message
|
||||
* @return the content type, or {@code null} if not known
|
||||
*/
|
||||
@Nullable
|
||||
protected MimeType getDefaultContentType(Object payload) {
|
||||
List<MimeType> mimeTypes = getSupportedMimeTypes();
|
||||
return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public final Object fromMessage(Message<?> message, Class<?> targetClass) {
|
||||
@@ -181,10 +166,6 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
|
||||
return convertFromInternal(message, targetClass, conversionHint);
|
||||
}
|
||||
|
||||
protected boolean canConvertFrom(Message<?> message, Class<?> targetClass) {
|
||||
return (supports(targetClass) && supportsMimeType(message.getHeaders()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public final Message<?> toMessage(Object payload, @Nullable MessageHeaders headers) {
|
||||
@@ -224,6 +205,11 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
protected boolean canConvertFrom(Message<?> message, Class<?> targetClass) {
|
||||
return (supports(targetClass) && supportsMimeType(message.getHeaders()));
|
||||
}
|
||||
|
||||
protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) {
|
||||
return (supports(payload.getClass()) && supportsMimeType(headers));
|
||||
}
|
||||
@@ -249,6 +235,22 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter
|
||||
return (headers != null && this.contentTypeResolver != null ? this.contentTypeResolver.resolve(headers) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default content type for the payload. Called when
|
||||
* {@link #toMessage(Object, MessageHeaders)} is invoked without
|
||||
* message headers or without a content type header.
|
||||
* <p>By default, this returns the first element of the
|
||||
* {@link #getSupportedMimeTypes() supportedMimeTypes}, if any.
|
||||
* Can be overridden in subclasses.
|
||||
* @param payload the payload being converted to a message
|
||||
* @return the content type, or {@code null} if not known
|
||||
*/
|
||||
@Nullable
|
||||
protected MimeType getDefaultContentType(Object payload) {
|
||||
List<MimeType> mimeTypes = getSupportedMimeTypes();
|
||||
return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether the given class is supported by this converter.
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
@@ -141,6 +142,7 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean canConvertFrom(Message<?> message, @Nullable Class<?> targetClass) {
|
||||
if (targetClass == null || !supportsMimeType(message.getHeaders())) {
|
||||
@@ -212,7 +214,7 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||
Object payload = message.getPayload();
|
||||
Class<?> view = getSerializationView(conversionHint);
|
||||
try {
|
||||
if (targetClass.isInstance(payload)) {
|
||||
if (ClassUtils.isAssignableValue(targetClass, payload)) {
|
||||
return payload;
|
||||
}
|
||||
else if (payload instanceof byte[]) {
|
||||
@@ -248,7 +250,7 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||
Type genericParameterType = param.getNestedGenericParameterType();
|
||||
Class<?> contextClass = param.getContainingClass();
|
||||
Type type = GenericTypeResolver.resolveType(genericParameterType, contextClass);
|
||||
return this.objectMapper.getTypeFactory().constructType(type);
|
||||
return this.objectMapper.constructType(type);
|
||||
}
|
||||
return this.objectMapper.constructType(targetClass);
|
||||
}
|
||||
@@ -333,7 +335,7 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||
* @return the JSON encoding to use (never {@code null})
|
||||
*/
|
||||
protected JsonEncoding getJsonEncoding(@Nullable MimeType contentType) {
|
||||
if (contentType != null && (contentType.getCharset() != null)) {
|
||||
if (contentType != null && contentType.getCharset() != null) {
|
||||
Charset charset = contentType.getCharset();
|
||||
for (JsonEncoding encoding : JsonEncoding.values()) {
|
||||
if (charset.name().equals(encoding.getJavaName())) {
|
||||
|
||||
@@ -47,6 +47,8 @@ import org.springframework.util.MimeType;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 4.2
|
||||
* @see Marshaller
|
||||
* @see Unmarshaller
|
||||
*/
|
||||
public class MarshallingMessageConverter extends AbstractMessageConverter {
|
||||
|
||||
@@ -62,7 +64,8 @@ public class MarshallingMessageConverter extends AbstractMessageConverter {
|
||||
* {@link #setUnmarshaller(Unmarshaller)} to be invoked separately.
|
||||
*/
|
||||
public MarshallingMessageConverter() {
|
||||
this(new MimeType("application", "xml"), new MimeType("text", "xml"), new MimeType("application", "*+xml"));
|
||||
this(new MimeType("application", "xml"), new MimeType("text", "xml"),
|
||||
new MimeType("application", "*+xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +164,7 @@ public class MarshallingMessageConverter extends AbstractMessageConverter {
|
||||
return new StreamSource(new ByteArrayInputStream((byte[]) payload));
|
||||
}
|
||||
else {
|
||||
return new StreamSource(new StringReader((String) payload));
|
||||
return new StreamSource(new StringReader(payload.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -75,13 +75,8 @@ public class MappingJackson2MessageConverterTests {
|
||||
@Test
|
||||
public void fromMessage() {
|
||||
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
|
||||
String payload = "{" +
|
||||
"\"bytes\":\"AQI=\"," +
|
||||
"\"array\":[\"Foo\",\"Bar\"]," +
|
||||
"\"number\":42," +
|
||||
"\"string\":\"Foo\"," +
|
||||
"\"bool\":true," +
|
||||
"\"fraction\":42.0}";
|
||||
String payload = "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"]," +
|
||||
"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
|
||||
Message<?> message = MessageBuilder.withPayload(payload.getBytes(StandardCharsets.UTF_8)).build();
|
||||
MyBean actual = (MyBean) converter.fromMessage(message, MyBean.class);
|
||||
|
||||
@@ -245,9 +240,12 @@ public class MappingJackson2MessageConverterTests {
|
||||
public void jsonViewPayload(@JsonView(MyJacksonView2.class) JacksonViewBean payload) {
|
||||
}
|
||||
|
||||
void handleList(List<Long> payload) {}
|
||||
void handleList(List<Long> payload) {
|
||||
}
|
||||
|
||||
void handleMessage(Message<MyBean> message) {
|
||||
}
|
||||
|
||||
void handleMessage(Message<MyBean> message) {}
|
||||
|
||||
public static class MyBean {
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
|
||||
|
||||
@Override
|
||||
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
|
||||
JavaType javaType = getObjectMapper().getTypeFactory().constructType(elementType.getType());
|
||||
JavaType javaType = getObjectMapper().constructType(elementType.getType());
|
||||
// Skip String: CharSequenceDecoder + "*/*" comes after
|
||||
return (!CharSequence.class.isAssignableFrom(elementType.toClass()) &&
|
||||
getObjectMapper().canDeserialize(javaType) && supportsMimeType(mimeType));
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
@@ -100,8 +99,7 @@ public abstract class Jackson2CodecSupport {
|
||||
}
|
||||
|
||||
protected JavaType getJavaType(Type type, @Nullable Class<?> contextClass) {
|
||||
TypeFactory typeFactory = this.objectMapper.getTypeFactory();
|
||||
return typeFactory.constructType(GenericTypeResolver.resolveType(type, contextClass));
|
||||
return this.objectMapper.constructType(GenericTypeResolver.resolveType(type, contextClass));
|
||||
}
|
||||
|
||||
protected Map<String, Object> getHints(ResolvableType resolvableType) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
|
||||
* Strategy interface for converting from and to HTTP requests and responses.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
@@ -54,7 +54,7 @@ public interface HttpMessageConverter<T> {
|
||||
|
||||
/**
|
||||
* Return the list of {@link MediaType} objects supported by this converter.
|
||||
* @return the list of supported media types
|
||||
* @return the list of supported media types, potentially an immutable copy
|
||||
*/
|
||||
List<MediaType> getSupportedMediaTypes();
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
|
||||
import com.fasterxml.jackson.databind.ser.FilterProvider;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
@@ -376,8 +375,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
|
||||
* @return the Jackson JavaType
|
||||
*/
|
||||
protected JavaType getJavaType(Type type, @Nullable Class<?> contextClass) {
|
||||
TypeFactory typeFactory = this.objectMapper.getTypeFactory();
|
||||
return typeFactory.constructType(GenericTypeResolver.resolveType(type, contextClass));
|
||||
return this.objectMapper.constructType(GenericTypeResolver.resolveType(type, contextClass));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -109,9 +108,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
ClassLoader classLoader = RestTemplate.class.getClassLoader();
|
||||
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
|
||||
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
|
||||
jackson2Present =
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
|
||||
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
|
||||
jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
|
||||
@@ -912,7 +910,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
HttpHeaders httpHeaders = httpRequest.getHeaders();
|
||||
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
|
||||
if (!requestHeaders.isEmpty()) {
|
||||
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new LinkedList<>(values)));
|
||||
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new ArrayList<>(values)));
|
||||
}
|
||||
if (httpHeaders.getContentLength() < 0) {
|
||||
httpHeaders.setContentLength(0L);
|
||||
@@ -931,7 +929,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
(GenericHttpMessageConverter<Object>) messageConverter;
|
||||
if (genericConverter.canWrite(requestBodyType, requestBodyClass, requestContentType)) {
|
||||
if (!requestHeaders.isEmpty()) {
|
||||
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new LinkedList<>(values)));
|
||||
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new ArrayList<>(values)));
|
||||
}
|
||||
logBody(requestBody, requestContentType, genericConverter);
|
||||
genericConverter.write(requestBody, requestBodyType, requestContentType, httpRequest);
|
||||
@@ -940,7 +938,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
}
|
||||
else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
|
||||
if (!requestHeaders.isEmpty()) {
|
||||
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new LinkedList<>(values)));
|
||||
requestHeaders.forEach((key, values) -> httpHeaders.put(key, new ArrayList<>(values)));
|
||||
}
|
||||
logBody(requestBody, requestContentType, messageConverter);
|
||||
((HttpMessageConverter<Object>) messageConverter).write(
|
||||
|
||||
@@ -233,7 +233,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
|
||||
}
|
||||
builder.scheme(scheme);
|
||||
if (opaque) {
|
||||
String ssp = uri.substring(scheme.length()).substring(1);
|
||||
String ssp = uri.substring(scheme.length() + 1);
|
||||
if (StringUtils.hasLength(fragment)) {
|
||||
ssp = ssp.substring(0, ssp.length() - (fragment.length() + 1));
|
||||
}
|
||||
@@ -394,9 +394,8 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
|
||||
* characters that should have been encoded.
|
||||
*/
|
||||
public UriComponents build(boolean encoded) {
|
||||
return buildInternal(encoded ?
|
||||
EncodingHint.FULLY_ENCODED :
|
||||
this.encodeTemplate ? EncodingHint.ENCODE_TEMPLATE : EncodingHint.NONE);
|
||||
return buildInternal(encoded ? EncodingHint.FULLY_ENCODED :
|
||||
(this.encodeTemplate ? EncodingHint.ENCODE_TEMPLATE : EncodingHint.NONE));
|
||||
}
|
||||
|
||||
private UriComponents buildInternal(EncodingHint hint) {
|
||||
@@ -408,8 +407,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
|
||||
HierarchicalUriComponents uric = new HierarchicalUriComponents(this.scheme, this.fragment,
|
||||
this.userInfo, this.host, this.port, this.pathBuilder.build(), this.queryParams,
|
||||
hint == EncodingHint.FULLY_ENCODED);
|
||||
|
||||
result = hint == EncodingHint.ENCODE_TEMPLATE ? uric.encodeTemplate(this.charset) : uric;
|
||||
result = (hint == EncodingHint.ENCODE_TEMPLATE ? uric.encodeTemplate(this.charset) : uric);
|
||||
}
|
||||
if (!this.uriVariables.isEmpty()) {
|
||||
result = result.expand(name -> this.uriVariables.getOrDefault(name, UriTemplateVariables.SKIP_VALUE));
|
||||
@@ -466,9 +464,8 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
|
||||
* @see UriComponents#toUriString()
|
||||
*/
|
||||
public String toUriString() {
|
||||
return this.uriVariables.isEmpty() ?
|
||||
build().encode().toUriString() :
|
||||
buildInternal(EncodingHint.ENCODE_TEMPLATE).toUriString();
|
||||
return (this.uriVariables.isEmpty() ? build().encode().toUriString() :
|
||||
buildInternal(EncodingHint.ENCODE_TEMPLATE).toUriString());
|
||||
}
|
||||
|
||||
|
||||
@@ -849,12 +846,10 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
|
||||
scheme("https");
|
||||
port(null);
|
||||
}
|
||||
|
||||
String hostHeader = headers.getFirst("X-Forwarded-Host");
|
||||
if (StringUtils.hasText(hostHeader)) {
|
||||
adaptForwardedHost(StringUtils.tokenizeToStringArray(hostHeader, ",")[0]);
|
||||
}
|
||||
|
||||
String portHeader = headers.getFirst("X-Forwarded-Port");
|
||||
if (StringUtils.hasText(portHeader)) {
|
||||
port(Integer.parseInt(StringUtils.tokenizeToStringArray(portHeader, ",")[0]));
|
||||
|
||||
Reference in New Issue
Block a user