mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-30 14:43:27 +01:00
fix exceptions when reloading the server (#1689)
This commit is contained in:
parent
a2bf242097
commit
4f18d37832
@ -4,10 +4,14 @@ import io.netty.channel.Channel;
|
|||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
@SuppressWarnings("NullableProblems")
|
@SuppressWarnings("NullableProblems")
|
||||||
final class ListeningList implements List<Object> {
|
final class ListeningList implements List<Object> {
|
||||||
@ -25,17 +29,23 @@ final class ListeningList implements List<Object> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return this.original.size();
|
synchronized (this) {
|
||||||
|
return this.original.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return this.original.isEmpty();
|
synchronized (this) {
|
||||||
|
return this.original.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
return this.original.contains(o);
|
synchronized (this) {
|
||||||
|
return this.original.contains(o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -43,81 +53,113 @@ final class ListeningList implements List<Object> {
|
|||||||
return this.original.iterator();
|
return this.original.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forEach(Consumer<? super Object> action) {
|
||||||
|
synchronized (this) {
|
||||||
|
this.original.forEach(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] toArray() {
|
public Object[] toArray() {
|
||||||
return this.original.toArray();
|
synchronized (this) {
|
||||||
|
return this.original.toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T[] toArray(T[] a) {
|
public <T> T[] toArray(T[] a) {
|
||||||
//noinspection SuspiciousToArrayCall
|
synchronized (this) {
|
||||||
return this.original.toArray(a);
|
//noinspection SuspiciousToArrayCall
|
||||||
|
return this.original.toArray(a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(Object o) {
|
public boolean add(Object o) {
|
||||||
this.processInsert(o);
|
synchronized (this) {
|
||||||
return this.original.add(o);
|
this.processInsert(o);
|
||||||
|
return this.original.add(o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(int index, Object element) {
|
public void add(int index, Object element) {
|
||||||
this.processInsert(element);
|
synchronized (this) {
|
||||||
this.original.add(index, element);
|
this.processInsert(element);
|
||||||
|
this.original.add(index, element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(Collection<?> c) {
|
public boolean addAll(Collection<?> c) {
|
||||||
c.forEach(this::processInsert);
|
synchronized (this) {
|
||||||
return this.original.addAll(c);
|
c.forEach(this::processInsert);
|
||||||
|
return this.original.addAll(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(int index, Collection<?> c) {
|
public boolean addAll(int index, Collection<?> c) {
|
||||||
c.forEach(this::processInsert);
|
synchronized (this) {
|
||||||
return this.original.addAll(index, c);
|
c.forEach(this::processInsert);
|
||||||
|
return this.original.addAll(index, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object set(int index, Object element) {
|
public Object set(int index, Object element) {
|
||||||
this.processInsert(element);
|
synchronized (this) {
|
||||||
|
this.processInsert(element);
|
||||||
|
|
||||||
Object prev = this.original.set(index, element);
|
Object prev = this.original.set(index, element);
|
||||||
this.processRemove(prev);
|
this.processRemove(prev);
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
if (this.original.remove(o)) {
|
synchronized (this) {
|
||||||
this.processRemove(o);
|
if (this.original.remove(o)) {
|
||||||
return true;
|
this.processRemove(o);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(Collection<?> c) {
|
public boolean containsAll(Collection<?> c) {
|
||||||
return this.original.containsAll(c);
|
synchronized (this) {
|
||||||
|
//noinspection SlowListContainsAll
|
||||||
|
return this.original.containsAll(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object remove(int index) {
|
public Object remove(int index) {
|
||||||
Object removed = this.original.remove(index);
|
synchronized (this) {
|
||||||
this.processRemove(removed);
|
Object removed = this.original.remove(index);
|
||||||
return removed;
|
this.processRemove(removed);
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(Object o) {
|
public int indexOf(Object o) {
|
||||||
return this.original.indexOf(o);
|
synchronized (this) {
|
||||||
|
return this.original.indexOf(o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lastIndexOf(Object o) {
|
public int lastIndexOf(Object o) {
|
||||||
return this.original.lastIndexOf(o);
|
synchronized (this) {
|
||||||
|
return this.original.lastIndexOf(o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -132,33 +174,77 @@ final class ListeningList implements List<Object> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Object> subList(int fromIndex, int toIndex) {
|
public List<Object> subList(int fromIndex, int toIndex) {
|
||||||
return this.original.subList(fromIndex, toIndex);
|
synchronized (this) {
|
||||||
|
return this.original.subList(fromIndex, toIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(Collection<?> c) {
|
public boolean removeAll(Collection<?> c) {
|
||||||
c.forEach(element -> {
|
synchronized (this) {
|
||||||
if (this.original.contains(element)) {
|
c.forEach(element -> {
|
||||||
this.processRemove(element);
|
if (this.original.contains(element)) {
|
||||||
}
|
this.processRemove(element);
|
||||||
});
|
}
|
||||||
return this.original.removeAll(c);
|
});
|
||||||
|
return this.original.removeAll(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeIf(Predicate<? super Object> filter) {
|
||||||
|
synchronized (this) {
|
||||||
|
return this.original.removeIf(object -> {
|
||||||
|
boolean shouldRemove = filter.test(object);
|
||||||
|
if (shouldRemove) {
|
||||||
|
this.processRemove(object);
|
||||||
|
}
|
||||||
|
return shouldRemove;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retainAll(Collection<?> c) {
|
public boolean retainAll(Collection<?> c) {
|
||||||
return this.original.retainAll(c);
|
synchronized (this) {
|
||||||
|
return this.original.retainAll(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replaceAll(UnaryOperator<Object> operator) {
|
||||||
|
synchronized (this) {
|
||||||
|
this.original.replaceAll(value -> {
|
||||||
|
Object newValue = operator.apply(value);
|
||||||
|
if (newValue != value) {
|
||||||
|
this.processRemove(value);
|
||||||
|
this.processInsert(newValue);
|
||||||
|
}
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sort(Comparator<? super Object> c) {
|
||||||
|
synchronized (this) {
|
||||||
|
this.original.sort(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
this.original.forEach(this::processRemove);
|
synchronized (this) {
|
||||||
this.original.clear();
|
this.original.forEach(this::processRemove);
|
||||||
|
this.original.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get(int index) {
|
public Object get(int index) {
|
||||||
return this.original.get(index);
|
synchronized (this) {
|
||||||
|
return this.original.get(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processInsert(Object element) {
|
private void processInsert(Object element) {
|
||||||
|
@ -26,7 +26,6 @@ import io.netty.channel.ChannelFuture;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -205,7 +204,7 @@ public class NetworkManagerInjector implements ChannelListener {
|
|||||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||||
synchronized (value) {
|
synchronized (value) {
|
||||||
// override the list field with our list
|
// override the list field with our list
|
||||||
List<Object> newList = Collections.synchronizedList(new ListeningList(value, this.pipelineInjectorHandler));
|
List<Object> newList = new ListeningList(value, this.pipelineInjectorHandler);
|
||||||
accessor.set(serverConnection, newList);
|
accessor.set(serverConnection, newList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +214,6 @@ public class NetworkManagerInjector implements ChannelListener {
|
|||||||
this.injected = true;
|
this.injected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void close() {
|
public void close() {
|
||||||
if (this.closed || !this.injected) {
|
if (this.closed || !this.injected) {
|
||||||
return;
|
return;
|
||||||
@ -229,10 +227,10 @@ public class NetworkManagerInjector implements ChannelListener {
|
|||||||
for (Pair<Object, FieldAccessor> list : this.overriddenLists) {
|
for (Pair<Object, FieldAccessor> list : this.overriddenLists) {
|
||||||
// get the value of the field we've overridden, if it is no longer a ListeningList someone probably jumped in
|
// get the value of the field we've overridden, if it is no longer a ListeningList someone probably jumped in
|
||||||
// and replaced the field himself - we are out safely as the other person needs to clean the mess...
|
// and replaced the field himself - we are out safely as the other person needs to clean the mess...
|
||||||
List<Object> value = (List<Object>) list.getSecond().get(list.getFirst());
|
Object currentFieldValue = list.getSecond().get(list.getFirst());
|
||||||
if (value instanceof ListeningList) {
|
if (currentFieldValue instanceof ListeningList) {
|
||||||
// just reset to the list we wrapped originally
|
// just reset to the list we wrapped originally
|
||||||
ListeningList ourList = (ListeningList) value;
|
ListeningList ourList = (ListeningList) currentFieldValue;
|
||||||
List<Object> original = ourList.getOriginal();
|
List<Object> original = ourList.getOriginal();
|
||||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||||
synchronized (original) {
|
synchronized (original) {
|
||||||
|
Loading…
Reference in New Issue
Block a user