restx.AbstractResponse Maven / Gradle / Ivy
package restx;
import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import restx.http.HTTP;
import restx.http.HttpStatus;
import restx.security.RestxSessionCookieDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
/**
* Date: 1/3/14
* Time: 20:46
*/
public abstract class AbstractResponse implements RestxResponse {
private static final Logger logger = LoggerFactory.getLogger(AbstractResponse.class);
private final Class responseClass;
private final R response;
private HttpStatus status = HttpStatus.OK;
private Charset charset;
private PrintWriter writer;
private OutputStream outputStream;
private RestxLogLevel logLevel = RestxLogLevel.DEFAULT;
private boolean closed;
// used to store headers set to be able to return them in getHeader()
private final Map headers = new LinkedHashMap<>();
protected AbstractResponse(Class responseClass, R response) {
this.responseClass = responseClass;
this.response = response;
}
@Override
public HttpStatus getStatus() {
return status;
}
@Override
public RestxResponse setStatus(HttpStatus httpStatus) {
this.status = httpStatus;
doSetStatus(httpStatus);
return this;
}
@Override
public RestxResponse setContentType(String s) {
if (HTTP.isTextContentType(s)) {
Optional cs = HTTP.charsetFromContentType(s);
if (!cs.isPresent()) {
s += "; charset=UTF-8";
charset = Charsets.UTF_8;
} else {
charset = Charset.forName(cs.get());
}
}
setHeader("Content-Type", s);
return this;
}
public Optional getCharset() {
return Optional.fromNullable(charset);
}
@Override
public PrintWriter getWriter() throws IOException {
if (writer != null) {
return writer;
}
if (charset == null) {
logger.warn("no charset defined while getting writer to write http response." +
" Make sure you call setContentType() before calling getWriter(). Using UTF-8 charset.");
charset = Charsets.UTF_8;
}
return writer = new PrintWriter(
new OutputStreamWriter(doGetOutputStream(), charset), true);
}
@Override
public OutputStream getOutputStream() throws IOException {
if (outputStream != null) {
return outputStream;
}
return outputStream = doGetOutputStream();
}
@Override
public void close() throws Exception {
if (isClosed()) {
return;
}
try {
if (writer != null) {
writer.print("\n");
writer.flush();
writer.close();
}
if (outputStream != null) {
outputStream.close();
}
closeResponse();
} finally {
closed = true;
}
}
@Override
public boolean isClosed() {
return closed;
}
public RestxLogLevel getLogLevel() {
return logLevel;
}
public RestxResponse setLogLevel(RestxLogLevel logLevel) {
this.logLevel = logLevel;
return this;
}
@Override
public RestxResponse addCookie(String cookie, String value, RestxSessionCookieDescriptor cookieDescriptor) {
addCookie(cookie, value, cookieDescriptor, Duration.ZERO);
return this;
}
@Override
public final RestxResponse setHeader(String headerName, String header) {
doSetHeader(headerName, header);
headers.put(headerName.toLowerCase(Locale.ENGLISH), header);
return this;
}
protected abstract void doSetHeader(String headerName, String header);
@Override
public Optional getHeader(String headerName) {
return Optional.fromNullable(headers.get(headerName.toLowerCase(Locale.ENGLISH)));
}
@Override
public String toString() {
return "[RESTX RESPONSE] " + status;
}
@Override
@SuppressWarnings("unchecked")
public T unwrap(Class clazz) {
if (clazz == this.responseClass) {
return (T) response;
}
throw new IllegalArgumentException("underlying implementation is " + this.responseClass.getName()
+ ", not " + clazz.getName());
}
protected abstract void closeResponse() throws IOException;
protected abstract OutputStream doGetOutputStream() throws IOException;
protected abstract void doSetStatus(HttpStatus httpStatus);
}