package com.psddev.cms.view;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
/**
* An abstraction of an HTTP response that contains information on how a real
* HTTP response should be constructed.
*/
public class ViewResponse extends RuntimeException {
private Integer status;
private Map<String, List<String>> headers = new LinkedHashMap<>();
private List<Cookie> cookies = new ArrayList<>();
private List<Cookie> signedCookies = new ArrayList<>();
private String redirectUri;
private Boolean isRedirectPermanent;
/**
* Gets the status for the response.
*
* @return the status to be sent with the response.
*/
public Integer getStatus() {
return status;
}
/**
* Sets the status for the response.
*
* @param status the status to set.
*/
public void setStatus(int status) {
this.status = status;
}
/**
* Gets the headers to be sent with the response.
*
* @return the headers to be sent with the response.
*/
public Map<String, List<String>> getHeaders() {
return headers;
}
/**
* Adds a header to be sent with the response. This will append to any
* previously added headers by the same {@code name}.
*
* @param name the the header name.
* @param value the header value.
* @see #setHeader(String, String)
*/
public void addHeader(String name, String value) {
if (name != null && value != null) {
List<String> values = headers.get(name);
if (values == null) {
values = new ArrayList<>();
headers.put(name, values);
}
values.add(value);
}
}
/**
* Sets a header to be sent with the response. Any previously added headers
* by the same name will be removed. If the {@code value} is null, then the
* header will be removed.
*
* @param name the header name.
* @param value the header value.
* @see #addHeader(String, String)
*/
public void setHeader(String name, String value) {
if (name != null) {
List<String> values = headers.get(name);
if (values == null) {
values = new ArrayList<>();
headers.put(name, values);
} else {
values.clear();
}
if (value != null) {
values.add(value);
} else {
headers.remove(name);
}
}
}
/**
* Gets the list of cookies to be sent with the response.
*
* @return the list of cookies to be sent with response.
*/
public List<Cookie> getCookies() {
return cookies;
}
/**
* Adds a cookie to be sent with the response.
*
* @param cookie the cookie to add.
*/
public void addCookie(Cookie cookie) {
if (cookie != null) {
cookies.add(cookie);
}
}
/**
* Gets the list of cookies in need of signing to be sent with the response.
*
* @return the list of cookies in need of signing to be sent with the
* response.
*/
public List<Cookie> getSignedCookies() {
return signedCookies;
}
/**
* Adds a cookie in need of signing to the response.
*
* @param cookie the cookie to add that needs signing.
*/
public void addSignedCookie(Cookie cookie) {
if (cookie != null) {
signedCookies.add(cookie);
}
}
/**
* Gets the redirect URI intended for the response.
*
* @return the redirect URI.
*/
public String getRedirectUri() {
return redirectUri;
}
/**
* Signals that the response should contain a permanent redirect to the
* specified {@code uri}. Calls to this method will usually be followed
* by {@code throw response} to halt execution and signal that writing to
* the response is complete.
*
* @param uri the uri to redirect to.
*/
public void redirectPermanently(String uri) {
redirectUri = uri;
isRedirectPermanent = true;
}
/**
* Signals that the response should contain a temporary redirect to the
* specified {@code uri}. Calls to this method will usually be followed
* by {@code throw response} to halt execution and signal that writing to
* the response is complete.
*
* @param uri the uri to redirect to.
*/
public void redirectTemporarily(String uri) {
redirectUri = uri;
isRedirectPermanent = false;
}
/**
* @return true if a permanent redirect has been issued, false otherwise.
*/
public boolean isRedirectPermanent() {
return Boolean.TRUE.equals(isRedirectPermanent);
}
/**
* @return true if a permanent redirect has been issued, false otherwise.
*/
public boolean isRedirectTemporary() {
return Boolean.FALSE.equals(isRedirectPermanent);
}
@Override
public String getMessage() {
return "Request is finished.";
}
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
/**
* @deprecated Use {@link #redirectTemporarily(String)} instead.
*/
@Deprecated
public void redirect(String uri) {
redirectTemporarily(uri);
}
/**
* Finds the first ViewResponse in an exception stack by traversing the
* causes of the {@code throwable} argument.
*
* @param throwable the exception stack to search through.
* @return the first ViewResponse found in the exception stack.
*/
public static ViewResponse findInExceptionChain(Throwable throwable) {
if (throwable instanceof ViewResponse) {
return (ViewResponse) throwable;
} else if (throwable != null) {
return findInExceptionChain(throwable.getCause());
} else {
return null;
}
}
}