@Test
  public void test_user_wrong_salt_hash_format() throws Exception {

    final String providedUsername = "******";
    when(clientCredentialsData.getUsername()).thenReturn(Optional.of(providedUsername));
    final String providedPassword = "******";
    when(clientCredentialsData.getPassword()).thenReturn(Optional.of(providedPassword));
    when(clientCredentialsData.getInetAddress())
        .thenReturn(Optional.of(InetAddress.getLoopbackAddress()));

    final String filePassword = "******";
    when(configuration.getUser(providedUsername)).thenReturn(filePassword);
    when(configuration.isSalted()).thenReturn(true);
    when(configuration.isHashed()).thenReturn(true);
    final String algorithm = "SHA-512";
    when(configuration.getHashingAlgorithm()).thenReturn(algorithm);
    final int iterations = 1000000;
    when(configuration.getHashingIterations()).thenReturn(iterations);

    final String salt = "salt";
    final String hash = "hash";
    HashedSaltedPassword abc = new HashedSaltedPassword(hash, salt);

    fileAuthenticator = new FileAuthenticator(configuration, passwordComparator);
    when(passwordComparator.validateHashedAndSaltedPassword(
            algorithm, providedPassword, hash, iterations, salt))
        .thenReturn(true);

    FileAuthenticatorForTest2 fileAuthenticator =
        new FileAuthenticatorForTest2(configuration, passwordComparator, abc);
    final Boolean isAuthenticated = fileAuthenticator.checkCredentials(clientCredentialsData);

    assertFalse(isAuthenticated);
  }
예제 #2
0
  private LauncherServer() throws IOException {
    this.refCount = new AtomicLong(0);

    ServerSocket server = new ServerSocket();
    try {
      server.setReuseAddress(true);
      server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));

      this.clients = new ArrayList<>();
      this.threadIds = new AtomicLong();
      this.factory = new NamedThreadFactory(THREAD_NAME_FMT);
      this.pending = new ConcurrentHashMap<>();
      this.timeoutTimer = new Timer("LauncherServer-TimeoutTimer", true);
      this.server = server;
      this.running = true;

      this.serverThread =
          factory.newThread(
              new Runnable() {
                @Override
                public void run() {
                  acceptConnections();
                }
              });
      serverThread.start();
    } catch (IOException ioe) {
      close();
      throw ioe;
    } catch (Exception e) {
      close();
      throw new IOException(e);
    }
  }
  @Test
  public void test_user_correct_hashed_password() throws Exception {

    final String providedUsername = "******";
    when(clientCredentialsData.getUsername()).thenReturn(Optional.of(providedUsername));
    final String providedPassword = "******";
    when(clientCredentialsData.getPassword()).thenReturn(Optional.of(providedPassword));
    when(clientCredentialsData.getInetAddress())
        .thenReturn(Optional.of(InetAddress.getLoopbackAddress()));

    final String filePassword = "******";
    when(configuration.getUser(providedUsername)).thenReturn(filePassword);
    when(configuration.isSalted()).thenReturn(false);
    when(configuration.isHashed()).thenReturn(true);
    final String algorithm = "SHA-512";
    when(configuration.getHashingAlgorithm()).thenReturn(algorithm);
    final int iterations = 1000000;
    when(configuration.getHashingIterations()).thenReturn(iterations);

    fileAuthenticator = new FileAuthenticator(configuration, passwordComparator);
    when(passwordComparator.validateHashedPassword(
            algorithm, providedPassword, filePassword, iterations))
        .thenReturn(true);

    FileAuthenticator fileAuthenticator = new FileAuthenticator(configuration, passwordComparator);
    final Boolean isAuthenticated = fileAuthenticator.checkCredentials(clientCredentialsData);

    assertTrue(isAuthenticated);
  }
  private Map<String, String> resolveTlsVerification(Map<String, String> config) {

    URI serverUri = URI.create(config.get(CubeDockerConfiguration.DOCKER_URI));
    String scheme = serverUri.getScheme();

    if (scheme.equals(HTTP_SCHEME) || scheme.equals(HTTPS_SCHEME)) {
      config.put(CubeDockerConfiguration.TLS_VERIFY, Boolean.toString(scheme.equals(HTTPS_SCHEME)));

      try {
        // docker-java supports only tcp and unix schemes
        serverUri = new URI(TCP_SCHEME, serverUri.getSchemeSpecificPart(), serverUri.getFragment());
        config.put(CubeDockerConfiguration.DOCKER_URI, serverUri.toString());
      } catch (URISyntaxException e) {
        throw new IllegalArgumentException(e);
      }
    }

    if (!config.containsKey(CubeDockerConfiguration.TLS_VERIFY)) {
      config.put(CubeDockerConfiguration.TLS_VERIFY, Boolean.toString(true));

      if (this.operatingSystemFamilyInstanceProducer.get() == OperatingSystemFamily.LINUX) {

        String dockerServerIp = config.get(CubeDockerConfiguration.DOCKER_SERVER_IP);

        if (isDockerMachineSet(config)) {

          if (InetAddress.getLoopbackAddress().getHostAddress().equals(dockerServerIp)
              || InetAddress.getLoopbackAddress().getHostName().equals(dockerServerIp)) {
            config.put(CubeDockerConfiguration.TLS_VERIFY, Boolean.toString(false));
          } else {
            config.put(CubeDockerConfiguration.TLS_VERIFY, Boolean.toString(true));
          }

        } else {
          config.put(CubeDockerConfiguration.TLS_VERIFY, Boolean.toString(false));
        }
      }
    }

    if (Boolean.FALSE.toString().equals(config.get(CubeDockerConfiguration.TLS_VERIFY))) {
      config.remove(CubeDockerConfiguration.CERT_PATH);
    }

    return config;
  }
예제 #5
0
 // constructor with exception
 public ClientCommunicate(int port) throws IOException {
   port_number = port;
   loopback = InetAddress.getLoopbackAddress();
   // try to connect to server
   client_socket = new Socket(loopback, port_number);
   // grab the output and input streams
   output = new PrintWriter(client_socket.getOutputStream(), true);
   input = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
 }
 @NotNull
 default InetSocketAddress computeDebugAddress() throws ExecutionException {
   try {
     return new InetSocketAddress(
         InetAddress.getLoopbackAddress(), NetUtils.findAvailableSocketPort());
   } catch (IOException e) {
     throw new ExecutionException("Cannot find available port", e);
   }
 }
예제 #7
0
 @Override
 public String getRemote() {
   try {
     return localhost.getAddress();
   } catch (
       @SuppressWarnings("unused")
       final UnknownHostException e) {
     return InetAddress.getLoopbackAddress().getHostAddress();
   }
 }
예제 #8
0
  /** @return never returns <code>null</code> */
  public static IHostIdentifier getLocalHost() {
    InetAddress localHostAddress;
    try {
      localHostAddress = InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
      // fallback
      localHostAddress = InetAddress.getLoopbackAddress();
    }

    return of(localHostAddress);
  }
예제 #9
0
  @Test
  public void testManageAttributes() throws ParseException {
    Map<String, Collection<String>> map = new HashedMap();

    map.put("integer", asList("1"));
    map.put("long", asList("" + Long.MAX_VALUE));
    map.put("string", asList("some string"));
    map.put("date", asList("12/12/2016"));
    map.put("ip_network_address", asList("127.0.0.1"));
    map.put("host_network_address", asList("localhost"));
    map.put("multi_valued", asList("1", "2", "3", "4"));

    Attributes attributes = Attributes.from(map);

    map.keySet()
        .forEach(
            new Consumer<String>() {
              @Override
              public void accept(String name) {
                assertTrue(attributes.exists(name));
              }
            });

    assertFalse(attributes.exists("not_found"));
    assertTrue(attributes.containsValue("integer", "1"));
    assertTrue(attributes.containsValue("multi_valued", "3"));

    assertEquals(1, attributes.getValue("multi_valued").asInt(0));
    assertEquals(4, attributes.getValue("multi_valued").asInt(3));

    assertEquals(
        new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2016"),
        attributes.getValue("date").asDate(0, "dd/MM/yyyy"));

    assertEquals(
        InetAddress.getLoopbackAddress(),
        attributes.getValue("ip_network_address").asInetAddress(0));
    assertEquals(
        InetAddress.getLoopbackAddress(),
        attributes.getValue("host_network_address").asInetAddress(0));
  }
  @Test
  public void test_no_password() throws Exception {

    when(clientCredentialsData.getUsername()).thenReturn(Optional.of("user"));
    when(clientCredentialsData.getPassword()).thenReturn(Optional.<String>absent());
    when(clientCredentialsData.getInetAddress())
        .thenReturn(Optional.of(InetAddress.getLoopbackAddress()));

    fileAuthenticator = new FileAuthenticator(configuration, passwordComparator);
    final Boolean isAuthenticated = fileAuthenticator.checkCredentials(clientCredentialsData);

    assertFalse(isAuthenticated);
  }
  @Test
  public ReadHandle make() {
    ArrayList<SocketAddress> clusterMembers = new ArrayList<SocketAddress>();
    clusterMembers.add(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
    Var<Addr> cluster = Var$.MODULE$.apply(Addr.Bound$.MODULE$.apply(clusterMembers));

    return MultiReader.apply(cluster, "the-queue")
        .clientBuilder(
            ClientBuilder.get()
                .codec(new Kestrel())
                .hostConnectionLimit(1)
                .requestTimeout(Duration.fromTimeUnit(30, TimeUnit.SECONDS)))
        .build();
  }
  @Test
  public void test_user_is_not_present_in_credential_file() throws Exception {

    final String providedUsername = "******";
    when(clientCredentialsData.getUsername()).thenReturn(Optional.of(providedUsername));
    when(clientCredentialsData.getPassword()).thenReturn(Optional.of("password"));
    when(clientCredentialsData.getInetAddress())
        .thenReturn(Optional.of(InetAddress.getLoopbackAddress()));

    when(configuration.getUser(providedUsername)).thenReturn(null);

    fileAuthenticator = new FileAuthenticator(configuration, passwordComparator);
    final Boolean isAuthenticated = fileAuthenticator.checkCredentials(clientCredentialsData);

    assertFalse(isAuthenticated);
  }
예제 #13
0
  private static void runServer() {
    Service<Request, Response> service =
        new Service<Request, Response>() {
          public Future<Response> apply(Request request) {
            Response response = Response.apply();
            // Respond right away.
            response.setContent(ChannelBuffers.wrappedBuffer("yo".getBytes()));

            Future<Response> future = Future.value(response);
            return future;
          }
        };

    ServerBuilder.safeBuild(
        service,
        ServerBuilder.get()
            .codec(Http.get())
            .bindTo(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0))
            .name("HttpServer"));
  }
  @Test
  public void test_user_correct_plaintext_password() throws Exception {

    final String providedUsername = "******";
    when(clientCredentialsData.getUsername()).thenReturn(Optional.of(providedUsername));
    final String providedPassword = "******";
    when(clientCredentialsData.getPassword()).thenReturn(Optional.of(providedPassword));
    when(clientCredentialsData.getInetAddress())
        .thenReturn(Optional.of(InetAddress.getLoopbackAddress()));

    final String filePassword = "******";
    when(configuration.getUser(providedUsername)).thenReturn(filePassword);
    when(configuration.isHashed()).thenReturn(false);

    when(passwordComparator.validatePlaintextPassword(filePassword, providedPassword))
        .thenReturn(true);

    fileAuthenticator = new FileAuthenticator(configuration, passwordComparator);
    final Boolean isAuthenticated = fileAuthenticator.checkCredentials(clientCredentialsData);

    assertTrue(isAuthenticated);
  }
  /** Test case for https://issues.apache.org/jira/browse/ZOOKEEPER-2299 */
  @Test
  public void testClientAddress() throws Exception {
    QuorumPeer quorumPeer = new QuorumPeer();
    LocalPeerBean remotePeerBean = new LocalPeerBean(quorumPeer);

    /** Case 1: When cnxnFactory is null */
    String result = remotePeerBean.getClientAddress();
    assertNotNull(result);
    assertEquals(0, result.length());

    /** Case 2: When only client port is configured */
    ServerCnxnFactory cnxnFactory = ServerCnxnFactory.createFactory();
    int clientPort = PortAssignment.unique();
    InetSocketAddress address = new InetSocketAddress(clientPort);
    cnxnFactory.configure(address, 5, false);
    quorumPeer.setCnxnFactory(cnxnFactory);

    result = remotePeerBean.getClientAddress();
    String ipv4 = "0.0.0.0:" + clientPort;
    String ipv6 = "0:0:0:0:0:0:0:0:" + clientPort;
    assertTrue(result.equals(ipv4) || result.equals(ipv6));
    // cleanup
    cnxnFactory.shutdown();

    /** Case 3: When both client port and client address is configured */
    clientPort = PortAssignment.unique();
    InetAddress clientIP = InetAddress.getLoopbackAddress();
    address = new InetSocketAddress(clientIP, clientPort);
    cnxnFactory = ServerCnxnFactory.createFactory();
    cnxnFactory.configure(address, 5, false);
    quorumPeer.setCnxnFactory(cnxnFactory);

    result = remotePeerBean.getClientAddress();
    String expectedResult = clientIP.getHostAddress() + ":" + clientPort;
    assertEquals(expectedResult, result);
    // cleanup
    cnxnFactory.shutdown();
  }
예제 #16
0
 private synchronized RConnection connectLocal() {
   Logger.getLogger(RserveConnectionFactory.class.getName())
       .info("Trying to connect to local Rserve ...");
   RConnection connection = null;
   RserveConnection rserveConnection;
   try {
     Logger.getLogger(RserveConnectionFactory.class.getName())
         .info("Checking for an already running Rserve");
     rserveConnection = new RserveConnection(InetAddress.getLoopbackAddress(), 6311, false);
     connection = rserveConnection.getConnection();
     isLocalServer = true;
     Logger.getLogger(RserveConnectionFactory.class.getName())
         .info("Found an already running Rserve instance!");
     setConnection(connection);
     return connection;
   } catch (RserveException ex) {
     Logger.getLogger(RserveConnectionFactory.class.getName())
         .severe(
             "Received an Rserve Exception: "
                 + ex.getLocalizedMessage()
                 + " with description: "
                 + ex.getRequestErrorDescription());
     Logger.getLogger(RserveConnectionFactory.class.getName())
         .info("Failed to connect to local Rserve ... launching new local instance!");
     connection = startLocalAndConnect();
     if (connection != null) {
       if (connection.isConnected()) {
         isLocalServer = true;
         setConnection(connection);
         Logger.getLogger(RserveConnectionFactory.class.getName()).info("Connected to Rserve!");
         return connection;
       }
     }
   }
   throw new NullPointerException();
 }
예제 #17
0
/**
 * Should we make it singleton?
 *
 * @author Vicho
 */
public class SecureNetworkMessenger implements Runnable {
  private static Map<String, MessageResponder> responders = new HashMap<String, MessageResponder>();
  private static ObjectOutputStream outgoingSerial;
  private static ObjectInputStream incomingSerial;
  private static final InetAddress localhost = InetAddress.getLoopbackAddress();
  private static final int PORT = 2343;
  private static MessageQueue incomingMessagesQueue = MessageQueue.getInstance();
  private static final SecureNetworkMessenger instance = new SecureNetworkMessenger();

  public static SecureNetworkMessenger getSecureInstance() {
    return SecureNetworkMessenger.instance;
  }

  private SecureNetworkMessenger() {
    /*
     * Here we should add the various message responders?
     */

    registerResponder(new AddTicketResponder());
  }

  private void registerResponder(MessageResponder responder) {
    responders.put(responder.getType(), responder);
  }

  public static MessageResponder getResponder(String msgType) {
    return responders.get(msgType);
  }

