Fix invalid CommandCooldowns causing NPEs (#4210)

* Fix invalid CommandCooldowns causing NPEs

* Add Map support
This commit is contained in:
Josh Roy 2021-06-08 12:40:52 -04:00 committed by GitHub
parent 6e6561a267
commit a28d0823b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 1 deletions

View File

@ -1,7 +1,9 @@
package com.earth2me.essentials.config;
import com.earth2me.essentials.config.annotations.DeleteIfIncomplete;
import com.earth2me.essentials.config.annotations.DeleteOnEmpty;
import com.earth2me.essentials.config.entities.LazyLocation;
import com.earth2me.essentials.config.processors.DeleteIfIncompleteProcessor;
import com.earth2me.essentials.config.processors.DeleteOnEmptyProcessor;
import com.earth2me.essentials.config.serializers.BigDecimalTypeSerializer;
import com.earth2me.essentials.config.serializers.LocationTypeSerializer;
@ -46,6 +48,7 @@ public class EssentialsConfiguration {
private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
private static final ObjectMapper.Factory MAPPER_FACTORY = ObjectMapper.factoryBuilder()
.addProcessor(DeleteOnEmpty.class, (data, value) -> new DeleteOnEmptyProcessor())
.addProcessor(DeleteIfIncomplete.class, (data, value) -> new DeleteIfIncompleteProcessor())
.build();
private static final TypeSerializerCollection SERIALIZERS = TypeSerializerCollection.defaults().childBuilder()
.registerAnnotatedObjects(MAPPER_FACTORY)

View File

@ -0,0 +1,15 @@
package com.earth2me.essentials.config.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate to Configurate that the annotated field should be
* treated as null if it is treated as incomplete.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DeleteIfIncomplete {
}

View File

@ -1,11 +1,12 @@
package com.earth2me.essentials.config.entities;
import com.earth2me.essentials.config.processors.DeleteIfIncompleteProcessor;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import java.util.regex.Pattern;
@ConfigSerializable
public class CommandCooldown {
public class CommandCooldown implements DeleteIfIncompleteProcessor.IncompleteEntity {
private Pattern pattern;
public Pattern pattern() {
@ -25,4 +26,9 @@ public class CommandCooldown {
public void value(final Long value) {
this.value = value;
}
@Override
public boolean isIncomplete() {
return value == null || pattern == null;
}
}

View File

@ -1,5 +1,6 @@
package com.earth2me.essentials.config.holders;
import com.earth2me.essentials.config.annotations.DeleteIfIncomplete;
import com.earth2me.essentials.config.annotations.DeleteOnEmpty;
import com.earth2me.essentials.config.entities.CommandCooldown;
import com.earth2me.essentials.config.entities.LazyLocation;
@ -413,6 +414,7 @@ public class UserConfigHolder {
}
@DeleteOnEmpty
@DeleteIfIncomplete
private @MonotonicNonNull List<CommandCooldown> commandCooldowns;
public List<CommandCooldown> commandCooldowns() {

View File

@ -0,0 +1,55 @@
package com.earth2me.essentials.config.processors;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.objectmapping.meta.Processor;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DeleteIfIncompleteProcessor implements Processor<Object> {
@Override
public void process(Object value, ConfigurationNode destination) {
if (value == null) {
return;
}
try {
if (value instanceof IncompleteEntity && ((IncompleteEntity) value).isIncomplete()) {
destination.set(null);
} else if (value instanceof List<?>) {
boolean modified = false;
final List<?> newList = new ArrayList<>((List<?>) value);
for (final Object o : (List<?>) value) {
if (o instanceof IncompleteEntity && ((IncompleteEntity) o).isIncomplete()) {
newList.remove(o);
modified = true;
}
}
if (modified) {
destination.set(newList);
}
} else if (value instanceof Map<?, ?>) {
boolean modified = false;
final Map<?, ?> newMap = new HashMap<>((Map<?, ?>) value);
for (final Map.Entry<?, ?> entry : newMap.entrySet()) {
if (entry.getValue() instanceof IncompleteEntity && ((IncompleteEntity) entry.getValue()).isIncomplete()) {
newMap.remove(entry.getKey());
modified = true;
}
}
if (modified) {
destination.set(newMap);
}
}
} catch (final SerializationException e) {
e.printStackTrace();
}
}
public interface IncompleteEntity {
boolean isIncomplete();
}
}