📄 serve.java
字号:
return;
} catch (ClassNotFoundException e) {
log("Class not found: " + className);
} catch (ClassCastException e) {
log("Class cast problem: " + e.getMessage());
} catch (InstantiationException e) {
log("Instantiation problem: " + e.getMessage());
} catch (IllegalAccessException e) {
log("Illegal class access: " + e.getMessage());
} catch (Exception e) {
log("Unexpected problem creating servlet: " + e, e);
}
}
// / Register a Servlet. Registration consists of a URL pattern,
// which can contain wildcards, and the Servlet to
// launch when a matching URL comes in. Patterns are checked for
// matches in the order they were added, and only the first match is run.
public void addServlet(String urlPat, Servlet servlet) {
addServlet(urlPat, servlet, (Hashtable) null);
}
public synchronized void addServlet(String urlPat, Servlet servlet, Hashtable initParams) {
try {
if (getServlet(urlPat) != null)
log("Servlet overriden by " + servlet + ", for path:" + urlPat);
servlet.init(new ServeConfig((ServletContext) this, initParams, urlPat));
registry.put(urlPat, servlet);
} catch (ServletException e) { //
// it handles UnavailableException as well without an attempt to re-adding
log("Problem initializing servlet, it won't be used: " + e);
}
}
// / Register a standard set of Servlets. These will return
// files or directory listings, and run CGI programs, much like a
// standard HTTP server.
// <P>
// Because of the pattern checking order, this should be called
// <B>after</B> you've added any custom Servlets.
// <P>
// The current set of default servlet mappings:
// <UL>
// <LI> If enabled, *.cgi goes to CgiServlet, and gets run as a CGI program.
// <LI> * goes to FileServlet, and gets served up as a file or directory.
// </UL>
// @param cgi whether to run CGI programs
// TODO: provide user specified CGI directory
public void addDefaultServlets(String cgi) {
try {
addDefaultServlets(cgi, null);
} catch (IOException ioe) { /* ignore, makes sense only for throtles */
}
}
/**
* Register a standard set of Servlets, with optional throttles. These will return files or directory listings, and run CGI programs, much like a standard
* HTTP server.
* <P>
* Because of the pattern checking order, this should be called <B>after</B> you've added any custom Servlets.
* <P>
* The current set of default servlet mappings:
* <UL>
* <LI> If enabled, *.cgi goes to CgiServlet, and gets run as a CGI program.
* <LI> * goes to FileServlet, and gets served up as a file or directory.
* </UL>
*
* @param cgi
* whether to run CGI programs
* @param throttles
* filename to read FileServlet throttle settings from, can be null
* @throws IOException
*/
public void addDefaultServlets(String cgi, String throttles) throws IOException {
// TODO: provide user specified CGI directory
if (cgi != null) {
if (getServlet("/" + cgi) == null)
addServlet("/" + cgi, new Acme.Serve.CgiServlet());
else
log("Servlet for path '/" + cgi + "' already defined and no default will be used.");
}
if (getServlet("/") == null)
if (throttles != null)
addServlet("/", new Acme.Serve.FileServlet(throttles, null));
else
addServlet("/", new Acme.Serve.FileServlet());
else
log("Servlet for path '/' already defined and no default will be used.");
}
protected void addWarDeployer(String deployerFactory, String throttles) {
if (deployerFactory == null) // try to use def
deployerFactory = "rogatkin.web.WarRoller";
try {
WarDeployer wd = (WarDeployer) Class.forName(deployerFactory).newInstance();
wd.deploy(this);
} catch (ClassNotFoundException cnf) {
log("Problem initializing war deployer: " + cnf);
} catch (Exception e) {
log("Problem war(s) deployment", e);
}
}
protected File getPersistentFile() {
if (arguments.get(ARG_SESSION_PERSIST) == null || (Boolean) arguments.get(ARG_SESSION_PERSIST) == Boolean.FALSE)
return null;
return new File(workPath, hostName + '-'
+ (arguments.get(ARG_PORT) == null ? String.valueOf(DEF_PORT) : arguments.get(ARG_PORT))
+ "-session.obj");
}
// Run the server. Returns only on errors.
transient boolean running = true;
protected transient ServerSocket serverSocket;
protected transient Thread ssclThread;
public int serve() {
try {
serverSocket = createServerSocket();
if (arguments.get(ARG_BINDADDRESS) != null)
hostName = serverSocket.getInetAddress().getHostName();
else
hostName = InetAddress.getLocalHost().getHostName();
} catch (IOException e) {
log("Server socket: " + e);
return 1;
}
if (arguments.get(ARG_NOHUP) == null)
new Thread(new Runnable() {
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while (true) {
try {
System.out.print("Press \"q\" <ENTER>, for gracefully stopping the server ");
line = in.readLine();
if (line != null && line.length() > 0 && line.charAt(0) == 'q') {
notifyStop();
break;
}
} catch (IOException e) {
log("Exception in reading from console ", e);
break;
}
}
}
}, "Stop Monitor").start();
// else create kill signal handler
if (expiredIn > 0) {
ssclThread = new Thread(serverThreads, new Runnable() {
public void run() {
while (running) {
try {
Thread.sleep(expiredIn * 60 * 1000);
} catch (InterruptedException ie) {
if (running == false)
break;
}
Enumeration e = sessions.keys();
while (e.hasMoreElements()) {
Object sid = e.nextElement();
if (sid != null) {
AcmeSession as = (AcmeSession) sessions.get(sid);
if (as != null && (as.checkExpired() || !as.isValid())) { // log("sesion
as = (AcmeSession) sessions.remove(sid);
if (as != null && as.isValid())
try {
as.invalidate();
} catch (IllegalStateException ise) {
}
}
}
}
}
}
}, "Session cleaner");
ssclThread.setPriority(Thread.MIN_PRIORITY);
// ssclThread.setDaemon(true);
ssclThread.start();
} // else
// expiredIn = -expiredIn;
if (isKeepAlive()) {
keepAliveCleaner = new KeepAliveCleaner();
keepAliveCleaner.start();
}
File fsessions = getPersistentFile();
if (fsessions != null && fsessions.exists()) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(fsessions));
sessions = HttpSessionContextImpl.restore(br, Math.abs(expiredIn) * 60, this);
} catch (IOException ioe) {
log("Problem in restoring sessions.", ioe);
} catch (Exception e) {
log("Unexpected problem in restoring sessions.", e);
} finally {
if (br != null)
try {
br.close();
} catch (IOException ioe) {
}
}
}
if (sessions == null)
sessions = new HttpSessionContextImpl();
// TODO: display address as name and as ip
System.out.println("[" + new Date() + "] TJWS httpd " + hostName + " - " + serverSocket + " is listening.");
try {
while (running) {
try {
Socket socket = serverSocket.accept();
// TODO consider to use ServeConnection object pool
if (serve.keepAliveCleaner != null) // we need to add regardless of keep alive
serve.keepAliveCleaner.addConnection(new ServeConnection(socket, this));
else
new ServeConnection(socket, this); // TODO consider req/resp objects pooling
} catch (IOException e) {
log("Accept: " + e);
} catch (SecurityException se) {
log("Illegal access: " + se);
}
}
} catch (Throwable t) {
log("Unhandled exception: " + t + ", server is terminating.", t);
return -1;
} finally {
try {
if (serverSocket != null)
serverSocket.close();
} catch (IOException e) {
}
}
return 0;
}
protected void notifyStop() throws IOException {
running = false;
serverSocket.close();
serverSocket = null;
}
protected void killAliveThreads() {
serverThreads.interrupt();
ThreadGroup tg = Thread.currentThread().getThreadGroup();
while (tg.getParent() != null)
tg = tg.getParent();
int ac = tg.activeCount() + tg.activeGroupCount() + 10;
Thread[] ts = new Thread[ac];
ac = tg.enumerate(ts, true);
if (ac == ts.length)
log("Destroy:interruptRunningProcesses: Not all threads will be stopped.");
// kill non daemon
for (int i = 0; i < ac; i++)
if (ts[i].isDaemon() == false) {
String tn = ts[i].getName();
// System.err.println("Interrupting and kill " + tn);
if (ts[i] == Thread.currentThread() || "Stop Monitor".equals(tn) || "ShutDownHook".equals(tn)
|| "DestroyJavaVM".equals(tn) || (tn != null && tn.startsWith("AWT-")))
continue;
ts[i].interrupt();
Thread.yield();
if (ts[i].isAlive()) {
// System.out.println("Killing "+ts[i].getName());
try {
ts[i].stop();
} catch (Throwable t) {
if (t instanceof ThreadDeath)
throw (Error) t;
// System.out.println("Ex: "+t);
}
}
}
}
public static void stop() throws IOException {
serve.notifyStop();
}
public static interface SocketFactory {
public ServerSocket createSocket(Map arguments) throws IOException, IllegalArgumentException;
}
// TODO: add a paremeter to create secure only if requested
// it will allow to create one or two sockets for secure and non communications
protected ServerSocket createServerSocket() throws IOException {
String socketFactoryClass = (String) arguments.get(ARG_SOCKET_FACTORY);
if (socketFactoryClass != null)
try {
SocketFactory sf = (SocketFactory) Class.forName(socketFactoryClass).newInstance();
return sf.createSocket(arguments);
} catch (Exception e) {
log("Couldn't create a custom socket factory " + socketFactoryClass
+ " or call a creation method. Standard socket will be used instead.", e);
}
int bl = 50;
try {
// TODO: consider conversion at getting the argument
bl = Integer.parseInt((String) arguments.get(ARG_BACKLOG));
if (bl < 2)
bl = 2;
} catch (Exception e) {
}
int port = arguments.get(ARG_PORT) != null ? ((Integer) arguments.get(ARG_PORT)).intValue() : DEF_PORT;
InetAddress ia = null;
if (arguments.get(ARG_BINDADDRESS) != null)
try {
ia = InetAddress.getByName((String) arguments.get(ARG_BINDADDRESS));
} catch (Exception e) {
}
return new ServerSocket(port, bl, ia);
}
// Methods from ServletContext.
// / Gets a servlet by name.
// @param name the servlet name
// @return null if the servlet does not exist
public Servlet getServlet(String name) {
try {
return (Servlet) ((Object[]) registry.get(name))[0];
} catch (NullPointerException npe) {
return null;
}
}
// / Enumerates the servlets in this context (server). Only servlets that
// are accesible will be returned. This enumeration always includes the
// servlet itself.
public Enumeration getServlets() {
return registry.elements();
}
// / Enumerates the names of the servlets in this context (server). Only
// servlets that are accesible will be returned. This enumeration always
// includes the servlet itself.
public Enumeration getServletNames() {
return registry.keys();
}
// / Destroys all currently-loaded servlets.
public synchronized void destroyAllServlets() {
// log("Entering destroyAllServlets()");
// serialize sessions
// invalidate all sessions
// TODO consider merging two pieces below, generally if session is stored,
// it shouldn't be invalidated
File sf = getPersistentFile();
if (sf != null && sessions != null) {
Writer w = null;
try {
w = new FileWriter(sf);
sessions.save(w);
log("Sessions stored.");
} catch (IOException ioe) {
log("IO problem in storing sessions " + ioe);
} catch (Throwable t) {
log("Problem in storing sessions " + t);
} finally {
try {
w.close();
} catch (Exception e) {
}
}
Enumeration e = sessions.keys();
while (e.hasMoreElements()) {
Object sid = e.nextElement();
if (sid != null) {
AcmeSession as = (AcmeSession) sessions.get(sid);
if (as != null) {
as = (AcmeSession) sessions.remove(sid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -