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

📄 webserver.java

📁 xmlrpc-2.0-src.zip java程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 1999,2005 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.xmlrpc;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.IOException;import java.io.InterruptedIOException;import java.io.UnsupportedEncodingException;import java.net.BindException;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.util.EmptyStackException;import java.util.Stack;import java.util.StringTokenizer;import java.util.Vector;import org.apache.commons.codec.binary.Base64;/** * A minimal web server that exclusively handles XML-RPC requests. * * @author <a href="mailto:hannes@apache.org">Hannes Wallnoefer</a> * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> * @author Daniel L. Rall */public class WebServer implements Runnable{    protected XmlRpcServer xmlrpc;    protected ServerSocket serverSocket;    protected Thread listener;    protected Vector accept, deny;    protected Stack threadpool;    protected ThreadGroup runners;    // Inputs to setupServerSocket()    private InetAddress address;    private int port;    private boolean paranoid;    protected static final byte[] ctype =        toHTTPBytes("Content-Type: text/xml\r\n");    protected static final byte[] clength =        toHTTPBytes("Content-Length: ");    protected static final byte[] newline = toHTTPBytes("\r\n");    protected static final byte[] doubleNewline = toHTTPBytes("\r\n\r\n");    protected static final byte[] conkeep =        toHTTPBytes("Connection: Keep-Alive\r\n");    protected static final byte[] conclose =        toHTTPBytes("Connection: close\r\n");    protected static final byte[] ok = toHTTPBytes(" 200 OK\r\n");    protected static final byte[] server =        toHTTPBytes("Server: Apache XML-RPC 1.0\r\n");    protected static final byte[] wwwAuthenticate =        toHTTPBytes("WWW-Authenticate: Basic realm=XML-RPC\r\n");    private static final String HTTP_11 = "HTTP/1.1";    private static final String STAR = "*";    /**     * This <em>can</em> be called from command line, but you'll have to edit     * and recompile to change the server port or handler objects. By default,     * it sets up the following responders:     * <ul>     *   <li> A java.lang.String object </li>     *   <li> The java.lang.Math class (making its static methods callable via     *        XML-RPC) </li>     *   <li> An Echo handler that returns the argument array </li>     * </ul>     *     * @see #addDefaultHandlers()     */    public static void main(String[] argv)    {        int p = determinePort(argv, 8080);        // XmlRpc.setDebug (true);        XmlRpc.setKeepAlive(true);        WebServer webserver = new WebServer(p);        try        {            webserver.addDefaultHandlers();            webserver.start();        }        catch (Exception e)        {            System.err.println("Error running web server");            e.printStackTrace();            System.exit(1);        }    }    /**     * Examines command line arguments from <code>argv</code>.  If a     * port may have been provided, parses that port (exiting with     * error status if the port cannot be parsed).  If no port is     * specified, defaults to <code>defaultPort</code>.     *     * @param defaultPort The port to use if none was specified.     */    protected static int determinePort(String[] argv, int defaultPort)    {        int port = defaultPort;        if (argv.length > 0)        {            try            {                port = Integer.parseInt(argv[0]);            }            catch (NumberFormatException nfx)            {                System.err.println("Error parsing port number: " + argv[0]);                System.err.println("Usage: java " + WebServer.class.getName()                                   + " [port]");                System.exit(1);            }        }        return port;    }    /**     * Creates a web server at the specified port number.     */    public WebServer(int port)    {        this(port, null);    }    /**     * Creates a web server at the specified port number and IP address.     */    public WebServer(int port, InetAddress addr)    {        this(port, addr, new XmlRpcServer());    }    /**     * Creates a web server at the specified port number and IP     * address.     */    public WebServer(int port, InetAddress addr, XmlRpcServer xmlrpc)    {        this.address = addr;        this.port = port;        this.xmlrpc = xmlrpc;        accept = new Vector();        deny = new Vector();        threadpool = new Stack();        runners = new ThreadGroup("XML-RPC Runner");    }    /**     * Returns the US-ASCII encoded byte representation of text for     * HTTP use (as per section 2.2 of RFC 2068).     */    protected static final byte[] toHTTPBytes(String text)    {        try        {            return text.getBytes("US-ASCII");        }        catch (UnsupportedEncodingException e)        {            throw new Error(e.getMessage() +                            ": HTTP requires US-ASCII encoding");        }    }    /**     * Factory method to manufacture the server socket.  Useful as a     * hook method for subclasses to override when they desire     * different flavor of socket (i.e. a <code>SSLServerSocket</code>).     *     * @param port     * @param backlog     * @param addr If <code>null</code>, binds to     * <code>INADDR_ANY</code>, meaning that all network interfaces on     * a multi-homed host will be listening.     * @exception Exception Error creating listener socket.     */    protected ServerSocket createServerSocket(int port, int backlog,            InetAddress addr)            throws Exception    {        return new ServerSocket(port, backlog, addr);    }    /**     * Initializes this server's listener socket with the specified     * attributes, assuring that a socket timeout has been set.  The     * {@link #createServerSocket(int, int, InetAddress)} method can     * be overridden to change the flavor of socket used.     *     * @see #createServerSocket(int, int, InetAddress)     */    private synchronized void setupServerSocket(int backlog)            throws Exception    {        // Since we can't reliably set SO_REUSEADDR until JDK 1.4 is        // the standard, try to (re-)open the server socket several        // times.  Some OSes (Linux and Solaris, for example), hold on        // to listener sockets for a brief period of time for security        // reasons before relinquishing their hold.        int attempt = 1;        while (serverSocket == null)        {            try            {                serverSocket = createServerSocket(port, backlog, address);            }            catch (BindException e)            {                if (attempt == 10)                {                    throw e;                }                attempt++;                Thread.sleep(1000);            }        }        if (XmlRpc.debug)        {            StringBuffer msg = new StringBuffer();            msg.append("Opened XML-RPC server socket for ");            msg.append(address != null ? address.getHostName() : "localhost");            msg.append(':').append(port);            if (attempt > 1)            {                msg.append(" after ").append(attempt).append(" tries");            }            System.out.println(msg.toString());        }        // A socket timeout must be set.        if (serverSocket.getSoTimeout() <= 0)        {            serverSocket.setSoTimeout(4096);        }    }    /**     * Spawns a new thread which binds this server to the port it's     * configured to accept connections on.     *     * @see #run()     */    public void start()    {        try        {            setupServerSocket(50);        }        catch (Exception e)        {            listener = null;            e.printStackTrace();            throw new RuntimeException(e.getMessage());        }        // The listener reference is released upon shutdown().        if (listener == null)        {            listener = new Thread(this, "XML-RPC Weblistener");            // Not marked as daemon thread since run directly via main().            listener.start();        }    }    /**     * Register a handler object with this name. Methods of this objects will be     * callable over XML-RPC as "name.method".     */    public void addHandler(String name, Object target)    {        xmlrpc.addHandler(name, target);    }    /**     * Adds the bundled handlers to the server.  Called by {@link     * #main(String[])}.     */    protected void addDefaultHandlers()        throws Exception    {        // webserver.setParanoid (true);        // webserver.acceptClient ("192.168.*.*");        addHandler("string", "Welcome to XML-RPC!");        addHandler("math", Math.class);        addHandler("auth", new AuthDemo());        addHandler("$default", new Echo());        // XmlRpcClients can be used as Proxies in XmlRpcServers which is a        // cool feature for applets.        String url = "http://www.mailtothefuture.com:80/RPC2";        addHandler("mttf", new XmlRpcClient(url));        SystemHandler system = new SystemHandler();        system.addDefaultSystemHandlers();        addHandler("system", system);    }    /**     * Remove a handler object that was previously registered with this server.     */    public void removeHandler(String name)    {        xmlrpc.removeHandler(name);    }    /**     * Switch client filtering on/off.     * @see #acceptClient(java.lang.String)     * @see #denyClient(java.lang.String)     */    public void setParanoid(boolean p)    {        paranoid = p;    }    /**     * Add an IP address to the list of accepted clients. The parameter can     * contain '*' as wildcard character, e.g. "192.168.*.*". You must call     * setParanoid(true) in order for this to have any effect.     *     * @see #denyClient(java.lang.String)     * @see #setParanoid(boolean)     */    public void acceptClient(String address) throws IllegalArgumentException    {        try        {            AddressMatcher m = new AddressMatcher(address);            accept.addElement(m);        }        catch (Exception x)        {            throw new IllegalArgumentException("\"" + address                    + "\" does not represent a valid IP address");        }    }    /**     * Add an IP address to the list of denied clients. The parameter can     * contain '*' as wildcard character, e.g. "192.168.*.*". You must call     * setParanoid(true) in order for this to have any effect.     *     * @see #acceptClient(java.lang.String)     * @see #setParanoid(boolean)     */    public void denyClient(String address) throws IllegalArgumentException    {        try        {            AddressMatcher m = new AddressMatcher(address);            deny.addElement(m);        }        catch (Exception x)        {            throw new IllegalArgumentException("\"" + address                    + "\" does not represent a valid IP address");        }    }    /**     * Checks incoming connections to see if they should be allowed.     * If not in paranoid mode, always returns true.     *     * @param s The socket to inspect.     * @return Whether the connection should be allowed.     */    protected boolean allowConnection(Socket s)    {        if (!paranoid)        {            return true;        }        int l = deny.size();        byte address[] = s.getInetAddress().getAddress();        for (int i = 0; i < l; i++)        {            AddressMatcher match = (AddressMatcher)deny.elementAt(i);            if (match.matches(address))            {                return false;            }        }        l = accept.size();        for (int i = 0; i < l; i++)        {            AddressMatcher match = (AddressMatcher)accept.elementAt(i);            if (match.matches(address))            {                return true;            }        }        return false;    }    /**     * DEPRECATED: Do not use this method, it will be removed soon.     * Use {@link #allowConnection(Socket)} instead.     *     * @deprecated Use allowConnection(Socket) instead.     * @see #allowConnection(Socket)     */    protected boolean checkSocket(Socket s)    {        return allowConnection(s);    }    /**     * Listens for client requests until stopped.  Call {@link     * #start()} to invoke this method, and {@link #shutdown()} to     * break out of it.     *     * @throws RuntimeException Generally caused by either an     * <code>UnknownHostException</code> or <code>BindException</code>     * with the vanilla web server.     *     * @see #start()     * @see #shutdown()     */    public void run()    {        try        {            while (listener != null)            {                try                {                    Socket socket = serverSocket.accept();                    try                    {                        socket.setTcpNoDelay(true);                    }                    catch (SocketException socketOptEx)                    {                        System.err.println(socketOptEx);                    }                    if (allowConnection(socket))                    {                        Runner runner = getRunner();                        runner.handle(socket);                    }                    else                    {                        socket.close();                    }                }                catch (InterruptedIOException checkState)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -