package org.jboss.resteasy.springmvc; import org.jboss.resteasy.core.ServerResponseWriter; import org.jboss.resteasy.core.SynchronousDispatcher; import org.jboss.resteasy.specimpl.BuiltResponse; import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpResponse; import org.jboss.resteasy.spi.ResteasyDeployment; import org.jboss.resteasy.util.HttpHeaderNames; import org.jboss.resteasy.util.MediaTypeHelper; import org.springframework.validation.BindingResult; import org.springframework.web.servlet.View; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; /** * @author <a href="mailto:sduskis@gmail.com">Solomon Duskis</a> * @version $Revision: 1 $ */ @SuppressWarnings("rawtypes") public class ResteasyView implements View { private MediaType contentType = null; private List<MediaType> potentialContentTypes = null; private ResteasyDeployment deployment; public ResteasyView(String contentType, ResteasyDeployment deployment) { setContentType(contentType); this.deployment = deployment; } public ResteasyView() { } public ResteasyDeployment getDeployment() { return deployment; } public void setDeployment(ResteasyDeployment deployment) { this.deployment = deployment; } public String getContentType() { return contentType.toString(); } public List<String> getPotentialContentTypes() { List<String> contentTypes = new ArrayList<String>(potentialContentTypes.size()); for (MediaType mediaType : potentialContentTypes) { contentTypes.add(mediaType.toString()); } return contentTypes; } public void setPotentialContentTypes(List<String> potentialContentTypes) { this.potentialContentTypes = new ArrayList<MediaType>(); for (String type : potentialContentTypes) { this.potentialContentTypes.add(MediaType.valueOf(type)); } } public void render(final Map model, final HttpServletRequest servletRequest, final HttpServletResponse servletResponse) throws Exception { final SynchronousDispatcher dispatcher = (SynchronousDispatcher)deployment.getDispatcher(); ResteasyWebHandlerTemplate template = new ResteasyWebHandlerTemplate<Void>(dispatcher.getProviderFactory()) { protected Void handle(ResteasyRequestWrapper requestWrapper, HttpResponse response) throws Exception { HttpRequest httpRequest = requestWrapper.getHttpRequest(); dispatcher.pushContextObjects(httpRequest, response); try { try { MediaType resolvedContentType = resolveContentType(httpRequest, httpRequest.getHttpHeaders().getMediaType()); BuiltResponse responseInvoker = getResponse(model, resolvedContentType); if (responseInvoker != null) { ServerResponseWriter.writeNomapResponse(responseInvoker, httpRequest, response, dispatcher.getProviderFactory()); } } catch (Exception e) { dispatcher.writeException(httpRequest, response, e); } return null; } finally { dispatcher.clearContextData(); } } }; ResteasyRequestWrapper requestWrapper = RequestUtil.getRequestWrapper(servletRequest); template.handle(requestWrapper, servletResponse); } private MediaType resolveContentType(HttpRequest jaxrsRequest, MediaType mt) { if (mt == null || MediaType.MEDIA_TYPE_WILDCARD.equals(mt.getType())) { List<MediaType> acceptableMediaTypes = jaxrsRequest.getHttpHeaders() .getAcceptableMediaTypes(); if (contentType != null && isAcceptable(acceptableMediaTypes, contentType)) { return contentType; } return MediaTypeHelper.getBestMatch(potentialContentTypes, acceptableMediaTypes); } return mt; } private boolean isAcceptable(List<MediaType> acceptableMediaTypes, MediaType potentialContentType) { boolean isAcceptable = false; for (MediaType acceptableMediaType : acceptableMediaTypes) { if (acceptableMediaType.isCompatible(potentialContentType)) { isAcceptable = true; break; } } return isAcceptable; } protected BuiltResponse getResponse(Map model, MediaType mt) { Collection modelValues = model.values(); for (Object value : modelValues) { if (value instanceof BuiltResponse) { return (BuiltResponse) value; } } if (model.size() == 1) { return createResponse(modelValues.iterator().next(), mt); } if (model.size() == 2) { for (Object value : modelValues) { if (!(value instanceof BindingResult)) { return createResponse(value, mt); } } } return null; } private BuiltResponse createResponse(Object value, MediaType contentType) { BuiltResponse responseImpl = new BuiltResponse(); responseImpl.setEntity(value); if (contentType != null) responseImpl.getMetadata().putSingle(HttpHeaderNames.CONTENT_TYPE, contentType); return responseImpl; } public void setContentType(String contentType) { this.contentType = MediaType.valueOf(contentType); } }