jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java
changeset 3855 653df3a7256d
parent 2429 8ea224e457c6
child 5506 202f599c92aa
equal deleted inserted replaced
3854:b2a90c48e69f 3855:653df3a7256d
     1 /*
     1 /*
     2  * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    23  * have any questions.
    23  * have any questions.
    24  */
    24  */
    25 
    25 
    26 package sun.net.spi;
    26 package sun.net.spi;
    27 
    27 
    28 import sun.net.www.http.*;
       
    29 import sun.net.NetProperties;
    28 import sun.net.NetProperties;
    30 import java.net.*;
    29 import java.net.*;
    31 import java.util.*;
    30 import java.util.*;
    32 import java.util.regex.*;
       
    33 import java.io.*;
    31 import java.io.*;
    34 import sun.misc.RegexpPool;
    32 import sun.misc.RegexpPool;
    35 import java.security.AccessController;
    33 import java.security.AccessController;
    36 import java.security.PrivilegedAction;
    34 import java.security.PrivilegedAction;
    37 
    35 
   100      * basis, and change it only when the "source", i.e. the system property,
    98      * basis, and change it only when the "source", i.e. the system property,
   101      * did change.
    99      * did change.
   102      */
   100      */
   103 
   101 
   104     static class NonProxyInfo {
   102     static class NonProxyInfo {
       
   103         // Default value for nonProxyHosts, this provides backward compatibility
       
   104         // by excluding localhost and its litteral notations.
       
   105         static final String defStringVal = "localhost|127.*|[::1]";
       
   106 
   105         String hostsSource;
   107         String hostsSource;
   106         RegexpPool hostsPool;
   108         RegexpPool hostsPool;
   107         String property;
   109         final String property;
   108 
   110         final String defaultVal;
   109         static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
   111         static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
   110         static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
   112         static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
   111 
   113 
   112         NonProxyInfo(String p, String s, RegexpPool pool) {
   114         NonProxyInfo(String p, String s, RegexpPool pool, String d) {
   113             property = p;
   115             property = p;
   114             hostsSource = s;
   116             hostsSource = s;
   115             hostsPool = pool;
   117             hostsPool = pool;
       
   118             defaultVal = d;
   116         }
   119         }
   117     }
   120     }
   118 
   121 
   119 
   122 
   120     /**
   123     /**
   128         if (uri == null) {
   131         if (uri == null) {
   129             throw new IllegalArgumentException("URI can't be null.");
   132             throw new IllegalArgumentException("URI can't be null.");
   130         }
   133         }
   131         String protocol = uri.getScheme();
   134         String protocol = uri.getScheme();
   132         String host = uri.getHost();
   135         String host = uri.getHost();
   133         int port = uri.getPort();
       
   134 
   136 
   135         if (host == null) {
   137         if (host == null) {
   136             // This is a hack to ensure backward compatibility in two
   138             // This is a hack to ensure backward compatibility in two
   137             // cases: 1. hostnames contain non-ascii characters,
   139             // cases: 1. hostnames contain non-ascii characters,
   138             // internationalized domain names. in which case, URI will
   140             // internationalized domain names. in which case, URI will
   147                 if (i >= 0) {
   149                 if (i >= 0) {
   148                     auth = auth.substring(i+1);
   150                     auth = auth.substring(i+1);
   149                 }
   151                 }
   150                 i = auth.lastIndexOf(':');
   152                 i = auth.lastIndexOf(':');
   151                 if (i >= 0) {
   153                 if (i >= 0) {
   152                     try {
       
   153                         port = Integer.parseInt(auth.substring(i+1));
       
   154                     } catch (NumberFormatException e) {
       
   155                         port = -1;
       
   156                     }
       
   157                     auth = auth.substring(0,i);
   154                     auth = auth.substring(0,i);
   158                 }
   155                 }
   159                 host = auth;
   156                 host = auth;
   160             }
   157             }
   161         }
   158         }
   162 
   159 
   163         if (protocol == null || host == null) {
   160         if (protocol == null || host == null) {
   164             throw new IllegalArgumentException("protocol = "+protocol+" host = "+host);
   161             throw new IllegalArgumentException("protocol = "+protocol+" host = "+host);
   165         }
   162         }
   166         List<Proxy> proxyl = new ArrayList<Proxy>(1);
   163         List<Proxy> proxyl = new ArrayList<Proxy>(1);
   167 
       
   168         // special case localhost and loopback addresses to
       
   169         // not go through proxy
       
   170         if (isLoopback(host)) {
       
   171             proxyl.add(Proxy.NO_PROXY);
       
   172             return proxyl;
       
   173         }
       
   174 
   164 
   175         NonProxyInfo pinfo = null;
   165         NonProxyInfo pinfo = null;
   176 
   166 
   177         if ("http".equalsIgnoreCase(protocol)) {
   167         if ("http".equalsIgnoreCase(protocol)) {
   178             pinfo = NonProxyInfo.httpNonProxyInfo;
   168             pinfo = NonProxyInfo.httpNonProxyInfo;
   242                             // Let's get the NonProxyHosts property
   232                             // Let's get the NonProxyHosts property
   243                             if (nprop != null) {
   233                             if (nprop != null) {
   244                                 nphosts = NetProperties.get(nprop.property);
   234                                 nphosts = NetProperties.get(nprop.property);
   245                                 synchronized (nprop) {
   235                                 synchronized (nprop) {
   246                                     if (nphosts == null) {
   236                                     if (nphosts == null) {
   247                                         nprop.hostsSource = null;
   237                                         if (nprop.defaultVal != null) {
   248                                         nprop.hostsPool = null;
   238                                             nphosts = nprop.defaultVal;
   249                                     } else {
   239                                         } else {
       
   240                                             nprop.hostsSource = null;
       
   241                                             nprop.hostsPool = null;
       
   242                                         }
       
   243                                     }
       
   244                                     if (nphosts != null) {
   250                                         if (!nphosts.equals(nprop.hostsSource)) {
   245                                         if (!nphosts.equals(nprop.hostsSource)) {
   251                                             RegexpPool pool = new RegexpPool();
   246                                             RegexpPool pool = new RegexpPool();
   252                                             StringTokenizer st = new StringTokenizer(nphosts, "|", false);
   247                                             StringTokenizer st = new StringTokenizer(nphosts, "|", false);
   253                                             try {
   248                                             try {
   254                                                 while (st.hasMoreTokens()) {
   249                                                 while (st.hasMoreTokens()) {
   332         } else {
   327         } else {
   333             return -1;
   328             return -1;
   334         }
   329         }
   335     }
   330     }
   336 
   331 
   337     private boolean isLoopback(String host) {
       
   338         if (host == null || host.length() == 0)
       
   339             return false;
       
   340 
       
   341         if (host.equalsIgnoreCase("localhost"))
       
   342             return true;
       
   343 
       
   344         /* The string could represent a numerical IP address.
       
   345          * For IPv4 addresses, check whether it starts with 127.
       
   346          * For IPv6 addresses, check whether it is ::1 or its equivalent.
       
   347          * Don't check IPv4-mapped or IPv4-compatible addresses
       
   348          */
       
   349 
       
   350         if (host.startsWith("127.")) {
       
   351             // possible IPv4 loopback address
       
   352             int p = 4;
       
   353             int q;
       
   354             int n = host.length();
       
   355             // Per RFC2732: At most three digits per byte
       
   356             // Further constraint: Each element fits in a byte
       
   357             if ((q = scanByte(host, p, n)) <= p) return false;   p = q;
       
   358             if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0;  p = q;
       
   359             if ((q = scanByte(host, p, n)) <= p) return false;   p = q;
       
   360             if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0;  p = q;
       
   361             if ((q = scanByte(host, p, n)) <= p) return false;
       
   362             return q == n && number > 0;
       
   363         }
       
   364 
       
   365         if (host.endsWith(":1")) {
       
   366             final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
       
   367             return p6.matcher(host).matches();
       
   368         }
       
   369         return false;
       
   370     }
       
   371 
       
   372     // Character-class masks, in reverse order from RFC2396 because
       
   373     // initializers for static fields cannot make forward references.
       
   374 
       
   375     // Compute a low-order mask for the characters
       
   376     // between first and last, inclusive
       
   377     private static long lowMask(char first, char last) {
       
   378         long m = 0;
       
   379         int f = Math.max(Math.min(first, 63), 0);
       
   380         int l = Math.max(Math.min(last, 63), 0);
       
   381         for (int i = f; i <= l; i++)
       
   382             m |= 1L << i;
       
   383         return m;
       
   384     }
       
   385     // digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
       
   386     //            "8" | "9"
       
   387     private static final long L_DIGIT = lowMask('0', '9');
       
   388     private static final long H_DIGIT = 0L;
       
   389 
       
   390     // Scan a string of decimal digits whose value fits in a byte
       
   391     //
       
   392     private int number;
       
   393     private int scanByte(String input, int start, int n)
       
   394     {
       
   395         int p = start;
       
   396         int q = scan(input, p, n, L_DIGIT, H_DIGIT);
       
   397         if (q <= p) return q;
       
   398         number = Integer.parseInt(input.substring(p, q));
       
   399         if (number > 255) return p;
       
   400         return q;
       
   401     }
       
   402 
       
   403     // Scan a specific char: If the char at the given start position is
       
   404     // equal to c, return the index of the next char; otherwise, return the
       
   405     // start position.
       
   406     //
       
   407     private int scan(String input, int start, int end, char c) {
       
   408         if ((start < end) && (input.charAt(start) == c))
       
   409             return start + 1;
       
   410         return start;
       
   411     }
       
   412 
       
   413     // Scan chars that match the given mask pair
       
   414     //
       
   415     private int scan(String input, int start, int n, long lowMask, long highMask)
       
   416     {
       
   417         int p = start;
       
   418         while (p < n) {
       
   419             char c = input.charAt(p);
       
   420             if (match(c, lowMask, highMask)) {
       
   421                 p++;
       
   422                 continue;
       
   423             }
       
   424             break;
       
   425         }
       
   426         return p;
       
   427     }
       
   428 
       
   429     // Tell whether the given character is permitted by the given mask pair
       
   430     private boolean match(char c, long lowMask, long highMask) {
       
   431         if (c < 64)
       
   432             return ((1L << c) & lowMask) != 0;
       
   433         if (c < 128)
       
   434             return ((1L << (c - 64)) & highMask) != 0;
       
   435         return false;
       
   436     }
       
   437 
       
   438     private native static boolean init();
   332     private native static boolean init();
   439     private native Proxy getSystemProxy(String protocol, String host);
   333     private native Proxy getSystemProxy(String protocol, String host);
   440 }
   334 }