From 72e7687b8049c4e00b2d3f7effb25feabe2df95e Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 21 May 2018 15:14:28 -0400 Subject: [PATCH] Polish CodecConfigurer related classes Functionally equivalent updates to package private classes to improve the code and make it easier to understand. --- .../http/codec/ClientCodecConfigurer.java | 20 +- .../http/codec/CodecConfigurer.java | 60 +++- .../http/codec/ServerCodecConfigurer.java | 20 +- .../support/AbstractCodecConfigurer.java | 313 ------------------ .../codec/support/BaseCodecConfigurer.java | 168 ++++++++++ .../http/codec/support/BaseDefaultCodecs.java | 210 ++++++++++++ .../support/ClientDefaultCodecsImpl.java | 140 ++++++++ .../support/DefaultClientCodecConfigurer.java | 112 +------ .../support/DefaultServerCodecConfigurer.java | 66 +--- .../support/ServerDefaultCodecsImpl.java | 69 ++++ .../support/ClientCodecConfigurerTests.java | 4 +- .../codec/support/CodecConfigurerTests.java | 13 +- 12 files changed, 666 insertions(+), 529 deletions(-) delete mode 100644 spring-web/src/main/java/org/springframework/http/codec/support/AbstractCodecConfigurer.java create mode 100644 spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java create mode 100644 spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java create mode 100644 spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java create mode 100644 spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java diff --git a/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java index 63fe8e6bd30..19fa80c6a0a 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java @@ -20,27 +20,25 @@ import org.springframework.core.codec.Decoder; import org.springframework.core.codec.Encoder; /** - * Helps to configure a list of client-side HTTP message readers and writers - * with support for built-in defaults and options to register additional custom - * readers and writers via {@link #customCodecs()}. - * - *

The built-in defaults include basic data types such as various byte - * representations, resources, strings, forms, but also others like JAXB2 and - * Jackson 2 based on classpath detection. There are options to - * {@link #defaultCodecs() override} some of the defaults or to have them - * {@link #registerDefaults(boolean) turned off} completely. + * Extension of {@link CodecConfigurer} for HTTP message reader and writer + * options relevant on the client side. * * @author Rossen Stoyanchev * @since 5.0 */ public interface ClientCodecConfigurer extends CodecConfigurer { + /** + * {@inheritDoc} + *

On the client side, built-in default also include customizations related + * to multipart readers and writers, as well as the decoder for SSE. + */ @Override ClientDefaultCodecs defaultCodecs(); /** - * Create a new instance of the {@code ClientCodecConfigurer}. + * Static factory method for a {@code ClientCodecConfigurer}. */ static ClientCodecConfigurer create() { return CodecConfigurerFactory.create(ClientCodecConfigurer.class); @@ -48,7 +46,7 @@ public interface ClientCodecConfigurer extends CodecConfigurer { /** - * Extension of {@link CodecConfigurer.DefaultCodecs} with extra client options. + * {@link CodecConfigurer.DefaultCodecs} extension with extra client-side options. */ interface ClientDefaultCodecs extends DefaultCodecs { diff --git a/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java index e555569e62f..214319c0a2e 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -23,9 +23,30 @@ import org.springframework.core.codec.Encoder; /** * Defines a common interface for configuring either client or server HTTP - * message readers and writers. To obtain an instance use either - * {@link ClientCodecConfigurer#create()} or - * {@link ServerCodecConfigurer#create()}. + * message readers and writers. This is used as follows: + *

+ * + *

HTTP message readers and writers are divided into 3 categories that are + * ordered as follows: + *

    + *
  1. Typed readers and writers that support specific types, e.g. byte[], String. + *
  2. Object readers and writers, e.g. JSON, XML. + *
  3. Catch-all readers or writers, e.g. String with any media type. + *
+ * + *

Typed and object readers are further sub-divided and ordered as follows: + *

    + *
  1. Default HTTP reader and writer registrations. + *
  2. Custom readers and writers. + *
* * @author Rossen Stoyanchev * @since 5.0 @@ -33,22 +54,28 @@ import org.springframework.core.codec.Encoder; public interface CodecConfigurer { /** - * Configure or customize the default HTTP message readers and writers. + * Provides a way to customize or replace HTTP message readers and writers + * registered by default. + * @see #registerDefaults(boolean) */ DefaultCodecs defaultCodecs(); /** - * Whether to register default HTTP message readers and writers. - *

By default this is set to {@code "true"}; setting this to {@code false} - * disables default HTTP message reader and writer registrations. + * Register custom HTTP message readers or writers in addition to the ones + * registered by default. */ - void registerDefaults(boolean registerDefaults); + CustomCodecs customCodecs(); /** - * Register custom HTTP message readers or writers to use in addition to - * the ones registered by default. + * Provides a way to completely turn off registration of default HTTP message + * readers and writers, and instead rely only on the ones provided via + * {@link #customCodecs()}. + *

By default this is set to {@code "true"} in which case default + * registrations are made; setting this to {@code false} disables default + * registrations. */ - CustomCodecs customCodecs(); + void registerDefaults(boolean registerDefaults); + /** * Obtain the configured HTTP message readers. @@ -62,9 +89,10 @@ public interface CodecConfigurer { /** - * Assists with customizing the default HTTP message readers and writers. - * @see ClientCodecConfigurer.ClientDefaultCodecs - * @see ServerCodecConfigurer.ServerDefaultCodecs + * Customize or replace the HTTP message readers and writers registered by + * default. The options are further extended by + * {@link ClientCodecConfigurer.ClientDefaultCodecs ClientDefaultCodecs} and + * {@link ServerCodecConfigurer.ServerDefaultCodecs ServerDefaultCodecs}. */ interface DefaultCodecs { @@ -85,7 +113,7 @@ public interface CodecConfigurer { /** - * Registry and container for custom HTTP message readers and writers. + * Registry for custom HTTP message readers and writers. */ interface CustomCodecs { diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java index f1386b4bdba..74776f53b58 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java @@ -19,27 +19,25 @@ package org.springframework.http.codec; import org.springframework.core.codec.Encoder; /** - * Helps to configure a list of server-side HTTP message readers and writers - * with support for built-in defaults and options to register additional custom - * readers and writers via {@link #customCodecs()}. - * - *

The built-in defaults include basic data types such as various byte - * representations, resources, strings, forms, but also others like JAXB2 and - * Jackson 2 based on classpath detection. There are options to - * {@link #defaultCodecs() override} some of the defaults or to have them - * {@link #registerDefaults(boolean) turned off} completely. + * Extension of {@link CodecConfigurer} for HTTP message reader and writer + * options relevant on the server side. * * @author Rossen Stoyanchev * @since 5.0 */ public interface ServerCodecConfigurer extends CodecConfigurer { + /** + * {@inheritDoc} + *

On the server side, built-in default also include customizations + * related to the encoder for SSE. + */ @Override ServerDefaultCodecs defaultCodecs(); /** - * Create a new instance of the {@code ServerCodecConfigurer}. + * Static factory method for a {@code ServerCodecConfigurer}. */ static ServerCodecConfigurer create() { return CodecConfigurerFactory.create(ServerCodecConfigurer.class); @@ -47,7 +45,7 @@ public interface ServerCodecConfigurer extends CodecConfigurer { /** - * Extension of {@link CodecConfigurer.DefaultCodecs} with extra server options. + * {@link CodecConfigurer.DefaultCodecs} extension with extra client-side options. */ interface ServerDefaultCodecs extends DefaultCodecs { diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/AbstractCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/support/AbstractCodecConfigurer.java deleted file mode 100644 index 65b268544b7..00000000000 --- a/spring-web/src/main/java/org/springframework/http/codec/support/AbstractCodecConfigurer.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright 2002-2018 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.http.codec.support; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.ByteArrayDecoder; -import org.springframework.core.codec.ByteArrayEncoder; -import org.springframework.core.codec.ByteBufferDecoder; -import org.springframework.core.codec.ByteBufferEncoder; -import org.springframework.core.codec.CharSequenceEncoder; -import org.springframework.core.codec.DataBufferDecoder; -import org.springframework.core.codec.DataBufferEncoder; -import org.springframework.core.codec.Decoder; -import org.springframework.core.codec.Encoder; -import org.springframework.core.codec.ResourceDecoder; -import org.springframework.core.codec.StringDecoder; -import org.springframework.http.codec.CodecConfigurer; -import org.springframework.http.codec.DecoderHttpMessageReader; -import org.springframework.http.codec.EncoderHttpMessageWriter; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.HttpMessageWriter; -import org.springframework.http.codec.ResourceHttpMessageWriter; -import org.springframework.http.codec.json.Jackson2JsonDecoder; -import org.springframework.http.codec.json.Jackson2JsonEncoder; -import org.springframework.http.codec.json.Jackson2SmileDecoder; -import org.springframework.http.codec.json.Jackson2SmileEncoder; -import org.springframework.http.codec.xml.Jaxb2XmlDecoder; -import org.springframework.http.codec.xml.Jaxb2XmlEncoder; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -/** - * Default implementation of {@link CodecConfigurer}. - * - * @author Rossen Stoyanchev - * @since 5.0 - */ -abstract class AbstractCodecConfigurer implements CodecConfigurer { - - static final boolean jackson2Present = - ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", - AbstractCodecConfigurer.class.getClassLoader()) && - ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", - AbstractCodecConfigurer.class.getClassLoader()); - - private static final boolean jackson2SmilePresent = - ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", - AbstractCodecConfigurer.class.getClassLoader()); - - private static final boolean jaxb2Present = - ClassUtils.isPresent("javax.xml.bind.Binder", AbstractCodecConfigurer.class.getClassLoader()); - - - private final AbstractDefaultCodecs defaultCodecs; - - private final DefaultCustomCodecs customCodecs = new DefaultCustomCodecs(); - - - AbstractCodecConfigurer(AbstractDefaultCodecs defaultCodecs) { - Assert.notNull(defaultCodecs, "'defaultCodecs' is required"); - this.defaultCodecs = defaultCodecs; - this.defaultCodecs.setCustomCodecs(this.customCodecs); - } - - - @Override - public DefaultCodecs defaultCodecs() { - return this.defaultCodecs; - } - - @Override - public void registerDefaults(boolean shouldRegister) { - this.defaultCodecs.registerDefaults(shouldRegister); - } - - @Override - public CustomCodecs customCodecs() { - return this.customCodecs; - } - - @Override - public List> getReaders() { - List> result = new ArrayList<>(); - - result.addAll(this.defaultCodecs.getTypedReaders()); - result.addAll(this.customCodecs.getTypedReaders()); - - result.addAll(this.defaultCodecs.getObjectReaders()); - result.addAll(this.customCodecs.getObjectReaders()); - - result.addAll(this.defaultCodecs.getCatchAllReaders()); - return result; - } - - @Override - public List> getWriters() { - List> result = new ArrayList<>(); - - result.addAll(this.defaultCodecs.getTypedWriters()); - result.addAll(this.customCodecs.getTypedWriters()); - - result.addAll(this.defaultCodecs.getObjectWriters()); - result.addAll(this.customCodecs.getObjectWriters()); - - result.addAll(this.defaultCodecs.getCatchAllWriters()); - return result; - } - - - abstract static class AbstractDefaultCodecs implements DefaultCodecs { - - private boolean registerDefaults = true; - - @Nullable - private Decoder jackson2JsonDecoder; - - @Nullable - private Encoder jackson2JsonEncoder; - - @Nullable - private DefaultCustomCodecs customCodecs; - - void registerDefaults(boolean registerDefaults) { - this.registerDefaults = registerDefaults; - } - - boolean shouldRegisterDefaults() { - return this.registerDefaults; - } - - /** - * Access to custom codecs for subclasses, e.g. for multipart writers. - */ - void setCustomCodecs(@Nullable DefaultCustomCodecs customCodecs) { - this.customCodecs = customCodecs; - } - - @Nullable - DefaultCustomCodecs getCustomCodecs() { - return this.customCodecs; - } - - @Override - public void jackson2JsonDecoder(Decoder decoder) { - this.jackson2JsonDecoder = decoder; - } - - Decoder getJackson2JsonDecoder() { - return (this.jackson2JsonDecoder != null ? this.jackson2JsonDecoder : new Jackson2JsonDecoder()); - } - - @Override - public void jackson2JsonEncoder(Encoder encoder) { - this.jackson2JsonEncoder = encoder; - } - - Encoder getJackson2JsonEncoder() { - return (this.jackson2JsonEncoder != null ? this.jackson2JsonEncoder : new Jackson2JsonEncoder()); - } - - // Readers... - - List> getTypedReaders() { - if (!this.registerDefaults) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - result.add(new DecoderHttpMessageReader<>(new ByteArrayDecoder())); - result.add(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); - result.add(new DecoderHttpMessageReader<>(new DataBufferDecoder())); - result.add(new DecoderHttpMessageReader<>(new ResourceDecoder())); - result.add(new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly())); - return result; - } - - List> getObjectReaders() { - if (!this.registerDefaults) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - if (jackson2Present) { - result.add(new DecoderHttpMessageReader<>(getJackson2JsonDecoder())); - } - if (jackson2SmilePresent) { - result.add(new DecoderHttpMessageReader<>(new Jackson2SmileDecoder())); - } - if (jaxb2Present) { - result.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); - } - return result; - } - - List> getCatchAllReaders() { - if (!this.registerDefaults) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - result.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes())); - return result; - } - - // Writers... - - List> getTypedWriters() { - if (!this.registerDefaults) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - result.add(new EncoderHttpMessageWriter<>(new ByteArrayEncoder())); - result.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); - result.add(new EncoderHttpMessageWriter<>(new DataBufferEncoder())); - result.add(new ResourceHttpMessageWriter()); - result.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly())); - return result; - } - - List> getObjectWriters() { - if (!this.registerDefaults) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - if (jackson2Present) { - result.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder())); - } - if (jackson2SmilePresent) { - result.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder())); - } - if (jaxb2Present) { - result.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); - } - return result; - } - - List> getCatchAllWriters() { - if (!this.registerDefaults) { - return Collections.emptyList(); - } - List> result = new ArrayList<>(); - result.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); - return result; - } - } - - - static class DefaultCustomCodecs implements CustomCodecs { - - private final List> typedReaders = new ArrayList<>(); - - private final List> typedWriters = new ArrayList<>(); - - private final List> objectReaders = new ArrayList<>(); - - private final List> objectWriters = new ArrayList<>(); - - @Override - public void decoder(Decoder decoder) { - reader(new DecoderHttpMessageReader<>(decoder)); - } - - @Override - public void encoder(Encoder encoder) { - writer(new EncoderHttpMessageWriter<>(encoder)); - } - - @Override - public void reader(HttpMessageReader reader) { - boolean canReadToObject = reader.canRead(ResolvableType.forClass(Object.class), null); - (canReadToObject ? this.objectReaders : this.typedReaders).add(reader); - } - - @Override - public void writer(HttpMessageWriter writer) { - boolean canWriteObject = writer.canWrite(ResolvableType.forClass(Object.class), null); - (canWriteObject ? this.objectWriters : this.typedWriters).add(writer); - } - - List> getTypedReaders() { - return this.typedReaders; - } - - List> getTypedWriters() { - return this.typedWriters; - } - - List> getObjectReaders() { - return this.objectReaders; - } - - List> getObjectWriters() { - return this.objectWriters; - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java new file mode 100644 index 00000000000..2bf2ffc914d --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java @@ -0,0 +1,168 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.http.codec.support; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import org.springframework.core.ResolvableType; +import org.springframework.core.codec.Decoder; +import org.springframework.core.codec.Encoder; +import org.springframework.http.codec.CodecConfigurer; +import org.springframework.http.codec.DecoderHttpMessageReader; +import org.springframework.http.codec.EncoderHttpMessageWriter; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; +import org.springframework.util.Assert; + +/** + * Default implementation of {@link CodecConfigurer} that serves as a base for + * client and server specific variants. + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +class BaseCodecConfigurer implements CodecConfigurer { + + private final BaseDefaultCodecs defaultCodecs; + + private final DefaultCustomCodecs customCodecs = new DefaultCustomCodecs(); + + + /** + * Constructor with the base {@link BaseDefaultCodecs} to use, which can be + * a client or server specific variant. + */ + BaseCodecConfigurer(BaseDefaultCodecs defaultCodecs) { + Assert.notNull(defaultCodecs, "'defaultCodecs' is required"); + this.defaultCodecs = defaultCodecs; + } + + + @Override + public DefaultCodecs defaultCodecs() { + return this.defaultCodecs; + } + + @Override + public void registerDefaults(boolean shouldRegister) { + this.defaultCodecs.registerDefaults(shouldRegister); + } + + @Override + public CustomCodecs customCodecs() { + return this.customCodecs; + } + + @Override + public List> getReaders() { + List> result = new ArrayList<>(); + + result.addAll(this.defaultCodecs.getTypedReaders()); + result.addAll(this.customCodecs.getTypedReaders()); + + result.addAll(this.defaultCodecs.getObjectReaders()); + result.addAll(this.customCodecs.getObjectReaders()); + + result.addAll(this.defaultCodecs.getCatchAllReaders()); + return result; + } + + @Override + public List> getWriters() { + List> result = new ArrayList<>(); + + result.addAll(this.defaultCodecs.getTypedWriters()); + result.addAll(this.customCodecs.getTypedWriters()); + + result.addAll(this.defaultCodecs.getObjectWriters()); + result.addAll(this.customCodecs.getObjectWriters()); + + result.addAll(this.defaultCodecs.getCatchAllWriters()); + return result; + } + + + // Accessors for use in sub-classes... + + protected Supplier>> getCustomTypedWriters() { + return () -> this.customCodecs.typedWriters; + } + + protected Supplier>> getCustomObjectWriters() { + return () -> this.customCodecs.objectWriters; + } + + + /** + * Default implementation of {@code CustomCodecs}. + */ + private static final class DefaultCustomCodecs implements CustomCodecs { + + private final List> typedReaders = new ArrayList<>(); + + private final List> typedWriters = new ArrayList<>(); + + private final List> objectReaders = new ArrayList<>(); + + private final List> objectWriters = new ArrayList<>(); + + + @Override + public void decoder(Decoder decoder) { + reader(new DecoderHttpMessageReader<>(decoder)); + } + + @Override + public void encoder(Encoder encoder) { + writer(new EncoderHttpMessageWriter<>(encoder)); + } + + @Override + public void reader(HttpMessageReader reader) { + boolean canReadToObject = reader.canRead(ResolvableType.forClass(Object.class), null); + (canReadToObject ? this.objectReaders : this.typedReaders).add(reader); + } + + @Override + public void writer(HttpMessageWriter writer) { + boolean canWriteObject = writer.canWrite(ResolvableType.forClass(Object.class), null); + (canWriteObject ? this.objectWriters : this.typedWriters).add(writer); + } + + + // Package private accessors... + + List> getTypedReaders() { + return this.typedReaders; + } + + List> getTypedWriters() { + return this.typedWriters; + } + + List> getObjectReaders() { + return this.objectReaders; + } + + List> getObjectWriters() { + return this.objectWriters; + } + } + +} diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java b/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java new file mode 100644 index 00000000000..dc1183bd8f1 --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java @@ -0,0 +1,210 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.http.codec.support; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.core.codec.ByteArrayDecoder; +import org.springframework.core.codec.ByteArrayEncoder; +import org.springframework.core.codec.ByteBufferDecoder; +import org.springframework.core.codec.ByteBufferEncoder; +import org.springframework.core.codec.CharSequenceEncoder; +import org.springframework.core.codec.DataBufferDecoder; +import org.springframework.core.codec.DataBufferEncoder; +import org.springframework.core.codec.Decoder; +import org.springframework.core.codec.Encoder; +import org.springframework.core.codec.ResourceDecoder; +import org.springframework.core.codec.StringDecoder; +import org.springframework.http.codec.CodecConfigurer; +import org.springframework.http.codec.DecoderHttpMessageReader; +import org.springframework.http.codec.EncoderHttpMessageWriter; +import org.springframework.http.codec.FormHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; +import org.springframework.http.codec.ResourceHttpMessageWriter; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.http.codec.json.Jackson2SmileDecoder; +import org.springframework.http.codec.json.Jackson2SmileEncoder; +import org.springframework.http.codec.xml.Jaxb2XmlDecoder; +import org.springframework.http.codec.xml.Jaxb2XmlEncoder; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; + +/** + * Default implementation of {@link CodecConfigurer.DefaultCodecs} that serves + * as a base for client and server specific variants. + * + * @author Rossen Stoyanchev + */ +class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs { + + static final boolean jackson2Present = + ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", + BaseCodecConfigurer.class.getClassLoader()) && + ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", + BaseCodecConfigurer.class.getClassLoader()); + + private static final boolean jackson2SmilePresent = + ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", + BaseCodecConfigurer.class.getClassLoader()); + + private static final boolean jaxb2Present = + ClassUtils.isPresent("javax.xml.bind.Binder", BaseCodecConfigurer.class.getClassLoader()); + + + @Nullable + private Decoder jackson2JsonDecoder; + + @Nullable + private Encoder jackson2JsonEncoder; + + private boolean registerDefaults = true; + + + @Override + public void jackson2JsonDecoder(Decoder decoder) { + this.jackson2JsonDecoder = decoder; + } + + @Override + public void jackson2JsonEncoder(Encoder encoder) { + this.jackson2JsonEncoder = encoder; + } + + /** + * Delegate method used from {@link BaseCodecConfigurer#registerDefaults}. + */ + void registerDefaults(boolean registerDefaults) { + this.registerDefaults = registerDefaults; + } + + + // Package private access to the configured readers... + + final List> getTypedReaders() { + if (!this.registerDefaults) { + return Collections.emptyList(); + } + List> readers = new ArrayList<>(); + readers.add(new DecoderHttpMessageReader<>(new ByteArrayDecoder())); + readers.add(new DecoderHttpMessageReader<>(new ByteBufferDecoder())); + readers.add(new DecoderHttpMessageReader<>(new DataBufferDecoder())); + readers.add(new DecoderHttpMessageReader<>(new ResourceDecoder())); + readers.add(new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly())); + readers.add(new FormHttpMessageReader()); + extendTypedReaders(readers); + return readers; + } + + protected void extendTypedReaders(List> typedReaders) { + } + + final List> getObjectReaders() { + if (!this.registerDefaults) { + return Collections.emptyList(); + } + List> readers = new ArrayList<>(); + if (jackson2Present) { + readers.add(new DecoderHttpMessageReader<>(getJackson2JsonDecoder())); + } + if (jackson2SmilePresent) { + readers.add(new DecoderHttpMessageReader<>(new Jackson2SmileDecoder())); + } + if (jaxb2Present) { + readers.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder())); + } + extendObjectReaders(readers); + return readers; + } + + protected void extendObjectReaders(List> objectReaders) { + } + + final List> getCatchAllReaders() { + if (!this.registerDefaults) { + return Collections.emptyList(); + } + List> result = new ArrayList<>(); + result.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes())); + return result; + } + + + // Package private access to the configured writers... + + final List> getTypedWriters() { + if (!this.registerDefaults) { + return Collections.emptyList(); + } + List> writers = new ArrayList<>(); + writers.add(new EncoderHttpMessageWriter<>(new ByteArrayEncoder())); + writers.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder())); + writers.add(new EncoderHttpMessageWriter<>(new DataBufferEncoder())); + writers.add(new ResourceHttpMessageWriter()); + writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly())); + extendTypedWriters(writers); + return writers; + } + + protected void extendTypedWriters(List> typedWriters) { + } + + final List> getObjectWriters() { + if (!this.registerDefaults) { + return Collections.emptyList(); + } + List> writers = new ArrayList<>(); + if (jackson2Present) { + writers.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder())); + } + if (jackson2SmilePresent) { + writers.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder())); + } + if (jaxb2Present) { + writers.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder())); + } + extendObjectWriters(writers); + return writers; + } + + protected void extendObjectWriters(List> objectWriters) { + } + + List> getCatchAllWriters() { + if (!this.registerDefaults) { + return Collections.emptyList(); + } + List> result = new ArrayList<>(); + result.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); + return result; + } + + + // Accessors for use in sub-classes... + + protected Decoder getJackson2JsonDecoder() { + return (this.jackson2JsonDecoder != null ? this.jackson2JsonDecoder : new Jackson2JsonDecoder()); + } + + protected Encoder getJackson2JsonEncoder() { + return (this.jackson2JsonEncoder != null ? this.jackson2JsonEncoder : new Jackson2JsonEncoder()); + } + +} + diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java b/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java new file mode 100644 index 00000000000..d98f9b24e0b --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java @@ -0,0 +1,140 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.http.codec.support; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import org.springframework.core.codec.Decoder; +import org.springframework.core.codec.Encoder; +import org.springframework.http.codec.ClientCodecConfigurer; +import org.springframework.http.codec.EncoderHttpMessageWriter; +import org.springframework.http.codec.FormHttpMessageWriter; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; +import org.springframework.http.codec.ServerSentEventHttpMessageReader; +import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Default implementation of {@link ClientCodecConfigurer.ClientDefaultCodecs}. + * + * @author Rossen Stoyanchev + */ +class ClientDefaultCodecsImpl extends BaseDefaultCodecs implements ClientCodecConfigurer.ClientDefaultCodecs { + + @Nullable + private DefaultMultipartCodecs multipartCodecs; + + @Nullable + private Decoder sseDecoder; + + @Nullable + private Supplier>> customTypedWriters; + + @Nullable + private Supplier>> customObjectWriters; + + + void initCustomTypedWriters(Supplier>> supplier) { + this.customTypedWriters = supplier; + } + + void initCustomObjectWriters(Supplier>> supplier) { + this.customObjectWriters = supplier; + } + + + @Override + public ClientCodecConfigurer.MultipartCodecs multipartCodecs() { + if (this.multipartCodecs == null) { + this.multipartCodecs = new DefaultMultipartCodecs(); + } + return this.multipartCodecs; + } + + @Override + public void serverSentEventDecoder(Decoder decoder) { + this.sseDecoder = decoder; + } + + + @Override + protected void extendObjectReaders(List> objectReaders) { + objectReaders.add(new ServerSentEventHttpMessageReader(getSseDecoder())); + } + + @Nullable + private Decoder getSseDecoder() { + return this.sseDecoder != null ? this.sseDecoder : jackson2Present ? getJackson2JsonDecoder() : null; + } + + @Override + protected void extendTypedWriters(List> typedWriters) { + + MultipartHttpMessageWriter multipartWriter = new MultipartHttpMessageWriter( + resolvePartWriters(typedWriters, getObjectWriters()), new FormHttpMessageWriter()); + + typedWriters.add(multipartWriter); + } + + private List> resolvePartWriters(List> typedWriters, + List> objectWriters) { + + List> partWriters; + if (this.multipartCodecs != null) { + partWriters = this.multipartCodecs.getWriters(); + } + else { + Assert.notNull(this.customTypedWriters, "Expected custom typed writers supplier."); + Assert.notNull(this.customObjectWriters, "Expected custom object writers supplier."); + + partWriters = new ArrayList<>(typedWriters); + partWriters.addAll(this.customTypedWriters.get()); + + partWriters.addAll(objectWriters); + partWriters.addAll(this.customObjectWriters.get()); + + partWriters.addAll(super.getCatchAllWriters()); + } + return partWriters; + } + + + private static class DefaultMultipartCodecs implements ClientCodecConfigurer.MultipartCodecs { + + private final List> writers = new ArrayList<>(); + + + @Override + public ClientCodecConfigurer.MultipartCodecs encoder(Encoder encoder) { + writer(new EncoderHttpMessageWriter<>(encoder)); + return this; + } + + @Override + public ClientCodecConfigurer.MultipartCodecs writer(HttpMessageWriter writer) { + this.writers.add(writer); + return this; + } + + List> getWriters() { + return this.writers; + } + } +} diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java index e3a0bd0bc87..51eee366297 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java @@ -16,20 +16,7 @@ package org.springframework.http.codec.support; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.core.codec.Decoder; -import org.springframework.core.codec.Encoder; import org.springframework.http.codec.ClientCodecConfigurer; -import org.springframework.http.codec.EncoderHttpMessageWriter; -import org.springframework.http.codec.FormHttpMessageWriter; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.HttpMessageWriter; -import org.springframework.http.codec.ServerSentEventHttpMessageReader; -import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; -import org.springframework.lang.Nullable; /** * Default implementation of {@link ClientCodecConfigurer}. @@ -37,108 +24,19 @@ import org.springframework.lang.Nullable; * @author Rossen Stoyanchev * @since 5.0 */ -public class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements ClientCodecConfigurer { +public class DefaultClientCodecConfigurer extends BaseCodecConfigurer implements ClientCodecConfigurer { + public DefaultClientCodecConfigurer() { super(new ClientDefaultCodecsImpl()); + ((ClientDefaultCodecsImpl) defaultCodecs()).initCustomTypedWriters(getCustomTypedWriters()); + ((ClientDefaultCodecsImpl) defaultCodecs()).initCustomObjectWriters(getCustomObjectWriters()); } + @Override public ClientDefaultCodecs defaultCodecs() { return (ClientDefaultCodecs) super.defaultCodecs(); } - - private static class ClientDefaultCodecsImpl extends AbstractDefaultCodecs implements ClientDefaultCodecs { - - @Nullable - private DefaultMultipartCodecs multipartCodecs; - - @Nullable - private Decoder sseDecoder; - - @Override - public MultipartCodecs multipartCodecs() { - if (this.multipartCodecs == null) { - this.multipartCodecs = new DefaultMultipartCodecs(); - } - return this.multipartCodecs; - } - - @Override - public void serverSentEventDecoder(Decoder decoder) { - this.sseDecoder = decoder; - } - - @Override - List> getObjectReaders() { - if (!shouldRegisterDefaults()) { - return Collections.emptyList(); - } - List> result = super.getObjectReaders(); - result.add(new ServerSentEventHttpMessageReader(getSseDecoder())); - return result; - } - - @Nullable - private Decoder getSseDecoder() { - if (this.sseDecoder != null) { - return this.sseDecoder; - } - return (jackson2Present ? getJackson2JsonDecoder() : null); - } - - @Override - List> getTypedWriters() { - if (!shouldRegisterDefaults()) { - return Collections.emptyList(); - } - List> result = super.getTypedWriters(); - result.add(new MultipartHttpMessageWriter(getPartWriters(), new FormHttpMessageWriter())); - return result; - } - - private List> getPartWriters() { - List> partWriters; - if (this.multipartCodecs != null) { - partWriters = this.multipartCodecs.getWriters(); - } - else { - DefaultCustomCodecs customCodecs = getCustomCodecs(); - partWriters = new ArrayList<>(super.getTypedWriters()); - if (customCodecs != null) { - partWriters.addAll(customCodecs.getTypedWriters()); - } - partWriters.addAll(super.getObjectWriters()); - if (customCodecs != null) { - partWriters.addAll(customCodecs.getObjectWriters()); - } - partWriters.addAll(super.getCatchAllWriters()); - } - return partWriters; - } - } - - - private static class DefaultMultipartCodecs implements MultipartCodecs { - - private final List> writers = new ArrayList<>(); - - @Override - public MultipartCodecs encoder(Encoder encoder) { - writer(new EncoderHttpMessageWriter<>(encoder)); - return this; - } - - @Override - public MultipartCodecs writer(HttpMessageWriter writer) { - this.writers.add(writer); - return this; - } - - List> getWriters() { - return this.writers; - } - } - } diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/DefaultServerCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/support/DefaultServerCodecConfigurer.java index 7e92a181311..b6bdbe73e00 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/DefaultServerCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/DefaultServerCodecConfigurer.java @@ -16,19 +16,7 @@ package org.springframework.http.codec.support; -import java.util.Collections; -import java.util.List; - -import org.springframework.core.codec.Encoder; -import org.springframework.http.codec.FormHttpMessageReader; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.http.codec.ServerSentEventHttpMessageWriter; -import org.springframework.http.codec.multipart.MultipartHttpMessageReader; -import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader; -import org.springframework.lang.Nullable; -import org.springframework.util.ClassUtils; /** * Default implementation of {@link ServerCodecConfigurer}. @@ -36,11 +24,7 @@ import org.springframework.util.ClassUtils; * @author Rossen Stoyanchev * @since 5.0 */ -public class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements ServerCodecConfigurer { - - static final boolean synchronossMultipartPresent = - ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParser", - DefaultServerCodecConfigurer.class.getClassLoader()); +public class DefaultServerCodecConfigurer extends BaseCodecConfigurer implements ServerCodecConfigurer { public DefaultServerCodecConfigurer() { @@ -52,52 +36,4 @@ public class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implem return (ServerDefaultCodecs) super.defaultCodecs(); } - - /** - * Default implementation of {@link ServerDefaultCodecs}. - */ - private static class ServerDefaultCodecsImpl extends AbstractDefaultCodecs implements ServerDefaultCodecs { - - @Nullable - private Encoder sseEncoder; - - @Override - public void serverSentEventEncoder(Encoder encoder) { - this.sseEncoder = encoder; - } - - @Override - List> getTypedReaders() { - if (!shouldRegisterDefaults()) { - return Collections.emptyList(); - } - List> result = super.getTypedReaders(); - result.add(new FormHttpMessageReader()); - if (synchronossMultipartPresent) { - SynchronossPartHttpMessageReader partReader = new SynchronossPartHttpMessageReader(); - result.add(partReader); - result.add(new MultipartHttpMessageReader(partReader)); - } - return result; - } - - @Override - List> getObjectWriters() { - if (!shouldRegisterDefaults()) { - return Collections.emptyList(); - } - List> result = super.getObjectWriters(); - result.add(new ServerSentEventHttpMessageWriter(getSseEncoder())); - return result; - } - - @Nullable - private Encoder getSseEncoder() { - if (this.sseEncoder != null) { - return this.sseEncoder; - } - return jackson2Present ? getJackson2JsonEncoder() : null; - } - } - } diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java b/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java new file mode 100644 index 00000000000..ae43d3b295b --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.http.codec.support; + +import java.util.List; + +import org.springframework.core.codec.Encoder; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.HttpMessageWriter; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.http.codec.ServerSentEventHttpMessageWriter; +import org.springframework.http.codec.multipart.MultipartHttpMessageReader; +import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; + +/** + * Default implementation of {@link ServerCodecConfigurer.ServerDefaultCodecs}. + */ +class ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerCodecConfigurer.ServerDefaultCodecs { + + private static final boolean synchronossMultipartPresent = + ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParser", + DefaultServerCodecConfigurer.class.getClassLoader()); + + + @Nullable + private Encoder sseEncoder; + + + @Override + public void serverSentEventEncoder(Encoder encoder) { + this.sseEncoder = encoder; + } + + + @Override + protected void extendTypedReaders(List> typedReaders) { + if (synchronossMultipartPresent) { + SynchronossPartHttpMessageReader partReader = new SynchronossPartHttpMessageReader(); + typedReaders.add(partReader); + typedReaders.add(new MultipartHttpMessageReader(partReader)); + } + } + + @Override + protected void extendObjectWriters(List> objectWriters) { + objectWriters.add(new ServerSentEventHttpMessageWriter(getSseEncoder())); + } + + @Nullable + private Encoder getSseEncoder() { + return this.sseEncoder != null ? this.sseEncoder : jackson2Present ? getJackson2JsonEncoder() : null; + } + +} diff --git a/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java index 9657f9cb98f..0e5ba7e50a0 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java @@ -43,6 +43,7 @@ import org.springframework.http.MediaType; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.EncoderHttpMessageWriter; +import org.springframework.http.codec.FormHttpMessageReader; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ResourceHttpMessageWriter; @@ -74,12 +75,13 @@ public class ClientCodecConfigurerTests { @Test public void defaultReaders() { List> readers = this.configurer.getReaders(); - assertEquals(10, readers.size()); + assertEquals(11, readers.size()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass()); assertStringDecoder(getNextDecoder(readers), true); + assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass()); diff --git a/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java index 22190815a1b..948f5a38d85 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java @@ -37,6 +37,7 @@ import org.springframework.http.MediaType; import org.springframework.http.codec.CodecConfigurer; import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.EncoderHttpMessageWriter; +import org.springframework.http.codec.FormHttpMessageReader; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ResourceHttpMessageWriter; @@ -53,7 +54,7 @@ import static org.mockito.Mockito.*; import static org.springframework.core.ResolvableType.forClass; /** - * Unit tests for {@link AbstractCodecConfigurer.AbstractDefaultCodecs}. + * Unit tests for {@link BaseCodecConfigurer}. * @author Rossen Stoyanchev */ public class CodecConfigurerTests { @@ -66,12 +67,13 @@ public class CodecConfigurerTests { @Test public void defaultReaders() { List> readers = this.configurer.getReaders(); - assertEquals(9, readers.size()); + assertEquals(10, readers.size()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass()); assertStringDecoder(getNextDecoder(readers), true); + assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass()); @@ -115,12 +117,13 @@ public class CodecConfigurerTests { List> readers = this.configurer.getReaders(); - assertEquals(13, readers.size()); + assertEquals(14, readers.size()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass()); assertEquals(StringDecoder.class, getNextDecoder(readers).getClass()); + assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertSame(customDecoder1, getNextDecoder(readers)); assertSame(customReader1, readers.get(this.index.getAndIncrement())); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); @@ -284,13 +287,13 @@ public class CodecConfigurerTests { - private static class TestCodecConfigurer extends AbstractCodecConfigurer { + private static class TestCodecConfigurer extends BaseCodecConfigurer { TestCodecConfigurer() { super(new TestDefaultCodecs()); } - private static class TestDefaultCodecs extends AbstractDefaultCodecs { + private static class TestDefaultCodecs extends BaseDefaultCodecs { } }