📄 webappservlet.java
字号:
if ("yes".equals(System.getProperty(WAR_NAME_AS_CONTEXTPATH)) == false)
result.contextName = (String) xp.evaluate(prefix + "display-name", document, XPathConstants.STRING);
if (result.contextName == null || result.contextName.length() == 0)
result.contextName = context;
else
result.contextPath = "/" + result.contextName;
// context parameters
NodeList nodes = (NodeList) xp.evaluate(prefix + "context-param", document, XPathConstants.NODESET);
int nodesLen = nodes.getLength();
for (int p = 0; p < nodesLen; p++) {
result.contextParameters.put((String) xp.evaluate(prefix + "param-name", nodes.item(p),
XPathConstants.STRING), (String) xp.evaluate(prefix + "param-value", nodes.item(p),
XPathConstants.STRING));
}
// session-config <session-timeout>
Number num = (Number) xp.evaluate(prefix + "session-config/" + prefix + "session-timeout", document,
XPathConstants.NUMBER);
if (num != null)
result.sessionTimeout = num.intValue();
if (result.sessionTimeout < 0)
result.sessionTimeout = 0;
else
result.sessionTimeout *= 60;
Thread.currentThread().setContextClassLoader(result.ucl);
// listeners listener-class
nodes = (NodeList) xp.evaluate(prefix + "listener/" + prefix + "listener-class", document,
XPathConstants.NODESET);
nodesLen = nodes.getLength();
if (nodesLen > 0) {
result.listeners = new ArrayList<EventListener>(nodesLen);
for (int i = 0; i < nodesLen; i++)
try {
EventListener eventListener = (EventListener) result.ucl.loadClass(
nodes.item(i).getTextContent().trim()).newInstance();
if (eventListener instanceof HttpSessionListener) {
if (result.sessionListeners == null)
result.sessionListeners = new ArrayList<HttpSessionListener>(nodesLen);
result.sessionListeners.add((HttpSessionListener) eventListener);
}
result.listeners.add(eventListener); // because the same class can implement other listener interfaces
} catch (Exception e) {
result.log("Event listener " + nodes.item(i).getTextContent() + " can't be created.", e);
} catch (Error e) {
result.log("Event listener " + nodes.item(i).getTextContent() + " can't be created.", e);
}
}
// restore sessions for this context
// serve.sessions.restore for the current context
// notify context listeners
if (result.listeners != null)
for (EventListener listener : result.listeners) {
if (listener instanceof ServletContextListener)
try {
((ServletContextListener) listener).contextInitialized(new ServletContextEvent(result));
} catch (Exception e) {
throw new ServletException("A problem in a context listener initialization.", e);
}
}
// process filters
nodes = (NodeList) xp.evaluate(prefix + "filter", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
result.filters = new ArrayList<FilterAccessDescriptor>(nodesLen);
for (int i = 0; i < nodesLen; i++) {
Node n = nodes.item(i);
FilterAccessDescriptor fad = result.createFilterDescriptor();
fad.name = (String) xp.evaluate(prefix + "filter-name", n, XPathConstants.STRING);
fad.className = (String) xp.evaluate(prefix + "filter-class", n, XPathConstants.STRING);
if (fad.className == null)
throw new ServletException(String.format("Filter %s specified without or empty class.", fad.name));
else
fad.className = fad.className.trim();
fad.label = (String) xp.evaluate(prefix + "display-name", n, XPathConstants.STRING);
fad.descr = (String) xp.evaluate(prefix + "description", n, XPathConstants.STRING);
NodeList params = (NodeList) xp.evaluate(prefix + "init-param", n, XPathConstants.NODESET);
fad.initParams = new HashMap<String, String>(params.getLength());
for (int p = 0; p < params.getLength(); p++) {
fad.initParams.put((String) xp.evaluate(prefix + "param-name", params.item(p),
XPathConstants.STRING), (String) xp.evaluate(prefix + "param-value", params.item(p),
XPathConstants.STRING));
}
result.filters.add(fad);
}
// process filter's mapping
for (FilterAccessDescriptor fad : result.filters) {
nodes = (NodeList) xp.evaluate(prefix + "filter-mapping[" + prefix + "filter-name=\"" + fad.name
+ "\"]", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
if (nodesLen == 0)
throw new ServletException(String.format("No mappings were found for filter %s", fad.name));
for (int i = 0; i < nodesLen; i++) {
Node n = nodes.item(i);
NodeList clarifications = (NodeList) xp.evaluate(prefix + "url-pattern", n, XPathConstants.NODESET);
int claLen = clarifications.getLength();
for (int j = 0; j < claLen; j++) {
String mapUrl = clarifications.item(j).getTextContent();
if (mapUrl == null || mapUrl.length() == 0)
continue;
fad.add(new MappingEntry(clearPath(mapUrl), buildREbyPathPatt(mapUrl)));
}
clarifications = (NodeList) xp.evaluate(prefix + "dispatcher", n, XPathConstants.NODESET);
claLen = clarifications.getLength();
for (int j = 0; j < claLen; j++) {
String filterType = clarifications.item(j).getTextContent();
if (filterType == null || filterType.length() == 0)
fad.add(DispatchFilterType.REQUEST);
else
fad.add(DispatchFilterType.valueOf(filterType));
}
clarifications = (NodeList) xp.evaluate(prefix + "servlet-name", n, XPathConstants.NODESET);
claLen = clarifications.getLength();
for (int j = 0; j < claLen; j++) {
// adding servlet name
fad.add(clarifications.item(j).getTextContent());
}
}
result.newFilterInstance(fad);
}
// servlets
nodes = (NodeList) xp.evaluate(prefix + "servlet", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
result.servlets = new ArrayList<ServletAccessDescr>(nodesLen + 1); // +jsp
for (int i = 0; i < nodesLen; i++) {
Node n = nodes.item(i);
ServletAccessDescr sad = result.createDescriptor();
sad.name = (String) xp.evaluate(prefix + "servlet-name", n, XPathConstants.STRING);
sad.className = (String) xp.evaluate(prefix + "servlet-class", n, XPathConstants.STRING);
if (sad.className == null || sad.className.length() == 0) {
String jspFile = (String) xp.evaluate(prefix + "jsp-file", n, XPathConstants.STRING);
if (jspFile != null) {
result.log(String.format("Not supported servlet option jsp-file %s for %s, ignored.", jspFile,
sad.name));
continue;
} else
throw new ServletException(String.format("Servlet %s specified without class or jsp file.",
sad.name));
} else
sad.className = sad.className.trim();
sad.label = (String) xp.evaluate(prefix + "display-name", n, XPathConstants.STRING);
sad.descr = (String) xp.evaluate(prefix + "description", n, XPathConstants.STRING);
String loadOnStartVal = (String) xp.evaluate(prefix + "load-on-startup", n, XPathConstants.STRING);
sad.loadOnStart = loadOnStartVal != null && loadOnStartVal.length() > 0;
NodeList params = (NodeList) xp.evaluate(prefix + "init-param", n, XPathConstants.NODESET);
sad.initParams = new HashMap<String, String>(params.getLength());
for (int p = 0; p < params.getLength(); p++) {
sad.initParams.put((String) xp.evaluate(prefix + "param-name", params.item(p),
XPathConstants.STRING), (String) xp.evaluate(prefix + "param-value", params.item(p),
XPathConstants.STRING));
}
result.servlets.add(sad);
}
// get mappings
ServletAccessDescr wasDefault = null;
for (ServletAccessDescr sad : result.servlets) {
nodes = (NodeList) xp.evaluate(prefix + "servlet-mapping[" + prefix + "servlet-name=\"" + sad.name
+ "\"]", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
// System.err.printf("Found %d mappings for %s%n", nodesLen, sad);
if (nodesLen == 0) {
// no mapping at all
String urlPat = "/" + sad.name + "/*";
sad.add(new MappingEntry(clearPath(urlPat), buildREbyPathPatt(urlPat)));
} else
for (int i = 0; i < nodesLen; i++) {
NodeList maps = (NodeList) xp.evaluate(prefix + "url-pattern", nodes.item(i),
XPathConstants.NODESET);
int mapsLen = maps.getLength();
// System.err.printf("Found %d patterns for %s%n", mapsLen, sad);
if (mapsLen == 0) {
// mapping with empty pattern
String urlPat = "/" + sad.name + "/*";
sad.add(new MappingEntry(clearPath(urlPat), buildREbyPathPatt(urlPat)));
} else {
for (int j = 0; j < mapsLen; j++) {
String urlPat = maps.item(j).getTextContent();
if (urlPat.equals("/"))
if (wasDefault != null)
throw new ServletException("More than one default servlets defined " + sad);
else
wasDefault = sad;
sad.add(new MappingEntry(clearPath(urlPat), buildREbyPathPatt(urlPat)));
}
}
}
// System.err.printf("Servlet %s, path:%s\n", sad, sad.servPath);
if (sad.loadOnStart)
result.newInstance(sad);
}
// additional jsp mapping
nodes = (NodeList) xp.evaluate(prefix + "jsp-config/" + prefix + "jsp-property-group/" + prefix
+ "url-pattern", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
if (nodesLen > 0) {
List<String> jspPats = new ArrayList<String>(nodesLen);
for (int i = 0; i < nodesLen; i++) {
jspPats.add(nodes.item(i).getTextContent());
}
result.addJSPServlet(jspPats);
} else
result.addJSPServlet(null);
if (wasDefault != null) {
// re-add at the end
result.servlets.remove(wasDefault);
result.servlets.add(wasDefault);
}
// welcome files
nodes = (NodeList) xp.evaluate(prefix + "welcome-file-list/" + prefix + "welcome-file", document,
XPathConstants.NODESET);
result.welcomeFiles = new ArrayList<String>(nodes.getLength() + 1);
nodesLen = nodes.getLength();
if (nodesLen > 0)
for (int wfi = 0; wfi < nodesLen; wfi++)
result.welcomeFiles.add(nodes.item(wfi).getTextContent());
else {
result.welcomeFiles.add("index.html");
result.welcomeFiles.add("index.jsp");
}
// error pages
nodes = (NodeList) xp.evaluate(prefix + "error-page", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
if (nodesLen > 0) {
result.errorPages = new ArrayList<ErrorPageDescr>(nodesLen);
for (int i = 0; i < nodesLen; i++) {
Node n = nodes.item(i);
result.errorPages.add(new WebAppServlet.ErrorPageDescr((String) xp.evaluate(prefix + "location", n,
XPathConstants.STRING), (String) xp.evaluate(prefix + "exception-type", n,
XPathConstants.STRING), (String) xp.evaluate(prefix + "error-code", n,
XPathConstants.STRING)));
}
}
// mime types
nodes = (NodeList) xp.evaluate(prefix + "mime-mapping", document, XPathConstants.NODESET);
nodesLen = nodes.getLength();
if (nodesLen > 0) {
result.mimes = new HashMap<String, String>(nodesLen);
for (int i = 0; i < nodesLen; i++) {
Node n = nodes.item(i);
result.mimes.put(((String) xp.evaluate(prefix + "extension", n, XPathConstants.STRING))
.toLowerCase(), (String) xp.evaluate(prefix + "mime-type", n, XPathConstants.STRING));
}
}
} catch (IOException ioe) {
throw new ServletException("A problem in reading web.xml.", ioe);
} catch (XPathExpressionException xpe) {
xpe.printStackTrace();
throw new ServletException("A problem in parsing web.xml.", xpe);
} // finally { // streams will be closed by InputSource
return result;
}
static <D extends ServletAccessDescr> void addMultiple(NodeList list, D d) {
// TODO can be solution for more compact code
}
static public String buildREbyPathPatt(String pathPat) {
if (pathPat.equals("/"))
return "/.*";
if (pathPat.startsWith("*."))
return pathPat.replace(".", "\\.").replace("?", ".").replace("*", ".*").replace("|", "\\|"); // +"\\??.*";
// TODO think more
int wcp = pathPat.indexOf('*');
if (wcp > 0 && pathPat.charAt(wcp - 1) == '/')
pathPat = pathPat.substring(0, wcp - 1) + '*';
pathPat = pathPat.replace(".", "\\.").replace("?", ".").replace("*", ".*");
if (wcp < 0)
if (pathPat.endsWith("/") == false)
pathPat += "/?";
return pathPat;
}
static public String clearPath(String pathMask) {
if (pathMask.equals("/"))
return pathMask;
if (pathMask.startsWith("*."))
return "/";
int wcp = pathMask.indexOf('*');
if (wcp < 0)
return pathMask;
return pathMask.substring(0, wcp);
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// new Exception("call trace").printStackTrace();
// TODO check access rights
Thread.currentThread().setContextClassLoader(ucl);
if (req.isSecure())
fillSecureAttrs(req);
final HttpServletRequest hreq = (HttpServletRequest) req;
String path = hreq.getPathInfo();
// TODO: wrap request to implement methods like getRequestDispatcher()
// which supports relative path, no leading / means relative to currently called
if (_DEBUG)
System.err.printf("Full req:%s, ContextPath: %s, ServletPath:%s, pathInfo:%s\n", hreq.getRequestURI(), hreq
.getContextPath(), hreq.getServletPath(), path);
SimpleFilterChain sfc = new SimpleFilterChain();
if (path != null) {
// note a limitation, servlet name can't start with /WEB-INF
if (path.regionMatches(true, 0, "/WEB-INF", 0, "/WEB-INF".length())) {
((HttpServletResponse) res).sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
for (FilterAccessDescriptor fad : filters)
if (fad.matchDispatcher(DispatchFilterType.REQUEST) && fad.matchPath(path) >= 0)
sfc.add(fad);
for (ServletAccessDescr sad : servlets) {
if (_DEBUG)
System.err.println("Trying match " + path + " to " + Arrays.toString(sad.mapping) + " = "
+ sad.matchPath(path));
int patIndex;
if ((patIndex = sad.matchPath(path)) >= 0) {
if (sad.instance == null) {
if (sad.loadOnStart == false)
synchronized (sad) {
if (sad.instance == null)
newInstance(sad);
}
if (sad.instance == null) {
sad.loadOnStart |= true; // mark unsuccessful instantiation and ban the servlet?
((HttpServletResponse) res).sendError(HttpServletResponse.SC_GONE, "Servlet " + sad.name
+ " hasn't been instantiated successfully or has been unloaded.");
return;
}
} else {
if (sad.timeToReactivate > 0) {
if (sad.timeToReactivate > System.currentTimeMillis()) {
((HttpServletResponse) res).setIntHeader("Retry-After", (int)(sad.timeToReactivate - System.currentTimeMillis())/1000+1);
//((HttpServletResponse) res).setDateHeader("Retry-After", new Date(sad.timeToReactivate));
((HttpServletResponse) res).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
} else
sad.timeToReactivate = 0;
}
}
for (FilterAccessDescriptor fad : filters)
if (fad.matchDispatcher(DispatchFilterType.REQUEST) && fad.matchServlet(sad.name) >= 0)
sfc.add(fad);
// sfc.add(fad.filterInstance);
// System.err.println("used:"+ sad.servPath+", wanted:"+((WebAppServlet) sad.getServletContext()).contextPath);
sfc.setFilter(new WebAppContextFilter(sad.mapping[patIndex].servPath));
// add servlet in chain
sfc.setServlet(sad);
sfc.reset();
sfc.doFilter(req, res);
return;
}
}
} else {
((HttpServletResponse) res).sendRedirect(hreq.getRequestURI() + "/");
return;
}
// no matching, process as file
sfc.setFilter(new WebAppContextFilter());
sfc.setServlet(new HttpServlet() {
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
String path = ((HttpServletRequest) req).getPathTranslated();
returnFileContent(path, (HttpServletRequest) req, (HttpServletResponse) res);
}
});
sfc.reset();
sfc.doFilter(req, res);
}
protected void fillSecureAttrs(ServletRequest req) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -