diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsGroupSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsGroupSubject.java index da541a0d..05654173 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsGroupSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsGroupSubject.java @@ -80,7 +80,7 @@ public class LuckPermsGroupSubject extends LuckPermsSubject { } @Override - protected Tristate getPermissionValue(ContextSet contexts, String permission) { + public Tristate getPermissionValue(ContextSet contexts, String permission) { Map permissions = group.getAllNodesFiltered(service.calculateContexts(contexts)).stream() .map(LocalizedNode::getNode) .collect(Collectors.toMap(Node::getPermission, Node::getValue)); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java index a5f08027..9e4ac44f 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java @@ -34,11 +34,11 @@ import java.util.Set; public abstract class LuckPermsSubject implements Subject { - protected abstract Tristate getPermissionValue(ContextSet contexts, String permission); - protected abstract boolean isChildOf(ContextSet contexts, Subject parent); - protected abstract List getParents(ContextSet contexts); - protected abstract Optional getOption(ContextSet contexts, String s); - protected abstract ContextSet getActiveContextSet(); + public abstract Tristate getPermissionValue(ContextSet contexts, String permission); + public abstract boolean isChildOf(ContextSet contexts, Subject parent); + public abstract List getParents(ContextSet contexts); + public abstract Optional getOption(ContextSet contexts, String s); + public abstract ContextSet getActiveContextSet(); @Override @Deprecated diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsUserSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsUserSubject.java index f45175ae..a4d9a80a 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsUserSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsUserSubject.java @@ -97,19 +97,19 @@ public class LuckPermsUserSubject extends LuckPermsSubject { } @Override - protected Tristate getPermissionValue(ContextSet contexts, String permission) { + public Tristate getPermissionValue(ContextSet contexts, String permission) { return !hasData() ? Tristate.UNDEFINED : LuckPermsService.convertTristate(user.getUserData().getPermissionData(service.calculateContexts(contexts)).getPermissionValue(permission)); } @Override - protected boolean isChildOf(ContextSet contexts, Subject parent) { + public boolean isChildOf(ContextSet contexts, Subject parent) { return parent instanceof LuckPermsGroupSubject && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean(); } @Override - protected List getParents(ContextSet contexts) { + public List getParents(ContextSet contexts) { ImmutableList.Builder subjects = ImmutableList.builder(); if (hasData()) { @@ -132,7 +132,7 @@ public class LuckPermsUserSubject extends LuckPermsSubject { } @Override - protected Optional getOption(ContextSet contexts, String s) { + public Optional getOption(ContextSet contexts, String s) { if (hasData()) { MetaData data = user.getUserData().getMetaData(service.calculateContexts(contexts)); if (s.equalsIgnoreCase("prefix")) { @@ -161,7 +161,7 @@ public class LuckPermsUserSubject extends LuckPermsSubject { } @Override - protected ContextSet getActiveContextSet() { + public ContextSet getActiveContextSet() { return service.getPlugin().getContextManager().getApplicableContext(this); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/GroupCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/GroupCollection.java index 43ecca94..e9cae3c7 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/GroupCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/GroupCollection.java @@ -23,7 +23,9 @@ package me.lucko.luckperms.sponge.service.collections; import lombok.NonNull; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.groups.GroupManager; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.service.LuckPermsGroupSubject; import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.simple.SimpleCollection; @@ -72,7 +74,7 @@ public class GroupCollection implements SubjectCollection { public Iterable getAllSubjects() { return manager.getAll().values().stream() .map(u -> LuckPermsGroupSubject.wrapGroup(u, service)) - .collect(Collectors.toList()); + .collect(ImmutableCollectors.toImmutableList()); } @Override @@ -82,10 +84,11 @@ public class GroupCollection implements SubjectCollection { @Override public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { + ContextSet cs = LuckPermsService.convertContexts(contexts); return manager.getAll().values().stream() .map(u -> LuckPermsGroupSubject.wrapGroup(u, service)) - .filter(sub -> sub.getPermissionValue(contexts, node) != Tristate.UNDEFINED) - .collect(Collectors.toMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean())); + .filter(sub -> sub.getPermissionValue(cs, node) != Tristate.UNDEFINED) + .collect(Collectors.toMap(sub -> sub, sub -> sub.getPermissionValue(cs, node).asBoolean())); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/UserCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/UserCollection.java index bbb974af..fdd7d289 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/UserCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/collections/UserCollection.java @@ -22,11 +22,17 @@ package me.lucko.luckperms.sponge.service.collections; -import lombok.Getter; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import lombok.NonNull; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.commands.Util; import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.UserManager; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsUserSubject; import me.lucko.luckperms.sponge.service.simple.SimpleCollection; @@ -41,8 +47,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; +import java.util.concurrent.ExecutionException; /** * Manages low level Subject instances for the PermissionService. @@ -53,8 +58,30 @@ public class UserCollection implements SubjectCollection { private final UserManager manager; private final SimpleCollection fallback; - @Getter - private final Map users = new ConcurrentHashMap<>(); + private final LoadingCache users = CacheBuilder.newBuilder() + /* + .removalListener((RemovalListener) r -> { + if (r.getValue() != null) { + r.getValue().deprovision(); + } + }) + */ + .build(new CacheLoader() { + @Override + public LuckPermsUserSubject load(UUID uuid) throws Exception { + User user = manager.get(uuid); + if (user == null) { + throw new IllegalStateException("user not loaded"); + } + + return LuckPermsUserSubject.wrapUser(user, service); + } + + @Override + public ListenableFuture reload(UUID uuid, LuckPermsUserSubject s) { + return Futures.immediateFuture(s); // Never needs to be refreshed. + } + }); public UserCollection(LuckPermsService service, UserManager manager) { this.service = service; @@ -68,9 +95,7 @@ public class UserCollection implements SubjectCollection { } public void unload(UUID uuid) { - if (users.containsKey(uuid)) { - users.remove(uuid).deprovision(); - } + users.invalidate(uuid); } @Override @@ -89,7 +114,7 @@ public class UserCollection implements SubjectCollection { find: if (uuid == null) { - for (LuckPermsUserSubject subject : users.values()) { + for (LuckPermsUserSubject subject : users.asMap().values()) { if (subject.getUser().getName().equals(id)) { return Optional.of(subject); } @@ -103,22 +128,16 @@ public class UserCollection implements SubjectCollection { } } - if (uuid != null) { - UUID internal = service.getPlugin().getUuidCache().getUUID(uuid); - Subject s = users.computeIfAbsent(internal, u -> { - User user = manager.get(u); - if (user == null) return null; - - return LuckPermsUserSubject.wrapUser(user, service); - }); - - - if (s != null) { - return Optional.of(s); - } + if (uuid == null) { + return Optional.empty(); } - return Optional.empty(); + UUID internal = service.getPlugin().getUuidCache().getUUID(uuid); + try { + return Optional.of(users.get(internal)); + } catch (ExecutionException e) { + return Optional.empty(); + } } @Override @@ -128,7 +147,7 @@ public class UserCollection implements SubjectCollection { @Override public Iterable getAllSubjects() { - return users.values().stream().collect(Collectors.toList()); + return users.asMap().values().stream().collect(ImmutableCollectors.toImmutableList()); } @Override @@ -138,9 +157,10 @@ public class UserCollection implements SubjectCollection { @Override public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { - return users.values().stream() - .filter(sub -> sub.getPermissionValue(contexts, node) != Tristate.UNDEFINED) - .collect(Collectors.toMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean())); + ContextSet cs = LuckPermsService.convertContexts(contexts); + return users.asMap().values().stream() + .filter(sub -> sub.getPermissionValue(cs, node) != Tristate.UNDEFINED) + .collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(cs, node).asBoolean())); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java index 5ba9f9af..6e6d5407 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java @@ -25,9 +25,11 @@ package me.lucko.luckperms.sponge.service.persisted; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.service.LuckPermsService; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.Subject; @@ -35,10 +37,8 @@ import org.spongepowered.api.service.permission.SubjectCollection; import org.spongepowered.api.util.Tristate; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; /** * A simple persistable subject collection @@ -78,7 +78,7 @@ public class PersistedCollection implements SubjectCollection { @Override public Iterable getAllSubjects() { - return subjects.asMap().values().stream().map(s -> (Subject) s).collect(Collectors.toList()); + return subjects.asMap().values().stream().map(s -> (Subject) s).collect(ImmutableCollectors.toImmutableList()); } @Override @@ -88,7 +88,7 @@ public class PersistedCollection implements SubjectCollection { @Override public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { - Map m = new HashMap<>(); + ImmutableMap.Builder m = ImmutableMap.builder(); for (Subject subject : subjects.asMap().values()) { Tristate ts = subject.getPermissionValue(contexts, node); if (ts != Tristate.UNDEFINED) { @@ -96,7 +96,7 @@ public class PersistedCollection implements SubjectCollection { } } - return m; + return m.build(); } @Override