-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServerRemote.java
229 lines (187 loc) · 7.99 KB
/
ServerRemote.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Luca Lombardo, mat. 546688
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.rmi.ConnectException;
import java.rmi.RemoteException;
import java.rmi.server.RemoteObject;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ServerRemote extends RemoteObject implements ServerRemoteInterface {
private static final long serialVersionUID = 1L;
public ConcurrentHashMap<String, ClientRemoteInterface> clients; // Mappa che associa i nomi degli utenti alle rispettive ClientRemoteInterface
Object userSync; // Variabile per la sincronizzazione su utenti registrati e loggati
ArrayList<User> members; // Lista degli utenti registrati al servizio
ArrayList<User> loggedUsers; // Lista degli utenti loggati
// Costruttore
public ServerRemote(Object user, ArrayList<User> members, ArrayList<User> loggedUsers) throws RemoteException {
super();
this.userSync = user;
//clients = new ArrayList<ClientRemoteInterface>();
clients = new ConcurrentHashMap<String, ClientRemoteInterface>();
this.members = members;
this.loggedUsers = loggedUsers;
System.out.printf("%S REMOTE: creato ServerRemote.\n", Thread.currentThread().getName());
}
// Registrazione alla callback
public synchronized void registerForCallback (ClientRemoteInterface ClientInterface, String nickUtente) throws RemoteException {
if (!clients.containsKey(nickUtente)) {
clients.putIfAbsent(nickUtente, ClientInterface);
System.out.printf("%S REMOTE: client registrato alla callback.\n", Thread.currentThread().getName());
}
else {
System.err.printf("%S REMOTE: utente gia' presente!\n", Thread.currentThread().getName());
}
}
// Cancella registrazione alla callback
public synchronized void unregisterForCallback (ClientRemoteInterface ClientInterface, String nickUtente) throws RemoteException {
clients.remove(nickUtente);
}
// Chiama il metodo doCallbacks
public void update(ArrayList<User> members, ArrayList<User> loggedUsers) throws RemoteException {
AbstractMap.SimpleEntry<ArrayList<User>, ArrayList<User>> pair = new AbstractMap.SimpleEntry<ArrayList<User>, ArrayList<User>>(members, loggedUsers);
doCallbacks(pair);
}
// Manda callback a tutti i client registrati
public synchronized void doCallbacks(AbstractMap.SimpleEntry<ArrayList<User>, ArrayList<User>> pair) throws RemoteException {
System.out.printf("%S REMOTE: mando le callbacks.\n", Thread.currentThread().getName());
Iterator<String> i = clients.keySet().iterator();
ArrayList<String> remove = new ArrayList<String>();
while (i.hasNext()) {
String clientName = i.next();
ClientRemoteInterface client = (ClientRemoteInterface) clients.get(clientName);
try {
client.notifyEvent(pair); // Invoca il metodo remoto del client
} catch (ConnectException e) {
// Se un client ha chiuso la connessione senza prima fare il logout...
remove.add(clientName);
}
}
// ...eliminalo dalla lista dei client
for (String s : remove) {
clients.remove(s);
}
System.out.printf("%S REMOTE: callbacks completate.\n", Thread.currentThread().getName());
}
// Manda la callback all'utente che e' stato aggiunto a un progetto, se e' loggato
public synchronized void addMemberCallback(String nickUtente, String project, String ip) throws RemoteException {
boolean logged = false;
// Sincronizza l'accesso agli utenti registrati/loggati
synchronized(userSync) {
// Controlla che l'utente aggiunto al progetto sia loggato
for (User u : loggedUsers) {
if (u.getNickUtente().toLowerCase().equals(nickUtente.toLowerCase())) {
logged = true;
break;
}
}
}
// Fai la callback solo se l'utente aggiunto al progetto e' loggato
if (logged) {
for (String nick : clients.keySet()) {
if (nick.toLowerCase().equals(nickUtente.toLowerCase())) {
ClientRemoteInterface client = clients.get(nick);
try {
client.notifyProject(project, ip); // Invoca il metodo remoto del client
System.out.printf("%S REMOTE: mando la callback dell'addMember.\n", Thread.currentThread().getName());
} catch (ConnectException e) {
// Se un client ha chiuso la connessione senza prima fare il logout, eliminalo dalla lista dei client
clients.remove(nick);
}
break;
}
}
}
}
// Fai le callback a tutti gli utenti loggati che erano membri di un progetto appena cancellato
public synchronized void cancelProjectCallback(String projectName, Project p) throws RemoteException {
for (User u : p.getProjectMembers()) {
boolean logged = false;
// Sincronizza l'accesso agli utenti registrati/loggati
synchronized(userSync) {
for (User ul : loggedUsers) {
if (ul.getNickUtente().toLowerCase().equals(u.getNickUtente().toLowerCase())) {
logged = true;
break;
}
}
}
// Fai la callback solo se l'utente e' loggato
if (logged) {
for (String nick : clients.keySet()) {
if (nick.toLowerCase().equals(u.getNickUtente().toLowerCase())) {
ClientRemoteInterface client = clients.get(nick);
try {
client.notifyCancelProject(projectName);
System.out.printf("%S REMOTE: mando la callback della CancelProject all'utente %s.\n", Thread.currentThread().getName(), u.getNickUtente());
} catch (ConnectException e) {
// Se un client ha chiuso la connessione senza prima fare il logout, eliminalo dalla lista dei client
clients.remove(nick);
}
break;
}
}
}
}
}
// Operazione di registrazione
public int register(String nickUtente, String password) throws RemoteException {
ObjectMapper objectMapper = new ObjectMapper();
String fpath = "members.json";
File f = new File(fpath);
// Se la password inserita e' vuota, errore
if (password.equals("")) {
return 2;
}
// Sincronizza l'accesso agli utenti registrati/loggati
synchronized(userSync) {
Iterator<User> it = members.iterator();
// Controlla se esiste gia' un utente registrato con quel nickname
while (it.hasNext()) {
User u = it.next();
// Se esiste, ritorna un errore al client
if (u.getNickUtente().toLowerCase().equals(nickUtente.toLowerCase())) {
System.out.printf("%S REMOTE: Un client ha provato a registrarsi con un nick gia' presente.\n", Thread.currentThread().getName());
return 1;
}
}
User u = new User(nickUtente, password);
// Aggiungi il nuovo utente alla lista dei registrati
members.add(u);
FileOutputStream fos = null;
ByteBuffer buffer = null;
// Crea il nuovo file degli utenti registrati
try {
f.createNewFile();
fos = new FileOutputStream(f);
} catch (IOException e) {
System.err.printf("%S REMOTE: errore creazione file degli utenti registrati.\n", Thread.currentThread().getName());
e.printStackTrace();
}
FileChannel fc = fos.getChannel();
try {
buffer = ByteBuffer.wrap(objectMapper.writeValueAsBytes(members));
fc.write(buffer);
buffer.clear();
} catch (IOException e) {
System.err.printf("%S REMOTE: errore scrittura file degli utenti registrati.\n", Thread.currentThread().getName());
e.printStackTrace();
}
// Chiudi il FileOutputStream
try {
fos.close();
} catch (IOException e) {
System.err.printf("%S REMOTE: errore chiusura fos.\n", Thread.currentThread().getName());
e.printStackTrace();
}
System.out.printf("%S REMOTE: Un client si e' registrato con successo.\n", Thread.currentThread().getName());
update(members, loggedUsers); // Manda callback
}
return 0;
}
}