858 // but outside of synchronized block to avoid any chance of dead-locking |
853 // but outside of synchronized block to avoid any chance of dead-locking |
859 return addresses.get(); |
854 return addresses.get(); |
860 } |
855 } |
861 } |
856 } |
862 |
857 |
863 static InetAddressImpl impl; |
858 /** |
864 |
859 * NameService provides host and address lookup service |
865 private static NameService createNSProvider(String provider) { |
860 * |
866 if (provider == null) |
861 * @since 9 |
867 return null; |
862 */ |
868 |
863 private interface NameService { |
869 NameService nameService = null; |
864 |
870 if (provider.equals("default")) { |
865 /** |
871 // initialize the default name service |
866 * Lookup a host mapping by name. Retrieve the IP addresses |
872 nameService = new NameService() { |
867 * associated with a host |
|
868 * |
|
869 * @param host the specified hostname |
|
870 * @return array of IP addresses for the requested host |
|
871 * @throws UnknownHostException |
|
872 * if no IP address for the {@code host} could be found |
|
873 */ |
|
874 InetAddress[] lookupAllHostAddr(String host) |
|
875 throws UnknownHostException; |
|
876 |
|
877 /** |
|
878 * Lookup the host corresponding to the IP address provided |
|
879 * |
|
880 * @param addr byte array representing an IP address |
|
881 * @return {@code String} representing the host name mapping |
|
882 * @throws UnknownHostException |
|
883 * if no host found for the specified IP address |
|
884 */ |
|
885 String getHostByAddr(byte[] addr) throws UnknownHostException; |
|
886 |
|
887 } |
|
888 |
|
889 /** |
|
890 * The default NameService implementation, which delegates to the underlying |
|
891 * OS network libraries to resolve host address mappings. |
|
892 * |
|
893 * @since 9 |
|
894 */ |
|
895 private static final class PlatformNameService implements NameService { |
|
896 |
873 public InetAddress[] lookupAllHostAddr(String host) |
897 public InetAddress[] lookupAllHostAddr(String host) |
874 throws UnknownHostException { |
898 throws UnknownHostException { |
|
899 |
875 return impl.lookupAllHostAddr(host); |
900 return impl.lookupAllHostAddr(host); |
876 } |
901 |
877 public String getHostByAddr(byte[] addr) |
902 } |
878 throws UnknownHostException { |
903 |
879 return impl.getHostByAddr(addr); |
904 public String getHostByAddr(byte[] addr) throws UnknownHostException { |
880 } |
905 |
881 }; |
906 return impl.getHostByAddr(addr); |
882 } else { |
907 |
883 final String providerName = provider; |
908 } |
884 try { |
909 |
885 nameService = java.security.AccessController.doPrivileged( |
910 } |
886 new java.security.PrivilegedExceptionAction<>() { |
911 |
887 public NameService run() { |
912 /** |
888 Iterator<NameServiceDescriptor> itr = |
913 * The HostsFileNameService provides host address mapping |
889 ServiceLoader.load(NameServiceDescriptor.class) |
914 * by reading the entries in a hosts file, which is specified by |
890 .iterator(); |
915 * {@code jdk.net.hosts.file} system property |
891 while (itr.hasNext()) { |
916 * |
892 NameServiceDescriptor nsd = itr.next(); |
917 * <p>The file format is that which corresponds with the /etc/hosts file |
893 if (providerName. |
918 * IP Address host alias list. |
894 equalsIgnoreCase(nsd.getType()+"," |
919 * |
895 +nsd.getProviderName())) { |
920 * <p>When the file lookup is enabled it replaces the default NameService |
896 try { |
921 * implementation |
897 return nsd.createNameService(); |
922 * |
898 } catch (Exception e) { |
923 * @since 9 |
899 e.printStackTrace(); |
924 */ |
900 System.err.println( |
925 private static final class HostsFileNameService implements NameService { |
901 "Cannot create name service:" |
926 |
902 +providerName+": " + e); |
927 private final String hostsFile; |
903 } |
928 |
|
929 public HostsFileNameService (String hostsFileName) { |
|
930 this.hostsFile = hostsFileName; |
|
931 } |
|
932 |
|
933 private String addrToString(byte addr[]) { |
|
934 String stringifiedAddress = null; |
|
935 |
|
936 if (addr.length == Inet4Address.INADDRSZ) { |
|
937 stringifiedAddress = Inet4Address.numericToTextFormat(addr); |
|
938 } else { // treat as an IPV6 jobby |
|
939 byte[] newAddr |
|
940 = IPAddressUtil.convertFromIPv4MappedAddress(addr); |
|
941 if (newAddr != null) { |
|
942 stringifiedAddress = Inet4Address.numericToTextFormat(addr); |
|
943 } else { |
|
944 stringifiedAddress = Inet6Address.numericToTextFormat(addr); |
|
945 } |
|
946 } |
|
947 return stringifiedAddress; |
|
948 } |
|
949 |
|
950 /** |
|
951 * Lookup the host name corresponding to the IP address provided. |
|
952 * Search the configured host file a host name corresponding to |
|
953 * the specified IP address. |
|
954 * |
|
955 * @param addr byte array representing an IP address |
|
956 * @return {@code String} representing the host name mapping |
|
957 * @throws UnknownHostException |
|
958 * if no host found for the specified IP address |
|
959 */ |
|
960 @Override |
|
961 public String getHostByAddr(byte[] addr) throws UnknownHostException { |
|
962 String hostEntry; |
|
963 String host = null; |
|
964 |
|
965 String addrString = addrToString(addr); |
|
966 try (Scanner hostsFileScanner = new Scanner(new File(hostsFile), "UTF-8")) { |
|
967 while (hostsFileScanner.hasNextLine()) { |
|
968 hostEntry = hostsFileScanner.nextLine(); |
|
969 if (!hostEntry.startsWith("#")) { |
|
970 hostEntry = removeComments(hostEntry); |
|
971 if (hostEntry.contains(addrString)) { |
|
972 host = extractHost(hostEntry, addrString); |
|
973 if (host != null) { |
|
974 break; |
|
975 } |
|
976 } |
|
977 } |
|
978 } |
|
979 } catch (FileNotFoundException e) { |
|
980 throw new UnknownHostException("Unable to resolve address " |
|
981 + addrString + " as hosts file " + hostsFile |
|
982 + " not found "); |
|
983 } |
|
984 |
|
985 if ((host == null) || (host.equals("")) || (host.equals(" "))) { |
|
986 throw new UnknownHostException("Requested address " |
|
987 + addrString |
|
988 + " resolves to an invalid entry in hosts file " |
|
989 + hostsFile); |
|
990 } |
|
991 return host; |
|
992 } |
|
993 |
|
994 |
|
995 /** |
|
996 * <p>Lookup a host mapping by name. Retrieve the IP addresses |
|
997 * associated with a host. |
|
998 * |
|
999 * <p>Search the configured hosts file for the addresses assocaited with |
|
1000 * with the specified host name. |
|
1001 * |
|
1002 * @param host the specified hostname |
|
1003 * @return array of IP addresses for the requested host |
|
1004 * @throws UnknownHostException |
|
1005 * if no IP address for the {@code host} could be found |
|
1006 */ |
|
1007 |
|
1008 public InetAddress[] lookupAllHostAddr(String host) |
|
1009 throws UnknownHostException { |
|
1010 String hostEntry; |
|
1011 String addrStr = null; |
|
1012 InetAddress[] res = null; |
|
1013 byte addr[] = new byte[4]; |
|
1014 ArrayList<InetAddress> inetAddresses = null; |
|
1015 |
|
1016 // lookup the file and create a list InetAddress for the specfied host |
|
1017 try (Scanner hostsFileScanner = new Scanner(new File(hostsFile), "UTF-8")) { |
|
1018 while (hostsFileScanner.hasNextLine()) { |
|
1019 hostEntry = hostsFileScanner.nextLine(); |
|
1020 if (!hostEntry.startsWith("#")) { |
|
1021 hostEntry = removeComments(hostEntry); |
|
1022 if (hostEntry.contains(host)) { |
|
1023 addrStr = extractHostAddr(hostEntry, host); |
|
1024 if ((addrStr != null) && (!addrStr.equals(""))) { |
|
1025 addr = createAddressByteArray(addrStr); |
|
1026 if (inetAddresses == null) { |
|
1027 inetAddresses = new ArrayList<>(1); |
|
1028 } |
|
1029 if (addr != null) { |
|
1030 inetAddresses.add(InetAddress.getByAddress(host, addr)); |
904 } |
1031 } |
905 } |
1032 } |
906 |
|
907 return null; |
|
908 } |
1033 } |
909 } |
1034 } |
910 ); |
1035 } |
911 } catch (java.security.PrivilegedActionException e) { |
1036 } catch (FileNotFoundException e) { |
912 } |
1037 throw new UnknownHostException("Unable to resolve host " + host |
913 } |
1038 + " as hosts file " + hostsFile + " not found "); |
914 |
1039 } |
915 return nameService; |
1040 |
916 } |
1041 if (inetAddresses != null) { |
|
1042 res = inetAddresses.toArray(new InetAddress[inetAddresses.size()]); |
|
1043 } else { |
|
1044 throw new UnknownHostException("Unable to resolve host " + host |
|
1045 + " in hosts file " + hostsFile); |
|
1046 } |
|
1047 return res; |
|
1048 } |
|
1049 |
|
1050 private String removeComments(String hostsEntry) { |
|
1051 String filteredEntry = hostsEntry; |
|
1052 int hashIndex; |
|
1053 |
|
1054 if ((hashIndex = hostsEntry.indexOf("#")) != -1) { |
|
1055 filteredEntry = hostsEntry.substring(0, hashIndex); |
|
1056 } |
|
1057 return filteredEntry; |
|
1058 } |
|
1059 |
|
1060 private byte [] createAddressByteArray(String addrStr) { |
|
1061 byte[] addrArray; |
|
1062 // check if IPV4 address - most likely |
|
1063 addrArray = IPAddressUtil.textToNumericFormatV4(addrStr); |
|
1064 if (addrArray == null) { |
|
1065 addrArray = IPAddressUtil.textToNumericFormatV6(addrStr); |
|
1066 } |
|
1067 return addrArray; |
|
1068 } |
|
1069 |
|
1070 /** host to ip address mapping */ |
|
1071 private String extractHostAddr(String hostEntry, String host) { |
|
1072 String[] mapping = hostEntry.split("\\s+"); |
|
1073 String hostAddr = null; |
|
1074 |
|
1075 if (mapping.length >= 2) { |
|
1076 // look at the host aliases |
|
1077 for (int i = 1; i < mapping.length; i++) { |
|
1078 if (mapping[i].equalsIgnoreCase(host)) { |
|
1079 hostAddr = mapping[0]; |
|
1080 } |
|
1081 } |
|
1082 } |
|
1083 return hostAddr; |
|
1084 } |
|
1085 |
|
1086 /** |
|
1087 * IP Address to host mapping |
|
1088 * use first host alias in list |
|
1089 */ |
|
1090 private String extractHost(String hostEntry, String addrString) { |
|
1091 String[] mapping = hostEntry.split("\\s+"); |
|
1092 String host = null; |
|
1093 |
|
1094 if (mapping.length >= 2) { |
|
1095 if (mapping[0].equalsIgnoreCase(addrString)) { |
|
1096 host = mapping[1]; |
|
1097 } |
|
1098 } |
|
1099 return host; |
|
1100 } |
|
1101 } |
|
1102 |
|
1103 static final InetAddressImpl impl; |
917 |
1104 |
918 static { |
1105 static { |
919 // create the impl |
1106 // create the impl |
920 impl = InetAddressImplFactory.create(); |
1107 impl = InetAddressImplFactory.create(); |
921 |
1108 |
922 // get name service if provided and requested |
1109 // create name service |
923 String provider = null;; |
1110 nameService = createNameService(); |
924 String propPrefix = "sun.net.spi.nameservice.provider."; |
1111 } |
925 int n = 1; |
1112 |
926 nameServices = new ArrayList<>(); |
1113 /** |
927 provider = AccessController.doPrivileged( |
1114 * Create an instance of the NameService interface based on |
928 new GetPropertyAction(propPrefix + n)); |
1115 * the setting of the {@codejdk.net.hosts.file} system property. |
929 while (provider != null) { |
1116 * |
930 NameService ns = createNSProvider(provider); |
1117 * <p>The default NameService is the PlatformNameService, which typically |
931 if (ns != null) |
1118 * delegates name and address resolution calls to the underlying |
932 nameServices.add(ns); |
1119 * OS network libraries. |
933 |
1120 * |
934 n++; |
1121 * <p> A HostsFileNameService is created if the {@code jdk.net.hosts.file} |
935 provider = AccessController.doPrivileged( |
1122 * system property is set. If the specified file doesn't exist, the name or |
936 new GetPropertyAction(propPrefix + n)); |
1123 * address lookup will result in an UnknownHostException. Thus, non existent |
937 } |
1124 * hosts file is handled as if the file is empty. |
938 |
1125 * |
939 // if not designate any name services provider, |
1126 * @return a NameService |
940 // create a default one |
1127 */ |
941 if (nameServices.size() == 0) { |
1128 private static NameService createNameService() { |
942 NameService ns = createNSProvider("default"); |
1129 |
943 nameServices.add(ns); |
1130 String hostsFileName = AccessController |
944 } |
1131 .doPrivileged(new GetPropertyAction("jdk.net.hosts.file")); |
|
1132 NameService theNameService; |
|
1133 if (hostsFileName != null) { |
|
1134 theNameService = new HostsFileNameService(hostsFileName); |
|
1135 } else { |
|
1136 theNameService = new PlatformNameService(); |
|
1137 } |
|
1138 return theNameService; |
945 } |
1139 } |
946 |
1140 |
947 /** |
1141 /** |
948 * Creates an InetAddress based on the provided host name and IP address. |
1142 * Creates an InetAddress based on the provided host name and IP address. |
949 * No name service is checked for the validity of the address. |
1143 * No name service is checked for the validity of the address. |