📄 serve.java
字号:
* <p>
* The servlet container must implement the URL handlers and <code>URLConnection</code> objects that are necessary to access the resource.
*
* <p>
* This method returns <code>null</code> if no resource is mapped to the pathname.
*
* <p>
* Some containers may allow writing to the URL returned by this method using the methods of the URL class.
*
* <p>
* The resource content is returned directly, so be aware that requesting a <code>.jsp</code> page returns the JSP source code. Use a
* <code>RequestDispatcher</code> instead to include results of an execution.
*
* <p>
* This method has a different purpose than <code>java.lang.Class.getResource</code>, which looks up resources based on a class loader. This method does
* not use class loaders.
*
* @param path
* a <code>String</code> specifying the path to the resource
*
* @return the resource located at the named path, or <code>null</code> if there is no resource at that path
*
* @exception MalformedURLException
* if the pathname is not given in the correct form
*
*
*/
public URL getResource(String path) throws MalformedURLException {
if (path == null || path.length() == 0 || path.charAt(0) != '/')
throw new MalformedURLException("Path " + path + " is not in acceptable form.");
return new URL("file", "localhost", getRealPath(path));
}
/**
* Returns the resource located at the named path as an <code>InputStream</code> object.
*
* <p>
* The data in the <code>InputStream</code> can be of any type or length. The path must be specified according to the rules given in
* <code>getResource</code>. This method returns <code>null</code> if no resource exists at the specified path.
*
* <p>
* Meta-information such as content length and content type that is available via <code>getResource</code> method is lost when using this method.
*
* <p>
* The servlet container must implement the URL handlers and <code>URLConnection</code> objects necessary to access the resource.
*
* <p>
* This method is different from <code>java.lang.Class.getResourceAsStream</code>, which uses a class loader. This method allows servlet containers to
* make a resource available to a servlet from any location, without using a class loader.
*
*
* @param path
* a <code>String</code> specifying the path to the resource
*
* @return the <code>InputStream</code> returned to the servlet, or <code>null</code> if no resource exists at the specified path
*
*
*/
public InputStream getResourceAsStream(String path) {
try {
return getResource(path).openStream();
} catch (Exception e) {
}
return null;
}
public RequestDispatcher getRequestDispatcher(String urlpath) {
if (urlpath == null || urlpath.length() == 0 || urlpath.charAt(0) != '/')
return null;
try {
return new SimpleRequestDispatcher(urlpath);
} catch (NullPointerException npe) {
return null;
}
}
// no way to specify parameters for context
public String getInitParameter(String param) {
return null;
}
public Enumeration getInitParameterNames() {
return Utils.EMPTY_ENUMERATION;
}
public RequestDispatcher getNamedDispatcher(String name) {
// named resources are not supported
return null;
}
synchronized String generateSessionId() {
return "-" + System.currentTimeMillis() + '-' + (uniqer++) + '-' + Math.round(Math.random() * 1000);
}
protected class SimpleRequestDispatcher implements RequestDispatcher {
HttpServlet servlet;
String dispatchPath;
String dispatchQuery;
int dispatchLen;
SimpleRequestDispatcher(String path) {
// log("Dispatch to: " + path);
Object[] os = serve.registry.get(path);
servlet = (HttpServlet) os[0];
if (servlet == null)
throw new NullPointerException();
dispatchLen = ((Integer) os[1]).intValue();
int qmp = path.indexOf('?');
if (qmp < 0 || qmp >= path.length() - 1)
dispatchPath = path;
else {
dispatchPath = path.substring(0, qmp);
dispatchQuery = path.substring(qmp + 1);
}
}
public void forward(ServletRequest _request, ServletResponse _response) throws ServletException,
java.io.IOException {
_request.removeAttribute("javax.servlet.forward.request_uri"); // reset in case of nested
_response.reset();
servlet.service(new HttpServletRequestWrapper((HttpServletRequest) _request) {
public java.lang.String getPathInfo() {
return dispatchLen >= dispatchPath.length() ? null : dispatchPath.substring(dispatchLen);
}
public String getRequestURI() {
return dispatchPath;
}
public String getQueryString() {
return dispatchQuery;
}
public String getServletPath() {
return dispatchLen <= 0 ? "" : dispatchPath.substring(0, dispatchLen);
}
public synchronized java.util.Enumeration getAttributeNames() {
if (super.getAttribute("javax.servlet.forward.request_uri") == null) {
setAttribute("javax.servlet.forward.request_uri", super.getRequestURI());
setAttribute("javax.servlet.forward.context_path", this.getContextPath());
setAttribute("javax.servlet.forward.servlet_path", super.getServletPath());
setAttribute("javax.servlet.forward.path_info", super.getPathInfo());
setAttribute("javax.servlet.forward.query_string", super.getQueryString());
}
return super.getAttributeNames();
}
public Object getAttribute(String name) {
getAttributeNames(); // here is some overhead
return super.getAttribute(name);
}
}, _response);
((ServeConnection) _response).close();
}
public void include(ServletRequest _request, ServletResponse _response) throws ServletException,
java.io.IOException {
_request.removeAttribute("javax.servlet.include.request_uri"); // reset in case of nested
((Serve.ServeConnection) _response).setInInclude(true);
try {
servlet.service(new HttpServletRequestWrapper((HttpServletRequest) _request) {
public synchronized java.util.Enumeration getAttributeNames() {
if (super.getAttribute("javax.servlet.include.request_uri") == null) {
setAttribute("javax.servlet.include.request_uri", dispatchPath);
setAttribute("javax.servlet.include.context_path", this.getContextPath());
setAttribute("javax.servlet.include.servlet_path", dispatchLen <= 0 ? "" : dispatchPath
.substring(0, dispatchLen));
setAttribute("javax.servlet.include.path_info", dispatchLen >= dispatchPath.length() ? null
: dispatchPath.substring(dispatchLen));
setAttribute("javax.servlet.include.query_string", dispatchQuery);
}
return super.getAttributeNames();
}
public Object getAttribute(String name) {
getAttributeNames(); // here is some overhead
return super.getAttribute(name);
}
}, _response);
} finally {
((Serve.ServeConnection) _response).setInInclude(false);
}
}
}
// Keep Alive supporter, JDK 1.4 based for backwar compatibility
class KeepAliveCleaner extends Thread {
protected List connections;
protected List ingoings;
protected boolean stopped;
private boolean noCheckClose;
KeepAliveCleaner() {
super("KeepAlive cleaner");
connections = new ArrayList();
ingoings = new ArrayList();
setDaemon(true);
}
synchronized void addConnection(ServeConnection conn) {
synchronized (ingoings) {
if (stopped == false)
ingoings.add(conn);
}
}
public void run() {
long d = getKeepAliveDuration();
int maxUse = getMaxTimesConnectionUse();
while (true) {
synchronized (ingoings) {
Iterator i = ingoings.iterator();
while (i.hasNext()) {
connections.add(i.next());
i.remove();
}
}
Iterator i = connections.iterator();
long ct = System.currentTimeMillis();
d = getKeepAliveDuration();
while (i.hasNext()) {
ServeConnection conn = (ServeConnection) i.next();
boolean closed = conn.socket == null;
if (noCheckClose == false)
synchronized (conn) {
if (conn.socket != null)
try {
closed = ((Boolean) conn.socket.getClass().getMethod("isClosed",
Utils.EMPTY_CLASSES).invoke(conn.socket, Utils.EMPTY_OBJECTS))
.booleanValue();
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException e) {
noCheckClose = true;
}
}
if (closed || (conn.keepAlive && (ct - conn.lastWait > d && conn.lastRun < conn.lastWait))
|| stopped
/* || conn.timesRequested > maxUse */) {
i.remove();
synchronized (conn) {
if (conn.socket != null)
try {
// System.err.println("Closing socekt"); // !!!
conn.socket.close();
} catch (IOException ioe) {
// ignore
}
}
}
}
if (stopped && connections.size() == 0)
break;
try {
sleep(d);
} catch (InterruptedException ie) {
stopped = true; // not thread safe
}
}
}
}
final static class Identification {
public static final String serverName = "Rogatkin's JWS based on Acme.Serve";
public static final String serverVersion = "Version 1.27, $Revision: 1.112 $";
public static final String serverUrl = "http://tjws.sourceforge.net";
// / Write a standard-format HTML address for this server.
public static void writeAddress(OutputStream o) throws IOException {
PrintStream p = new PrintStream(o);
p.println("<ADDRESS><A HREF=\"" + serverUrl + "\">" + serverName + " " + serverVersion + "</A></ADDRESS>");
}
public static void writeAddress(StringBuffer sb) throws IOException {
sb.append("<ADDRESS><A HREF=\"" + serverUrl + "\">" + serverName + " " + serverVersion + "</A></ADDRESS>");
}
}
// ////////////////////////////////////////////////////////////////
protected static class ServeConfig implements ServletConfig {
private ServletContext context;
private Hashtable init_params;
private String servletName;
public ServeConfig(ServletContext context) {
this(context, null, "undefined");
}
public ServeConfig(ServletContext context, Hashtable initParams, String servletName) {
this.context = context;
this.init_params = initParams;
this.servletName = servletName;
}
// Methods from ServletConfig.
// / Returns the context for the servlet.
public ServletContext getServletContext() {
return context;
}
// / Gets an initialization parameter of the servlet.
// @param name the parameter name
public String getInitParameter(String name) {
// This server supports servlet init params. :)
if (init_params != null)
return (String) init_params.get(name);
return null;
}
// / Gets the names of the initialization parameters of the servlet.
// @param name the parameter name
public Enumeration getInitParameterNames() {
// This server does:) support servlet init params.
if (init_params != null)
return init_params.keys();
return new Vector().elements();
}
// 2.2
public String getServletName() {
return servletName;
}
}
// /////////////////////////////////////////////////////////////////////
/**
* provides request/response
*/
public static class ServeConnection implements Runnable, HttpServletRequest, HttpServletResponse {
private Socket socket;
private Serve serve;
private ServletInputStream in;
private ServletOutputStream out;
private String scheme;
public final static String WWWFORMURLENCODE = "application/x-www-form-urlencoded";
public final static String TRANSFERENCODING = "transfer-encoding".toLowerCase();
public final static String KEEPALIVE = "Keep-Alive".toLowerCase();
public final static String CONNECTION = "Connection".toLowerCase();
public final static String CHUNKED = "chunked";
public final static String CONTENTLENGTH = "Content-Length".toLowerCase();
public final static String CONTENTTYPE = "Content-Type".toLowerCase();
public final static String SETCOOKIE = "Set-Cookie".toLowerCase();
public final static String HOST = "Host".toLowerCase();
public final static String COOKIE = "Cookie".toLowerCase();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -