WebServer.java
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one
00003  * or more contributor license agreements.  See the NOTICE file
00004  * distributed with this work for additional information
00005  * regarding copyright ownership.  The ASF licenses this file
00006  * to you under the Apache License, Version 2.0 (the
00007  * "License"); you may not use this file except in compliance
00008  * with the License.  You may obtain a copy of the License at
00009  *
00010  *   http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing,
00013  * software distributed under the License is distributed on an
00014  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00015  * KIND, either express or implied.  See the License for the
00016  * specific language governing permissions and limitations
00017  * under the License.    
00018  */
00019 package org.apache.xmlrpc.webserver;
00020 
00021 import java.io.IOException;
00022 import java.io.InterruptedIOException;
00023 import java.net.BindException;
00024 import java.net.InetAddress;
00025 import java.net.ServerSocket;
00026 import java.net.Socket;
00027 import java.net.SocketException;
00028 import java.util.ArrayList;
00029 import java.util.List;
00030 import java.util.StringTokenizer;
00031 
00032 import org.apache.xmlrpc.server.XmlRpcStreamServer;
00033 import org.apache.xmlrpc.util.ThreadPool;
00034 
00035 
00072 public class WebServer implements Runnable {
00073         private class AddressMatcher {
00074                 private final int pattern[];
00075                 
00076                 AddressMatcher(String pAddress) {
00077                         try {
00078                                 pattern = new int[4];
00079                                 StringTokenizer st = new StringTokenizer(pAddress, ".");
00080                                 if (st.countTokens() != 4) {
00081                                         throw new IllegalArgumentException();
00082                                 }
00083                                 for (int i = 0; i < 4; i++)     {
00084                                         String next = st.nextToken();
00085                                         if ("*".equals(next)) {
00086                                                 pattern[i] = 256;
00087                                         } else {
00088                                             /* Note: *Not* pattern[i] = Integer.parseInt(next);
00089                                              * See XMLRPC-145
00090                                              */
00091                                                 pattern[i] = (byte) Integer.parseInt(next);
00092                                         }
00093                                 }
00094                         } catch (Exception e) {
00095                                 throw new IllegalArgumentException("\"" + pAddress
00096                                                 + "\" does not represent a valid IP address");
00097                         }
00098                 }
00099                 
00100                 boolean matches(byte[] pAddress) {
00101                         for (int i = 0; i < 4; i++)     {
00102                                 if (pattern[i] > 255) {
00103                                         continue; // Wildcard
00104                                 }
00105                                 if (pattern[i] != pAddress[i]) {
00106                                         return false;
00107                                 }
00108                         }
00109                         return true;
00110                 }
00111         }
00112 
00113         protected ServerSocket serverSocket;
00114         private Thread listener;
00115         private ThreadPool pool;
00116         protected final List accept = new ArrayList();
00117         protected final List deny = new ArrayList();
00118         protected final XmlRpcStreamServer server = newXmlRpcStreamServer();
00119 
00120         protected XmlRpcStreamServer newXmlRpcStreamServer(){
00121                 return new ConnectionServer();
00122         }
00123 
00124         // Inputs to setupServerSocket()
00125         private InetAddress address;
00126         private int port;
00127         
00128         private boolean paranoid;
00129         
00130         static final String HTTP_11 = "HTTP/1.1";
00135         public WebServer(int pPort) {
00136                 this(pPort, null);
00137         }
00138         
00144         public WebServer(int pPort, InetAddress pAddr) {
00145                 address = pAddr;
00146                 port = pPort;
00147         }
00148         
00162         protected ServerSocket createServerSocket(int pPort, int backlog, InetAddress addr)
00163                         throws IOException {
00164                 return new ServerSocket(pPort, backlog, addr);
00165         }
00166         
00175         private synchronized void setupServerSocket(int backlog) throws IOException {
00176                 // Since we can't reliably set SO_REUSEADDR until JDK 1.4 is
00177                 // the standard, try to (re-)open the server socket several
00178                 // times.  Some OSes (Linux and Solaris, for example), hold on
00179                 // to listener sockets for a brief period of time for security
00180                 // reasons before relinquishing their hold.
00181                 for (int i = 1;  ;  i++) {
00182                         try {
00183                                 serverSocket = createServerSocket(port, backlog, address);
00184                                 // A socket timeout must be set.
00185                                 if (serverSocket.getSoTimeout() <= 0) {
00186                                         serverSocket.setSoTimeout(4096);
00187                                 }
00188                                 return;
00189                         } catch (BindException e) {
00190                                 if (i == 10) {
00191                                         throw e;
00192                                 } else {
00193                                         long waitUntil = System.currentTimeMillis() + 1000;
00194                                         for (;;) {
00195                                                 long l = waitUntil - System.currentTimeMillis();
00196                                                 if (l > 0) {
00197                                                         try {
00198                                                                 Thread.sleep(l);
00199                                                         } catch (InterruptedException ex) {
00200                                                         }
00201                                                 } else {
00202                                                     break;
00203                         }
00204                                         }
00205                                 }
00206                         }
00207                 }
00208         }
00209         
00217         public void start() throws IOException {
00218                 setupServerSocket(50);
00219                 
00220                 // The listener reference is released upon shutdown().
00221                 if (listener == null) {
00222                         listener = new Thread(this, "XML-RPC Weblistener");
00223                         // Not marked as daemon thread since run directly via main().
00224                         listener.start();
00225                 }
00226         }
00227         
00234         public void setParanoid(boolean pParanoid) {
00235                 paranoid = pParanoid;
00236         }
00237 
00244         protected boolean isParanoid() {
00245                 return paranoid;
00246         }
00247         
00256         public void acceptClient(String pAddress) {
00257                 accept.add(new AddressMatcher(pAddress));
00258         }
00259         
00269         public void denyClient(String pAddress) {
00270                 deny.add(new AddressMatcher(pAddress));
00271         }
00272         
00280         protected boolean allowConnection(Socket s) {
00281                 if (!paranoid) {
00282                         return true;
00283                 }
00284                 
00285                 int l = deny.size();
00286                 byte addr[] = s.getInetAddress().getAddress();
00287                 for (int i = 0; i < l; i++) {
00288                         AddressMatcher match = (AddressMatcher) deny.get(i);
00289                         if (match.matches(addr))
00290                         {
00291                                 return false;
00292                         }
00293                 }
00294                 l = accept.size();
00295                 for (int i = 0; i < l; i++) {
00296                         AddressMatcher match = (AddressMatcher) accept.get(i);
00297                         if (match.matches(addr)) {
00298                                 return true;
00299                         }
00300                 }
00301                 return false;
00302         }
00303 
00304         protected ThreadPool.Task newTask(WebServer pServer, XmlRpcStreamServer pXmlRpcServer,
00305                                                                           Socket pSocket) throws IOException {
00306                 return new Connection(pServer, pXmlRpcServer, pSocket);
00307         }
00308 
00321         public void run() {
00322                 pool = newThreadPool();
00323                 try {
00324                         while (listener != null) {
00325                                 try {
00326                                         Socket socket = serverSocket.accept();
00327                                         try {
00328                                                 socket.setTcpNoDelay(true);
00329                                         } catch (SocketException socketOptEx) {
00330                                                 log(socketOptEx);
00331                                         }
00332                                         
00333                                         try {
00334                                                 if (allowConnection(socket)) {
00335                                                 // set read timeout to 30 seconds
00336                                                 socket.setSoTimeout(30000);
00337                                                         final ThreadPool.Task task = newTask(this, server, socket);
00338                                                         if (pool.startTask(task)) {
00339                                                                 socket = null;
00340                                                         } else {
00341                                                                 log("Maximum load of " + pool.getMaxThreads()
00342                                                                         + " exceeded, rejecting client");
00343                                                         }
00344                                                 }
00345                                         } finally {
00346                                                 if (socket != null) { try { socket.close(); } catch (Throwable ignore) {} }
00347                                         }
00348                                 } catch (InterruptedIOException checkState) {
00349                                         // Timeout while waiting for a client (from
00350                                         // SO_TIMEOUT)...try again if still listening.
00351                                 } catch (Throwable t) {
00352                                         log(t);
00353                                 }
00354                         }
00355                 } finally {
00356                         if (serverSocket != null) {
00357                                 try {
00358                                         serverSocket.close();
00359                                 } catch (IOException e) {
00360                                         log(e);
00361                                 }
00362                         }
00363                         
00364                         // Shutdown our Runner-based threads
00365                         pool.shutdown();
00366                 }
00367         }
00368 
00369     protected ThreadPool newThreadPool() {
00370         return new ThreadPool(server.getMaxThreads(), "XML-RPC");
00371     }
00372         
00380         public synchronized void shutdown() {
00381                 // Stop accepting client connections
00382                 if (listener != null) {
00383                         Thread l = listener;
00384                         listener = null;
00385                         l.interrupt();
00386             if (pool != null) {
00387                 pool.shutdown();
00388             }
00389                 }
00390         }
00391         
00396         public int getPort() { return serverSocket.getLocalPort(); }
00397 
00401         public void log(Throwable pError) {
00402             final String msg = pError.getMessage() == null ? pError.getClass().getName() : pError.getMessage();
00403             server.getErrorLogger().log(msg, pError);
00404         }
00405 
00409         public void log(String pMessage) {
00410         server.getErrorLogger().log(pMessage);
00411         }
00412 
00416         public XmlRpcStreamServer getXmlRpcServer() {
00417                 return server;
00418         }
00419 }


rosjava_core
Author(s):
autogenerated on Wed Aug 26 2015 16:06:49