1 package com.atlassian.user.impl.cache;
2
3 import com.atlassian.cache.Cache;
4 import com.atlassian.cache.CacheFactory;
5 import com.atlassian.user.Entity;
6 import com.atlassian.user.EntityException;
7 import com.atlassian.user.User;
8 import com.atlassian.user.UserManager;
9 import com.atlassian.user.impl.DefaultUser;
10 import com.atlassian.user.repository.RepositoryIdentifier;
11 import com.atlassian.user.search.page.Pager;
12 import com.atlassian.user.security.password.Credential;
13 import org.apache.log4j.Logger;
14
15 public class CachingUserManager implements UserManager
16 {
17 private static final Logger log = (Logger) Logger.getLogger(CachingUserManager.class);
18
19 private final UserManager underlyingUserManager;
20 private final CacheFactory cacheFactory;
21
22 private String userCacheName = null;
23 private String userROCacheName = null;
24 private String repositoryCacheName = null;
25
26 private static final String CACHE_SUFFIX_USERS = "users";
27 private static final String CACHE_SUFFIX_USERS_RO = "users_ro";
28 private static final String CACHE_SUFFIX_REPOSITORIES = "repository";
29
30 protected static User NULL_USER = new DefaultUser()
31 {
32 public String toString()
33 {
34 return "NULL USER";
35 }
36 };
37
38 public CachingUserManager(UserManager underlyingUserManager, CacheFactory cacheFactory)
39 {
40 this.underlyingUserManager = underlyingUserManager;
41 this.cacheFactory = cacheFactory;
42 }
43
44 public Pager<User> getUsers() throws EntityException
45 {
46 return underlyingUserManager.getUsers();
47 }
48
49 public Pager<String> getUserNames() throws EntityException
50 {
51 return underlyingUserManager.getUserNames();
52 }
53
54
55
56
57
58
59
60
61
62
63
64 public User getUser(String username) throws EntityException
65 {
66 User cachedUser = (User) getUserCache().get(username);
67 if (cachedUser != null)
68 {
69 return NULL_USER.equals(cachedUser) ? null : cachedUser;
70 }
71 else
72 {
73 User user = underlyingUserManager.getUser(username);
74 cacheUser(username, user);
75 return user;
76 }
77 }
78
79 private void cacheUser(String username, User user)
80 {
81 getUserCache().put(username, user == null ? NULL_USER : user);
82 }
83
84 private void cacheRepository(String username, RepositoryIdentifier repository)
85 {
86 getRepositoryCache().put(username, repository);
87 }
88
89 private void cacheUserROFlag(User user, boolean ro)
90 {
91 getUserROFlagCache().put(user.getName(), ro);
92 }
93
94 private Cache getUserCache()
95 {
96 synchronized(this)
97 {
98 if (userCacheName == null)
99 userCacheName = getCacheKey(CACHE_SUFFIX_USERS);
100 }
101 return cacheFactory.getCache(userCacheName);
102 }
103
104 private Cache getUserROFlagCache()
105 {
106 synchronized(this)
107 {
108 if (userROCacheName == null)
109 userROCacheName = getCacheKey(CACHE_SUFFIX_USERS_RO);
110 }
111 return cacheFactory.getCache(userROCacheName);
112 }
113
114 private Cache getRepositoryCache()
115 {
116 synchronized(this)
117 {
118 if (repositoryCacheName == null)
119 repositoryCacheName = getCacheKey(CACHE_SUFFIX_REPOSITORIES);
120 }
121 return cacheFactory.getCache(repositoryCacheName);
122 }
123
124 public User createUser(String username) throws EntityException
125 {
126 User user = underlyingUserManager.createUser(username);
127
128 if (user != null)
129 cacheUser(user.getName(), user);
130
131 return user;
132 }
133
134 public User createUser(User userTemplate, Credential credential) throws EntityException
135 {
136 User user = underlyingUserManager.createUser(userTemplate, credential);
137
138 if (user != null)
139 cacheUser(user.getName(), user);
140
141 return user;
142 }
143
144
145
146
147 public void alterPassword(User user, String plainTextPass) throws EntityException
148 {
149 underlyingUserManager.alterPassword(user, plainTextPass);
150 if (user != null)
151 cacheUser(user.getName(), underlyingUserManager.getUser(user.getName()));
152 }
153
154 public void saveUser(User user) throws EntityException
155 {
156 underlyingUserManager.saveUser(user);
157
158 if (user != null)
159 cacheUser(user.getName(), user);
160 }
161
162
163
164
165 public void removeUser(User user) throws EntityException
166 {
167 if (log.isDebugEnabled())
168 log.debug("removing user: " + user.getName());
169 underlyingUserManager.removeUser(user);
170 if (log.isDebugEnabled())
171 log.debug("user " + user.getName() + " removed from underlying user manager " + underlyingUserManager.getIdentifier().getName());
172
173 try
174 {
175 if (log.isDebugEnabled())
176 log.debug("removing user from cache: " + user.getName());
177 removeUserFromCache(user);
178 if (log.isDebugEnabled())
179 {
180 log.debug("removed user from cache: " + user.getName());
181
182
183 if (getUserCache().get(user.getName()) != null)
184 {
185 log.error("WTF???");
186 }
187 }
188 }
189 catch (Exception e)
190 {
191 throw new EntityException("User removed in underlying repository but could not remove from cache");
192 }
193 }
194
195 private void removeUserFromCache(User user)
196 {
197 if (user != null)
198 getUserCache().remove(user.getName());
199 }
200
201
202
203
204
205
206
207
208 public boolean isReadOnly(User user) throws EntityException
209 {
210 Boolean cachedROFlag = (Boolean) getUserROFlagCache().get(user.getName());
211
212 if (cachedROFlag == null)
213 {
214 boolean ro = underlyingUserManager.isReadOnly(user);
215 cacheUserROFlag(user, ro);
216 return ro;
217 }
218 else
219 {
220 return cachedROFlag;
221 }
222 }
223
224 public RepositoryIdentifier getIdentifier()
225 {
226 return underlyingUserManager.getIdentifier();
227 }
228
229
230
231
232 public RepositoryIdentifier getRepository(Entity entity) throws EntityException
233 {
234 RepositoryIdentifier cachedRepository = (RepositoryIdentifier) getRepositoryCache().get(entity.getName());
235 if (cachedRepository != null)
236 return cachedRepository;
237
238 RepositoryIdentifier repository = underlyingUserManager.getRepository(entity);
239 cacheRepository(entity.getName(), repository);
240 return repository;
241 }
242
243
244
245
246
247
248
249
250 public boolean isCreative()
251 {
252 return underlyingUserManager.isCreative();
253 }
254
255
256
257
258
259 private String getCacheKey(String cacheName)
260 {
261 String className = underlyingUserManager.getClass().getName();
262 String repositoryKey = underlyingUserManager.getIdentifier().getKey();
263 return className + "." + repositoryKey + "." + cacheName;
264 }
265
266 }