package org.etk.core.rest.impl;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.MessageBodyWriter;
import org.etk.common.logging.Logger;
import org.etk.core.rest.ContainerResponseWriter;
import org.etk.core.rest.GenericContainerResponse;
public class ContainerResponse implements GenericContainerResponse {
/**
* Logger.
*/
private static final Logger LOG = Logger.getLogger(ContainerResponse.class.getName());
/**
* See {@link ContainerResponseWriter}.
*/
private ContainerResponseWriter responseWriter;
/**
* @param responseWriter See {@link ContainerResponseWriter}
*/
public ContainerResponse(ContainerResponseWriter responseWriter) {
this.responseWriter = responseWriter;
}
// GenericContainerResponse
/**
* HTTP status.
*/
private int status;
/**
* Entity type.
*/
private Type entityType;
/**
* Entity.
*/
private Object entity;
/**
* HTTP response headers.
*/
private MultivaluedMap<String, Object> headers;
/**
* Response entity content-type.
*/
private MediaType contentType;
/**
* See {@link Response}, {@link ResponseBuilder}.
*/
private Response response;
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public void setResponse(Response response) {
this.response = response;
if (response == null) {
reset();
return;
}
status = response.getStatus();
headers = response.getMetadata();
entity = response.getEntity();
if (entity instanceof GenericEntity) {
GenericEntity ge = (GenericEntity) entity;
entity = ge.getEntity();
entityType = ge.getType();
} else {
if (entity != null)
entityType = entity.getClass();
}
Object contentTypeHeader = getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
if (contentTypeHeader instanceof MediaType)
contentType = (MediaType) contentTypeHeader;
else if (contentTypeHeader != null)
contentType = MediaType.valueOf(contentTypeHeader.toString());
else
contentType = null;
}
/**
* {@inheritDoc}
*/
public Response getResponse() {
return response;
}
/**
* Reset to default status.
*/
private void reset() {
this.status = Response.Status.NO_CONTENT.getStatusCode();
this.entity = null;
this.entityType = null;
this.contentType = null;
this.headers = null;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public void writeResponse() throws IOException {
if (entity == null) {
responseWriter.writeHeaders(this);
return;
}
ApplicationContext context = ApplicationContextImpl.getCurrent();
MediaType contentType = getContentType();
// if content-type is still not preset try determine it
if (contentType == null) {
List<MediaType> l = context.getProviders().getAcceptableWriterMediaTypes(entity.getClass(),
entityType,
null);
contentType = context.getContainerRequest().getAcceptableMediaType(l);
if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype())
contentType = MediaType.APPLICATION_OCTET_STREAM_TYPE;
this.contentType = contentType;
getHttpHeaders().putSingle(HttpHeaders.CONTENT_TYPE, contentType);
}
MessageBodyWriter entityWriter = context.getProviders().getMessageBodyWriter(entity.getClass(),
entityType,
null,
contentType);
if (entityWriter == null) {
String message = "Not found writer for " + entity.getClass() + " and MIME type "
+ contentType;
if (context.getContainerRequest().getMethod().equals(HttpMethod.HEAD)) {
// just warning here, HEAD method we do not need write entity
LOG.warn(message);
getHttpHeaders().putSingle(HttpHeaders.CONTENT_LENGTH, Long.toString(-1));
} else {
LOG.error(message);
throw new WebApplicationException(Response.status(Response.Status.NOT_ACCEPTABLE).build());
}
} else {
if (getHttpHeaders().getFirst(HttpHeaders.CONTENT_LENGTH) == null) {
long contentLength = entityWriter.getSize(entity,
entity.getClass(),
entityType,
null,
contentType);
if (contentLength >= 0)
getHttpHeaders().putSingle(HttpHeaders.CONTENT_LENGTH, Long.toString(contentLength));
}
}
if (context.getContainerRequest().getMethod().equals(HttpMethod.HEAD))
entity = null;
responseWriter.writeHeaders(this);
responseWriter.writeBody(this, entityWriter);
}
/**
* {@inheritDoc}
*/
public MediaType getContentType() {
return contentType;
}
/**
* {@inheritDoc}
*/
public Type getEntityType() {
return entityType;
}
/**
* {@inheritDoc}
*/
public Object getEntity() {
return entity;
}
/**
* {@inheritDoc}
*/
public MultivaluedMap<String, Object> getHttpHeaders() {
return headers;
}
/**
* {@inheritDoc}
*/
public int getStatus() {
return status;
}
}