  @Override
  public void run() {
    SSLServerSocketFactory sslserversocketfactory =
        (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
    SSLServerSocket sslserversocket;
    try {
      System.out.println("Desktop starting at port " + PORT);
      sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket();
      // certificate is made with: "keytool -genkey keystore -keyalg RSA"
      // this below is a 'hack' (the hack was adding all cipher suites, this is the only one we need
      sslserversocket.setEnabledCipherSuites(new String[] {"SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"});

      sslserversocket.bind(new InetSocketAddress(localhost, PORT));

      SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

      InputStream inputstream = sslsocket.getInputStream();
      OutputStream outputstream = sslsocket.getOutputStream();

      outgoingSerial = new ObjectOutputStream(outputstream);
      incomingSerial =
          new ObjectInputStream(inputstream) {
            //    			@Override
            //				public Object readObject(){
            //
            //    			}
          };
    } catch (IOException e) {
      e.printStackTrace();
    }
    sendNewTicketType();
    //		executor.scheduleAtFixedRate(new Runnable() {
    //
    //			@Override
    //			public void run() {
    while (true) {
      waitForMessages();
    }
    //				System.out.println("are we finished?");
    //
    //			}
    //		}, 0, 50, TimeUnit.MILLISECONDS);

    // in the rest of the lifetime...

  }

  private static void sendNewTicketType() {
    TicketType tt = new TicketType("the reason", 5, 3);
    NetworkMessage tobesent = new NetworkMessage(Messages.ADD_TICKET_TYPE, tt);
    try {
      outgoingSerial.writeObject(tobesent);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // taken from the messenger:

  private void waitForMessages() {
    Object message = null;
    System.out.println("x");
    try {
      if ((message = incomingSerial.readObject()) != null) {
        NetworkMessage incomingMessage = (NetworkMessage) message;
        System.out.println("recieved it!");
        if (incomingMessage == null
            || incomingMessage.getData() == null
            || incomingMessage.getType() == null
            || incomingMessage.getType() == "") {
          System.out.println("it is corrupt!");

          return;
        }
        try {
          System.out.println("getting on board..");
          incomingMessagesQueue.put(incomingMessage);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public boolean sendMessage(String msgType, Serializable data) {
    NetworkMessage message = new NetworkMessage(msgType, data);
    try {
      outgoingSerial.writeObject(message);
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }
}
  @Test
  public void sendIdempotent() throws Exception {
    TestReceiver serverReceiver = new TestReceiver();
    Function<Transport, FixpSession> clientAcceptor =
        new Function<Transport, FixpSession>() {

          public FixpSession apply(Transport serverTransport) {
            try {
              FixpSession serverSession =
                  FixpSession.builder()
                      .withReactor(engine.getReactor())
                      .withTransport(serverTransport)
                      .withBufferSupplier(
                          new SingleBufferSupplier(
                              ByteBuffer.allocate(16 * 1024).order(ByteOrder.nativeOrder())))
                      .withMessageConsumer(serverReceiver)
                      .withOutboundFlow(FlowType.Idempotent)
                      .withOutboundKeepaliveInterval(keepAliveInterval)
                      .asServer()
                      .build();

              serverSession.open();

              return serverSession;
            } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
            return null;
          }
        };

    KeyStore ksKeys = Crypto.createKeyStore();
    Crypto.addKeyCertificateEntry(ksKeys, "exchange", "CN=trading, O=myorg, C=US", storePassphrase);

    KeyStore ksTrust = Crypto.createKeyStore();
    Crypto.addKeyCertificateEntry(
        ksTrust, "customer", "CN=Trader1, O=SomeFCM, C=US", storePassphrase);

    final InetSocketAddress serverAddress =
        new InetSocketAddress(InetAddress.getLoopbackAddress(), 7741);

    try (TlsTcpAcceptor tcpAcceptor =
        new TlsTcpAcceptor(
            engine.getIOReactor().getSelector(),
            serverAddress,
            ksKeys,
            ksTrust,
            storePassphrase,
            clientAcceptor)) {
      tcpAcceptor.open().get();

      Transport clientTransport =
          new TlsTcpConnectorTransport(
              engine.getIOReactor().getSelector(), serverAddress, ksTrust, ksKeys, storePassphrase);
      TestReceiver clientReceiver = new TestReceiver();
      UUID sessionId = SessionId.generateUUID();

      FixpSession clientSession =
          FixpSession.builder()
              .withReactor(reactor2)
              .withTransport(clientTransport)
              .withBufferSupplier(
                  new SingleBufferSupplier(
                      ByteBuffer.allocate(16 * 1024).order(ByteOrder.nativeOrder())))
              .withMessageConsumer(clientReceiver)
              .withOutboundFlow(FlowType.Idempotent)
              .withSessionId(sessionId)
              .withClientCredentials(userCredentials.getBytes())
              .withOutboundKeepaliveInterval(keepAliveInterval)
              .build();

      SessionReadyFuture readyFuture = new SessionReadyFuture(sessionId, reactor2);
      // Completes when transport is established or throws if IO error
      clientSession.open().get(1000, TimeUnit.MILLISECONDS);
      // Completes when FIXP session is established
      readyFuture.get(3000, TimeUnit.MILLISECONDS);

      ByteBuffer buf = ByteBuffer.allocate(8096).order(ByteOrder.nativeOrder());
      int bytesSent = 0;
      for (int i = 0; i < messageCount; ++i) {
        buf.clear();
        bytesSent += encodeApplicationMessageWithFrame(buf, messages[i]);
        clientSession.send(buf);
      }

      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {

      }
      assertEquals(messageCount, serverReceiver.getMsgsReceived());

      SessionTerminatedFuture terminatedFuture = new SessionTerminatedFuture(sessionId, reactor2);
      clientSession.close();
      terminatedFuture.get(1000, TimeUnit.MILLISECONDS);
    }
  }
예제 #19
0
/**
 * @author V. Arun
 *     <p>This class has no special fields in addition to a generic ClientReconfigurationPacket. It
 *     just needs information about isFailed(), the correct set of reconfigurators, and the response
 *     message, all of which are in ClientReconfigurationPacket anyway.
 */
public class DeleteServiceName extends ClientReconfigurationPacket {

  /** Needed for unstringing InetSocketAddresses. */
  protected static final Stringifiable<InetSocketAddress> unstringer =
      new StringifiableDefault<InetSocketAddress>(
          new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));

  /** @param name */
  public DeleteServiceName(String name) {
    this(null, name, 0);
  }

  /**
   * @param initiator
   * @param name
   * @param epochNumber
   */
  public DeleteServiceName(InetSocketAddress initiator, String name, int epochNumber) {
    this(initiator, name, epochNumber, null);
  }

  /**
   * @param initiator
   * @param name
   * @param epochNumber
   * @param myReceiver
   */
  public DeleteServiceName(
      InetSocketAddress initiator, String name, int epochNumber, InetSocketAddress myReceiver) {
    super(
        initiator,
        ReconfigurationPacket.PacketType.DELETE_SERVICE_NAME,
        name,
        epochNumber,
        myReceiver);
  }

  /**
   * @param json
   * @param unstringer
   * @throws JSONException
   */
  public DeleteServiceName(JSONObject json, Stringifiable<?> unstringer) throws JSONException {
    super(json, DeleteServiceName.unstringer); // ignores unstringer
    // assert (this.getSender() != null) : json;
    // this.setSender(JSONNIOTransport.getSenderAddress(json));
  }

  /**
   * @param json
   * @throws JSONException
   */
  public DeleteServiceName(JSONObject json) throws JSONException {
    this(json, unstringer);
  }

  public JSONObject toJSONObjectImpl() throws JSONException {
    JSONObject json = super.toJSONObjectImpl();
    return json;
  }
}
public class PircBotXChatServiceTest extends AbstractPlainJavaFxTest {

  public static final String CHAT_USER_NAME = "junit";
  public static final String CHAT_PASSWORD = "******";
  private static final InetAddress LOOPBACK_ADDRESS = InetAddress.getLoopbackAddress();
  private static final long TIMEOUT = 3000;
  private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
  private static final String DEFAULT_CHANNEL_NAME = "#defaultChannel";
  private static final String OTHER_CHANNEL_NAME = "#otherChannel";
  private static final int IRC_SERVER_PORT = 123;
  private PircBotXChatService instance;

  private ChatUser chatUser1;
  private ChatUser chatUser2;

  @Mock private User user1;
  @Mock private User user2;
  @Mock private Channel defaultChannel;
  @Mock private PircBotX pircBotX;
  @Mock private Configuration configuration;
  @Mock private ListenerManager listenerManager;
  @Mock private UserChannelDaoSnapshot daoSnapshot;
  @Mock private UserSnapshot userSnapshot;
  @Mock private ChannelSnapshot channelSnapshot;
  @Mock private OutputIRC outputIrc;
  @Mock private UserService userService;
  @Mock private TaskService taskService;
  @Mock private PreferencesService preferencesService;
  @Mock private Preferences preferences;
  @Mock private ChatPrefs chatPrefs;
  @Mock private I18n i18n;
  @Mock private PircBotXFactory pircBotXFactory;
  @Mock private UserChannelDao<User, Channel> userChannelDao;
  @Mock private MapProperty<String, Color> userToColorProperty;
  @Mock private ObjectProperty<ChatColorMode> chatColorMode;
  @Mock private FafService fafService;
  @Mock private ExecutorService executorService;
  @Mock private UserHostmask userHostMask;

  private CountDownLatch botShutdownLatch;
  private CompletableFuture<Object> botStartedFuture;
  private BooleanProperty loggedInProperty;

  @Before
  public void setUp() throws Exception {
    instance = new PircBotXChatService();
    instance.fafService = fafService;
    instance.userService = userService;
    instance.taskService = taskService;
    instance.i18n = i18n;
    instance.pircBotXFactory = pircBotXFactory;
    instance.preferencesService = preferencesService;
    instance.executorService = executorService;

    chatUser1 = new ChatUser("chatUser1", null);
    chatUser2 = new ChatUser("chatUser2", null);
    loggedInProperty = new SimpleBooleanProperty();

    botShutdownLatch = new CountDownLatch(1);

    userToColorProperty = new SimpleMapProperty<>(FXCollections.observableHashMap());
    chatColorMode = new SimpleObjectProperty<>(CUSTOM);

    when(userService.getUsername()).thenReturn(CHAT_USER_NAME);
    when(userService.getPassword()).thenReturn(CHAT_PASSWORD);
    when(userService.loggedInProperty()).thenReturn(loggedInProperty);

    when(user1.getNick()).thenReturn(chatUser1.getUsername());
    when(user1.getChannels()).thenReturn(ImmutableSortedSet.of(defaultChannel));
    when(user1.getUserLevels(defaultChannel)).thenReturn(ImmutableSortedSet.of(UserLevel.VOICE));

    when(user2.getNick()).thenReturn(chatUser2.getUsername());
    when(user2.getChannels()).thenReturn(ImmutableSortedSet.of(defaultChannel));
    when(user2.getUserLevels(defaultChannel)).thenReturn(ImmutableSortedSet.of(UserLevel.VOICE));

    when(defaultChannel.getName()).thenReturn(DEFAULT_CHANNEL_NAME);
    when(pircBotX.getConfiguration()).thenReturn(configuration);
    when(pircBotX.sendIRC()).thenReturn(outputIrc);
    when(pircBotX.getUserChannelDao()).thenReturn(userChannelDao);

    doAnswer(
            invocation -> {
              CompletableFuture<Object> future = new CompletableFuture<>();
              WaitForAsyncUtils.async(
                  () -> {
                    invocation.getArgumentAt(0, Task.class).run();
                    future.complete(null);
                  });
              return future;
            })
        .when(executorService)
        .submit(any(Task.class));

    botStartedFuture = new CompletableFuture<>();
    doAnswer(
            invocation -> {
              botStartedFuture.complete(true);
              botShutdownLatch.await();
              return null;
            })
        .when(pircBotX)
        .startBot();

    when(pircBotXFactory.createPircBotX(any())).thenReturn(pircBotX);
    when(configuration.getListenerManager()).thenReturn(listenerManager);

    instance.ircHost = LOOPBACK_ADDRESS.getHostAddress();
    instance.ircPort = IRC_SERVER_PORT;
    instance.defaultChannelName = DEFAULT_CHANNEL_NAME;
    instance.reconnectDelay = 100;

    when(preferencesService.getPreferences()).thenReturn(preferences);
    when(preferences.getChat()).thenReturn(chatPrefs);

    when(chatPrefs.userToColorProperty()).thenReturn(userToColorProperty);
    when(chatPrefs.chatColorModeProperty()).thenReturn(chatColorMode);

    instance.postConstruct();
  }

  @After
  public void tearDown() {
    instance.close();
    botShutdownLatch.countDown();
  }

  @Test
  public void testOnChatUserList() throws Exception {
    ObservableMap<String, ChatUser> usersForChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);
    assertThat(usersForChannel.values(), empty());

    Map<String, ChatUser> users = new HashMap<>();
    users.put(chatUser1.getUsername(), chatUser1);
    users.put(chatUser2.getUsername(), chatUser2);

    instance.onChatUserList(DEFAULT_CHANNEL_NAME, users);

    assertThat(usersForChannel.values(), hasSize(2));
    assertThat(usersForChannel.get(chatUser1.getUsername()), sameInstance(chatUser1));
    assertThat(usersForChannel.get(chatUser2.getUsername()), sameInstance(chatUser2));
  }

  @Test
  public void testOnUserJoinedChannel() throws Exception {
    ObservableMap<String, ChatUser> usersForChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);
    assertThat(usersForChannel.values(), empty());

    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser2);

    assertThat(usersForChannel.values(), hasSize(2));
    assertThat(usersForChannel.get(chatUser1.getUsername()), sameInstance(chatUser1));
    assertThat(usersForChannel.get(chatUser2.getUsername()), sameInstance(chatUser2));
  }

  @Test
  public void testOnChatUserLeftChannel() throws Exception {
    ObservableMap<String, ChatUser> usersForChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);
    assertThat(usersForChannel.values(), empty());

    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser2);
    instance.onChatUserLeftChannel(chatUser1.getUsername(), DEFAULT_CHANNEL_NAME);

    assertThat(usersForChannel.values(), hasSize(1));
    assertThat(usersForChannel.get(chatUser2.getUsername()), sameInstance(chatUser2));
  }

  @Test
  public void testOnChatUserQuit() throws Exception {
    ObservableMap<String, ChatUser> usersForChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);
    assertThat(usersForChannel.values(), empty());

    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser2);
    instance.onChatUserQuit(chatUser1.getUsername());

    assertThat(usersForChannel.values(), hasSize(1));
    assertThat(usersForChannel.get(chatUser2.getUsername()), sameInstance(chatUser2));
  }

