package greencode.http;
import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.regex.Pattern;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.websocket.Session;
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.http.MimeHeaders;
import greencode.exception.OperationNotAllowedException;
import greencode.http.enumeration.RequestMethod;
import greencode.http.security.UserPrincipal;
import greencode.kernel.WebSocketData;
import greencode.util.FileUtils;
import greencode.util.LogMessage;
public final class HttpRequest extends HttpServletRequestWrapper implements HttpServletRequest {
private static final Pattern pattern = Pattern.compile("up.browser|up.link|windows ce|iphone|iemobile|mini|mmp|symbian|midp|wap|phone|pocket|mobile|pda|psp", Pattern.CASE_INSENSITIVE);
private static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
private static final SimpleDateFormat FORMATS[] = {
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
};
static {
for (SimpleDateFormat sdf : FORMATS) {
sdf.setTimeZone(GMT_ZONE);
}
}
private ViewSession viewSession;
private Extension extension;
private UserPrincipal userPrincipal;
private Boolean isMobile = null;
private final boolean isAjax, isIFrameHttpRequest;
private final int cid, viewId, localPort;
private final String methodType, remoteHost, requestURI, remoteAddr;
private final Conversation conversation;
private final ServletResponse response;
private final HttpSession httpSession;
private final Session webSocketSession;
private final StringBuffer requestURL;
private final MimeHeaders headers;
final Map<String, String[]> params;
final boolean contentIsHtml;
public HttpRequest(HttpServletRequest request, HttpServletResponse response) {
this(request, response, null);
}
public HttpRequest(HttpServletRequest request, ServletResponse response, WebSocketData wsData) {
super(request);
if (wsData != null) {
this.webSocketSession = wsData.getSession();
this.params = wsData.getParameters();
this.httpSession = wsData.getHttpSession();
this.isIFrameHttpRequest = false;
this.isAjax = false;
this.methodType = RequestMethod.POST.name(); // Método GET utiliza codificação de caracteres.
this.remoteHost = wsData.getRemoteHost();
this.requestURL = wsData.getRequestURL();
this.requestURI = wsData.getRequestURI();
this.localPort = wsData.getLocalPort();
this.headers = wsData.getHeaders();
this.remoteAddr = wsData.getRemoteAddr();
} else {
this.webSocketSession = null;
this.params = new HashMap<String, String[]>(request.getParameterMap());
this.httpSession = request.getSession();
this.isIFrameHttpRequest = request.getParameterMap().containsKey("isIframe");
this.isAjax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
this.methodType = request.getMethod();
this.remoteHost = request.getRemoteHost();
this.requestURL = request.getRequestURL();
this.requestURI = request.getRequestURI();
this.localPort = request.getLocalPort();
this.remoteAddr = request.getRemoteAddr();
this.headers = null;
}
this.response = response;
contentIsHtml = Boolean.parseBoolean(getParameter("__contentIsHtml")) || isFirst();
String v = getParameter("viewId");
if (v != null && !v.isEmpty()) {
viewId = Integer.parseInt(v);
getViewSession().isNew = false;
} else {
Integer lastViewID = (Integer) this.httpSession.getAttribute("LAST_VIEW_ID");
this.httpSession.setAttribute("LAST_VIEW_ID", viewId = (lastViewID == null ? 1 : ++lastViewID));
}
getViewSession().access();
this.cid = (v = getParameter("cid")) == null ? 1 : Integer.parseInt(v);
this.conversation = new Conversation(getViewSession(), cid);
this.userPrincipal = (UserPrincipal) getSession().getAttribute("__USER_PRINCIPAL__");
}
public String getHeader(String name) {
if(this.headers != null) {
return this.headers.getHeader(name);
}
return super.getHeader(name);
}
public Enumeration<String> getHeaderNames() {
if(this.headers != null) {
return this.headers.names();
}
return super.getHeaderNames();
}
public Enumeration<String> getHeaders(String name) {
if(this.headers != null) {
return this.headers.values(name);
}
return super.getHeaders(name);
}
public long getDateHeader(String name) {
if(this.headers != null) {
String value = getHeader(name);
if (value == null)
return (-1L);
long result = FastHttpDateFormat.parseDate(value, FORMATS);
if (result != (-1L)) {
return result;
}
throw new IllegalArgumentException(value);
}
return super.getDateHeader(name);
}
public int getIntHeader(String name) {
if(this.headers != null) {
String value = getHeader(name);
if (value == null) {
return (-1);
}
return Integer.parseInt(value);
}
return super.getIntHeader(name);
}
public boolean isFirst() {
return !(isAjax || isIFrameHttpRequest || isWebSocket());
}
public Session getWebSocketSession() {
return webSocketSession;
}
public boolean isWebSocket() {
return webSocketSession != null;
}
public String getRemoteHost() {
return this.remoteHost;
}
public String getRequestURI() {
return this.requestURI;
}
public StringBuffer getRequestURL() {
return this.requestURL;
}
public int getLocalPort() {
return this.localPort;
}
public Principal getUserPrincipal() {
return this.userPrincipal;
}
public void setUserPrincipal(UserPrincipal user) {
if (this.userPrincipal != null)
throw new OperationNotAllowedException(LogMessage.getMessage("green-0039"));
getSession().setAttribute("__USER_PRINCIPAL__", this.userPrincipal = user);
}
static boolean isMobile(HttpServletRequest request) {
return pattern.matcher(request.getHeader("user-agent")).find();
}
public boolean isMobile() {
return isMobile == null ? isMobile = isMobile(this) : isMobile;
}
public boolean isMethod(RequestMethod methodType) {
return getMethod().equals(methodType.name());
}
public boolean isAjax() {
return isAjax;
}
public int getConversationId() {
return cid;
}
public Extension getExtension() {
return (extension != null ? extension = new Extension(this.getServletPath()) : extension);
}
public ViewSession getViewSession() {
if (this.viewSession == null) {
ViewSessionContext viewContext = new ViewSessionContext(getSession());
if ((this.viewSession = viewContext.getViewSession(viewId)) == null) {
if (response.isCommitted())
throw new IllegalStateException("Cannot create a view session after the response has been committed");
this.viewSession = new ViewSession(viewId, getSession(), viewContext);
}
}
return this.viewSession;
}
public HttpSession getSession() {
return this.httpSession;
}
public HttpSession getSession(boolean create) {
return this.httpSession;
}
public String getMethod() {
return this.methodType;
}
public Conversation getConversation() {
return conversation;
}
public final class Extension {
private final String ext;
private final boolean isCss, isJS, isView;
private Extension(String path) {
ext = FileUtils.getExtension(path);
isCss = ext.equals("css");
isJS = ext.equals("js");
isView = ext.equals("html") || ext.equals("xhtml") || ext.equals("jsp") || ext.equals("htm");
}
public String get() {
return this.ext;
}
public boolean isCss() {
return this.isCss;
}
public boolean isJS() {
return this.isJS;
}
public boolean isView() {
return this.isView;
}
}
public String getParameter(String name) {
String[] values = params.get(name);
return values == null ? null : values[0];
}
public String[] getParameterValues(String name) {
String[] value;
int pos;
if (isWebSocket() && (pos = name.indexOf("[]")) != -1) {
value = params.get(name.substring(0, pos));
} else {
value = params.get(name);
}
return value;
}
public String[] getParameterValuesStartsWith(String name) {
return getParameterValues(name, true);
}
public String[] getParameterValuesEndWith(String name) {
return getParameterValues(name, false);
}
private String[] getParameterValues(String name, boolean start) {
List<String> values = new ArrayList<String>();
for (Entry<String, String[]> param : params.entrySet()) {
if(start && param.getKey().startsWith(name) || param.getKey().endsWith(name)) {
for (String v : param.getValue()) {
values.add(v);
}
}
}
if(values.size() == 0)
return null;
return values.toArray(new String[values.size()]);
}
public String getContextPath() {
return greencode.kernel.$GreenContext.getContextPath();
}
public boolean isIFrameHttpRequest() {
return isIFrameHttpRequest;
}
public String getRemoteAddr() {
return remoteAddr;
}
}