⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serve.java

📁 用java开发的
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			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 + -