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; }