Package com.davfx.ninio.telnet.util

Source Code of com.davfx.ninio.telnet.util.WaitingTelnetClientCache$Connectable

package com.davfx.ninio.telnet.util;

import java.io.IOException;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import com.davfx.ninio.common.Address;
import com.davfx.ninio.common.Queue;
import com.davfx.ninio.common.ReadyFactory;
import com.davfx.ninio.telnet.TelnetClient;
import com.davfx.util.Pair;

public final class WaitingTelnetClientCache implements AutoCloseable {
  private final Queue queue;
  private final ScheduledExecutorService callWithEmptyExecutor = Executors.newSingleThreadScheduledExecutor();
 
  private static final class Hold {
    public final WaitingTelnetClient client;
    public final List<WaitingTelnetClientHandler> handlers = new LinkedList<>();
    public final Deque<Pair<String, WaitingTelnetClientHandler.Callback.SendCallback>> toSend = new LinkedList<>();
    public WaitingTelnetClientHandler.Callback launchedCallback;

    public final StringBuilder initResponses = new StringBuilder();
    public String ready = null;
   
    public Hold(WaitingTelnetClient client) {
      this.client = client;
    }
  }
 
  private final Map<Address, Hold> clients = new HashMap<>();

  private double callWithEmptyTime = Double.NaN;
  private double endOfCommandTime = Double.NaN;
  private double timeout = Double.NaN;
  private ReadyFactory readyFactory = null;
 
  public WaitingTelnetClientCache(Queue queue) {
    this.queue = queue;
  }

  public WaitingTelnetClientCache withCallWithEmptyTime(double callWithEmptyTime) {
    this.callWithEmptyTime = callWithEmptyTime;
    return this;
  }
  public WaitingTelnetClientCache withEndOfCommandTime(double endOfCommandTime) {
    this.endOfCommandTime = endOfCommandTime;
    return this;
  }
  public WaitingTelnetClientCache withTimeout(double timeout) {
    this.timeout = timeout;
    return this;
  }

  public WaitingTelnetClientCache override(ReadyFactory readyFactory) {
    this.readyFactory = readyFactory;
    return this;
  }
 
  public static interface Connectable {
    Connectable init(String command);
    void connect(WaitingTelnetClientHandler clientHandler);
  }
 
