📄 webserver.java
字号:
{ // Timeout while waiting for a client (from // SO_TIMEOUT)...try again if still listening. } catch (Exception ex) { System.err.println("Exception in XML-RPC listener loop (" + ex + ")."); if (XmlRpc.debug) { ex.printStackTrace(); } } catch (Error err) { System.err.println("Error in XML-RPC listener loop (" + err + ")."); err.printStackTrace(); } } } catch (Exception exception) { System.err.println("Error accepting XML-RPC connections (" + exception + ")."); if (XmlRpc.debug) { exception.printStackTrace(); } } finally { if (serverSocket != null) { try { serverSocket.close(); if (XmlRpc.debug) { System.out.print("Closed XML-RPC server socket"); } serverSocket = null; } catch (IOException e) { e.printStackTrace(); } } // Shutdown our Runner-based threads if (runners != null) { ThreadGroup g = runners; runners = null; try { g.interrupt(); } catch (Exception e) { System.err.println(e); e.printStackTrace(); } } } } /** * Stop listening on the server port. Shutting down our {@link * #listener} effectively breaks it out of its {@link #run()} * loop. * * @see #run() */ public synchronized void shutdown() { // Stop accepting client connections if (listener != null) { Thread l = listener; listener = null; l.interrupt(); } } /** * * @return */ protected Runner getRunner() { try { return (Runner)threadpool.pop(); } catch (EmptyStackException empty) { int maxRequests = XmlRpc.getMaxThreads(); if (runners.activeCount() > XmlRpc.getMaxThreads()) { throw new RuntimeException("System overload: Maximum number " + "of concurrent requests (" + maxRequests + ") exceeded"); } return new Runner(); } } /** * Put <code>runner</code> back into {@link #threadpool}. * * @param runner The instance to reclaim. */ void repoolRunner(Runner runner) { threadpool.push(runner); } /** * Responsible for handling client connections. */ class Runner implements Runnable { Thread thread; Connection con; int count; /** * Handles the client connection on <code>socket</code>. * * @param socket The source to read the client's request from. */ public synchronized void handle(Socket socket) throws IOException { con = new Connection(socket); count = 0; if (thread == null || !thread.isAlive()) { thread = new Thread(runners, this); thread.start(); } else { // Wake the thread waiting in our run() method. this.notify(); } } /** * Delegates to <code>con.run()</code>. */ public void run() { while (con != null && Thread.currentThread() == thread) { con.run(); count++; con = null; if (count > 200 || threadpool.size() > 20) { // We're old, or the number of threads in the pool // is large. return; } synchronized(this) { repoolRunner(this); try { this.wait(); } catch (InterruptedException ir) { Thread.currentThread().interrupt(); } } } } } /** * */ class Connection implements Runnable { private Socket socket; private BufferedInputStream input; private BufferedOutputStream output; private String user, password; private Base64 base64Codec; byte[] buffer; /** * * @param socket * @throws IOException */ public Connection (Socket socket) throws IOException { // set read timeout to 30 seconds socket.setSoTimeout (30000); this.socket = socket; input = new BufferedInputStream(socket.getInputStream()); output = new BufferedOutputStream(socket.getOutputStream()); } /** * */ public void run() { try { boolean keepAlive = false; do { // reset user authentication user = null; password = null; String line = readLine(); // Netscape sends an extra \n\r after bodypart, swallow it if (line != null && line.length() == 0) { line = readLine(); } if (XmlRpc.debug) { System.out.println(line); } int contentLength = -1; // tokenize first line of HTTP request StringTokenizer tokens = new StringTokenizer(line); String method = tokens.nextToken(); String uri = tokens.nextToken(); String httpVersion = tokens.nextToken(); keepAlive = XmlRpc.getKeepAlive() && HTTP_11.equals(httpVersion); do { line = readLine(); if (line != null) { if (XmlRpc.debug) { System.out.println(line); } String lineLower = line.toLowerCase(); if (lineLower.startsWith("content-length:")) { contentLength = Integer.parseInt( line.substring(15).trim()); } if (lineLower.startsWith("connection:")) { keepAlive = XmlRpc.getKeepAlive() && lineLower.indexOf("keep-alive") > -1; } if (lineLower.startsWith("authorization: basic ")) { parseAuth (line); } } } while (line != null && line.length() != 0); if ("POST".equalsIgnoreCase(method)) { ServerInputStream sin = new ServerInputStream(input, contentLength); try { byte[] result = xmlrpc.execute(sin, user, password); writeResponse(result, httpVersion, keepAlive); } catch (AuthenticationFailed unauthorized) { keepAlive = false; writeUnauthorized(httpVersion, method); } } else { keepAlive = false; writeBadRequest(httpVersion, method); } output.flush(); } while (keepAlive); } catch (Exception exception) { if (XmlRpc.debug) { exception.printStackTrace(); } else { System.err.println(exception); } } finally { try { if (socket != null) { socket.close(); } } catch (IOException ignore) { } } } /** * * @return * @throws IOException */ private String readLine() throws IOException { if (buffer == null) { buffer = new byte[2048]; } int next; int count = 0; for (;;) { next = input.read(); if (next < 0 || next == '\n') { break; } if (next != '\r') { buffer[count++] = (byte) next; } if (count >= buffer.length) { throw new IOException("HTTP Header too long"); } } return new String(buffer, 0, count); } /** * * @param line */ private void parseAuth(String line) { try { byte[] c = base64Codec.decode(toHTTPBytes(line.substring(21))); String str = new String(c); int col = str.indexOf(':'); user = str.substring(0, col); password = str.substring(col + 1); } catch (Throwable ignore) { } } private void writeResponse(byte[] payload, String httpVersion, boolean keepAlive) throws IOException { output.write(toHTTPBytes(httpVersion)); output.write(ok); output.write(server); output.write(keepAlive ? conkeep : conclose); output.write(ctype); output.write(clength); output.write(toHTTPBytes(Integer.toString(payload.length))); output.write(doubleNewline); output.write(payload); } private void writeBadRequest(String httpVersion, String httpMethod) throws IOException { output.write(toHTTPBytes(httpVersion)); output.write(toHTTPBytes(" 400 Bad Request")); output.write(newline); output.write(server); output.write(newline); output.write(toHTTPBytes("Method " + httpMethod + " not implemented (try POST)")); } private void writeUnauthorized(String httpVersion, String httpMethod) throws IOException { output.write(toHTTPBytes(httpVersion)); output.write(toHTTPBytes(" 401 Unauthorized")); output.write(newline); output.write(server); output.write(wwwAuthenticate); output.write(newline); output.write(toHTTPBytes("Method " + httpMethod + " requires a " + "valid user name and password")); } } /** * */ class AddressMatcher { int pattern[]; /** * * @param address * @throws Exception */ public AddressMatcher(String address) throws Exception { pattern = new int[4]; StringTokenizer st = new StringTokenizer(address, "."); if (st.countTokens() != 4) { throw new Exception("\"" + address + "\" does not represent a valid IP address"); } for (int i = 0; i < 4; i++) { String next = st.nextToken(); if (STAR.equals(next)) { pattern[i] = 256; } else { pattern[i] = (byte) Integer.parseInt(next); } } } /** * * @param address * @return */ public boolean matches (byte address[]) { for (int i = 0; i < 4; i++) { if (pattern[i] > 255)// wildcard { continue; } if (pattern[i] != address[i]) { return false; } } return true; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -