All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.firefly.server.http2.servlet.HTTPServletRequestImpl Maven / Gradle / Ivy
package com.firefly.server.http2.servlet;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ReadListener;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import com.firefly.codec.http2.encode.UrlEncoded;
import com.firefly.codec.http2.model.CookieParser;
import com.firefly.codec.http2.model.HttpHeader;
import com.firefly.codec.http2.model.MetaData.Request;
import com.firefly.codec.http2.model.MetaData.Response;
import com.firefly.codec.http2.stream.HTTP2Configuration;
import com.firefly.codec.http2.stream.HTTPConnection;
import com.firefly.codec.http2.stream.HTTPOutputStream;
import com.firefly.server.exception.HttpServerException;
import com.firefly.utils.StringUtils;
import com.firefly.utils.VerifyUtils;
import com.firefly.utils.collection.MultiMap;
import com.firefly.utils.io.ByteArrayPipedStream;
import com.firefly.utils.io.FilePipedStream;
import com.firefly.utils.io.IO;
import com.firefly.utils.io.PipedStream;
import com.firefly.utils.lang.StringParser;
import com.firefly.utils.log.Log;
import com.firefly.utils.log.LogFactory;
public class HTTPServletRequestImpl implements HttpServletRequest, Closeable {
private static Log log = LogFactory.getInstance().getLog("firefly-system");
private final HTTPConnection connection;
private final Request request;
private final HTTPServletResponseImpl response;
private static final Cookie[] EMPTY_COOKIE_ARR = new Cookie[0];
private Cookie[] cookies;
private MultiMap parameterMap;
private Map _parameterMap;
private List localeList;
private Collection parts;
final HTTP2Configuration http2Configuration;
private Charset encoding;
private String characterEncoding;
private Map attributeMap = new HashMap();
private boolean requestedSessionIdFromCookie;
private boolean requestedSessionIdFromURL;
private String requestedSessionId;
private HttpSession httpSession;
private PipedStream bodyPipedStream;
private ServletInputStream servletInputStream;
private BufferedReader bufferedReader;
private AsyncContextImpl asyncContext;
private RequestDispatcherImpl requestDispatcher;
public HTTPServletRequestImpl(HTTP2Configuration http2Configuration, Request request, Response response,
HTTPOutputStream output, HTTPConnection connection) {
this.request = request;
this.connection = connection;
this.http2Configuration = http2Configuration;
try {
this.setCharacterEncoding(http2Configuration.getCharacterEncoding());
} catch (UnsupportedEncodingException e) {
log.error("set character encoding error", e);
}
this.response = new HTTPServletResponseImpl(response, output, this);
}
private static class IteratorWrap implements Enumeration {
private final Iterator iterator;
public IteratorWrap(Iterator iterator) {
this.iterator = iterator;
}
@Override
public boolean hasMoreElements() {
return iterator.hasNext();
}
@Override
public T nextElement() {
return iterator.next();
}
}
HTTPServletResponseImpl getResponse() {
return response;
}
// set and get request attribute
@Override
public void setAttribute(String name, Object o) {
attributeMap.put(name, o);
}
@Override
public void removeAttribute(String name) {
attributeMap.remove(name);
}
@Override
public Object getAttribute(String name) {
return attributeMap.get(name);
}
@Override
public Enumeration getAttributeNames() {
return new IteratorWrap(attributeMap.keySet().iterator());
}
// get the connection attributes
@Override
public String getCharacterEncoding() {
return characterEncoding;
}
@Override
public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
this.encoding = Charset.forName(env);
this.characterEncoding = env;
}
@Override
public boolean isSecure() {
return http2Configuration.isSecureConnectionEnabled();
}
@Override
public String getServerName() {
return connection.getLocalAddress().getHostName();
}
@Override
public int getServerPort() {
return connection.getLocalAddress().getPort();
}
@Override
public String getRemoteAddr() {
return connection.getRemoteAddress().getAddress().getHostAddress();
}
@Override
public String getRemoteHost() {
return connection.getRemoteAddress().getHostName();
}
@Override
public int getRemotePort() {
return connection.getRemoteAddress().getPort();
}
@Override
public String getLocalName() {
return connection.getLocalAddress().getHostName();
}
@Override
public String getLocalAddr() {
return connection.getLocalAddress().getAddress().getHostAddress();
}
@Override
public int getLocalPort() {
return connection.getLocalAddress().getPort();
}
// get HTTP heads
@Override
public long getDateHeader(String name) {
return request.getFields().getDateField(name);
}
@Override
public String getHeader(String name) {
return request.getFields().get(name);
}
@Override
public Enumeration getHeaders(String name) {
return request.getFields().getValues(name);
}
@Override
public Enumeration getHeaderNames() {
return request.getFields().getFieldNames();
}
@Override
public int getIntHeader(String name) {
return (int) request.getFields().getLongField(name);
}
@Override
public int getContentLength() {
return (int) request.getContentLength();
}
@Override
public long getContentLengthLong() {
return request.getContentLength();
}
@Override
public String getContentType() {
return request.getFields().get(HttpHeader.CONTENT_TYPE);
}
// get HTTP request line
@Override
public String getMethod() {
return request.getMethod();
}
@Override
public String getRequestURI() {
return request.getURI().getPath();
}
@Override
public StringBuffer getRequestURL() {
StringBuffer url = new StringBuffer();
String scheme = getScheme();
int port = getServerPort();
if (port < 0)
port = 80; // Work around java.net.URL bug
url.append(scheme);
url.append("://");
url.append(getServerName());
if ((scheme.equals("http") && (port != 80)) || (scheme.equals("https") && (port != 443))) {
url.append(':');
url.append(port);
}
url.append(getRequestURI());
return url;
}
@Override
public String getProtocol() {
return request.getVersion().asString();
}
@Override
public String getScheme() {
return request.getURI().getScheme();
}
@Override
public String getQueryString() {
return request.getURI().getQuery();
}
// get locale
@Override
public Locale getLocale() {
parseLocales();
return localeList.get(0);
}
@Override
public Enumeration getLocales() {
parseLocales();
return new IteratorWrap(localeList.iterator());
}
private void parseLocales() {
if (localeList == null) {
localeList = new ArrayList<>();
Enumeration values = getHeaders("accept-language");
while (values.hasMoreElements()) {
parseLocalesHeader(values.nextElement());
}
if (localeList.size() == 0) {
localeList.add(Locale.getDefault());
}
}
}
/**
* Parse accept-language header value.
*
* @param value
* The head string
*/
private void parseLocalesHeader(String value) {
StringParser parser = new StringParser();
// Store the accumulated languages that have been requested in
// a local collection, sorted by the quality value (so we can
// add Locales in descending order). The values will be ArrayLists
// containing the corresponding Locales to be added
TreeMap> locales = new TreeMap>();
// Preprocess the value to remove all whitespace
int white = value.indexOf(' ');
if (white < 0)
white = value.indexOf('\t');
if (white >= 0) {
StringBuilder sb = new StringBuilder();
int len = value.length();
for (int i = 0; i < len; i++) {
char ch = value.charAt(i);
if ((ch != ' ') && (ch != '\t'))
sb.append(ch);
}
value = sb.toString();
}
// Process each comma-delimited language specification
parser.setString(value); // ASSERT: parser is available to us
int length = parser.getLength();
while (true) {
// Extract the next comma-delimited entry
int start = parser.getIndex();
if (start >= length)
break;
int end = parser.findChar(',');
String entry = parser.extract(start, end).trim();
parser.advance(); // For the following entry
// Extract the quality factor for this entry
double quality = 1.0;
int semi = entry.indexOf(";q=");
if (semi >= 0) {
try {
String strQuality = entry.substring(semi + 3);
if (strQuality.length() <= 5) {
quality = Double.parseDouble(strQuality);
} else {
quality = 0.0;
}
} catch (NumberFormatException e) {
quality = 0.0;
}
entry = entry.substring(0, semi);
}
// Skip entries we are not going to keep track of
if (quality < 0.00005)
continue; // Zero (or effectively zero) quality factors
if ("*".equals(entry))
continue; // FIXME - "*" entries are not handled
// Extract the language and country for this entry
String language = null;
String country = null;
String variant = null;
int dash = entry.indexOf('-');
if (dash < 0) {
language = entry;
country = "";
variant = "";
} else {
language = entry.substring(0, dash);
country = entry.substring(dash + 1);
int vDash = country.indexOf('-');
if (vDash > 0) {
String cTemp = country.substring(0, vDash);
variant = country.substring(vDash + 1);
country = cTemp;
} else {
variant = "";
}
}
if (!StringUtils.isAlpha(language) || !StringUtils.isAlpha(country) || !StringUtils.isAlpha(variant)) {
continue;
}
// Add a new Locale to the list of Locales for this quality level
Locale locale = new Locale(language, country, variant);
Double key = new Double(-quality); // Reverse the order
ArrayList values = locales.get(key);
if (values == null) {
values = new ArrayList();
locales.put(key, values);
}
values.add(locale);
}
// Process the quality values in highest->lowest order (due to
// negating the Double value when creating the key)
Iterator keys = locales.keySet().iterator();
while (keys.hasNext()) {
Double key = keys.next();
ArrayList list = locales.get(key);
if (list != null && list.size() > 0) {
localeList.addAll(list);
}
}
}
@Override
public Cookie[] getCookies() {
if (cookies == null) {
String cookieStr = getHeader("Cookie");
if (VerifyUtils.isEmpty(cookieStr)) {
cookies = EMPTY_COOKIE_ARR;
} else {
List list = CookieParser.parserServletCookie(cookieStr);
cookies = list.toArray(EMPTY_COOKIE_ARR);
}
return cookies;
} else {
return cookies;
}
}
// get HTTP body
PipedStream getBodyPipedStream() {
if (bodyPipedStream == null) {
long contentLength = request.getContentLength();
if (contentLength > 0) {
if (contentLength > http2Configuration.getHttpBodyThreshold()) {
bodyPipedStream = new FilePipedStream(http2Configuration.getTemporaryDirectory());
} else {
bodyPipedStream = new ByteArrayPipedStream((int) contentLength);
}
} else {
bodyPipedStream = new FilePipedStream(http2Configuration.getTemporaryDirectory());
}
return bodyPipedStream;
} else {
return bodyPipedStream;
}
}
boolean hasData() {
return bodyPipedStream != null;
}
void completeDataReceiving() {
if (hasData()) {
try {
getBodyPipedStream().getOutputStream().close();
} catch (IOException e) {
log.error("close http body piped output stream exception", e);
}
}
}
@Override
public void close() {
if (hasData()) {
try {
getBodyPipedStream().close();
} catch (IOException e) {
log.error("close http body piped stream exception", e);
}
if (parts != null) {
for (Part part : parts) {
try {
part.delete();
} catch (IOException e) {
log.error("delete temporary file exception", e);
}
}
}
}
}
private class HTTPServletInputStream extends ServletInputStream {
@Override
public int available() throws IOException {
if (hasData()) {
return getBodyPipedStream().getInputStream().available();
} else {
return 0;
}
}
@Override
public void close() throws IOException {
if (hasData()) {
getBodyPipedStream().getInputStream().close();
}
}
@Override
public boolean isFinished() {
return hasData();
}
@Override
public boolean isReady() {
return hasData();
}
@Override
public void setReadListener(ReadListener readListener) {
if (hasData()) {
try {
readListener.onDataAvailable();
readListener.onAllDataRead();
} catch (IOException e) {
readListener.onError(e);
}
}
}
@Override
public int read() throws IOException {
if (hasData()) {
return getBodyPipedStream().getInputStream().read();
} else {
return -1;
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (hasData()) {
return getBodyPipedStream().getInputStream().read(b, off, len);
} else {
return -1;
}
}
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (servletInputStream == null) {
servletInputStream = new HTTPServletInputStream();
return servletInputStream;
} else {
return servletInputStream;
}
}
@Override
public BufferedReader getReader() throws IOException {
if (bufferedReader == null) {
bufferedReader = new BufferedReader(new InputStreamReader(getInputStream(), encoding));
return bufferedReader;
} else {
return bufferedReader;
}
}
private MultiMap getParameters() {
if (parameterMap == null) {
parameterMap = new MultiMap();
try {
request.getURI().decodeQueryTo(parameterMap, encoding);
} catch (UnsupportedEncodingException e) {
log.error("parse parameters exception", e);
}
String contentType = getContentType();
if (hasData() && "POST".equals(request.getMethod()) && contentType != null
&& contentType.startsWith("application/x-www-form-urlencoded")) {
try (BufferedReader in = getReader()) {
String urlencodedForm = IO.toString(in);
UrlEncoded.decodeTo(urlencodedForm, parameterMap, encoding);
} catch (IOException e) {
log.error("parse urlencoded form exception", e);
}
}
return parameterMap;
} else {
return parameterMap;
}
}
@Override
public String getParameter(String name) {
List values = getParameters().get(name);
if (values != null && values.size() > 0) {
return values.get(0);
} else {
return null;
}
}
@Override
public Enumeration getParameterNames() {
Set names = getParameters().keySet();
if (names != null && names.size() > 0) {
return new IteratorWrap<>(names.iterator());
} else {
return Collections.emptyEnumeration();
}
}
@Override
public String[] getParameterValues(String name) {
List values = getParameters().getValues(name);
if (values != null) {
return values.toArray(StringUtils.EMPTY_STRING_ARRAY);
} else {
return null;
}
}
@Override
public Map getParameterMap() {
if (_parameterMap == null) {
_parameterMap = getParameters().toStringArrayMap();
}
return _parameterMap;
}
@Override
public Collection getParts() throws IOException, ServletException {
if (parts == null) {
try (ServletInputStream input = getInputStream()) {
parts = MultipartFormDataParser.parse(http2Configuration, input, getContentType(), encoding);
}
return parts;
} else {
return parts;
}
}
@Override
public Part getPart(String name) throws IOException, ServletException {
for (Part part : getParts()) {
if (part.getName().equals(name))
return part;
}
return null;
}
// get session
public static String getSessionId(String uri, String sessionIdName) {
String sessionId = null;
int i = uri.indexOf(';');
int j = uri.indexOf('#');
if (i > 0) {
String tmp = j > i ? uri.substring(i + 1, j) : uri.substring(i + 1);
int m = 0;
for (int k = 0; k < tmp.length(); k++) {
if (tmp.charAt(k) == '=') {
m = k;
break;
}
}
if (m > 0) {
String name = tmp.substring(0, m);
String value = tmp.substring(m + 1);
if (name.equals(sessionIdName)) {
sessionId = value;
}
}
}
return sessionId;
}
@Override
public String getRequestedSessionId() {
if (requestedSessionId != null) {
return requestedSessionId;
} else if (isRequestedSessionIdFromCookie()) {
return requestedSessionId;
} else if (isRequestedSessionIdFromURL()) {
return requestedSessionId;
} else {
return null;
}
}
private HttpSession _getSession() {
if (httpSession == null) {
String sid = getRequestedSessionId();
httpSession = sid != null ? http2Configuration.getHttpSessionManager().get(sid) : null;
return httpSession;
} else {
return httpSession;
}
}
@Override
public HttpSession getSession(boolean create) {
if (create) {
httpSession = http2Configuration.getHttpSessionManager().create();
requestedSessionId = httpSession.getId();
response.addCookie(new Cookie(http2Configuration.getSessionIdName(), httpSession.getId()));
return httpSession;
} else {
return _getSession();
}
}
@Override
public HttpSession getSession() {
httpSession = _getSession();
if (httpSession == null) {
return getSession(true);
} else {
return httpSession;
}
}
@Override
public String changeSessionId() {
getSession(true);
return requestedSessionId;
}
@Override
public boolean isRequestedSessionIdValid() {
String sid = getRequestedSessionId();
if (sid == null) {
return false;
} else {
return http2Configuration.getHttpSessionManager().containsKey(sid);
}
}
@Override
public boolean isRequestedSessionIdFromCookie() {
if (requestedSessionId != null)
return requestedSessionIdFromCookie;
for (Cookie cookie : getCookies()) {
if (cookie.getName().equals(http2Configuration.getSessionIdName())) {
requestedSessionId = cookie.getValue();
requestedSessionIdFromCookie = true;
requestedSessionIdFromURL = false;
return true;
}
}
return false;
}
@Override
public boolean isRequestedSessionIdFromURL() {
if (requestedSessionId != null)
return requestedSessionIdFromURL;
String sessionId = getSessionId(getRequestURI(), http2Configuration.getSessionIdName());
if (VerifyUtils.isNotEmpty(sessionId)) {
requestedSessionId = sessionId;
requestedSessionIdFromURL = true;
requestedSessionIdFromCookie = false;
return true;
}
return false;
}
@Override
public boolean isRequestedSessionIdFromUrl() {
return isRequestedSessionIdFromURL();
}
// asynchronous servlet
@Override
public AsyncContext startAsync() throws IllegalStateException {
return startAsync(this, response);
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
throws IllegalStateException {
if (asyncContext == null) {
asyncContext = new AsyncContextImpl();
}
asyncContext.startAsync(servletRequest, servletResponse,
(servletRequest == this && servletResponse == response),
http2Configuration.getAsynchronousContextTimeout());
return asyncContext;
}
@Override
public boolean isAsyncStarted() {
if (asyncContext == null)
return false;
return asyncContext.isStartAsync();
}
@Override
public boolean isAsyncSupported() {
return true;
}
@Override
public AsyncContext getAsyncContext() {
if (!isAsyncStarted())
throw new IllegalStateException("asynchronous servlet doesn't start!");
return asyncContext;
}
@Override
public RequestDispatcher getRequestDispatcher(String path) {
if (requestDispatcher == null) {
requestDispatcher = new RequestDispatcherImpl();
}
requestDispatcher.path = path;
return requestDispatcher;
}
@Override
public DispatcherType getDispatcherType() {
return DispatcherType.REQUEST;
}
@Override
public String getContextPath() {
return "";
}
@Override
public String getServletPath() {
return "";
}
@Override
public String getRealPath(String path) {
throw new HttpServerException("not implement this method!");
}
@Override
public ServletContext getServletContext() {
throw new HttpServerException("not implement this method!");
}
@Override
public String getAuthType() {
throw new HttpServerException("not implement this method!");
}
@Override
public String getPathInfo() {
throw new HttpServerException("not implement this method!");
}
@Override
public String getPathTranslated() {
throw new HttpServerException("not implement this method!");
}
@Override
public String getRemoteUser() {
throw new HttpServerException("not implement this method!");
}
@Override
public boolean isUserInRole(String role) {
throw new HttpServerException("not implement this method!");
}
@Override
public Principal getUserPrincipal() {
throw new HttpServerException("not implement this method!");
}
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
throw new HttpServerException("not implement this method!");
}
@Override
public void login(String username, String password) throws ServletException {
throw new HttpServerException("not implement this method!");
}
@Override
public void logout() throws ServletException {
throw new HttpServerException("not implement this method!");
}
@Override
public T upgrade(Class handlerClass) throws IOException, ServletException {
throw new HttpServerException("not implement this method!");
}
}