Refactor permission processors, misc cleanup

This commit is contained in:
Luck 2018-02-04 18:39:34 +00:00
parent 31df29194b
commit fd937e3209
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
20 changed files with 151 additions and 107 deletions

View File

@ -28,17 +28,19 @@ package me.lucko.luckperms.bukkit.processors;
import com.google.common.collect.Maps;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.processors.AbstractPermissionProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Permission Processor for Bukkits "child" permission system.
*/
public class ChildProcessor implements PermissionProcessor {
public class ChildProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
private final ChildPermissionProvider provider;
private final Map<String, Boolean> childPermissions = new ConcurrentHashMap<>();
private Map<String, Boolean> childPermissions = Collections.emptyMap();
public ChildProcessor(ChildPermissionProvider provider) {
this.provider = provider;
@ -50,13 +52,14 @@ public class ChildProcessor implements PermissionProcessor {
}
@Override
public void updateBacking(Map<String, Boolean> map) {
this.childPermissions.clear();
for (Map.Entry<String, Boolean> e : map.entrySet()) {
public void refresh() {
Map<String, Boolean> builder = new ConcurrentHashMap<>();
for (Map.Entry<String, Boolean> e : this.sourceMap.entrySet()) {
Map<String, Boolean> children = this.provider.getPermissions().get(Maps.immutableEntry(e.getKey(), e.getValue()));
if (children != null) {
this.childPermissions.putAll(children);
builder.putAll(children);
}
}
this.childPermissions = builder;
}
}

View File

@ -31,8 +31,6 @@ import me.lucko.luckperms.common.processors.PermissionProcessor;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
import java.util.Map;
/**
* Permission Processor for Bukkits "default" permission system.
*/
@ -55,9 +53,4 @@ public class DefaultsProcessor implements PermissionProcessor {
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(this.isOp));
}
@Override
public void updateBacking(Map<String, Boolean> map) {
// Do nothing, this doesn't use the backing
}
}

View File

@ -72,7 +72,7 @@ public class PermissionCache implements PermissionData {
this.permissionsUnmodifiable = Collections.unmodifiableMap(this.permissions);
this.calculator = calculatorFactory.build(contexts, metadata);
this.calculator.updateBacking(this.permissions); // Initial setup.
this.calculator.setSourcePermissions(this.permissions); // Initial setup.
}
@Override
@ -83,7 +83,7 @@ public class PermissionCache implements PermissionData {
private void setPermissionsInternal(Map<String, Boolean> permissions) {
this.permissions.clear();
this.permissions.putAll(permissions);
this.calculator.updateBacking(this.permissions);
this.calculator.setSourcePermissions(this.permissions);
invalidateCache();
}

View File

@ -44,11 +44,25 @@ import javax.annotation.Nonnull;
* Calculates and caches permissions
*/
public class PermissionCalculator implements CacheLoader<String, Tristate> {
/**
* The plugin instance
*/
private final LuckPermsPlugin plugin;
/**
* Info about the nature of this calculator.
*/
private final PermissionCalculatorMetadata metadata;
/**
* The processors which back this calculator
*/
private final ImmutableList<PermissionProcessor> processors;
// caches lookup calls.
/**
* Loading cache for permission checks
*/
private final LoadingCache<String, Tristate> lookupCache = Caffeine.newBuilder().build(this);
public PermissionCalculator(LuckPermsPlugin plugin, PermissionCalculatorMetadata metadata, ImmutableList<PermissionProcessor> processors) {
@ -57,16 +71,16 @@ public class PermissionCalculator implements CacheLoader<String, Tristate> {
this.processors = processors;
}
public List<PermissionProcessor> getProcessors() {
return this.processors;
}
public void invalidateCache() {
this.lookupCache.invalidateAll();
}
/**
* Performs a permission check against this calculator.
*
* <p>The result is calculated using the calculators backing 'processors'.</p>
*
* @param permission the permission to check
* @param origin marks where this check originated from
* @return the result
*/
public Tristate getPermissionValue(String permission, CheckOrigin origin) {
// convert the permission to lowercase, as all values in the backing map are also lowercase.
// this allows fast case insensitive lookups
permission = permission.toLowerCase().intern();
@ -83,7 +97,6 @@ public class PermissionCalculator implements CacheLoader<String, Tristate> {
@Override
public Tristate load(@Nonnull String permission) {
// offer the permission to the permission vault
// we only need to do this once per permission, so it doesn't matter
// that this call is behind the cache.
@ -91,19 +104,32 @@ public class PermissionCalculator implements CacheLoader<String, Tristate> {
for (PermissionProcessor processor : this.processors) {
Tristate result = processor.hasPermission(permission);
if (result == Tristate.UNDEFINED) {
continue;
if (result != Tristate.UNDEFINED) {
return result;
}
return result;
}
return Tristate.UNDEFINED;
}
public synchronized void updateBacking(Map<String, Boolean> map) {
/**
* Defines the source permissions map which should be used when calculating
* a result.
*
* @param sourceMap the source map
*/
public synchronized void setSourcePermissions(Map<String, Boolean> sourceMap) {
for (PermissionProcessor processor : this.processors) {
processor.updateBacking(map);
processor.setSource(sourceMap);
processor.refresh();
}
}
public List<PermissionProcessor> getProcessors() {
return this.processors;
}
public void invalidateCache() {
this.lookupCache.invalidateAll();
}
}

View File

@ -28,6 +28,9 @@ package me.lucko.luckperms.common.calculators;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.references.HolderType;
/**
* Metadata about a given {@link PermissionCalculator}.
*/
public class PermissionCalculatorMetadata {
public static PermissionCalculatorMetadata of(HolderType holderType, String objectName, ContextSet context) {

View File

@ -43,20 +43,20 @@ public enum Dependency {
ASM(
"org.ow2.asm",
"asm",
"5.2",
"Pl6g19osUVXvT0cNkJLULeNOP1PbZYnHwH1nIa30uj4="
"6.0",
"3Ylxx0pOaXiZqOlcquTqh2DqbEhtxrl7F5XnV2BCBGE="
),
ASM_COMMONS(
"org.ow2.asm",
"asm-commons",
"5.2",
"zBMYiX4sdxy3l6aNX06mQcI6UfBDfKUXq+z5ZN2yZAs="
"6.0",
"8bzlxkipagF73NAf5dWa+YRSl/17ebgcAVpvu9lxmr8="
),
JAR_RELOCATOR(
"me.lucko",
"jar-relocator",
"1.2",
"ECR0wrAMwmM0dpmuY1ifCG+2rpObOIlSI127jBbSrbI="
"1.3",
"mmz3ltQbS8xXGA2scM0ZH6raISlt4nukjCiU2l9Jxfs="
),
CAFFEINE(

View File

@ -29,9 +29,10 @@ import java.util.Arrays;
import java.util.List;
public final class Relocation {
private static final String RELOCATION_PREFIX = "me.lucko.luckperms.lib.";
public static Relocation of(String id, String pattern) {
return new Relocation(pattern.replace("{}", "."), "me.lucko.luckperms.lib." + id);
return new Relocation(pattern.replace("{}", "."), RELOCATION_PREFIX + id);
}
public static List<Relocation> allOf(Relocation... relocations) {

View File

@ -43,6 +43,8 @@ import java.util.Set;
*/
public class RelocationHandler {
private static final Set<Dependency> DEPENDENCIES = EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR);
private static final String JAR_RELOCATOR_CLASS = "me.lucko.jarrelocator.JarRelocator";
private static final String JAR_RELOCATOR_RUN_METHOD = "run";
private final Constructor<?> jarRelocatorConstructor;
private final Method jarRelocatorRunMethod;
@ -55,13 +57,13 @@ public class RelocationHandler {
IsolatedClassLoader classLoader = dependencyManager.obtainClassLoaderWith(DEPENDENCIES);
// load the relocator class
Class<?> jarRelocatorClass = classLoader.loadClass("me.lucko.jarrelocator.JarRelocator");
Class<?> jarRelocatorClass = classLoader.loadClass(JAR_RELOCATOR_CLASS);
// prepare the the reflected constructor & method instances
this.jarRelocatorConstructor = jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class);
this.jarRelocatorConstructor.setAccessible(true);
this.jarRelocatorRunMethod = jarRelocatorClass.getDeclaredMethod("run");
this.jarRelocatorRunMethod = jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD);
this.jarRelocatorRunMethod.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);

View File

@ -51,7 +51,7 @@ public abstract class CachedPrimaryGroupHolder extends StoredHolder implements S
protected abstract String calculateValue();
@Override
public String getValue() {
public final String getValue() {
String s = this.cache.get();
return s != null ? s : getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME);
}

View File

@ -0,0 +1,38 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.processors;
import java.util.Collections;
import java.util.Map;
public abstract class AbstractPermissionProcessor implements PermissionProcessor {
protected Map<String, Boolean> sourceMap = Collections.emptyMap();
@Override
public void setSource(Map<String, Boolean> sourceMap) {
this.sourceMap = sourceMap;
}
}

View File

@ -27,20 +27,11 @@ package me.lucko.luckperms.common.processors;
import me.lucko.luckperms.api.Tristate;
import java.util.Map;
public class MapProcessor implements PermissionProcessor {
private Map<String, Boolean> map = null;
public class MapProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
@Override
public Tristate hasPermission(String permission) {
return Tristate.fromNullableBoolean(this.map.get(permission));
return Tristate.fromNullableBoolean(this.sourceMap.get(permission));
}
@Override
public void updateBacking(Map<String, Boolean> map) {
if (this.map == null) {
this.map = map;
}
}
}

View File

@ -26,11 +26,15 @@
package me.lucko.luckperms.common.processors;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import java.util.Map;
/**
* A processor within a {@link me.lucko.luckperms.common.calculators.PermissionCalculator}.
* A processor within a {@link PermissionCalculator}.
*
* <p>Processors should not implement any sort of caching. This is handled in
* the parent calculator.</p>
*/
public interface PermissionProcessor {
@ -43,14 +47,19 @@ public interface PermissionProcessor {
Tristate hasPermission(String permission);
/**
* Called each time the permission calculators backing is updated.
* Sets the source permissions which should be used by this processor
*
* <p>Note that the same map instance is passed to this method on each update,
* so, if no processing is needed on the backing map, this can be cached on
* the first invocation.</p>
*
* @param map the map
* @param sourceMap the source map
*/
void updateBacking(Map<String, Boolean> map);
default void setSource(Map<String, Boolean> sourceMap) {
}
/**
* Called after a change has been made to the source map
*/
default void refresh() {
}
}

View File

@ -25,15 +25,17 @@
package me.lucko.luckperms.common.processors;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.utils.PatternCache;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
public class RegexProcessor implements PermissionProcessor {
private final Map<Pattern, Boolean> regexPermissions = new ConcurrentHashMap<>();
public class RegexProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
private Map<Pattern, Boolean> regexPermissions = Collections.emptyMap();
@Override
public Tristate hasPermission(String permission) {
@ -47,9 +49,9 @@ public class RegexProcessor implements PermissionProcessor {
}
@Override
public void updateBacking(Map<String, Boolean> map) {
this.regexPermissions.clear();
for (Map.Entry<String, Boolean> e : map.entrySet()) {
public void refresh() {
ImmutableMap.Builder<Pattern, Boolean> builder = ImmutableMap.builder();
for (Map.Entry<String, Boolean> e : this.sourceMap.entrySet()) {
if (!e.getKey().startsWith("r=") && !e.getKey().startsWith("R=")) {
continue;
}
@ -61,7 +63,8 @@ public class RegexProcessor implements PermissionProcessor {
continue;
}
this.regexPermissions.put(p, e.getValue());
builder.put(p, e.getValue());
}
this.regexPermissions = builder.build();
}
}

View File

@ -28,15 +28,11 @@ package me.lucko.luckperms.common.processors;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.node.ImmutableNode;
import java.util.Map;
public class WildcardProcessor implements PermissionProcessor {
public class WildcardProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
public static final String WILDCARD_SUFFIX = ".*";
private static final String GLOBAL_WILDCARD_1 = "*";
private static final String GLOBAL_WILDCARD_2 = "'*'";
private Map<String, Boolean> map = null;
@Override
public Tristate hasPermission(String permission) {
String node = permission;
@ -49,25 +45,19 @@ public class WildcardProcessor implements PermissionProcessor {
node = node.substring(0, endIndex);
if (!node.isEmpty()) {
Tristate t = Tristate.fromNullableBoolean(this.map.get(node + WILDCARD_SUFFIX));
Tristate t = Tristate.fromNullableBoolean(this.sourceMap.get(node + WILDCARD_SUFFIX));
if (t != Tristate.UNDEFINED) {
return t;
}
}
}
Tristate t = Tristate.fromNullableBoolean(this.map.get(GLOBAL_WILDCARD_1));
Tristate t = Tristate.fromNullableBoolean(this.sourceMap.get(GLOBAL_WILDCARD_1));
if (t != Tristate.UNDEFINED) {
return t;
}
return Tristate.fromNullableBoolean(this.map.get(GLOBAL_WILDCARD_2));
return Tristate.fromNullableBoolean(this.sourceMap.get(GLOBAL_WILDCARD_2));
}
@Override
public void updateBacking(Map<String, Boolean> map) {
if (this.map == null) {
this.map = map;
}
}
}

View File

@ -26,12 +26,12 @@
package me.lucko.luckperms.common.storage.dao.sql.connection.file;
import me.lucko.luckperms.common.dependencies.Dependency;
import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
@ -55,7 +55,7 @@ public class H2ConnectionFactory extends FlatfileConnectionFactory {
}
// setup the classloader
URLClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER));
IsolatedClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER));
try {
Class<?> driverClass = classLoader.loadClass("org.h2.Driver");
Method loadMethod = driverClass.getMethod("load");

View File

@ -26,12 +26,12 @@
package me.lucko.luckperms.common.storage.dao.sql.connection.file;
import me.lucko.luckperms.common.dependencies.Dependency;
import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.EnumSet;
@ -54,7 +54,7 @@ public class SQLiteConnectionFactory extends FlatfileConnectionFactory {
}
// setup the classloader
URLClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.SQLITE_DRIVER));
IsolatedClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.SQLITE_DRIVER));
try {
Class<?> jdcbClass = classLoader.loadClass("org.sqlite.JDBC");
this.createConnectionMethod = jdcbClass.getMethod("createConnection", String.class, Properties.class);

View File

@ -50,7 +50,7 @@ public class HttpClient {
return response;
}
public static RuntimeException exceptionForUnsuccessfulResponse(Response response) {
private static RuntimeException exceptionForUnsuccessfulResponse(Response response) {
String msg = "";
try (ResponseBody responseBody = response.body()) {
if (responseBody != null) {

View File

@ -31,8 +31,6 @@ import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import java.util.Map;
public abstract class DefaultsProcessor implements PermissionProcessor {
private final LuckPermsService service;
private final ImmutableContextSet contexts;
@ -58,9 +56,4 @@ public abstract class DefaultsProcessor implements PermissionProcessor {
return Tristate.UNDEFINED;
}
@Override
public void updateBacking(Map<String, Boolean> map) {
// Do nothing, this doesn't use the backing
}
}

View File

@ -27,12 +27,10 @@ package me.lucko.luckperms.sponge.processors;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.node.ImmutableNode;
import me.lucko.luckperms.common.processors.AbstractPermissionProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import java.util.Map;
public class SpongeWildcardProcessor implements PermissionProcessor {
private Map<String, Boolean> map = null;
public class SpongeWildcardProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
@Override
public Tristate hasPermission(String permission) {
@ -46,7 +44,7 @@ public class SpongeWildcardProcessor implements PermissionProcessor {
node = node.substring(0, endIndex);
if (!node.isEmpty()) {
Tristate t = Tristate.fromNullableBoolean(this.map.get(node));
Tristate t = Tristate.fromNullableBoolean(this.sourceMap.get(node));
if (t != Tristate.UNDEFINED) {
return t;
}
@ -56,10 +54,4 @@ public class SpongeWildcardProcessor implements PermissionProcessor {
return Tristate.UNDEFINED;
}
@Override
public void updateBacking(Map<String, Boolean> map) {
if (this.map == null) {
this.map = map;
}
}
}

View File

@ -330,13 +330,13 @@ public class CalculatedSubjectData implements LPSubjectData {
public CalculatorHolder(PermissionCalculator calculator) {
this.calculator = calculator;
this.permissions = new ConcurrentHashMap<>();
this.calculator.updateBacking(this.permissions);
this.calculator.setSourcePermissions(this.permissions);
}
public void setPermissions(Map<String, Boolean> permissions) {
this.permissions.clear();
this.permissions.putAll(permissions);
this.calculator.updateBacking(this.permissions);
this.calculator.setSourcePermissions(this.permissions);
this.calculator.invalidateCache();
}