  @Test
  public void testAddOnMessageListenerWithMessage() throws Exception {
    CompletableFuture<String> channelNameFuture = new CompletableFuture<>();
    CompletableFuture<ChatMessage> chatMessageFuture = new CompletableFuture<>();
    instance.addOnMessageListener(
        (channelName, chatMessage) -> {
          channelNameFuture.complete(channelName);
          chatMessageFuture.complete(chatMessage);
        });

    String message = "chat message";

    User user = mock(User.class);
    when(user.getNick()).thenReturn(chatUser1.getUsername());

    Channel channel = mock(Channel.class);
    when(channel.getName()).thenReturn(DEFAULT_CHANNEL_NAME);

    UserHostmask userHostMask = mock(UserHostmask.class);
    ImmutableMap<String, String> tags = new ImmutableMap.Builder<String, String>().build();
    instance.onEvent(
        new MessageEvent(
            pircBotX, channel, DEFAULT_CHANNEL_NAME, userHostMask, user, message, tags));

    assertThat(channelNameFuture.get(), is(DEFAULT_CHANNEL_NAME));
    assertThat(chatMessageFuture.get().getMessage(), is(message));
    assertThat(chatMessageFuture.get().getUsername(), is(chatUser1.getUsername()));
    assertThat(
        chatMessageFuture.get().getTime(),
        is(greaterThan(Instant.ofEpochMilli(System.currentTimeMillis() - 1000))));
    assertThat(chatMessageFuture.get().isAction(), is(false));
  }

  @Test
  public void testAddOnMessageListenerWithAction() throws Exception {
    CompletableFuture<String> channelNameFuture = new CompletableFuture<>();
    CompletableFuture<ChatMessage> chatMessageFuture = new CompletableFuture<>();
    instance.addOnMessageListener(
        (channelName, chatMessage) -> {
          channelNameFuture.complete(channelName);
          chatMessageFuture.complete(chatMessage);
        });

    String action = "chat action";

    User user = mock(User.class);
    when(user.getNick()).thenReturn(chatUser1.getUsername());

    Channel channel = mock(Channel.class);
    when(channel.getName()).thenReturn(DEFAULT_CHANNEL_NAME);

    UserHostmask userHostMask = mock(UserHostmask.class);
    instance.onEvent(
        new ActionEvent(pircBotX, userHostMask, user, channel, DEFAULT_CHANNEL_NAME, action));

    assertThat(channelNameFuture.get(), is(DEFAULT_CHANNEL_NAME));
    assertThat(chatMessageFuture.get().getMessage(), is(action));
    assertThat(chatMessageFuture.get().getUsername(), is(chatUser1.getUsername()));
    assertThat(
        chatMessageFuture.get().getTime(),
        is(greaterThan(Instant.ofEpochMilli(System.currentTimeMillis() - 1000))));
    assertThat(chatMessageFuture.get().isAction(), is(true));
  }

