/*
 * 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.protobuf.ProtobufDecoder;
import org.springframework.http.codec.protobuf.ProtobufEncoder;
import org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter;
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 DefaultCodecs that serves as a base for client and server specific variants.
Author:Rossen Stoyanchev, Sebastien Deleuze
/** * Default implementation of {@link CodecConfigurer.DefaultCodecs} that serves * as a base for client and server specific variants. * * @author Rossen Stoyanchev * @author Sebastien Deleuze */
class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs { static final boolean jackson2Present; private static final boolean jackson2SmilePresent; private static final boolean jaxb2Present; private static final boolean protobufPresent; static { ClassLoader classLoader = BaseCodecConfigurer.class.getClassLoader(); jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader); jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader); protobufPresent = ClassUtils.isPresent("com.google.protobuf.Message", classLoader); } @Nullable private Decoder<?> jackson2JsonDecoder; @Nullable private Encoder<?> jackson2JsonEncoder; @Nullable private Decoder<?> protobufDecoder; @Nullable private Encoder<?> protobufEncoder; @Nullable private Decoder<?> jaxb2Decoder; @Nullable private Encoder<?> jaxb2Encoder; private boolean enableLoggingRequestDetails = false; private boolean registerDefaults = true; @Override public void jackson2JsonDecoder(Decoder<?> decoder) { this.jackson2JsonDecoder = decoder; } @Override public void jackson2JsonEncoder(Encoder<?> encoder) { this.jackson2JsonEncoder = encoder; } @Override public void protobufDecoder(Decoder<?> decoder) { this.protobufDecoder = decoder; } @Override public void protobufEncoder(Encoder<?> encoder) { this.protobufEncoder = encoder; } @Override public void jaxb2Decoder(Decoder<?> decoder) { this.jaxb2Decoder = decoder; } @Override public void jaxb2Encoder(Encoder<?> encoder) { this.jaxb2Encoder = encoder; } @Override public void enableLoggingRequestDetails(boolean enable) { this.enableLoggingRequestDetails = enable; } protected boolean isEnableLoggingRequestDetails() { return this.enableLoggingRequestDetails; }
Delegate method used from BaseCodecConfigurer.registerDefaults.
/** * Delegate method used from {@link BaseCodecConfigurer#registerDefaults}. */
void registerDefaults(boolean registerDefaults) { this.registerDefaults = registerDefaults; }
Return readers that support specific types.
/** * Return readers that support specific types. */
final List<HttpMessageReader<?>> getTypedReaders() { if (!this.registerDefaults) { return Collections.emptyList(); } List<HttpMessageReader<?>> 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())); if (protobufPresent) { Decoder<?> decoder = this.protobufDecoder != null ? this.protobufDecoder : new ProtobufDecoder(); readers.add(new DecoderHttpMessageReader<>(decoder)); } FormHttpMessageReader formReader = new FormHttpMessageReader(); formReader.setEnableLoggingRequestDetails(this.enableLoggingRequestDetails); readers.add(formReader); extendTypedReaders(readers); return readers; }
Hook for client or server specific typed readers.
/** * Hook for client or server specific typed readers. */
protected void extendTypedReaders(List<HttpMessageReader<?>> typedReaders) { }
Return Object readers (JSON, XML, SSE).
/** * Return Object readers (JSON, XML, SSE). */
final List<HttpMessageReader<?>> getObjectReaders() { if (!this.registerDefaults) { return Collections.emptyList(); } List<HttpMessageReader<?>> readers = new ArrayList<>(); if (jackson2Present) { readers.add(new DecoderHttpMessageReader<>(getJackson2JsonDecoder())); } if (jackson2SmilePresent) { readers.add(new DecoderHttpMessageReader<>(new Jackson2SmileDecoder())); } if (jaxb2Present) { Decoder<?> decoder = this.jaxb2Decoder != null ? this.jaxb2Decoder : new Jaxb2XmlDecoder(); readers.add(new DecoderHttpMessageReader<>(decoder)); } extendObjectReaders(readers); return readers; }
Hook for client or server specific Object readers.
/** * Hook for client or server specific Object readers. */
protected void extendObjectReaders(List<HttpMessageReader<?>> objectReaders) { }
Return readers that need to be at the end, after all others.
/** * Return readers that need to be at the end, after all others. */
final List<HttpMessageReader<?>> getCatchAllReaders() { if (!this.registerDefaults) { return Collections.emptyList(); } List<HttpMessageReader<?>> result = new ArrayList<>(); result.add(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes())); return result; }
Return writers that support specific types.
Params:
  • forMultipart – whether to returns writers for general use ("false"), or for multipart requests only ("true"). Generally the two sets are the same except for the multipart writer itself.
/** * Return writers that support specific types. * @param forMultipart whether to returns writers for general use ("false"), * or for multipart requests only ("true"). Generally the two sets are the * same except for the multipart writer itself. */
@SuppressWarnings("unchecked") final List<HttpMessageWriter<?>> getTypedWriters(boolean forMultipart) { if (!this.registerDefaults) { return Collections.emptyList(); } List<HttpMessageWriter<?>> 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())); // No client or server specific multipart writers currently.. if (!forMultipart) { extendTypedWriters(writers); } if (protobufPresent) { Encoder<?> encoder = this.protobufEncoder != null ? this.protobufEncoder : new ProtobufEncoder(); writers.add(new ProtobufHttpMessageWriter((Encoder) encoder)); } return writers; }
Hook for client or server specific typed writers.
/** * Hook for client or server specific typed writers. */
protected void extendTypedWriters(List<HttpMessageWriter<?>> typedWriters) { }
Return Object writers (JSON, XML, SSE).
Params:
  • forMultipart – whether to returns writers for general use ("false"), or for multipart requests only ("true"). Generally the two sets are the same except for the multipart writer itself.
/** * Return Object writers (JSON, XML, SSE). * @param forMultipart whether to returns writers for general use ("false"), * or for multipart requests only ("true"). Generally the two sets are the * same except for the multipart writer itself. */
final List<HttpMessageWriter<?>> getObjectWriters(boolean forMultipart) { if (!this.registerDefaults) { return Collections.emptyList(); } List<HttpMessageWriter<?>> writers = new ArrayList<>(); if (jackson2Present) { writers.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder())); } if (jackson2SmilePresent) { writers.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder())); } if (jaxb2Present) { Encoder<?> encoder = this.jaxb2Encoder != null ? this.jaxb2Encoder : new Jaxb2XmlEncoder(); writers.add(new EncoderHttpMessageWriter<>(encoder)); } // No client or server specific multipart writers currently.. if (!forMultipart) { extendObjectWriters(writers); } return writers; }
Hook for client or server specific Object writers.
/** * Hook for client or server specific Object writers. */
protected void extendObjectWriters(List<HttpMessageWriter<?>> objectWriters) { }
Return writers that need to be at the end, after all others.
/** * Return writers that need to be at the end, after all others. */
List<HttpMessageWriter<?>> getCatchAllWriters() { if (!this.registerDefaults) { return Collections.emptyList(); } List<HttpMessageWriter<?>> result = new ArrayList<>(); result.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); return result; } // Accessors for use in subclasses... protected Decoder<?> getJackson2JsonDecoder() { return (this.jackson2JsonDecoder != null ? this.jackson2JsonDecoder : new Jackson2JsonDecoder()); } protected Encoder<?> getJackson2JsonEncoder() { return (this.jackson2JsonEncoder != null ? this.jackson2JsonEncoder : new Jackson2JsonEncoder()); } }