/*
* Copyright 2014-2016 Jakub Jirutka <jakub@jirutka.cz>.
*
* 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 cz.jirutka.spring.exhandler.support;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.util.ClassUtils;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public final class HttpMessageConverterUtils {
private static final ClassLoader CLASSLOADER = HttpMessageConverterUtils.class.getClassLoader();
private HttpMessageConverterUtils() {}
/**
* Determine whether a JAXB binder is present on the classpath and can be loaded. Will return
* <tt>false</tt> if either the {@link javax.xml.bind.Binder} or one of its dependencies is not
* present or cannot be loaded.
*/
public static boolean isJaxb2Present() {
return ClassUtils.isPresent("javax.xml.bind.Binder", CLASSLOADER);
}
/**
* Determine whether Jackson 2.x is present on the classpath and can be loaded. Will return
* <tt>false</tt> if either the {@code com.fasterxml.jackson.databind.ObjectMapper},
* {@code com.fasterxml.jackson.core.JsonGenerator} or one of its dependencies is not present
* or cannot be loaded.
*/
public static boolean isJackson2Present() {
return ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", CLASSLOADER) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", CLASSLOADER);
}
/**
* Determine whether Jackson 1.x is present on the classpath and can be loaded. Will return
* <tt>false</tt> if either the {@code org.codehaus.jackson.map.ObjectMapper},
* {@code org.codehaus.jackson.JsonGenerator} or one of its dependencies is not present or
* cannot be loaded.
*/
@Deprecated
public static boolean isJacksonPresent() {
return ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", CLASSLOADER) &&
ClassUtils.isPresent("org.codehaus.jackson.JsonGenerator", CLASSLOADER);
}
/**
* Returns default {@link HttpMessageConverter} instances, i.e.:
*
* <ul>
* <li>{@linkplain ByteArrayHttpMessageConverter}</li>
* <li>{@linkplain StringHttpMessageConverter}</li>
* <li>{@linkplain ResourceHttpMessageConverter}</li>
* <li>{@linkplain Jaxb2RootElementHttpMessageConverter} (when JAXB is present)</li>
* <li>{@linkplain MappingJackson2HttpMessageConverter} (when Jackson 2.x is present)</li>
* <li>{@linkplain org.springframework.http.converter.json.MappingJacksonHttpMessageConverter}
* (when Jackson 1.x is present and 2.x not)</li>
* </ul>
*
* <p>Note: It does not return all of the default converters defined in Spring, but just thus
* usable for exception responses.</p>
*/
@SuppressWarnings("deprecation")
public static List<HttpMessageConverter<?>> getDefaultHttpMessageConverters() {
List<HttpMessageConverter<?>> converters = new ArrayList<>();
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
stringConverter.setWriteAcceptCharset(false); // See SPR-7316
converters.add(new ByteArrayHttpMessageConverter());
converters.add(stringConverter);
converters.add(new ResourceHttpMessageConverter());
if (isJaxb2Present()) {
converters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (isJackson2Present()) {
converters.add(new MappingJackson2HttpMessageConverter());
} else if (isJacksonPresent()) {
try {
Class<?> clazz = Class.forName("org.springframework.http.converter.json.MappingJacksonHttpMessageConverter");
converters.add((HttpMessageConverter<?>) clazz.newInstance());
} catch (ClassNotFoundException ex) {
// Ignore it, this class is not available since Spring 4.1.0.
} catch (InstantiationException | IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
}
return converters;
}
}