  @Test
  public void testAddOnPrivateChatMessageListener() throws Exception {
    CompletableFuture<String> usernameFuture = new CompletableFuture<>();
    CompletableFuture<ChatMessage> chatMessageFuture = new CompletableFuture<>();
    instance.addOnPrivateChatMessageListener(
        (username, chatMessage) -> {
          usernameFuture.complete(username);
          chatMessageFuture.complete(chatMessage);
        });

    String message = "private message";

    User user = mock(User.class);
    when(user.getNick()).thenReturn(chatUser1.getUsername());

    Channel channel = mock(Channel.class);
    when(channel.getName()).thenReturn(DEFAULT_CHANNEL_NAME);

    UserHostmask userHostMask = mock(UserHostmask.class);
    instance.onEvent(new PrivateMessageEvent(pircBotX, userHostMask, user, message));

    assertThat(chatMessageFuture.get().getMessage(), is(message));
    assertThat(chatMessageFuture.get().getUsername(), is(chatUser1.getUsername()));
    assertThat(
        chatMessageFuture.get().getTime(),
        is(greaterThan(Instant.ofEpochMilli(System.currentTimeMillis() - 1000))));
    assertThat(chatMessageFuture.get().isAction(), is(false));
  }

  @Test
  public void testAddOnChatConnectedListener() throws Exception {
    CompletableFuture<Boolean> onChatConnectedFuture = new CompletableFuture<>();

    instance
        .connectionStateProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              switch (newValue) {
                case CONNECTED:
                  onChatConnectedFuture.complete(null);
                  break;
              }
            });

    String password = "******";
    when(userService.getPassword()).thenReturn(password);

    mockTaskService();

    instance.onEvent(new ConnectEvent(pircBotX));

    assertThat(onChatConnectedFuture.get(TIMEOUT, TIMEOUT_UNIT), is(nullValue()));
  }

  @SuppressWarnings("unchecked")
  private void mockTaskService() {
    doAnswer(
            (InvocationOnMock invocation) -> {
              PrioritizedTask<Boolean> prioritizedTask =
                  invocation.getArgumentAt(0, PrioritizedTask.class);
              prioritizedTask.run();

              Future<Boolean> result = WaitForAsyncUtils.asyncFx(prioritizedTask::getValue);
              return CompletableFuture.completedFuture(result.get(1, TimeUnit.SECONDS));
            })
        .when(instance.taskService)
        .submitTask(any());
  }

  @Test
  public void testAddOnUserListListener() throws Exception {
    CompletableFuture<String> channelNameFuture = new CompletableFuture<>();
    CompletableFuture<Map<String, ChatUser>> usersFuture = new CompletableFuture<>();
    instance.addOnUserListListener(
        (channelName, users) -> {
          channelNameFuture.complete(channelName);
          usersFuture.complete(users);
        });
    when(chatPrefs.getChatColorMode()).thenReturn(chatColorMode.get());
    when(chatPrefs.getUserToColor()).thenReturn(userToColorProperty);

    when(user2.compareTo(user1)).thenReturn(1);
    ImmutableSortedSet<User> users = ImmutableSortedSet.of(user1, user2);
    instance.onEvent(new UserListEvent(pircBotX, defaultChannel, users, true));

    assertThat(channelNameFuture.get(TIMEOUT, TIMEOUT_UNIT), is(DEFAULT_CHANNEL_NAME));

    Map<String, ChatUser> userMap = usersFuture.get(TIMEOUT, TIMEOUT_UNIT);
    assertThat(userMap.values(), hasSize(2));
    assertThat(userMap.get(chatUser1.getUsername()), is(chatUser1));
    assertThat(userMap.get(chatUser2.getUsername()), is(chatUser2));
  }

  @Test
  public void testAddOnChatDisconnectedListener() throws Exception {
    CompletableFuture<Void> onChatDisconnectedFuture = new CompletableFuture<>();
    instance
        .connectionStateProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              switch (newValue) {
                case DISCONNECTED:
                  onChatDisconnectedFuture.complete(null);
                  break;
              }
            });

    instance.onEvent(new DisconnectEvent(pircBotX, daoSnapshot, null));

    onChatDisconnectedFuture.get(TIMEOUT, TIMEOUT_UNIT);
  }

  @Test
  public void testAddOnChatUserJoinedChannelListener() throws Exception {
    when(chatPrefs.getChatColorMode()).thenReturn(chatColorMode.get());
    when(chatPrefs.getUserToColor()).thenReturn(userToColorProperty);

    CompletableFuture<String> channelNameFuture = new CompletableFuture<>();
    CompletableFuture<ChatUser> userFuture = new CompletableFuture<>();
    instance.addOnChatUserJoinedChannelListener(
        (channelName, chatUser) -> {
          channelNameFuture.complete(channelName);
          userFuture.complete(chatUser);
        });

    instance.onEvent(new JoinEvent(pircBotX, defaultChannel, userHostMask, user1));

    assertThat(channelNameFuture.get(TIMEOUT, TIMEOUT_UNIT), is(DEFAULT_CHANNEL_NAME));
    assertThat(userFuture.get(TIMEOUT, TIMEOUT_UNIT), is(chatUser1));
  }

  @Test
  public void testAddOnChatUserLeftChannelListener() throws Exception {
    CompletableFuture<String> usernameFuture = new CompletableFuture<>();
    CompletableFuture<String> channelNameFuture = new CompletableFuture<>();
    instance.addOnChatUserLeftChannelListener(
        (username, channelName) -> {
          usernameFuture.complete(username);
          channelNameFuture.complete(channelName);
        });

    when(channelSnapshot.getName()).thenReturn(DEFAULT_CHANNEL_NAME);
    when(userSnapshot.getNick()).thenReturn(chatUser1.getUsername());

    String reason = "Part reason";
    instance.onEvent(
        new PartEvent(pircBotX, daoSnapshot, channelSnapshot, userHostMask, userSnapshot, reason));

    assertThat(channelNameFuture.get(TIMEOUT, TIMEOUT_UNIT), is(DEFAULT_CHANNEL_NAME));
    assertThat(usernameFuture.get(TIMEOUT, TIMEOUT_UNIT), is(chatUser1.getUsername()));
  }

  @Test
  public void testAddOnModeratorSetListener() throws Exception {

    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);

    ObservableSet<String> moderatorInChannels =
        instance
            .getChatUsersForChannel(DEFAULT_CHANNEL_NAME)
            .get(chatUser1.getUsername())
            .getModeratorInChannels();

    assertThat(moderatorInChannels, empty());

    instance.onModeratorSet(DEFAULT_CHANNEL_NAME, chatUser1.getUsername());

    assertThat(moderatorInChannels, hasSize(1));
    assertThat(moderatorInChannels.iterator().next(), is(DEFAULT_CHANNEL_NAME));
  }

  @Test
  public void testAddOnChatUserQuitListener() throws Exception {
    CompletableFuture<Boolean> quitFuture = new CompletableFuture<>();
    instance.addOnChatUserQuitListener((username) -> quitFuture.complete(true));

    instance.onEvent(new QuitEvent(pircBotX, daoSnapshot, userHostMask, userSnapshot, "reason"));

    assertThat(quitFuture.get(TIMEOUT, TIMEOUT_UNIT), is(true));
  }

  @Test
  @SuppressWarnings("unchecked")
  public void testConnect() throws Exception {
    ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);

    instance.connect();
    botStartedFuture.get(TIMEOUT, TIMEOUT_UNIT);

    verify(pircBotX).startBot();
    verify(pircBotXFactory).createPircBotX(captor.capture());
    Configuration configuration = captor.getValue();

    assertThat(configuration.getName(), is(CHAT_USER_NAME));
    assertThat(configuration.getLogin(), is(CHAT_USER_NAME));
    assertThat(configuration.getRealName(), is(CHAT_USER_NAME));
    assertThat(
        configuration.getServers().get(0).getHostname(), is(LOOPBACK_ADDRESS.getHostAddress()));
    assertThat(configuration.getServers().get(0).getPort(), is(IRC_SERVER_PORT));
  }

  @Test
  public void testReconnect() throws Exception {
    CompletableFuture<Boolean> firstStartFuture = new CompletableFuture<>();
    CompletableFuture<Boolean> secondStartFuture = new CompletableFuture<>();
    doAnswer(
            invocation -> {
              if (!firstStartFuture.isDone()) {
                firstStartFuture.complete(true);
                throw new IOException("test exception");
              }

              secondStartFuture.complete(true);
              botShutdownLatch.await();
              return null;
            })
        .when(pircBotX)
        .startBot();

    instance.connect();
    firstStartFuture.get(TIMEOUT, TIMEOUT_UNIT);

    secondStartFuture.get(TIMEOUT, TIMEOUT_UNIT);

    verify(pircBotX, times(2)).startBot();
  }

  @Test
  @SuppressWarnings("unchecked")
  public void testSendMessageInBackground() throws Exception {
    instance.connect();

    String message = "test message";

    mockTaskService();

    CompletableFuture<String> future =
        instance.sendMessageInBackground(DEFAULT_CHANNEL_NAME, message);

    assertThat(future.get(TIMEOUT, TIMEOUT_UNIT), is(message));
    verify(pircBotX).sendIRC();
    verify(outputIrc).message(DEFAULT_CHANNEL_NAME, message);
  }

  @Test
  public void testGetChatUsersForChannelEmpty() throws Exception {
    ObservableMap<String, ChatUser> chatUsersForChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);
    assertThat(chatUsersForChannel.values(), empty());
  }

  @Test
  public void testGetChatUsersForChannelTwoUsersInDifferentChannel() throws Exception {
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    instance.onUserJoinedChannel(OTHER_CHANNEL_NAME, chatUser2);

    ObservableMap<String, ChatUser> chatUsersForDefaultChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);
    ObservableMap<String, ChatUser> chatUsersForOtherChannel =
        instance.getChatUsersForChannel(OTHER_CHANNEL_NAME);

    assertThat(chatUsersForDefaultChannel.values(), hasSize(1));
    assertThat(chatUsersForDefaultChannel.values().iterator().next(), sameInstance(chatUser1));
    assertThat(chatUsersForOtherChannel.values(), hasSize(1));
    assertThat(chatUsersForOtherChannel.values().iterator().next(), sameInstance(chatUser2));
  }

  @Test
  public void testGetChatUsersForChannelTwoUsersInSameChannel() throws Exception {
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser2);

    ObservableMap<String, ChatUser> chatUsersForDefaultChannel =
        instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME);

    assertThat(chatUsersForDefaultChannel.values(), hasSize(2));
    assertThat(chatUsersForDefaultChannel.values(), containsInAnyOrder(chatUser1, chatUser2));
  }

  @Test
  public void testAddChannelUserListListener() throws Exception {
    @SuppressWarnings("unchecked")
    MapChangeListener<String, ChatUser> listener = mock(MapChangeListener.class);

    instance.addChannelUserListListener(DEFAULT_CHANNEL_NAME, listener);
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser2);

    verify(listener, times(2)).onChanged(any());
  }

  @Test
  public void testLeaveChannel() throws Exception {
    OutputChannel outputChannel = mock(OutputChannel.class);

    when(userChannelDao.getChannel(DEFAULT_CHANNEL_NAME)).thenReturn(defaultChannel);
    when(defaultChannel.send()).thenReturn(outputChannel);

    instance.connect();
    instance.leaveChannel(DEFAULT_CHANNEL_NAME);

    verify(outputChannel).part();
  }

  @Test
  public void testSendActionInBackground() throws Exception {
    instance.connect();

    String action = "test action";

    when(taskService.submitTask(any())).thenReturn(CompletableFuture.completedFuture(action));
    mockTaskService();

    CompletableFuture<String> future =
        instance.sendActionInBackground(DEFAULT_CHANNEL_NAME, action);

    verify(pircBotX).sendIRC();
    verify(outputIrc).action(DEFAULT_CHANNEL_NAME, action);
    assertThat(future.get(TIMEOUT, TIMEOUT_UNIT), is(action));
  }

  @Ignore("hangs when run with other tests")
  @Test
  public void testJoinChannel() throws Exception {
    CountDownLatch connectedLatch = new CountDownLatch(1);
    String channelToJoin = "#anotherChannel";
    doAnswer(
            invocation -> {
              connectedLatch.countDown();
              return null;
            })
        .when(outputIrc)
        .joinChannel(DEFAULT_CHANNEL_NAME);

    when(taskService.submitTask(any())).thenReturn(CompletableFuture.completedFuture(null));

    instance.connect();
    instance.connectionStateProperty().set(ConnectionState.CONNECTED);

    assertTrue(connectedLatch.await(TIMEOUT, TIMEOUT_UNIT));

    instance.joinChannel(channelToJoin);

    verify(outputIrc).joinChannel(DEFAULT_CHANNEL_NAME);
    verify(outputIrc).joinChannel(channelToJoin);
  }

  @Test
  @SuppressWarnings("unchecked")
  public void testAddOnJoinChannelsRequestListener() throws Exception {
    Consumer<List<String>> listener = mock(Consumer.class);

    instance.addOnJoinChannelsRequestListener(listener);

    verify(fafService).addOnMessageListener(eq(SocialMessage.class), any());
  }

  @Test
  public void testIsDefaultChannel() throws Exception {
    assertTrue(instance.isDefaultChannel(DEFAULT_CHANNEL_NAME));
  }

  @Test
  public void testOnConnected() throws Exception {
    String password = "******";

    when(userService.getPassword()).thenReturn(password);
    instance.connect();

    botStartedFuture.get(TIMEOUT, TIMEOUT_UNIT);

    CountDownLatch latch = new CountDownLatch(1);
    doAnswer(
            invocation -> {
              latch.countDown();
              return null;
            })
        .when(outputIrc)
        .joinChannel(DEFAULT_CHANNEL_NAME);

    mockTaskService();
    instance.connectionStateProperty().set(ConnectionState.CONNECTED);

    String md5Password = Hashing.md5().hashString(password, StandardCharsets.UTF_8).toString();
    verify(outputIrc).message("NICKSERV", String.format("IDENTIFY %s", md5Password));

    assertTrue("Channel has not been joined within timeout", latch.await(TIMEOUT, TIMEOUT_UNIT));
  }

  private String asdf() {
    return null;
  }

  @Test
  public void testOnDisconnected() throws Exception {
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    assertThat(instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME).values(), hasSize(1));

    instance.connectionStateProperty().set(ConnectionState.DISCONNECTED);

    assertThat(instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME).values(), empty());
  }

  @Test
  public void testOnModeratorSet() throws Exception {
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    ObservableSet<String> moderatorInChannels =
        instance
            .getChatUsersForChannel(DEFAULT_CHANNEL_NAME)
            .get(chatUser1.getUsername())
            .getModeratorInChannels();

    assertThat(moderatorInChannels, empty());

    instance.onModeratorSet(DEFAULT_CHANNEL_NAME, chatUser1.getUsername());

    assertThat(moderatorInChannels, contains(DEFAULT_CHANNEL_NAME));
  }

  @Test
  public void testOnModeratorSetUserNotInChannelDoesntThrowException() throws Exception {
    instance.onModeratorSet(DEFAULT_CHANNEL_NAME, chatUser1.getUsername());
  }

  @Test
  public void testClose() {
    instance.close();
  }

  @Test
  public void testOnConnectedAutomaticallyRegisters() {}

  @Test
  public void testCreateOrGetChatUserStringEmptyMap() throws Exception {
    when(chatPrefs.getChatColorMode()).thenReturn(chatColorMode.get());
    when(chatPrefs.getUserToColor()).thenReturn(userToColorProperty);

    ChatUser returnedUser = instance.createOrGetChatUser("chatUser1");

    assert returnedUser != chatUser1;
    assertEquals(returnedUser, chatUser1);
  }

  @Test
  public void testCreateOrGetChatUserStringPopulatedMap() throws Exception {
    when(chatPrefs.getChatColorMode()).thenReturn(chatColorMode.get());
    when(chatPrefs.getUserToColor()).thenReturn(userToColorProperty);

    ChatUser addedUser = instance.createOrGetChatUser("chatUser1");
    ChatUser returnedUser = instance.createOrGetChatUser("chatUser1");

    assert returnedUser == addedUser;
    assertEquals(returnedUser, addedUser);
  }

  @Test
  public void testCreateOrGetChatUserUserObjectEmptyMap() throws Exception {
    when(chatPrefs.getChatColorMode()).thenReturn(chatColorMode.get());
    when(chatPrefs.getUserToColor()).thenReturn(userToColorProperty);

    ChatUser returnedUser = instance.createOrGetChatUser("chatUser1");

    assert returnedUser != chatUser1;
    assertEquals(returnedUser, chatUser1);
  }

  @Test
  public void testCreateOrGetChatUserUserObjectPopulatedMap() throws Exception {
    when(chatPrefs.getChatColorMode()).thenReturn(chatColorMode.get());
    when(chatPrefs.getUserToColor()).thenReturn(userToColorProperty);

    ChatUser addedUser = instance.createOrGetChatUser("chatUser1");
    ChatUser returnedUser = instance.createOrGetChatUser("chatUser1");

    assert returnedUser == addedUser;
    assertEquals(returnedUser, addedUser);
  }
}
예제 #21
0
  public static void main(String[] args) {

    esAddress = InetAddress.getLoopbackAddress();

    final Options options = new Options();
    options.addOption("h", "help", false, "print this message");
    options.addOption(
        "A",
        "autocorrect",
        false,
        "enables auto correction:"
            + newline
            + "- try to fix lines with less columns than the header specifies"
            + newline
            + "- if only one date column could be parsed assign this value to both date fields"
            + newline
            + "(for catalog parsing only)");
    options.addOption("c", "catalog", false, "parse and import cdfinder/neofinder catalog files");
    options.addOption(
        "r",
        "readerrors",
        false,
        "ignore read errors" + newline + "(for file system scanning only)");
    options.addOption(
        "n",
        "newindex",
        false,
        "create a new elasticsearch index "
            + newline
            + "(if an old one with the same name exists it will be deleted)");
    options.addOption("v", "verbose", false, "show JSON objects that are added to the index");
    options.addOption(
        Option.builder("a")
            .longOpt("address")
            .desc(
                "the address of the elasticsearch index "
                    + newline
                    + "(omitting this the local loopback address will be used)")
            .hasArg()
            .argName("ADDRESS")
            .build());
    options.addOption(
        Option.builder("i")
            .longOpt("indexname")
            .desc(
                "the name of the elasticsearch index "
                    + newline
                    + "(omitting this the name '"
                    + esIndexName
                    + "' will be used)")
            .hasArg()
            .argName("NAME")
            .build());
    options.addOption(
        Option.builder("I")
            .longOpt("ignore")
            .desc(
                "the field or fields to ignore potentially invalid data for"
                    + newline
                    + "if multiple fields are specified they must be comma separated"
                    + newline
                    + "(use with care as this may create records that will miss the specified fields)"
                    + newline
                    + "(for catalog parsing only)")
            .hasArgs()
            .valueSeparator(',')
            .argName("FIELDLIST")
            .build());
    options.addOption(
        Option.builder("e")
            .longOpt("esclustername")
            .desc(
                "the name of the elasticsearch cluster "
                    + newline
                    + "(omitting this the default name 'elasticsearch' will be used)")
            .hasArg()
            .argName("NAME")
            .build());
    options.addOption(
        Option.builder("m")
            .longOpt("mimetype")
            .desc(
                "the mime type fetch strategy to use:"
                    + newline
                    + "0: no mime type information is fetched (default)"
                    + newline
                    + "1: mime type is 'guessed' based on file extension"
                    + newline
                    + "2: mime type is detected by inspecting the file (most accurate but slow)"
                    + newline
                    + "(for file system scanning only)")
            .hasArg()
            .argName("STRATEGY")
            .build());
    options.addOption(
        Option.builder()
            .longOpt("iknowiamonlyimportingpathandvolume")
            .desc("import only path and volume" + newline + "(for catalog parsing only)")
            .build());

    String address = "";
    List<String> argList = null;
    try {
      final CommandLineParser parser = new DefaultParser();
      final CommandLine cmd = parser.parse(options, args);
      argList = cmd.getArgList();
      if (!argList.isEmpty()) {
        scanMode = !cmd.hasOption("c");
        autoCorrect = !scanMode && cmd.hasOption("A");
        minimalImport = !scanMode && cmd.hasOption("iknowiamonlyimportingpathandvolume");
        verbose = cmd.hasOption("v");
        if (cmd.hasOption("a")) {
          address = cmd.getOptionValue("a");
          esAddress = InetAddress.getByName(address);
        }
        if (cmd.hasOption("e")) {
          esClusterName = cmd.getOptionValue("e");
        }
        if (cmd.hasOption("i")) {
          esIndexName = cmd.getOptionValue("i");
        }
        if (scanMode && cmd.hasOption("m")) {
          mimeInfo = Integer.valueOf(cmd.getOptionValue("m"));
        }
        if (!scanMode && cmd.hasOption("I")) {
          ignoreFields = Arrays.stream(cmd.getOptionValues("I")).collect(Collectors.toSet());
          Map<String, List<String>> tokenMap = Mapping.getTokenMap();
          for (String field : ignoreFields) {
            if (!tokenMap.containsKey(field)) {
              System.out.println("Unknown field '" + field + "'.");
              System.exit(4);
            }
          }
        }
      } else {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp(
            "neofindertoes [options] FILE_OR_DIRECTORY1 [FILE_OR_DIRECTORY2 "
                + "[FILE_OR_DIRECTORY3] ...]\nOptions:",
            options);
        System.exit(0);
      }

      esService = new ESService(esAddress, esClusterName, esIndexName);
      System.out.println(
          "Elasticsearch cluster: " + esAddress.toString() + " [" + esClusterName + ']');
      if (esService.isClusterAvailable()) {
        if (cmd.hasOption("n")) {
          if (esService.indexExists()) {
            esService.deleteIndex();
          }
          if (!esService.createIndex()) {
            System.out.println("Failed to create elasticsearch index");
            System.exit(3);
          }
          System.out.println("Adding to newly created index '" + esIndexName + "'\n");
        } else {
          if (!esService.indexExists()) {
            if (!esService.createIndex()) {
              System.out.println("Failed to create elasticsearch index");
              System.exit(3);
            }
          }
          System.out.println("Adding to existing index '" + esIndexName + "'\n");
        }
      } else {
        System.exit(7);
      }
    } catch (ParseException ex) {
      if (ex instanceof UnrecognizedOptionException) {
        System.out.println(ex.getMessage());
        System.exit(1);
      }
      System.out.println("Failed to parse command line options.\n" + ex.getMessage());
      System.exit(2);
    } catch (UnknownHostException ex) {
      System.out.println("Host '" + address + "' not found.");
      System.exit(6);
    }

    final ProgressRotating progressIndicator = new ProgressRotating();
    for (String filename : argList) {
      try {
        File scanDirectory = new File(filename).getCanonicalFile();

        if (!scanDirectory.exists()) {
          System.err.println("Source '" + filename + "' does not exist.");
          continue;
        }

        if (!progressIndicator.isAlive()) {
          progressIndicator.start();
        }

        if (scanDirectory.isDirectory()) {
          if (scanMode) {
            new FileSystemScanner(esService).scan(scanDirectory, maxThreads, mimeInfo, verbose);
          } else {
            String[] files = scanDirectory.list();
            for (final String file : files) {
              new CsvReader(esService, verbose, progressIndicator)
                  .read(scanDirectory + "/" + file, autoCorrect, ignoreFields, minimalImport);
            }
          }
        } else {
          if (!scanMode) {
            new CsvReader(esService, verbose, progressIndicator)
                .read(scanDirectory.getAbsolutePath(), autoCorrect, ignoreFields, minimalImport);
          }
        }
      } catch (IOException ex) {
        System.out.println("Could not read '" + filename + "'.");
      }
    }

    esService.close();

    if (progressIndicator.isAlive()) {
      progressIndicator.terminate();
    }
  }
