root/trunk/test/java/org/jcoderz/commons/connector/http/transport/SimpleServer.java

Revision 1375, 7.4 kB (checked in by amandel, 3 years ago)

Try to avoid that test hangs to long after an exception.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons.connector.http.transport;
34
35import java.net.ServerSocket;
36import java.net.Socket;
37import java.net.SocketTimeoutException;
38import java.util.HashMap;
39import java.util.Iterator;
40import java.util.Map;
41import java.util.logging.Level;
42import java.util.logging.Logger;
43
44/**
45 * This class defines a simple http server used for testing
46 * the HttpConnectionImpl based on the commons-httpclient lib.
47 */
48public class SimpleServer
49      extends Thread
50{
51   /** Class name used for logging. */
52   private static final String CLASSNAME
53         = SimpleServer.class.getName();
54   /** Logger in use. */
55   private static final Logger logger
56         = Logger.getLogger(CLASSNAME);
57   private static final int SOCKET_TIMEOUT = 10000;
58   private static final int JOIN_TIMEFRAME = 5000;
59   private static final int WAITING_LOOPS = 10;
60   /** Thread for stopping the server. */
61   private final Terminator mTerminator;
62   /** Flag indicating that the server have to be stopped. */
63   private boolean mDoStop = false;
64   /** Used for sychronize stopping the server. */
65   private final Object mMonitor = new Object();
66   /** Handler for client requests. */
67   private final Map mHandler = new HashMap();
68   /** Server port. */
69   private final int mPort;
70   /** Flag indicating if the server has been started. */
71   private volatile boolean mServerStarted = false;
72
73
74   /**
75    * Constructor.
76    * @param port
77    *          the server port in use
78    */
79   public SimpleServer (int port)
80   {
81      mPort = port;
82      mTerminator = new Terminator(this);
83   }
84
85   /**
86    * Main method. Starts a thread for terminating the server and starts
87    * a ClientHandler thread for every incomming request.
88    * @param args
89    *          args include the port number to use
90    */
91   public static void main (String[] args)
92   {
93      if (args.length != 1)
94      {
95         logger.info("Usage: SimpleServer <port>");
96         return;
97      }
98      final SimpleServer server = new SimpleServer(Integer.parseInt(args[0]));
99      server.startServer();
100      server.stopServer();
101   }
102
103   /**
104    * Starts the server thread.
105    */
106   public void run ()
107   {
108      startServer();
109      stopServer();
110   }
111
112   /**
113    * Creates a client socket for every incoming request and creates a
114    * ClientHandler thread to handle the request/response.
115    * Server will be stopped after a certain timeframe.
116    */
117   public void startServer ()
118   {
119      logger.info("Starting server..");
120      try
121      {
122         final ServerSocket s = new ServerSocket(mPort);
123         s.setSoTimeout(SOCKET_TIMEOUT);
124         int clientCounter = 0;
125         int waitingCounter = 0;
126         ClientHandler client = null;
127         logger.info("Waiting for connection on " + s);
128         while (!haveToStop() && waitingCounter < WAITING_LOOPS)
129         {
130            Socket incoming = null;
131            try
132            {
133               mServerStarted = true;
134               incoming = s.accept();
135            }
136            catch (SocketTimeoutException ste)
137            {
138               waitingCounter++;
139            }
140
141            if (incoming != null)
142            {
143               clientCounter++;
144               client = new ClientHandler(incoming, clientCounter);
145               mHandler.put(Integer.toString(clientCounter), client);
146               client.start();
147            }
148         }
149      }
150      catch (Exception e)
151      {
152         logger.log(Level.WARNING, "Failed to start SimpleServer: " + e, e);
153         e.printStackTrace();
154      }
155      // don't let others wait for ever.
156      mServerStarted = true;
157   }
158
159   /**
160    * Sets the flag for stopping the server.
161    */
162   public void doStop ()
163   {
164      synchronized (mMonitor)
165      {
166         mDoStop = true;
167      }
168   }
169
170   /**
171    * Checks the flag for stopping the server.
172    * @return boolean
173    *          the flag for stopping the server
174    */
175   public boolean haveToStop ()
176   {
177      synchronized (mMonitor)
178      {
179         return mDoStop;
180      }
181   }
182
183   /**
184    * Stops the client handler threads.
185    *
186    */
187   public void stopServer ()
188   {
189      logger.info("\n---Stopping Server with " + mHandler.size()
190            + " client handler---\n");
191      final Iterator it = mHandler.keySet().iterator();
192      while (it.hasNext())
193      {
194         try
195         {
196            final String clientId = (String) it.next();
197            final ClientHandler client = (ClientHandler) mHandler.get(clientId);
198            if (client != null)
199            {
200               client.haveToStop();
201               client.join(JOIN_TIMEFRAME);
202               if (client.isAlive())
203               {
204                  interruptClient(client);
205               }
206            }
207         }
208         catch (Exception ex)
209         {
210            // ignore
211         }
212      }
213      if (mTerminator != null && mTerminator.isAlive())
214      {
215         mTerminator.interrupt();
216      }
217
218      logger.warning("---Stopping DONE---");
219   }
220
221   /**
222    * Returns <tt>true</tt> if the server has been started.
223    * @return <tt>true</tt> if the server has been started;
224    *       <tt>false</tt> otherwise.
225    */
226   public boolean isServerStarted ()
227   {
228      return mServerStarted;
229   }
230   /**
231    * Interrupts the client handler thread.
232    * @param client
233    *          the thread to interrupt
234    * @throws InterruptedException
235    *          if interrupt fails
236    */
237   private void interruptClient (ClientHandler client)
238         throws InterruptedException
239   {
240      try
241      {
242         client.interrupt();
243         logger.info("Needed to interrupt client handler thread.");
244      }
245      catch (Exception ex)
246      {
247         logger.log(Level.WARNING,
248            "Exception while interrupting client handler thread: "
249            + ex.getMessage(), ex);
250      }
251      client.join(JOIN_TIMEFRAME);
252      if (client.isAlive())
253      {
254         logger.warning("unable to interrupt client thread");
255      }
256   }
257}
Note: See TracBrowser for help on using the browser.