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
54
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 }