/** A builder providing a fluent way of defining EmbeddedLdapRule instances */
public class EmbeddedLdapRuleBuilder {

  public static final String DEFAULT_DOMAIN = "dc=example,dc=com";
  public static final String DEFAULT_BIND_DSN = "cn=Directory manager";
  public static final String DEFAULT_BIND_CREDENTIALS = "password";
  public static final String LDAP_SERVER_LISTENER_NAME = "test-listener";
  public static final int MIN_PORT_EXCLUSIVE = 0;
  public static final int MAX_PORT_EXCLUSIVE = 65535;
  private List<String> domainDsn = new LinkedList<>();

  private String bindDSN = DEFAULT_BIND_DSN;

  private String bindCredentials = DEFAULT_BIND_CREDENTIALS;

  private List<String> ldifsToImport = new LinkedList<>();

  private List<String> schemaLdifs = new LinkedList<>();

  private boolean addDefaultSchema = true;

  private Integer bindPort = 0;

  private InetAddress bindAddress = InetAddress.getLoopbackAddress();

  private AuthenticationConfiguration authenticationConfiguration;

  public EmbeddedLdapRuleBuilder() {}

  /**
   * Creates a new builder
   *
   * @return a new EmbeddedLdapRuleBuilder instance
   */
  public static EmbeddedLdapRuleBuilder newInstance() {
    return new EmbeddedLdapRuleBuilder();
  }

