View Javadoc

1   package uba.db.sql.server;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.net.InetSocketAddress;
6   import java.net.ServerSocket;
7   import java.net.Socket;
8   import java.net.SocketException;
9   
10  import org.apache.commons.lang.exception.ExceptionUtils;
11  import org.apache.commons.logging.Log;
12  import org.apache.commons.logging.LogFactory;
13  
14  /***
15   * @version $Revision$
16   */
17  public class Server {
18      private static final Log log = LogFactory.getLog(Server.class);
19      private InetSocketAddress serverAddress;
20      private ServerProcessor serverProcessor;
21      private ServerSocket serverSocket;
22      private ServerState state;
23  
24      private static final String SERVER_THREAD_NAME = "UBADB Database Server Thread";
25  
26      public Server(InetSocketAddress serverAddress, File databaseDirectory) {
27          this.serverAddress = serverAddress;
28          serverProcessor = new ServerProcessor(databaseDirectory);
29          switchToStopped();
30      }
31  
32      public boolean isRunning() {
33          return state.isRunning();
34      }
35  
36      public synchronized void start() throws ServerStartUpException,
37              ServerAlreadyRunningException {
38          state.start();
39      }
40  
41      public synchronized void stop() throws ServerAlreadyStoppedException {
42          state.stop();
43      }
44  
45      private void acceptConnectionFromClient() {
46          try {
47              Socket clientSocket = serverSocket.accept();
48              log.info("Se establecio una conexión con: "
49                      + clientSocket.getRemoteSocketAddress());
50  
51              handleRequestFrom(clientSocket);
52          } catch (SocketException e) {
53              // cuando se cierra el server se hace un close que genera esta excepcion
54              // ese caso es normal, asi que no hay que mostrar ningun mensaje de error
55              if (!isRunning()) {
56                  log.error("Error en la conexion con el cliente", e);
57              }
58          } catch (IOException e) {
59              
60              log.error("No se pudo establecer la conexion con el cliente", e);
61          }
62      }
63  
64      private void closeServerSocket() {
65          log.debug("Cerrando el socket del servidor");
66  
67          try {
68              serverSocket.close();
69              log.debug("Socket del servidor cerrado correctamente");
70          } catch (Throwable t) {
71              log.error("No se pudo cerrar correctamente el socket del servidor", t);
72          }
73  
74          serverSocket = null;
75      }
76  
77      private void connectionAcceptLoop() {
78          while (isRunning()) {
79              acceptConnectionFromClient();
80          }
81      }
82  
83      private void createServerSocket() throws ServerStartUpException {
84          log.info("Creando el socket servidor en: " + serverAddress);
85  
86          try {
87              serverSocket = new ServerSocket();
88              serverSocket.bind(serverAddress);
89          } catch (IOException e) {
90              switchToStopped();
91              throw new ServerStartUpException(e);
92          }
93      }
94  
95      private void handleRequestFrom(Socket clientSocket) {
96          ClientRequestProcessor clientRequestProcessor = null;
97  
98          try {
99              clientRequestProcessor = new ClientRequestProcessor(new DBProtocol(
100                     serverProcessor), clientSocket.getInputStream(), clientSocket
101                     .getOutputStream());
102         } catch (IOException e) {
103             log.error("No se pudo obtener la entrada/salida con el cliente", e);
104             return;
105         }
106 
107         try {
108             clientRequestProcessor.handleRequests();
109         } catch (ClientResquestHandlingException e) {
110             log.error("Ocurrio un error al manejar los pedidos del cliente",
111                       ExceptionUtils.getCause(e));
112         }
113     }
114 
115     private void switchToRunning() {
116         state = new ServerRunning(this);
117     }
118 
119     private void switchToStopped() {
120         state = new ServerStopped(this);
121     }
122 
123     protected void startWhenStopped() throws ServerStartUpException {
124         switchToRunning();
125         createServerSocket();
126         Thread serverThread = new Thread(connectionAcceptRunnable(), SERVER_THREAD_NAME);
127         serverThread.start();
128     }
129 
130     private Runnable connectionAcceptRunnable() {
131         return new Runnable() {
132             public void run() {
133                 try {
134                     connectionAcceptLoop();
135                 } finally {
136                     log.info("Servidor finalizado");
137                 }
138             }
139         };
140     }
141 
142     protected synchronized void stopWhenRunning() {
143         log.info("Parando la ejecución del servidor");
144         switchToStopped();
145         closeServerSocket();
146         notifyAll();
147     }
148 }