Correctly clean up the old injection handler.

This commit is contained in:
Kristian S. Stangeland 2013-12-13 21:34:03 +01:00
parent 74d83b3ed6
commit c568481da3
2 changed files with 95 additions and 19 deletions

View File

@ -1,17 +1,18 @@
package com.comphenix.protocol.injector.netty;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import com.google.common.collect.ForwardingList;
import com.google.common.collect.Lists;
// Hopefully, CB won't version these as well
import net.minecraft.util.io.netty.channel.ChannelFuture;
import net.minecraft.util.io.netty.channel.ChannelHandler;
class BootstrapList extends ForwardingList<Object> {
class BootstrapList implements List<Object> {
private List<Object> delegate;
private ChannelHandler handler;
@ -33,30 +34,25 @@ class BootstrapList extends ForwardingList<Object> {
}
@Override
protected List<Object> delegate() {
return delegate;
}
@Override
public boolean add(Object element) {
public synchronized boolean add(Object element) {
processElement(element);
return super.add(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends Object> collection) {
public synchronized boolean addAll(Collection<? extends Object> collection) {
List<Object> copy = Lists.newArrayList(collection);
// Process the collection before we pass it on
for (Object element : copy) {
processElement(element);
}
return super.addAll(copy);
return delegate.addAll(copy);
}
@Override
public Object set(int index, Object element) {
Object old = super.set(index, element);
public synchronized Object set(int index, Object element) {
Object old = delegate.set(index, element);
// Handle the old future, and the newly inserted future
if (old != element) {
@ -110,8 +106,90 @@ class BootstrapList extends ForwardingList<Object> {
/**
* Close and revert all changes.
*/
public void close() {
public synchronized void close() {
for (Object element : this)
unprocessElement(element);
}
// Boiler plate
public synchronized int size() {
return delegate.size();
}
public synchronized boolean isEmpty() {
return delegate.isEmpty();
}
public boolean contains(Object o) {
return delegate.contains(o);
}
public synchronized Iterator<Object> iterator() {
return delegate.iterator();
}
public synchronized Object[] toArray() {
return delegate.toArray();
}
public synchronized <T> T[] toArray(T[] a) {
return delegate.toArray(a);
}
public synchronized boolean remove(Object o) {
return delegate.remove(o);
}
public synchronized boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
public synchronized boolean addAll(int index, Collection<? extends Object> c) {
return delegate.addAll(index, c);
}
public synchronized boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
public synchronized boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
public synchronized void clear() {
delegate.clear();
}
public synchronized Object get(int index) {
return delegate.get(index);
}
public synchronized void add(int index, Object element) {
delegate.add(index, element);
}
public synchronized Object remove(int index) {
return delegate.remove(index);
}
public synchronized int indexOf(Object o) {
return delegate.indexOf(o);
}
public synchronized int lastIndexOf(Object o) {
return delegate.lastIndexOf(o);
}
public synchronized ListIterator<Object> listIterator() {
return delegate.listIterator();
}
public synchronized ListIterator<Object> listIterator(int index) {
return delegate.listIterator(index);
}
public synchronized List<Object> subList(int fromIndex, int toIndex) {
return delegate.subList(fromIndex, toIndex);
}
// End boiler plate
}

View File

@ -5,7 +5,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.bukkit.Bukkit;
@ -112,10 +111,9 @@ public class NettyProtocolInjector implements ChannelListener {
final List<Object> list = (List<Object>) field.getValue();
// Synchronize with each list before we attempt to replace them.
// We also reapply the synchronized list wrapper.
field.setValue(Collections.synchronizedList(new BootstrapList(
field.setValue(new BootstrapList(
list, connectionHandler
)));
));
}
injected = true;
@ -174,7 +172,7 @@ public class NettyProtocolInjector implements ChannelListener {
for (VolatileField field : bootstrapFields) {
Object value = field.getValue();
// Undo the processed channels, if any
if (value instanceof BootstrapList) {
((BootstrapList) value).close();