  /**
   * Sets a domainDsn to be used. May be multiple values. If not set, it will default to the value
   * of the {@link #DEFAULT_DOMAIN DEFAULT_DOMAIN} field
   *
   * @param domainDsn a valid DSN string
   * @return same EmbeddedLdapRuleBuilder instance with the domainDsn field set
   */
  public EmbeddedLdapRuleBuilder usingDomainDsn(final String domainDsn) {
    this.domainDsn.add(domainDsn);
    return this;
  }

  /**
   * Sets the DSN to bind to when authenticating. If not set, it will default to the value of the
   * {@link #DEFAULT_BIND_DSN DEFAULT_BIND_DSN} field
   *
   * @param bindDSN a valid DSN string
   * @return same EmbeddedLdapRuleBuilder instance with the bindDSN field set
   */
  public EmbeddedLdapRuleBuilder usingBindDSN(final String bindDSN) {
    this.bindDSN = bindDSN;
    return this;
  }

  /**
   * Sets the credentials to be used to authenticate. If not set, it will default to the value of
   * the {@link #DEFAULT_BIND_CREDENTIALS DEFAULT_BIND_CREDENTIALS} field
   *
   * @param bindCredentials a password string
   * @return same EmbeddedLdapRuleBuilder instance with the bindCredentials field set
   */
  public EmbeddedLdapRuleBuilder usingBindCredentials(final String bindCredentials) {
    this.bindCredentials = bindCredentials;
    return this;
  }

  /**
   * Sets the port that the in-memory LDAP server will bind to. If not set, an available port will
   * be picked automatically
   *
   * @param port a port number
   * @return same EmbeddedLdapRuleBuilder instance with the port field set
   * @throws IllegalArgumentException if the provided value for port is not between @{link
   *     MIN_PORT_EXCLUSIVE} and @{MAX_PORT_EXCLUSIVE} (exclusive)
   */
  public EmbeddedLdapRuleBuilder bindingToPort(final int port) {
    if ((port < MIN_PORT_EXCLUSIVE) || (port > MAX_PORT_EXCLUSIVE)) {
      throw new IllegalArgumentException(
          String.format("Value \"%s\" is not a valid port number", port));
    }
    this.bindPort = Integer.valueOf(port);
    return this;
  }

  /**
   * Allows the listening address for the embedded LDAP server to be set. If not set it will bind to
   * <em>localhost/127.0.0.1</em>.
   *
   * @param address a valid hostname or textual representation of an IP address
   * @return same EmbeddedLdapRuleBuilder instance with the bindAddress field set
   * @throws IllegalArgumentException if the value provided for \"address\" is invalid
   */
  public EmbeddedLdapRuleBuilder bindingToAddress(final String address) {
    Objects.requireNonNull(address);
    try {
      final InetAddress addressByName = InetAddress.getByName(address);
      this.bindAddress = addressByName;
    } catch (UnknownHostException e) {
      throw new IllegalArgumentException(String.format("Unknown host address \"%s\"", address), e);
    }
    return this;
  }

  /**
   * Avoid adding UnboundID's default schema that contains the most common LDAP elements defined
   * through various RFC's.
   *
   * @return same EmbeddedLdapRuleBuilder instance with the withoutDefaultSchema field set to FALSE
   */
  public EmbeddedLdapRuleBuilder withoutDefaultSchema() {
    this.addDefaultSchema = false;
    return this;
  }

  /**
   * Define schemas to be used for the server. If not defined, UnboundID will set up a default
   * schema.
   *
   * @param ldifSchemaFiles LDIF-files containing schema element definitions
   * @return same EmbeddedLdapRuleBuilder with the given LDIF-files added to the internal schema
   *     file collection.
   */
  public EmbeddedLdapRuleBuilder withSchema(final String... ldifSchemaFiles) {
    this.schemaLdifs.addAll(Arrays.asList(ldifSchemaFiles));
    return this;
  }

  /**
   * Specify one or more LDIF resources to be imported on startup.
   *
   * @param ldifFiles LDIF-files to import
   * @return same EmbeddedLdapRuleBuilder instance with the provided ldifFiles added to the list of
   *     LDIF files to import
   */
  public EmbeddedLdapRuleBuilder importingLdifs(final String... ldifFiles) {
    if (ldifFiles != null) {
      ldifsToImport.addAll(Arrays.asList(ldifFiles));
    }
    return this;
  }

  /**
   * Creates a new rule based on the information that was previously provided
   *
   * @return a new EmbeddedLdapRule instance
   */
  public EmbeddedLdapRule build() {
    Objects.requireNonNull(bindDSN, "\"bindDSN\" can not be null");
    return EmbeddedLdapRuleImpl.createForConfiguration(
        createInMemoryServerConfiguration(), authenticationConfiguration, ldifsToImport);
  }

  private InMemoryDirectoryServerConfig createInMemoryServerConfiguration() {
    try {
      final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig =
          new InMemoryDirectoryServerConfig(domainDsnArray());

      if (bindCredentials != null) {
        this.authenticationConfiguration =
            new AuthenticationConfiguration(bindDSN, bindCredentials);
        inMemoryDirectoryServerConfig.addAdditionalBindCredentials(bindDSN, bindCredentials);
      }

      final InMemoryListenerConfig listenerConfig =
          InMemoryListenerConfig.createLDAPConfig(
              LDAP_SERVER_LISTENER_NAME, bindAddress, bindPort, null);
      inMemoryDirectoryServerConfig.setListenerConfigs(listenerConfig);
      for (Schema s : customSchema().asSet()) {
        inMemoryDirectoryServerConfig.setSchema(s);
      }
      return inMemoryDirectoryServerConfig;
    } catch (LDAPException e) {
      throw new IllegalStateException(
          "Could not create configuration for the in-memory LDAP instance due to an exception", e);
    }
  }

  private String[] domainDsnArray() {
    if (domainDsn.size() == 0) {
      return new String[] {DEFAULT_DOMAIN};
    } else {
      return domainDsn.toArray(new String[] {});
    }
  }

  private Optional<Schema> customSchema() {
    final List<File> schemaFiles = schemaFiles();

    try {
      final Schema initialSchema = (addDefaultSchema ? Schema.getDefaultStandardSchema() : null);
      if (!schemaFiles.isEmpty()) {
        final Schema customSchema =
            initialSchema == null
                ? Schema.getSchema(schemaFiles)
                : Schema.mergeSchemas(initialSchema, Schema.getSchema(schemaFiles));
        return Optional.fromNullable(customSchema);
      } else {
        return Optional.absent();
      }

    } catch (IOException | LDIFException | LDAPException e) {
      throw new IllegalArgumentException(
          "Could not create custom LDAP schema due, probably caused by an incorrectly formatted schema",
          e);
    }
  }

  private List<File> schemaFiles() {
    return Lists.newArrayList(
        Lists.transform(
            this.schemaLdifs,
            new Function<String, File>() {
              @Override
              public File apply(final String input) {
                try {
                  final File file = new File(Resources.getResource(input).toURI());
                  if (!file.isFile()) {
                    throw new IllegalArgumentException(
                        String.format(
                            "The resource named \"%s\" can not be found or is not a file", input));
                  }
                  return file;
                } catch (URISyntaxException e) {
                  throw new IllegalArgumentException(
                      String.format(
                          "The resource named \"%s\" is not a valid file reference", input),
                      e);
                }
              }
            }));
  }
}