  public Connectable get(String host) {
    return get(new Address(host, TelnetClient.DEFAULT_PORT));
  }
  public Connectable get(Address address) {
    return new Connectable() {
      private final List<String> initCommands = new LinkedList<String>();
      @Override
      public Connectable init(String command) {
        initCommands.add(command);
        return this;
      }
     
      @Override
      public void connect(WaitingTelnetClientHandler clientHandler) {
        Hold c = clients.get(address);
        if (c == null) {
          TelnetClient telnetClient = new TelnetClient();
          if (!Double.isNaN(callWithEmptyTime)) {
            telnetClient.withCallWithEmptyTime(callWithEmptyTime);
          }
          if (readyFactory != null) {
            telnetClient.override(readyFactory);
          }
         
          WaitingTelnetClient waitingTelnetClient = new WaitingTelnetClient(telnetClient.withAddress(address).withQueue(queue, callWithEmptyExecutor));
          if (!Double.isNaN(endOfCommandTime)) {
            waitingTelnetClient.withEndOfCommandTime(endOfCommandTime);
          }
          if (!Double.isNaN(timeout)) {
            waitingTelnetClient.withTimeout(timeout);
          }
         
          c = new Hold(waitingTelnetClient);
         
          Hold cc = c;
          clients.put(address, cc);
          c.handlers.add(clientHandler);
         
          WaitingTelnetClientHandler.Callback.SendCallback continueToSendCallback = new WaitingTelnetClientHandler.Callback.SendCallback() {
            @Override
            public void failed(IOException e) {
              clients.remove(address);
              for (WaitingTelnetClientHandler h : cc.handlers) {
                h.failed(e);
              }
            }
            @Override
            public void received(String text) {
              Pair<String, WaitingTelnetClientHandler.Callback.SendCallback> current = cc.toSend.removeFirst();
             
              if (!cc.toSend.isEmpty()) {
                Pair<String, WaitingTelnetClientHandler.Callback.SendCallback> next = cc.toSend.getFirst();
                cc.launchedCallback.send(next.first, this);
              }
             
              current.second.received(text);
            }
          };
         
          Runnable readyRunnable = new Runnable() {
            @Override
            public void run() {
              cc.ready = cc.initResponses.toString();
              for (WaitingTelnetClientHandler h : cc.handlers) {
                h.launched(cc.ready, new WaitingTelnetClientHandler.Callback() {
                  @Override
                  public void close() {
                    // Never actually closed
                  }
                  @Override
                  public void send(String line, SendCallback sendCallback) {
                    boolean send = cc.toSend.isEmpty();
                   
                    cc.toSend.add(new Pair<String, WaitingTelnetClientHandler.Callback.SendCallback>(line, sendCallback));
                   
                    if (send) {
                      cc.launchedCallback.send(line, continueToSendCallback);
                    }
                  }
                });
              }
            }
          };
         
          WaitingTelnetClientHandler.Callback.SendCallback globalInitCallback = new WaitingTelnetClientHandler.Callback.SendCallback() {
            @Override
            public void received(String text) {
              cc.initResponses.append(text);
             
              cc.toSend.removeFirst();
             
              if (!cc.toSend.isEmpty()) {
                Pair<String, WaitingTelnetClientHandler.Callback.SendCallback> next = cc.toSend.getFirst();
                cc.launchedCallback.send(next.first, this);
              } else {
                readyRunnable.run();
              }
            }
            @Override
            public void failed(IOException e) {
              clients.remove(address);
              for (WaitingTelnetClientHandler h : cc.handlers) {
                h.failed(e);
              }
            }
          };
          Iterator<String> ii = initCommands.iterator();
          while (ii.hasNext()) {
            String initCommand = ii.next();
            cc.toSend.add(new Pair<String, WaitingTelnetClientHandler.Callback.SendCallback>(initCommand, globalInitCallback));
          }
         
          cc.client.connect(new WaitingTelnetClientHandler() {
            @Override
            public void failed(IOException e) {
              clients.remove(address);
              for (WaitingTelnetClientHandler h : cc.handlers) {
                h.failed(e);
              }
            }
            @Override
            public void close() {
              clients.remove(address);
              for (WaitingTelnetClientHandler h : cc.handlers) {
                h.close();
              }
            }
     
            @Override
            public void launched(String init, Callback callback) {
              cc.initResponses.append(init);
              cc.launchedCallback = callback;
              if (cc.toSend.isEmpty()) {
                readyRunnable.run();
              } else {
                Pair<String, WaitingTelnetClientHandler.Callback.SendCallback> p = cc.toSend.getFirst();
                cc.launchedCallback.send(p.first, p.second);
              }
            }
          });
        } else {
          Hold cc = c;
         
          cc.handlers.add(clientHandler);
          if (cc.ready != null) {
            WaitingTelnetClientHandler.Callback.SendCallback continueToSendCallback = new WaitingTelnetClientHandler.Callback.SendCallback() {
              @Override
              public void failed(IOException e) {
                clients.remove(address);
                for (WaitingTelnetClientHandler h : cc.handlers) {
                  h.failed(e);
                }
              }
              @Override
              public void received(String text) {
                Pair<String, WaitingTelnetClientHandler.Callback.SendCallback> current = cc.toSend.removeFirst();
               
                if (!cc.toSend.isEmpty()) {
                  Pair<String, WaitingTelnetClientHandler.Callback.SendCallback> next = cc.toSend.getFirst();
                  cc.launchedCallback.send(next.first, this);
                }

                current.second.received(text);
              }
            };
           
            clientHandler.launched(cc.ready, new WaitingTelnetClientHandler.Callback() {
              @Override
              public void close() {
                // Never actually closed
              }
              @Override
              public void send(String line, SendCallback sendCallback) {
                boolean send = cc.toSend.isEmpty();
               
                cc.toSend.add(new Pair<String, WaitingTelnetClientHandler.Callback.SendCallback>(line, sendCallback));
               
                if (send) {
                  cc.launchedCallback.send(line, continueToSendCallback);
                }
              }
            });
          }
        }
      }
    };
  }
 
  @Override
  public void close() {
    callWithEmptyExecutor.shutdown();
    // Queue not closed here but by caller
   
    for(Hold c : clients.values()) {
      if (c.launchedCallback != null) {
        c.launchedCallback.close();
      }
      c.handlers.clear();
    }
  }
}
TOP

Related Classes of com.davfx.ninio.telnet.util.WaitingTelnetClientCache$Connectable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.