Erori fixate, imbunatatiri threading, debug output optional.
[ChatApp.git] / ChatApp / appClient.java
blob173786da8638b1171499dead5dee8207c91020d4
1 /*
2 * © 2010 ROBO Design
3 * http://www.robodesign.ro
5 * $Date: 2010-05-19 18:42:42 +0300 $
6 */
8 package ChatApp;
10 import java.io.BufferedReader;
11 import java.io.InputStreamReader;
12 import java.io.PrintStream;
13 import java.net.Socket;
14 import java.net.UnknownHostException;
15 import javax.swing.DefaultListModel;
16 import javax.swing.SwingUtilities;
18 // clasa ce se ocupa de conectarea unui client la un server de chat.
20 public class appClient extends Thread {
21 private appMain myApp;
22 private volatile String serverAdresa;
23 private volatile int serverPort;
24 private volatile String numeUtilizator;
25 private volatile boolean serverConectat;
26 private Socket clientSocket;
27 private PrintStream clientOut;
28 private BufferedReader clientIn;
29 private DefaultListModel listaClienti;
31 // initializare clasa
32 public appClient (appMain rootApp) {
33 myApp = rootApp;
34 listaClienti = new DefaultListModel();
36 serverAdresa = "";
37 serverPort = 0;
38 numeUtilizator = "";
39 serverConectat = false;
41 clientSocket = null;
42 clientOut = null;
43 clientIn = null;
46 // conectare la server
47 public boolean conectare (String nume, String server, int port) {
48 if (serverConectat) {
49 if (server.equals(serverAdresa) && port == serverPort && nume.equals(numeUtilizator)) {
50 return true;
51 } else {
52 System.err.println("appClient.conectare: aplicatia este deja conectata la un alt server.");
53 return false;
55 } else if (clientSocket != null) {
56 System.err.println("appClient.conectare: aplicatia este intr-o stare invalida.");
57 return false;
60 // verificare nume
61 if (nume == null || nume.isEmpty() || nume.trim().isEmpty() || nume.indexOf(" ") != -1 || nume.equals("#server") || listaClienti.contains(nume)) {
62 System.err.println("appClient.conectare: numele dat este invalid. " + nume);
63 return false;
66 serverAdresa = server;
67 serverPort = port;
68 numeUtilizator = nume;
70 myApp.mesajDebug("appClient.conectare " + numeUtilizator + " " + serverAdresa + " " + serverPort);
72 // pornire conexiune socket
73 try {
74 clientSocket = new Socket(serverAdresa, serverPort);
75 clientOut = new PrintStream(clientSocket.getOutputStream(), true, "utf-8");
76 clientIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "utf-8"));
78 } catch (UnknownHostException ex) {
79 System.err.println("appClient.conectare: Serverul nu poate fi gasit: " + serverAdresa + ". " + ex);
80 ex.printStackTrace();
82 clientSocket = null;
83 clientOut = null;
84 clientIn = null;
86 return false;
88 } catch (Exception ex) {
89 System.err.println("appClient.conectare: Conectarea la server a esuat. " + ex);
90 ex.printStackTrace();
92 clientSocket = null;
93 clientOut = null;
94 clientIn = null;
96 return false;
99 serverConectat = true;
101 // pornire thread separat de monitorizare a socketului
102 start();
104 return true;
107 // metoda ce ruleaza constant intr-un thread separat, cat timp utilizatorul
108 // este conectat la server.
109 public void run () {
110 if (!serverConectat || clientIn == null || clientSocket == null || clientSocket.isClosed()) {
111 System.err.println("appClient.run: starea aplicatiei este invalida.");
112 serverConectat = false;
113 return;
116 myApp.mesajDebug("appClient.run start " + numeUtilizator);
118 try {
119 SwingUtilities.invokeAndWait(new Runnable () {
120 public void run () {
121 myApp.afisarePaginaChat();
124 } catch (Exception ex) {
125 System.err.println("appClient.run: afisarePaginaChat() a esuat. " + ex);
126 ex.printStackTrace();
127 serverConectat = false;
130 if (!trimiteComanda("/conectare " + numeUtilizator)) {
131 System.err.println("appClient.run: trimiteComanda('/conectare') a esuat. ");
132 serverConectat = false;
135 String cmd = null;
137 while (serverConectat && clientIn != null && clientSocket != null && !clientSocket.isClosed()) {
138 try {
139 cmd = clientIn.readLine();
140 } catch (Exception ex) {
141 System.err.println("appClient.run: clientIn.readLine a esuat. " + ex);
142 ex.printStackTrace();
143 break;
146 if (cmd == null || cmd.trim().isEmpty()) {
147 break;
150 procesareComanda(cmd);
151 cmd = null;
154 myApp.mesajDebug("appClient.run end " + numeUtilizator);
156 serverConectat = false;
158 try {
159 if (clientOut != null) {
160 clientOut.close();
162 if (clientIn != null) {
163 clientIn.close();
165 if (clientSocket != null && !clientSocket.isClosed()) {
166 clientSocket.close();
168 } catch (Exception ex) {
169 System.err.println("appClient.deconectare: inchidere socket esuata. " + ex);
170 ex.printStackTrace();
173 clientSocket = null;
174 clientOut = null;
175 clientIn = null;
177 if (!listaClienti.isEmpty()) {
178 listaClienti.clear();
181 SwingUtilities.invokeLater(new Runnable () {
182 public void run () {
183 myApp.deconectareClientCompleta();
188 // metoda ce permite trimiterea de comenzi de la client catre server.
189 private synchronized boolean trimiteComanda (String cmd) {
190 if (!serverConectat || clientSocket == null || clientSocket.isClosed() || clientOut == null || clientOut.checkError() || cmd == null || cmd.isEmpty()) {
191 System.err.println("appClient.trimiteComanda a esuat. Serverul nu este conectat, sau starea aplicatiei este invalida.");
192 return false;
195 myApp.mesajDebug("appClient.trimiteComanda " + cmd);
197 try {
198 clientOut.println(cmd);
199 } catch (Exception ex) {
200 System.err.println("appClient.trimiteComanda a esuat. " + ex);
201 ex.printStackTrace();
202 return false;
205 return !clientOut.checkError();
208 // metoda ce proceseaza comenzile primite de la server.
209 private boolean procesareComanda (String cmd) {
210 if (!serverConectat) {
211 System.err.println("appClient.procesareComanda: serverul nu este conectat.");
212 return false;
215 String[] arg = cmd.split(" ");
216 String fn = arg[0]; // functia, primul element
218 myApp.mesajDebug("appClient.procesareComanda " + fn + " cmd " + cmd);
220 if ("/conectare".equals(fn) && arg.length == 2) {
221 ev_conectareClient(arg[1]);
222 } else if ("/deconectare".equals(fn) && arg.length == 2) {
223 ev_deconectareClient(arg[1]);
224 } else if ("/conflict-nume".equals(fn) && arg.length == 1) {
225 ev_conflictNume();
226 } else if ("/mesaj".equals(fn) && arg.length > 2) {
227 ev_mesajPrimit(arg[1], arg[2], myApp.stringArrayJoin(arg, " ", 3));
228 } else if ("/nume".equals(fn) && arg.length == 3) {
229 ev_schimbareNume(arg[1], arg[2]);
230 } else if ("/lista".equals(fn) && arg.length > 1) {
231 ev_listaClienti(arg);
232 } else {
233 return false;
236 return true;
239 // metoda permite trimiterea de mesaje catre alti utilizatori, de la
240 // utilizatorul/clientul actual.
241 public boolean trimiteMesaj (String catre, String msg) {
242 if (!serverConectat || catre == null || catre.trim().isEmpty() || catre.indexOf(" ") != -1 || msg == null || msg.trim().isEmpty() || catre.equals(numeUtilizator) || (!catre.equals("#server") && !listaClienti.contains(catre))) {
243 System.err.println("appClient.trimiteMesaj: parametrii nu sunt validati.");
244 return false;
247 return trimiteComanda("/mesaj " + numeUtilizator + " " + catre + " " + msg);
250 // metoda permite clientului sa-si schimbe numele.
251 public boolean schimbareNume (String numeNou) {
252 if (!serverConectat || numeNou == null || numeNou.trim().isEmpty() || numeNou.indexOf(" ") != -1 || numeNou.equals("#server") || listaClienti.contains(numeNou)) {
253 System.err.println("appClient.schimbareNume: parametrii nu sunt validati.");
254 return false;
257 return trimiteComanda("/nume " + numeUtilizator + " " + numeNou);
260 // urmeaza cateva metode care sunt chemate in funcite de comenzile primite de
261 // la server.
263 private synchronized void ev_conectareClient (String nume) {
264 myApp.mesajDebug("appClient.ev_conectareClient " + nume);
266 if (nume.equals("#server")) {
267 System.err.println("appClient.ev_conectareClient numele este invalid: " + nume);
268 return;
271 if (!listaClienti.contains(nume)) {
272 listaClienti.addElement(nume);
273 myApp.ev_conectareClient(nume);
274 } else {
275 System.err.println("appClient.ev_conectareClient numele exista deja " + nume);
279 private synchronized void ev_deconectareClient (String nume) {
280 myApp.mesajDebug("appClient.ev_deconectareClient " + nume);
282 if (nume.equals("#server") || nume.equals(numeUtilizator)) {
283 deconectare();
284 myApp.ev_deconectareClient(nume);
285 } else if (listaClienti.contains(nume)) {
286 listaClienti.removeElement(nume);
287 myApp.ev_deconectareClient(nume);
288 } else {
289 System.err.println("appClient.ev_deconectareClient numele nu exista " + nume);
293 private void ev_conflictNume () {
294 String numeNou = myApp.ev_conflictNume();
295 if (numeNou == null || numeNou.trim().isEmpty() || numeNou.indexOf(" ") != -1 || numeNou.equals("#server")) {
296 myApp.deconectareGUI();
297 return;
300 numeUtilizator = numeNou;
301 trimiteComanda("/conectare " + numeNou);
304 private synchronized void ev_schimbareNume (String numeVechi, String numeNou) {
305 if (numeVechi.equals("#server") || numeNou.equals("#server")) {
306 return;
309 int i = listaClienti.indexOf(numeVechi);
310 if (i != -1) {
311 listaClienti.set(i, numeNou);
312 } else {
313 System.err.println("appClient.ev_schimbareNume numeVechi nu exista: " + numeVechi);
314 listaClienti.addElement(numeNou);
317 // schimbarea numelui, la clientul local
318 if (numeVechi.equals(numeUtilizator)) {
319 numeUtilizator = numeNou;
322 myApp.ev_schimbareNume(numeVechi, numeNou);
325 private synchronized void ev_listaClienti (String[] raw) {
326 myApp.mesajDebug("appClient.ev_listaClienti");
328 if (!raw[0].equals("/lista")) {
329 System.err.println("appClient.ev_listaClienti raw[0] != /lista");
330 return;
333 listaClienti.clear();
334 for (int i = 1; i < raw.length; i++) {
335 listaClienti.addElement(raw[i]);
338 myApp.ev_listaClienti();
341 private void ev_mesajPrimit (String dela, String catre, String msg) {
342 myApp.mesajDebug("appClient.ev_mesajPrimit dela " + dela + " catre " + catre);
344 if (dela.equals(catre) || dela.equals("#server")) {
345 System.err.println("appClient.ev_mesajPrimit eronat dela " + dela + " catre " + catre);
346 } else if (catre.equals("#server") || dela.equals(numeUtilizator) || catre.equals(numeUtilizator)) {
347 myApp.ev_mesajPrimit(dela, catre, msg);
348 } else {
349 System.err.println("appClient.ev_mesajPrimit eronat dela " + dela + " catre " + catre);
353 // metoda permite deconectarea de la server
354 public void deconectare () {
355 if (!serverConectat) {
356 return;
358 myApp.mesajDebug("appClient.deconectare " + numeUtilizator);
360 trimiteComanda("/deconectare " + numeUtilizator);
362 serverConectat = false;
363 if (!listaClienti.isEmpty()) {
364 listaClienti.clear();
368 public boolean getServerConectat () {
369 return serverConectat;
372 public String getServerAdresa () {
373 return serverAdresa;
376 public int getServerPort () {
377 return serverPort;
380 public String getNumeUtilizator () {
381 return numeUtilizator;
384 public DefaultListModel getListaClienti () {
385 return listaClienti;
389 // vim:set fo=wancroql tw=80 ts=2 sw=2 sts=2 sta et ai cin ff=unix: