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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/**
* Copyright (C) 2004-2009 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.openfire.privacy;
import org.dom4j.Element;
import org.jivesoftware.util.cache.Cache;
import org.jivesoftware.util.cache.CacheFactory;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* A Privacy list manager creates, gets, updates and removes privacy lists. Loaded lists
* are kept in memory using a cache that will keep them at most for 6 hours.
*
* @author Gaston Dombiak
*/
public class PrivacyListManager {
private static final PrivacyListManager instance = new PrivacyListManager();
private static Cache<String, PrivacyList> listsCache;
private PrivacyListProvider provider = new PrivacyListProvider();
private List<PrivacyListEventListener> listeners = new CopyOnWriteArrayList<PrivacyListEventListener>();
static {
PrivacyListEventListener eventListener = new PrivacyListEventListener() {
public void privacyListCreated(PrivacyList list) {
// Do nothing
}
public void privacyListDeleting(String listName) {
// Do nothing
}
public void privacyListModified(PrivacyList list) {
// Set object again in cache. This is done so that other cluster nodes
// get refreshed with latest version of the object
listsCache.put(getCacheKey(list.getUserJID().getNode(), list.getName()), list);
}
};
instance.addListener(eventListener);
}
/**
* Returns the unique instance of this class.
*
* @return the unique instance of this class.
*/
public static PrivacyListManager getInstance() {
return instance;
}
private PrivacyListManager() {
// Create the cache of privacy lists
String cacheName = "Privacy Lists";
listsCache = CacheFactory.createCache(cacheName);
}
/**
* Creates a new privacy list for the specified user.
*
* @param username the username of the list owner.
* @param listName the name of the new privacy list.
* @param listElement the XML that specifies the list and its items.
* @return the newly created PrivacyList.
*/
public PrivacyList createPrivacyList(String username, String listName, Element listElement) {
// Create new list
PrivacyList list = new PrivacyList(username, listName, false, listElement);
// Add new list to cache
listsCache.put(getCacheKey(username, listName), list);
// Save new list to database
provider.createPrivacyList(username, list);
// Trigger event that a new privacy list has been created
for (PrivacyListEventListener listener : listeners) {
listener.privacyListCreated(list);
}
return list;
}
/**
* Deletes an existing privacy list of a user. If the privacy list being deleted was
* the default list then the user will end up with no default list. Therefore, the user
* will have to set a new default list.
*
* @param username the username of the list owner.
* @param listName the name of the list being deleted.
*/
public void deletePrivacyList(String username, String listName) {
// Trigger event that a privacy list is being deleted
for (PrivacyListEventListener listener : listeners) {
listener.privacyListDeleting(listName);
}
// Remove the list from the cache
listsCache.remove(getCacheKey(username, listName));
// Delete the privacy list from the DB
provider.deletePrivacyList(username, listName);
// Check if deleted list was the default list
PrivacyList defaultList = listsCache.get(getDefaultCacheKey(username));
if (defaultList != null && listName.equals(defaultList.getName())) {
listsCache.remove(getDefaultCacheKey(username));
}
}
/**
* Deletes all privacy lists of a user. This may be necessary when a user is being
* deleted from the system.
*
* @param username the username of the list owner.
*/
public void deletePrivacyLists(String username) {
for (String listName : provider.getPrivacyLists(username).keySet()) {
// Remove the list from the cache
listsCache.remove(getCacheKey(username, listName));
// Trigger event that a privacy list is being deleted
for (PrivacyListEventListener listener : listeners) {
listener.privacyListDeleting(listName);
}
}
// Delete user privacy lists from the DB
provider.deletePrivacyLists(username);
}
/**
* Returns the default privacy list of the specified user or <tt>null</tt> if
* none was found.
*
* @param username the name of the user to get his default list.
* @return the default privacy list of the specified user or <tt>null</tt> if
* none was found.
*/
public PrivacyList getDefaultPrivacyList(String username) {
// Check if we have the default list in the cache
String cacheKey = getDefaultCacheKey(username);
PrivacyList list = listsCache.get(cacheKey);
if (list == null) {
synchronized (username.intern()) {
list = listsCache.get(cacheKey);
if (list == null) {
// Load default list from the database
list = provider.loadDefaultPrivacyList(username);
if (list != null) {
listsCache.put(cacheKey, list);
}
}
}
}
return list;
}
/**
* Returns a specific privacy list of the specified user or <tt>null</tt> if
* none was found.
*
* @param username the name of the user to get his privacy list.
* @param listName the name of the list to get.
* @return a privacy list of the specified user or <tt>null</tt> if
* none was found.
*/
public PrivacyList getPrivacyList(String username, String listName) {
// Check if we have a list in the cache
String cacheKey = getCacheKey(username, listName);
PrivacyList list = listsCache.get(cacheKey);
if (list == null) {
// Load the list from the database
list = provider.loadPrivacyList(username, listName);
if (list != null) {
listsCache.put(cacheKey, list);
}
}
return list;
}
/**
* Sets a given privacy list as the new default list of the user.
*
* @param username the name of the user that is setting a new default list.
* @param newDefault the new default privacy list.
* @param oldDefault the previous privacy list or <tt>null</tt> if no default list existed.
*/
public void changeDefaultList(String username, PrivacyList newDefault, PrivacyList oldDefault) {
// TODO Analyze concurrency issues when other resource may log in while doing this change
if (oldDefault != null) {
// Update old default list to become just another list
oldDefault.setDefaultList(false);
provider.updatePrivacyList(username, oldDefault);
}
// Update new list to become the default
newDefault.setDefaultList(true);
// Set new default list in the cache
listsCache.put(getDefaultCacheKey(username), newDefault);
// Update both lists in the database
provider.updatePrivacyList(username, newDefault);
}
/**
* Registers a listener to receive events when a privacy list is created, updated or deleted.
*
* @param listener the listener.
*/
public void addListener(PrivacyListEventListener listener) {
if (listener == null) {
throw new NullPointerException();
}
listeners.add(listener);
}
/**
* Unregisters a listener to receive events.
*
* @param listener the listener.
*/
public void removeListener(PrivacyListEventListener listener) {
listeners.remove(listener);
}
/**
* Returns the key to use to locate a privacy list in the cache.
*/
private static String getCacheKey(String username, String listName) {
return username + listName;
}
/**
* Returns the key to use to locate default privacy lists in the cache.
*/
private static String getDefaultCacheKey(String username) {
return getCacheKey(username, "__d_e_f_a_u_l_t__");
}
void dispatchModifiedEvent(PrivacyList privacyList) {
// Trigger event that a privacy list has been modified
for (PrivacyListEventListener listener : listeners) {
listener.privacyListModified(privacyList);
}
}
}