+ protected void run() throws Exception {
+ while (isRunning()) {
+
+ Set<Channel> missingChannels = new HashSet<>();
+ for (Channel channel : channels) {
+ if (joinedChannels.contains(channel) || channelsBeingJoined.contains(channel)) {
+ continue;
+ }
+ if (channelBanManager.isBanned(channel)) {
+ continue;
+ }
+ if (!networkConnections.containsKey(channel.network()) || networkConnections.get(channel.network()).established()) {
+ missingChannels.add(channel);
+ }
+ }
+ Set<Network> missingNetworks = missingChannels.stream()
+ .map(Channel::network)
+ .distinct()
+ .filter((network) -> !networkConnections.containsKey(network))
+ .collect(Collectors.toSet());
+
+ if (missingNetworks.isEmpty()) {
+ if (!missingChannels.isEmpty()) {
+ for (Channel missingChannel : missingChannels) {
+ Network network = missingChannel.network();
+ eventBus.post(new GenericMessage(String.format("Trying to join %s on %s...", missingChannel.name(), network)));
+ try {
+ channelsBeingJoined.add(missingChannel);
+ networkConnections.get(network).joinChannel(missingChannel.name());
+ } catch (IOException ioe1) {
+ logger.warn(String.format("Could not join %s on %s!", missingChannel.name(), network.name()), ioe1);
+ }
+ }
+ } else {
+ synchronized (syncObject) {
+ try {
+ syncObject.wait(TimeUnit.MINUTES.toMillis(1));
+ } catch (InterruptedException ie1) {
+ /* ignore. */
+ }
+ }
+ }
+ continue;
+ }
+
+ Map<Long, Network> timesForNextConnects = new TreeMap<>(missingNetworks.stream()
+ .collect(Collectors.toMap(connectionBackoff::getConnectionTime, Function.identity(), (network, ignore) -> network)));
+
+ Optional<Entry<Long, Network>> firstNetwork = Optional.fromNullable(timesForNextConnects.entrySet().stream().findFirst().orElse(null));
+ if (!firstNetwork.isPresent()) {
+ continue;
+ }
+ if (firstNetwork.get().getKey() > System.currentTimeMillis()) {
+ eventBus.post(new GenericMessage(String.format("Will connect to %2$s at %1$tH:%1$tM...", firstNetwork.get().getKey(), firstNetwork.get().getValue().name())));
+ synchronized (syncObject) {
+ try {
+ syncObject.wait(firstNetwork.get().getKey() - System.currentTimeMillis());
+ } catch (InterruptedException ie1) {
+ /* ignore. */
+ }
+ }
+ if (!isRunning()) {
+ break;
+ }
+ if (firstNetwork.get().getKey() > System.currentTimeMillis()) {
+ continue;
+ }
+ }
+
+ connectNetwork(firstNetwork.get().getValue());
+ }
+ }
+
+ @Override
+ protected void triggerShutdown() {
+ synchronized (syncObject) {
+ syncObject.notifyAll();
+ }