1 | // Copyright 2004-2007 Jean-Francois Poilpret |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package net.sourceforge.hiveboard.facade; |
16 | |
17 | import java.util.ArrayList; |
18 | import java.util.Date; |
19 | import java.util.HashSet; |
20 | import java.util.Iterator; |
21 | import java.util.List; |
22 | import java.util.Set; |
23 | |
24 | import org.apache.hivemind.Discardable; |
25 | |
26 | import net.sourceforge.hiveboard.Account; |
27 | import net.sourceforge.hiveboard.Board; |
28 | import net.sourceforge.hiveboard.Event; |
29 | import net.sourceforge.hiveboard.ServerSettings; |
30 | import net.sourceforge.hiveboard.Snapshot; |
31 | import net.sourceforge.hiveboard.WhiteBoardUserService; |
32 | import net.sourceforge.hiveboard.business.WhiteBoardManager; |
33 | import net.sourceforge.hiveboard.security.HiveBoardPrincipal; |
34 | import net.sourceforge.hiveevents.Channel; |
35 | import net.sourceforge.hiveevents.Filter; |
36 | import net.sourceforge.hivelock.SecurityService; |
37 | |
38 | public class WhiteBoardUserServiceImpl |
39 | implements WhiteBoardUserService, |
40 | Discardable |
41 | { |
42 | public WhiteBoardUserServiceImpl( SecurityService security, |
43 | WhiteBoardManager manager, |
44 | Channel<Event> channel, |
45 | long pullTimeout) |
46 | { |
47 | _manager = manager; |
48 | _security = security; |
49 | _channel = channel; |
50 | _pullTimeout = pullTimeout; |
51 | HiveBoardPrincipal user = (HiveBoardPrincipal) security.getCurrentUser(); |
52 | _idUser = user.getId(); |
53 | |
54 | // Listen to channel |
55 | _channel.block(); |
56 | |
57 | // Get all initial events (create accounts and create board) |
58 | List<Event> events = _manager.login(_idUser); |
59 | Iterator<Event> i = events.iterator(); |
60 | while (i.hasNext()) |
61 | { |
62 | if (!mustPassEvent(i.next())) |
63 | { |
64 | i.remove(); |
65 | } |
66 | } |
67 | _specificEvents.addAll(events); |
68 | |
69 | Filter<Event> filter = new Filter<Event>() |
70 | { |
71 | public boolean passEvent(Event event) |
72 | { |
73 | return mustPassEvent(event); |
74 | } |
75 | }; |
76 | _idConsumer = _channel.registerPullConsumer(filter); |
77 | _channel.unblock(); |
78 | } |
79 | |
80 | public void threadDidDiscardService() |
81 | { |
82 | _channel.unregisterConsumer(_idConsumer); |
83 | } |
84 | |
85 | protected boolean mustPassEvent(Event event) |
86 | { |
87 | if (mustPassAccountEvent(event)) |
88 | { |
89 | return true; |
90 | } |
91 | if (mustPassBoardManagementEvent(event)) |
92 | { |
93 | return true; |
94 | } |
95 | if (mustPassParticipantsManagementEvent(event)) |
96 | { |
97 | return true; |
98 | } |
99 | if (mustPassBoardLifeCycleEvent(event)) |
100 | { |
101 | return true; |
102 | } |
103 | if (mustPassBoardActionEvent(event)) |
104 | { |
105 | return true; |
106 | } |
107 | return false; |
108 | } |
109 | |
110 | protected boolean mustPassAccountEvent(Event event) |
111 | { |
112 | switch (event.getType()) |
113 | { |
114 | case EVT_LOGIN: |
115 | // Fall through |
116 | |
117 | case EVT_LOGOUT: |
118 | // Fall through |
119 | |
120 | case EVT_CREATE_ACCOUNT: |
121 | // Fall through |
122 | |
123 | case EVT_MODIFY_ACCOUNT: |
124 | // Fall through |
125 | |
126 | case EVT_DESTROY_ACCOUNT: |
127 | // These events are always forwarded to everybody |
128 | return true; |
129 | |
130 | default: |
131 | return false; |
132 | } |
133 | } |
134 | |
135 | protected boolean mustPassBoardManagementEvent(Event event) |
136 | { |
137 | Integer where = new Integer(event.getWhere()); |
138 | |
139 | switch (event.getType()) |
140 | { |
141 | case EVT_CREATE_BOARD: |
142 | // Forward only to board participants |
143 | if (event.getBoard().getParticipants().contains(_idUser)) |
144 | { |
145 | // Add this board to the list of user participated boards |
146 | _participateInBoards.add(where); |
147 | if (event.getBoard().getInitiator() == _idUser) |
148 | { |
149 | _initiatorOfBoards.add(where); |
150 | } |
151 | return true; |
152 | } |
153 | return false; |
154 | |
155 | case EVT_MODIFY_BOARD: |
156 | if (event.getBoard().getParticipants().contains(_idUser)) |
157 | { |
158 | // Forward to board participants (new or previous participants) |
159 | _participateInBoards.add(where); |
160 | if (event.getBoard().getInitiator() == _idUser) |
161 | { |
162 | _initiatorOfBoards.add(where); |
163 | } |
164 | else |
165 | { |
166 | _initiatorOfBoards.remove(where); |
167 | } |
168 | return true; |
169 | } |
170 | // Forward only if previously board participant |
171 | _presentInBoards.remove(where); |
172 | return _participateInBoards.remove(where); |
173 | |
174 | case EVT_DESTROY_BOARD: |
175 | // Forward only to board participants (and remove form participated boards) |
176 | _initiatorOfBoards.remove(where); |
177 | _presentInBoards.remove(where); |
178 | return _participateInBoards.remove(where); |
179 | |
180 | default: |
181 | return false; |
182 | } |
183 | } |
184 | |
185 | protected boolean mustPassParticipantsManagementEvent(Event event) |
186 | { |
187 | Integer where = new Integer(event.getWhere()); |
188 | |
189 | switch (event.getType()) |
190 | { |
191 | case EVT_BOARD_ADD_PARTICIPANT: |
192 | if (event.getWho() == _idUser) |
193 | { |
194 | // Add this board to the list of user participated boards |
195 | _participateInBoards.add(where); |
196 | return (event.getBoard() != null); |
197 | } |
198 | // Forward only to board participants |
199 | return ((event.getBoard() == null) && _participateInBoards.contains(where)); |
200 | |
201 | case EVT_BOARD_DEL_PARTICIPANT: |
202 | if (event.getWho() == _idUser) |
203 | { |
204 | // Remove this board from the list of user participated boards |
205 | _participateInBoards.remove(where); |
206 | _presentInBoards.remove(where); |
207 | return true; |
208 | } |
209 | // Forward only to board participants |
210 | return _participateInBoards.contains(where); |
211 | |
212 | default: |
213 | return false; |
214 | } |
215 | } |
216 | |
217 | protected boolean mustPassBoardLifeCycleEvent(Event event) |
218 | { |
219 | Integer where = new Integer(event.getWhere()); |
220 | |
221 | switch (event.getType()) |
222 | { |
223 | case EVT_JOIN_BOARD: |
224 | // Forward only to board participants |
225 | if (!_participateInBoards.contains(where)) |
226 | { |
227 | return false; |
228 | } |
229 | boolean hasRaster = (event.getRaster() != null); |
230 | if (event.getWho() == _idUser) |
231 | { |
232 | _presentInBoards.add(where); |
233 | // Only let pass the one with non-null bulk |
234 | return hasRaster; |
235 | } |
236 | // Only let pass the one with null bulk |
237 | return !hasRaster; |
238 | |
239 | case EVT_LEAVE_BOARD: |
240 | // Forward only to board participants |
241 | if (!_participateInBoards.contains(where)) |
242 | { |
243 | return false; |
244 | } |
245 | if (event.getWho() == _idUser) |
246 | { |
247 | _presentInBoards.remove(where); |
248 | } |
249 | return true; |
250 | |
251 | default: |
252 | return false; |
253 | } |
254 | } |
255 | |
256 | protected boolean mustPassBoardActionEvent(Event event) |
257 | { |
258 | Integer where = new Integer(event.getWhere()); |
259 | |
260 | switch (event.getType()) |
261 | { |
262 | case EVT_GIVE_TOKEN: |
263 | // Forward only to board participants |
264 | return _participateInBoards.contains(where); |
265 | |
266 | case EVT_SEND_DRAWING: |
267 | // Fall through |
268 | |
269 | case EVT_SEND_COMMENT: |
270 | // Check that current user is inside board |
271 | return _presentInBoards.contains(where); |
272 | |
273 | case EVT_REQUEST_TOKEN: |
274 | // Check that current user is inside board (or is the initiator of that board) |
275 | return _presentInBoards.contains(where) |
276 | || _initiatorOfBoards.contains(where); |
277 | |
278 | default: |
279 | return false; |
280 | } |
281 | } |
282 | |
283 | // Current Account management |
284 | public Account getSelfAccount() |
285 | { |
286 | return _manager.getAccount(_idUser); |
287 | } |
288 | |
289 | public ServerSettings getServerSettings() |
290 | { |
291 | return _manager.getServerSettings(_idUser); |
292 | } |
293 | |
294 | public void logout() |
295 | { |
296 | _channel.unblockPullConsumer(_idConsumer); |
297 | _security.logout(); |
298 | } |
299 | |
300 | public void changePassword(String password) |
301 | { |
302 | _manager.changePassword(_idUser, password); |
303 | } |
304 | |
305 | public void join(int board) |
306 | { |
307 | _manager.join(_idUser, board); |
308 | } |
309 | |
310 | public void comment(int board, String comment) |
311 | { |
312 | _manager.comment(_idUser, board, comment); |
313 | } |
314 | |
315 | public void draw(int board, byte[] drawing) |
316 | { |
317 | _manager.draw(_idUser, board, drawing); |
318 | } |
319 | |
320 | public void requestToken(int board) |
321 | { |
322 | _manager.requestToken(_idUser, board); |
323 | } |
324 | |
325 | public void leave(int board) |
326 | { |
327 | _manager.leave(_idUser, board); |
328 | } |
329 | |
330 | public void takeSnapshot(int board) |
331 | { |
332 | _manager.takeSnapshot(_idUser, board); |
333 | } |
334 | |
335 | public void giveToken(int board, int account) |
336 | { |
337 | _manager.giveToken(_idUser, board, account); |
338 | } |
339 | |
340 | public void addParticipant(int board, int account) |
341 | { |
342 | _manager.addParticipant(_idUser, board, account); |
343 | } |
344 | |
345 | public void removeParticipant(int board, int account) |
346 | { |
347 | _manager.removeParticipant(_idUser, board, account); |
348 | } |
349 | |
350 | public void createBoard(Board board) |
351 | { |
352 | _manager.createBoard(_idUser, board); |
353 | } |
354 | |
355 | public void modifyBoard(Board board) |
356 | { |
357 | _manager.modifyBoard(_idUser, board); |
358 | } |
359 | |
360 | public void closeBoard(int board) |
361 | { |
362 | _manager.closeBoard(_idUser, board); |
363 | } |
364 | |
365 | // Events pulling from server |
366 | public Event[] pull() |
367 | { |
368 | Event[] events = getSpecificEvents(); |
369 | if (events != null) |
370 | { |
371 | return events; |
372 | } |
373 | else |
374 | { |
375 | return _channel.pull(_idConsumer, _pullTimeout); |
376 | } |
377 | } |
378 | |
379 | public void createAccount(Account account) |
380 | { |
381 | _manager.createAccount(_idUser, account); |
382 | } |
383 | |
384 | public void modifyAccount(Account account) |
385 | { |
386 | _manager.modifyAccount(_idUser, account); |
387 | } |
388 | |
389 | public void changeAccountPassword(int id, String password) |
390 | { |
391 | _manager.changeAccountPassword(_idUser, id, password); |
392 | } |
393 | |
394 | public void removeAccount(int idAccount) |
395 | { |
396 | _manager.removeAccount(_idUser, idAccount); |
397 | } |
398 | |
399 | public Event[] getBoardComments(int board, Date after, Date until) |
400 | { |
401 | List<Event> events = _manager.getBoardComments(_idUser, board, after, until); |
402 | return events.toArray(new Event[events.size()]); |
403 | } |
404 | |
405 | public Snapshot[] getSnapshots(int board) |
406 | { |
407 | List<Snapshot> snapshots = _manager.getSnapshots(_idUser, board); |
408 | return snapshots.toArray(new Snapshot[snapshots.size()]); |
409 | } |
410 | |
411 | public byte[] getSnapshot(int idSnapshot) |
412 | { |
413 | return _manager.getSnapshot(_idUser, idSnapshot); |
414 | } |
415 | |
416 | protected Event[] getSpecificEvents() |
417 | { |
418 | synchronized (_specificEvents) |
419 | { |
420 | if (_specificEvents.isEmpty()) |
421 | { |
422 | return null; |
423 | } |
424 | |
425 | Event[] events = _specificEvents.toArray(new Event[_specificEvents.size()]); |
426 | _specificEvents.clear(); |
427 | return events; |
428 | } |
429 | } |
430 | |
431 | private final WhiteBoardManager _manager; |
432 | private final SecurityService _security; |
433 | private final Channel<Event> _channel; |
434 | private final int _idConsumer; |
435 | private final long _pullTimeout; |
436 | private final int _idUser; |
437 | private final Set<Integer> _presentInBoards = new HashSet<Integer>(); |
438 | private final Set<Integer> _participateInBoards = new HashSet<Integer>(); |
439 | private final Set<Integer> _initiatorOfBoards = new HashSet<Integer>(); |
440 | private final List<Event> _specificEvents = new ArrayList<Event>(); |
441 | } |