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