2017-02-06 13:31:55 +01:00
|
|
|
package tc.oc.api.minecraft.connectable;
|
2017-01-30 01:43:34 +01:00
|
|
|
|
2017-02-06 13:05:31 +01:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Deque;
|
|
|
|
import java.util.IdentityHashMap;
|
|
|
|
import java.util.LinkedList;
|
2017-01-30 01:43:34 +01:00
|
|
|
import java.util.Set;
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import javax.inject.Singleton;
|
|
|
|
|
2017-02-06 13:31:55 +01:00
|
|
|
import tc.oc.api.connectable.Connectable;
|
2017-01-30 01:43:34 +01:00
|
|
|
import tc.oc.commons.core.exception.ExceptionHandler;
|
|
|
|
import tc.oc.commons.core.logging.Loggers;
|
|
|
|
import tc.oc.commons.core.util.ExceptionUtils;
|
2017-02-06 13:05:31 +01:00
|
|
|
import tc.oc.minecraft.api.event.Enableable;
|
2017-01-30 01:43:34 +01:00
|
|
|
|
|
|
|
import static com.google.common.base.Preconditions.checkState;
|
|
|
|
|
|
|
|
@Singleton
|
2017-02-06 13:05:31 +01:00
|
|
|
class Connector implements Enableable {
|
2017-01-30 01:43:34 +01:00
|
|
|
|
|
|
|
protected final Logger logger;
|
|
|
|
private final ExceptionHandler exceptionHandler;
|
2017-02-06 13:05:31 +01:00
|
|
|
private final Set<Connectable> registered = Collections.newSetFromMap(new IdentityHashMap<>());
|
|
|
|
private final Deque<Connectable> pending = new LinkedList<>();
|
|
|
|
private final Deque<Connectable> connected = new LinkedList<>();
|
|
|
|
private boolean finishedConnecting;
|
2017-01-30 01:43:34 +01:00
|
|
|
|
2017-02-06 13:05:31 +01:00
|
|
|
@Inject Connector(Loggers loggers, ExceptionHandler exceptionHandler) {
|
2017-01-30 01:43:34 +01:00
|
|
|
this.exceptionHandler = exceptionHandler;
|
|
|
|
this.logger = loggers.get(getClass());
|
|
|
|
}
|
|
|
|
|
2017-02-06 13:05:31 +01:00
|
|
|
void register(Connectable connectable) {
|
|
|
|
if(registered.add(connectable)) {
|
|
|
|
if(finishedConnecting) {
|
|
|
|
throw new IllegalStateException("Tried to provision a " + Connectable.class.getSimpleName() +
|
|
|
|
" when already connected");
|
|
|
|
}
|
|
|
|
pending.add(connectable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-30 01:43:34 +01:00
|
|
|
@Override
|
|
|
|
public void enable() {
|
2017-02-06 13:05:31 +01:00
|
|
|
checkState(!finishedConnecting, "already connected");
|
2017-01-30 01:43:34 +01:00
|
|
|
logger.fine(() -> "Connecting all services");
|
2017-02-06 13:05:31 +01:00
|
|
|
for(;;) {
|
|
|
|
final Connectable connectable = pending.poll();
|
|
|
|
if(connectable == null) break;
|
2017-02-06 13:31:55 +01:00
|
|
|
|
|
|
|
logger.fine(() -> "Connecting " + connectable.getClass().getName());
|
|
|
|
ExceptionUtils.propagate(connectable::connect);
|
2017-02-06 13:05:31 +01:00
|
|
|
connected.push(connectable);
|
|
|
|
}
|
|
|
|
finishedConnecting = true;
|
2017-01-30 01:43:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void disable() {
|
2017-02-06 13:05:31 +01:00
|
|
|
checkState(finishedConnecting, "not connected");
|
2017-01-30 01:43:34 +01:00
|
|
|
logger.fine(() -> "Disconnecting all services");
|
2017-02-06 13:05:31 +01:00
|
|
|
while(!connected.isEmpty()) {
|
2017-02-06 13:31:55 +01:00
|
|
|
final Connectable connectable = connected.pop();
|
|
|
|
logger.fine(() -> "Disconnecting " + connectable.getClass().getName());
|
|
|
|
exceptionHandler.run(connectable::disconnect);
|
2017-02-06 13:05:31 +01:00
|
|
|
}
|
2017-01-30 01:43:34 +01:00
|
|
|
}
|
|
|
|
}
|