public static EndpointDescription select(EndpointDescription[] endpoints, String url)
      throws ServiceResultException {
    // Use best endpoint of the same uri
    EndpointDescription[] endpointsOfTheSameUri =
        EndpointUtil.select(endpoints, url, null, null, null, null);
    if (endpointsOfTheSameUri.length > 0) {
      return select(endpointsOfTheSameUri);
    }

    // Use best endpoint of the same scheme
    String scheme = UriUtil.getTransportProtocol(url);
    EndpointDescription[] endpointsOfTheSameScheme =
        EndpointUtil.select(endpoints, null, scheme, null, null, null);
    if (endpointsOfTheSameScheme.length > 0) {
      return select(endpointsOfTheSameScheme);
    }

    // Just choose one endpoint
    return select(endpoints);
  }
  /**
   * Convert endpoint url to socket addresses.
   *
   * @param endpointUrl
   * @return a collection of bind addresses
   * @throws IllegalArgumentException endpointUrl is problematic some way
   */
  public static List<SocketAddress> toSocketAddresses(String endpointUrl)
      throws IllegalArgumentException {
    List<SocketAddress> result = new ArrayList<SocketAddress>();

    if (endpointUrl == null) throw new IllegalArgumentException("URL not valid.");
    try {
      URI uri = new URI(endpointUrl);
      String proto = UriUtil.getTransportProtocol(endpointUrl);
      String host = uri.getHost();
      int port = uri.getPort();
      if (host == null) {
        // Do a custom parse, if the URI is not valid, possibly because it
        // does not conform to RFC 2396. This occurs, for example, if the
        // host name contains '_' characters, which are used by some Windows
        // computers
        String[] parts = endpointUrl.split("/+");
        //				proto = parts[0].split(":")[0]; // // Use the proto parsed from URI, which should be
        // fine, already
        String[] host_port = parts[1].split(":");
        host = host_port[0];
        try {
          port = Integer.parseInt(host_port[1]);
        } catch (NumberFormatException e1) {
          port = 0;
        } catch (ArrayIndexOutOfBoundsException e2) {
          port = 0;
        }
      }

      proto = proto.toLowerCase();

      if (port == 0 || port == -1) port = UriUtil.defaultPort(proto);

      if (proto.equals("opc.tcp") || proto.equals("http") || proto.equals("https")) {
        // Bind to the host in endpoint uri, and to no other interface

        try {
          // !!WORKAROUND!! Java6 cannot bind to IPv6
          // Hostnames (e.g. localhost) resolves to 127.0.0.1 and 0::1
          // This workaround omits IPv6 addresses if IPv4 addresses
          // exist, but lets error to be thrown if there are only
          // IPv6 addresses. This is to show IPv6 cannot be bound

          InetAddress addrs[] = InetAddress.getAllByName(host);
          boolean hasIPv4 = false;
          boolean hasIPv6 = false;
          for (InetAddress addr : addrs) {
            hasIPv4 |= addr instanceof Inet4Address;
            hasIPv6 |= addr instanceof Inet6Address;
          }

          for (InetAddress addr : InetAddress.getAllByName(host)) {
            boolean IPv6 = addr instanceof Inet6Address;

            if (IPv6 && hasIPv6 && hasIPv4) {
              logger.warn(
                  "Binding of "
                      + endpointUrl
                      + " to "
                      + addr.getHostAddress()
                      + " was omited. (Workaround)");
              continue;
            }

            SocketAddress sa = new InetSocketAddress(addr, port);
            result.add(sa);
          }
        } catch (UnknownHostException e) {
          throw new IllegalArgumentException(e);
        }

      } else {
        throw new IllegalArgumentException("Unsupported protocol " + proto);
      }
    } catch (URISyntaxException ex) {
      throw new IllegalArgumentException("Invalid URL", ex);
    }
    return result;
  }