All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.grinder.communication.Connector Maven / Gradle / Ivy

There is a newer version: 3.11
Show newest version
// Copyright (C) 2000 - 2012 Philip Aston
// All rights reserved.
//
// This file is part of The Grinder software distribution. Refer to
// the file LICENSE which is part of The Grinder distribution for
// licensing details. The Grinder distribution is available on the
// Internet at http://grinder.sourceforge.net/
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

package net.grinder.communication;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import net.grinder.common.UncheckedInterruptedException;


/**
 * Connection factory.
 *
 * @author Philip Aston
 */
public final class Connector {

  private final String m_hostString;
  private final int m_port;
  private final ConnectionType m_connectionType;

  /**
   * Constructor.
   *
   * @param hostString TCP address to connect to.
   * @param port TCP port to connect to.
   * @param connectionType Connection type.
   */
  public Connector(String hostString,
                   int port,
                   ConnectionType connectionType) {
    m_hostString = hostString;
    m_port = port;
    m_connectionType = connectionType;
  }

  /**
   * Factory method that makes a TCP connection and returns a
   * corresponding socket.
   *
   * @return A socket wired to the connection.
   * @throws CommunicationException If connection could not be
   * establish.
   */
  Socket connect() throws CommunicationException {
    return connect(null);
  }

  Socket connect(Address address) throws CommunicationException {
    final InetAddress inetAddress;

    try {
      inetAddress = InetAddress.getByName(m_hostString);
    }
    catch (UnknownHostException e) {
      throw new CommunicationException(
        "Could not resolve host '" + m_hostString + '\'', e);
    }

    try {
      // Bind to any local port.
      final Socket socket = new Socket(inetAddress, m_port);

      final OutputStream outputStream = socket.getOutputStream();

      final ObjectOutputStream objectStream =
        new ObjectOutputStream(outputStream);
      objectStream.writeObject(m_connectionType);
      objectStream.writeObject(address);
      objectStream.flush();
      return socket;
    }
    catch (IOException e) {
      UncheckedInterruptedException.ioException(e);
      throw new CommunicationException(
        "Failed to connect to '" + inetAddress + ':' + m_port + '\'', e);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override public int hashCode() {
    return m_hostString.hashCode() ^ m_port ^ m_connectionType.hashCode();
  }

  /**
   * {@inheritDoc}
   */
  @Override public boolean equals(Object o) {
    if (o == this) {
      return true;
    }

    if (o == null || o.getClass() != Connector.class) {
      return false;
    }

    final Connector other = (Connector)o;

    return
      m_port == other.m_port &&
      m_connectionType.equals(other.m_connectionType) &&
      m_hostString.equals(other.m_hostString);
  }

  /**
   * Return a description of the connection address.
   *
   * @return The description.
   */
  public String getEndpointAsString() {
    String host;

    try {
      host = InetAddress.getByName(m_hostString).toString();
    }
    catch (UnknownHostException e) {
      host = m_hostString;
    }

    return host + ":" + m_port;
  }

  /**
   * Connection details read from a stream.
   * @see Connector#read
   */
  static final class ConnectDetails {
    private final ConnectionType m_connectionType;
    private final Address m_address;

    private ConnectDetails(ConnectionType connectionType, Address address) {
      m_connectionType = connectionType;
      m_address = address;
    }

    public ConnectionType getConnectionType() {
      return m_connectionType;
    }

    public Address getAddress() {
      return m_address;
    }
  }

  /**
   * Read connection details from a stream.
   *
   * @param in The stream.
   * @return The details.
   * @throws CommunicationException If the details could not be read.
   */
  static ConnectDetails read(InputStream in) throws CommunicationException {

    try {
      final ObjectInputStream objectInputStream = new ObjectInputStream(in);
      final ConnectionType type =
        (ConnectionType) objectInputStream.readObject();
      final Address address = (Address) objectInputStream.readObject();
      return new ConnectDetails(type, address);
    }
    catch (IOException e) {
      throw new CommunicationException("Could not read address details", e);
    }
    catch (ClassNotFoundException e) {
      throw new CommunicationException("Could not read address details", e);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy