1 25 26 29 package net.killingar.forum.internal.caches; 30 31 import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap; 32 import it.unimi.dsi.fastutil.longs.LongIterator; 33 import net.killingar.forum.internal.Group; 34 import net.killingar.forum.internal.User; 35 import net.killingar.forum.internal.managers.AbstractManager; 36 import net.killingar.forum.internal.managers.ForumManager; 37 38 import java.sql.*; 39 import java.util.*; 40 41 public class GroupMembershipsCache 42 { 43 protected Timestamp latestUpdate = new Timestamp(0); 44 45 protected Long2ObjectAVLTreeMap userToGroups = new Long2ObjectAVLTreeMap(); 47 protected Long2ObjectAVLTreeMap groupToUsers = new Long2ObjectAVLTreeMap(); 49 50 protected UsersCache usersCache; 51 protected GroupsCache groupsCache; 52 53 public GroupMembershipsCache(UsersCache inUsersCache, GroupsCache inGroupsCache) 54 { 55 usersCache = inUsersCache; 56 groupsCache = inGroupsCache; 57 } 58 59 public void update() throws SQLException 60 { 61 update(false); 62 } 63 64 public synchronized void update(boolean hardUpdate) throws SQLException 65 { 66 if (!hardUpdate && System.currentTimeMillis()-latestUpdate.getTime() < 1500) 67 return; 68 69 Timestamp now = new Timestamp(System.currentTimeMillis()-1001); 70 71 Connection c = null; 72 PreparedStatement statement = null; 73 ResultSet result = null; 74 75 try 76 { 77 c = AbstractManager.getNewConnection(); 78 statement = c.prepareStatement("select Parent, User, Deleted from GroupMemberships where LastChanged > ?"); 79 80 statement.setTimestamp(1, latestUpdate); 81 82 result = statement.executeQuery(); 83 while (result.next()) 84 { 85 long groupKey = result.getLong(1); 86 long userKey = result.getLong(2); 87 boolean deleted = result.getBoolean(3); 88 89 if (deleted) 91 { 92 removeSafe(userToGroups, userKey, groupKey); 93 removeSafe(groupToUsers, groupKey, userKey); 94 } 95 else 96 { 97 Long2ObjectAVLTreeMap userEntry = getEntryAlways(userToGroups, userKey); 98 Long2ObjectAVLTreeMap groupEntry = getEntryAlways(groupToUsers, groupKey); 99 100 userEntry.put(groupKey, groupsCache.getGroup(groupKey)); 101 groupEntry.put(userKey, usersCache.getUserItem(userKey)); 102 } 103 } 104 } 105 finally { AbstractManager.closeAll(c, statement, result); } 106 107 latestUpdate = now; 108 } 109 110 private synchronized Long2ObjectAVLTreeMap getEntryAlways(Long2ObjectAVLTreeMap map, long key) 111 { 112 Long2ObjectAVLTreeMap entry = (Long2ObjectAVLTreeMap)map.get(key); 113 if (entry == null) 114 { 115 entry = new Long2ObjectAVLTreeMap(); 116 map.put(key, entry); 117 } 118 119 return entry; 120 } 121 122 private synchronized void removeSafe(Long2ObjectAVLTreeMap map, long key, long removeKey) 123 { 124 Long2ObjectAVLTreeMap foo = (Long2ObjectAVLTreeMap)map.get(key); 125 if (foo != null) 126 foo.remove(removeKey); 127 } 128 129 public synchronized Group[] getGroupsOfUser(long userID) throws SQLException 130 { 131 Long2ObjectAVLTreeMap foo = (Long2ObjectAVLTreeMap)userToGroups.get(userID); 132 133 if (foo == null) 134 return new Group[0]; 135 136 Group[] r = (Group[])valuesToArray(foo, Group.class); 138 139 return r; 140 } 141 142 public synchronized User[] getUsersInGroup(ForumManager manager, long groupID) throws SQLException 143 { 144 Long2ObjectAVLTreeMap foo = (Long2ObjectAVLTreeMap)groupToUsers.get(groupID); 145 146 if (foo == null) 147 return new User[0]; 148 149 UserItem[] bar = (UserItem[])valuesToArray(foo, UserItem.class); 151 152 User[] r = new User[bar.length]; 153 for (int i = 0; i != r.length; i++) 154 r[i] = bar[i].getUser(manager); 155 156 return r; 157 } 158 159 private static Object valuesToArray(Map inMap, Class inClass) 160 { 161 Set s = inMap.entrySet(); 162 163 List l = new ArrayList(); 164 165 for (Iterator i = s.iterator(); i.hasNext();) 166 { 167 Map.Entry key = (Map.Entry)i.next(); 168 if (key.getValue() != null) 169 l.add(key.getValue()); 170 } 171 172 Object [] r = l.toArray((Object [])java.lang.reflect.Array.newInstance(inClass, l.size())); 173 Arrays.sort(r); 174 175 return r; 176 } 177 178 182 public synchronized boolean sharesGroup(long userID1, long userID2, String type) throws SQLException 183 { 184 if (userID1 == userID2) 185 return true; 186 187 update(); 188 189 Long2ObjectAVLTreeMap 190 groupsOf1 = (Long2ObjectAVLTreeMap)userToGroups.get(userID1), 191 groupsOf2 = (Long2ObjectAVLTreeMap)userToGroups.get(userID2); 192 193 if (groupsOf1 == null || groupsOf2 == null) 194 return false; 195 196 for (LongIterator i = (LongIterator)groupsOf1.keySet().iterator(); i.hasNext();) 197 { 198 long key = i.nextLong(); 199 200 Group g = (Group)groupsOf2.get(key); 201 202 if (g != null) 203 { 204 if (type == null || type.equalsIgnoreCase(g.getType())) 205 return true; 206 } 207 } 208 209 return false; 210 } 211 212 public synchronized boolean sharesGroup(long userID1, long userID2) throws SQLException 213 { 214 return sharesGroup(userID1, userID2, null); 215 } 216 217 public synchronized User[] getCommonGroupUsers(ForumManager manager, long userID) throws SQLException 218 { 219 update(); 220 221 Long2ObjectAVLTreeMap foo = new Long2ObjectAVLTreeMap(); 222 223 Long2ObjectAVLTreeMap groupsOfUser = (Long2ObjectAVLTreeMap)userToGroups.get(userID); 224 225 if (groupsOfUser == null) 226 return new User[0]; 227 228 for (LongIterator i = (LongIterator)groupsOfUser.keySet().iterator(); i.hasNext();) 229 { 230 long key = i.nextLong(); 231 232 Long2ObjectAVLTreeMap usersOfGroup = (Long2ObjectAVLTreeMap)groupToUsers.get(key); 233 234 for (Iterator j = usersOfGroup.entrySet().iterator(); j.hasNext();) 235 { 236 Map.Entry entry = (Map.Entry)j.next(); 237 foo.put(entry.getKey(), entry.getValue()); 238 } 239 } 240 241 UserItem[] bar = (UserItem[])valuesToArray(foo, UserItem.class); 243 244 User[] r = new User[bar.length]; 245 for (int i = 0; i != r.length; i++) 246 r[i] = bar[i].getUser(manager); 247 248 return r; 249 } 250 251 public synchronized long getUserAccess(long userID) throws SQLException 252 { 253 update(); 254 255 long access = 0; 256 257 Long2ObjectAVLTreeMap groupsOfUser = (Long2ObjectAVLTreeMap)userToGroups.get(userID); 258 259 if (groupsOfUser != null) 260 { 261 for (Iterator i = groupsOfUser.entrySet().iterator(); i.hasNext();) 262 { 263 Map.Entry entry = (Map.Entry)i.next(); 264 265 access |= ((Group)entry.getValue()).getAccess(); 266 } 267 } 268 return access; 269 } 270 271 public synchronized boolean isUserInGroup(long userID, long groupID) throws SQLException 272 { 273 update(); 274 275 return getEntryAlways(userToGroups, userID).containsKey(groupID); 276 } 277 } 278 | Popular Tags |