org.cloudfoundry.identity.uaa.web.ConvertingExceptionView Maven / Gradle / Ivy
/*******************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file.
*******************************************************************************/
package org.cloudfoundry.identity.uaa.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.servlet.View;
/**
* @author Dave Syer
*
*/
public class ConvertingExceptionView implements View {
private static final Log logger = LogFactory.getLog(ConvertingExceptionView.class);
private ResponseEntity extends ExceptionReport> responseEntity;
private final HttpMessageConverter>[] messageConverters;
public ConvertingExceptionView(ResponseEntity extends ExceptionReport> responseEntity,
HttpMessageConverter>[] messageConverters) {
this.responseEntity = responseEntity;
this.messageConverters = messageConverters;
}
@Override
public String getContentType() {
return MediaType.ALL_VALUE;
}
@Override
public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
HttpInputMessage inputMessage = createHttpInputMessage(request);
HttpOutputMessage outputMessage = createHttpOutputMessage(response);
handleHttpEntityResponse(responseEntity, inputMessage, outputMessage);
} catch (Exception invocationEx) {
logger.error("Invoking request method resulted in exception", invocationEx);
}
}
/**
* Template method for creating a new HttpInputMessage instance.
*
* The default implementation creates a standard
* {@link ServletServerHttpRequest}. This can be overridden for custom
* {@code HttpInputMessage} implementations
*
* @param servletRequest current HTTP request
* @return the HttpInputMessage instance to use
* @throws Exception in case of errors
*/
protected HttpInputMessage createHttpInputMessage(HttpServletRequest servletRequest) throws Exception {
return new ServletServerHttpRequest(servletRequest);
}
/**
* Template method for creating a new HttpOuputMessage instance.
*
* The default implementation creates a standard
* {@link ServletServerHttpResponse}. This can be overridden for custom
* {@code HttpOutputMessage} implementations
*
* @param servletResponse current HTTP response
* @return the HttpInputMessage instance to use
* @throws Exception in case of errors
*/
protected HttpOutputMessage createHttpOutputMessage(HttpServletResponse servletResponse) throws Exception {
return new ServletServerHttpResponse(servletResponse);
}
private void handleHttpEntityResponse(ResponseEntity extends ExceptionReport> responseEntity,
HttpInputMessage inputMessage, HttpOutputMessage outputMessage) throws Exception {
if (outputMessage instanceof ServerHttpResponse) {
((ServerHttpResponse) outputMessage).setStatusCode(responseEntity.getStatusCode());
}
if (responseEntity.getBody() != null) {
writeWithMessageConverters(responseEntity.getBody(), inputMessage, outputMessage);
}
else {
// flush headers
outputMessage.getBody();
}
}
@SuppressWarnings("unchecked")
private void writeWithMessageConverters(Object returnValue, HttpInputMessage inputMessage,
HttpOutputMessage outputMessage) throws IOException, HttpMediaTypeNotAcceptableException {
List acceptedMediaTypes = inputMessage.getHeaders().getAccept();
if (acceptedMediaTypes.isEmpty()) {
acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
}
MediaType.sortByQualityValue(acceptedMediaTypes);
Class> returnValueType = returnValue.getClass();
List allSupportedMediaTypes = new ArrayList();
if (messageConverters != null) {
for (MediaType acceptedMediaType : acceptedMediaTypes) {
for (@SuppressWarnings("rawtypes")
HttpMessageConverter messageConverter : messageConverters) {
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
if (logger.isDebugEnabled()) {
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = acceptedMediaType;
}
logger.debug("Written [" + returnValue + "] as \"" + contentType + "\" using ["
+ messageConverter + "]");
}
// this.responseArgumentUsed = true;
return;
}
}
}
for (@SuppressWarnings("rawtypes")
HttpMessageConverter messageConverter : messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
}
}
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}
}