src/java.base/share/classes/java/net/URL.java

Print this page




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.net;
  27 
  28 import java.io.IOException;
  29 import java.io.InputStream;





  30 import java.util.Hashtable;
  31 import java.util.StringTokenizer;





  32 import sun.security.util.SecurityConstants;
  33 
  34 /**
  35  * Class {@code URL} represents a Uniform Resource
  36  * Locator, a pointer to a "resource" on the World
  37  * Wide Web. A resource can be something as simple as a file or a
  38  * directory, or it can be a reference to a more complicated object,
  39  * such as a query to a database or to a search engine. More
  40  * information on the types of URLs and their formats can be found at:
  41  * <a href=
  42  * "http://web.archive.org/web/20051219043731/http://archive.ncsa.uiuc.edu/SDG/Software/Mosaic/Demo/url-primer.html">
  43  * <i>Types of URL</i></a>
  44  * <p>
  45  * In general, a URL can be broken into several parts. Consider the
  46  * following example:
  47  * <blockquote><pre>
  48  *     http://www.example.com/docs/resource1.html
  49  * </pre></blockquote>
  50  * <p>
  51  * The URL above indicates that the protocol to use is


 225      * number, and {@code file}.<p>
 226      *
 227      * {@code host} can be expressed as a host name or a literal
 228      * IP address. If IPv6 literal address is used, it should be
 229      * enclosed in square brackets ({@code '['} and {@code ']'}), as
 230      * specified by <a
 231      * href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>;
 232      * However, the literal IPv6 address format defined in <a
 233      * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IP
 234      * Version 6 Addressing Architecture</i></a> is also accepted.<p>
 235      *
 236      * Specifying a {@code port} number of {@code -1}
 237      * indicates that the URL should use the default port for the
 238      * protocol.<p>
 239      *
 240      * If this is the first URL object being created with the specified
 241      * protocol, a <i>stream protocol handler</i> object, an instance of
 242      * class {@code URLStreamHandler}, is created for that protocol:
 243      * <ol>
 244      * <li>If the application has previously set up an instance of
 245      *     {@code URLStreamHandlerFactory} as the stream handler factory,


 246      *     then the {@code createURLStreamHandler} method of that instance
 247      *     is called with the protocol string as an argument to create the
 248      *     stream protocol handler.
 249      * <li>If no {@code URLStreamHandlerFactory} has yet been set up,
 250      *     or if the factory's {@code createURLStreamHandler} method
 251      *     returns {@code null}, then the constructor finds the
 252      *     value of the system property:
 253      *     <blockquote><pre>
 254      *         java.protocol.handler.pkgs
 255      *     </pre></blockquote>
 256      *     If the value of that system property is not {@code null},
 257      *     it is interpreted as a list of packages separated by a vertical
 258      *     slash character '{@code |}'. The constructor tries to load
 259      *     the class named:
 260      *     <blockquote><pre>
 261      *         &lt;<i>package</i>&gt;.&lt;<i>protocol</i>&gt;.Handler
 262      *     </pre></blockquote>
 263      *     where &lt;<i>package</i>&gt; is replaced by the name of the package
 264      *     and &lt;<i>protocol</i>&gt; is replaced by the name of the protocol.
 265      *     If this class does not exist, or if the class exists but it is not
 266      *     a subclass of {@code URLStreamHandler}, then the next package
 267      *     in the list is tried.

 268      * <li>If the previous step fails to find a protocol handler, then the
 269      *     constructor tries to load a built-in protocol handler.
 270      *     If this class does not exist, or if the class exists but it is not a
 271      *     subclass of {@code URLStreamHandler}, then a
 272      *     {@code MalformedURLException} is thrown.
 273      * </ol>
 274      *
 275      * <p>Protocol handlers for the following protocols are guaranteed
 276      * to exist on the search path :-
 277      * <blockquote><pre>
 278      *     http, https, file, and jar
 279      * </pre></blockquote>
 280      * Protocol handlers for additional protocols may also be
 281      * available.

 282      *
 283      * <p>No validation of the inputs is performed by this constructor.
 284      *
 285      * @param      protocol   the name of the protocol to use.
 286      * @param      host       the name of the host.
 287      * @param      port       the port number on the host.
 288      * @param      file       the file on the host
 289      * @exception  MalformedURLException  if an unknown protocol is specified.
 290      * @see        java.lang.System#getProperty(java.lang.String)
 291      * @see        java.net.URL#setURLStreamHandlerFactory(
 292      *                  java.net.URLStreamHandlerFactory)
 293      * @see        java.net.URLStreamHandler
 294      * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
 295      *                  java.lang.String)
 296      */
 297     public URL(String protocol, String host, int port, String file)
 298         throws MalformedURLException
 299     {
 300         this(protocol, host, port, file, null);
 301     }


1052     /**
1053      * Gets the contents of this URL. This method is a shorthand for:
1054      * <blockquote><pre>
1055      *     openConnection().getContent(classes)
1056      * </pre></blockquote>
1057      *
1058      * @param classes an array of Java types
1059      * @return     the content object of this URL that is the first match of
1060      *               the types specified in the classes array.
1061      *               null if none of the requested types are supported.
1062      * @exception  IOException  if an I/O exception occurs.
1063      * @see        java.net.URLConnection#getContent(Class[])
1064      * @since 1.3
1065      */
1066     public final Object getContent(Class<?>[] classes)
1067     throws java.io.IOException {
1068         return openConnection().getContent(classes);
1069     }
1070 
1071     /**
1072      * The URLStreamHandler factory.
1073      */
1074     private static volatile URLStreamHandlerFactory factory;
1075 




1076     /**
1077      * Sets an application's {@code URLStreamHandlerFactory}.
1078      * This method can be called at most once in a given Java Virtual
1079      * Machine.
1080      *
1081      *<p> The {@code URLStreamHandlerFactory} instance is used to
1082      *construct a stream protocol handler from a protocol name.
1083      *
1084      * <p> If there is a security manager, this method first calls
1085      * the security manager's {@code checkSetFactory} method
1086      * to ensure the operation is allowed.
1087      * This could result in a SecurityException.
1088      *
1089      * @param      fac   the desired factory.
1090      * @exception  Error  if the application has already set a factory.
1091      * @exception  SecurityException  if a security manager exists and its
1092      *             {@code checkSetFactory} method doesn't allow
1093      *             the operation.
1094      * @see        java.net.URL#URL(java.lang.String, java.lang.String,
1095      *             int, java.lang.String)
1096      * @see        java.net.URLStreamHandlerFactory
1097      * @see        SecurityManager#checkSetFactory
1098      */
1099     public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
1100         synchronized (streamHandlerLock) {
1101             if (factory != null) {
1102                 throw new Error("factory already defined");
1103             }
1104             SecurityManager security = System.getSecurityManager();
1105             if (security != null) {
1106                 security.checkSetFactory();
1107             }
1108             handlers.clear();
1109 
1110             // ensure the core protocol handlers are loaded before setting
1111             // a custom URLStreamHandlerFactory
1112             ensureHandlersLoaded("jrt", "jar", "file");
1113 
1114             // safe publication of URLStreamHandlerFactory with volatile write
1115             factory = fac;
1116         }
1117     }
1118 
1119     /**
1120      * A table of protocol handlers.


























1121      */
1122     static Hashtable<String,URLStreamHandler> handlers = new Hashtable<>();
1123     private static Object streamHandlerLock = new Object();






1124 
1125     /**
1126      * Returns the Stream Handler.
1127      * @param protocol the protocol to use
1128      */
1129     static URLStreamHandler getURLStreamHandler(String protocol) {
1130 
1131         URLStreamHandler handler = handlers.get(protocol);
1132         if (handler == null) {
1133 
1134             boolean checkedWithFactory = false;
















1135 










1136             // Use the factory (if any). Volatile read makes
1137             // URLStreamHandlerFactory appear fully initialized to current thread.
1138             URLStreamHandlerFactory fac = factory;
1139             if (fac != null) {
1140                 handler = fac.createURLStreamHandler(protocol);
1141                 checkedWithFactory = true;








1142             }
1143 
1144             // Try java protocol handler
1145             if (handler == null) {
1146                 String packagePrefixList = null;

1147 
1148                 packagePrefixList
1149                     = java.security.AccessController.doPrivileged(
1150                     new sun.security.action.GetPropertyAction(
1151                         protocolPathProp,""));
1152                 if (packagePrefixList != "") {
1153                     packagePrefixList += "|";












1154                 }

1155 
1156                 // REMIND: decide whether to allow the "null" class prefix
1157                 // or not.
1158                 packagePrefixList += "sun.net.www.protocol";











1159 
1160                 StringTokenizer packagePrefixIter =
1161                     new StringTokenizer(packagePrefixList, "|");
1162 
1163                 while (handler == null &&
1164                        packagePrefixIter.hasMoreTokens()) {

1165 
1166                     String packagePrefix =
1167                       packagePrefixIter.nextToken().trim();
1168                     try {
1169                         String clsName = packagePrefix + "." + protocol +
1170                           ".Handler";
1171                         Class<?> cls = null;
1172                         try {
1173                             cls = Class.forName(clsName);
1174                         } catch (ClassNotFoundException e) {
1175                             ClassLoader cl = ClassLoader.getSystemClassLoader();
1176                             if (cl != null) {
1177                                 cls = cl.loadClass(clsName);
1178                             }

1179                         }
1180                         if (cls != null) {
1181                             handler  =
1182                               (URLStreamHandler)cls.newInstance();




1183                         }
1184                     } catch (Exception e) {
1185                         // any number of exceptions can get thrown here

























1186                     }
1187                 }



1188             }
1189 
1190             synchronized (streamHandlerLock) {
1191 
1192                 URLStreamHandler handler2 = null;
1193 
1194                 // Check again with hashtable just in case another
1195                 // thread created a handler since we last checked
1196                 handler2 = handlers.get(protocol);
1197 
1198                 if (handler2 != null) {
1199                     return handler2;
1200                 }
1201 
1202                 // Check with factory if another thread set a
1203                 // factory since our last check
1204                 if (!checkedWithFactory && (fac = factory) != null) {
1205                     handler2 = fac.createURLStreamHandler(protocol);
1206                 }
1207 
1208                 if (handler2 != null) {
1209                     // The handler from the factory must be given more
1210                     // importance. Discard the default handler that
1211                     // this thread created.
1212                     handler = handler2;
1213                 }
1214 
1215                 // Insert this handler into the hashtable
1216                 if (handler != null) {
1217                     handlers.put(protocol, handler);
1218                 }
1219 
1220             }
1221         }
1222 
1223         return handler;
1224 
1225     }
1226 
1227     /**
1228      * Ensures that the given protocol handlers are loaded
1229      */
1230     private static void ensureHandlersLoaded(String... protocols) {
1231         for (String protocol: protocols) {
1232             getURLStreamHandler(protocol);
1233         }
1234     }
1235 
1236 
1237     /**
1238      * WriteObject is called to save the state of the URL to an
1239      * ObjectOutputStream. The handler is not saved since it is
1240      * specific to this system.
1241      *
1242      * @serialData the default write object value. When read back in,
1243      * the reader must ensure that calling getURLStreamHandler with
1244      * the protocol variable returns a valid URLStreamHandler and
1245      * throw an IOException if it does not.
1246      */
1247     private synchronized void writeObject(java.io.ObjectOutputStream s)
1248         throws IOException
1249     {
1250         s.defaultWriteObject(); // write the fields
1251     }
1252 
1253     /**
1254      * readObject is called to restore the state of the URL from the
1255      * stream.  It reads the components of the URL and finds the local




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.net;
  27 
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 import java.util.ArrayList;
  33 import java.util.Collection;
  34 import java.util.Collections;
  35 import java.util.Hashtable;
  36 import java.util.List;
  37 import java.util.Objects;
  38 import java.util.ServiceLoader;
  39 import java.util.Set;
  40 import java.util.concurrent.CopyOnWriteArrayList;
  41 
  42 import sun.security.util.SecurityConstants;
  43 
  44 /**
  45  * Class {@code URL} represents a Uniform Resource
  46  * Locator, a pointer to a "resource" on the World
  47  * Wide Web. A resource can be something as simple as a file or a
  48  * directory, or it can be a reference to a more complicated object,
  49  * such as a query to a database or to a search engine. More
  50  * information on the types of URLs and their formats can be found at:
  51  * <a href=
  52  * "http://web.archive.org/web/20051219043731/http://archive.ncsa.uiuc.edu/SDG/Software/Mosaic/Demo/url-primer.html">
  53  * <i>Types of URL</i></a>
  54  * <p>
  55  * In general, a URL can be broken into several parts. Consider the
  56  * following example:
  57  * <blockquote><pre>
  58  *     http://www.example.com/docs/resource1.html
  59  * </pre></blockquote>
  60  * <p>
  61  * The URL above indicates that the protocol to use is


 235      * number, and {@code file}.<p>
 236      *
 237      * {@code host} can be expressed as a host name or a literal
 238      * IP address. If IPv6 literal address is used, it should be
 239      * enclosed in square brackets ({@code '['} and {@code ']'}), as
 240      * specified by <a
 241      * href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>;
 242      * However, the literal IPv6 address format defined in <a
 243      * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IP
 244      * Version 6 Addressing Architecture</i></a> is also accepted.<p>
 245      *
 246      * Specifying a {@code port} number of {@code -1}
 247      * indicates that the URL should use the default port for the
 248      * protocol.<p>
 249      *
 250      * If this is the first URL object being created with the specified
 251      * protocol, a <i>stream protocol handler</i> object, an instance of
 252      * class {@code URLStreamHandler}, is created for that protocol:
 253      * <ol>
 254      * <li>If the application has previously set up an instance of
 255      *     {@code URLStreamHandlerFactory}, through {@linkplain
 256      *     #setURLStreamHandlerFactory(URLStreamHandlerFactory)
 257      *     setURLStreamHandlerFactory}, as the stream handler factory,
 258      *     then the {@code createURLStreamHandler} method of that instance
 259      *     is called with the protocol string as an argument to create the
 260      *     stream protocol handler.
 261      * <li>If no {@code URLStreamHandlerFactory} has yet been set up,
 262      *     or if the factory's {@code createURLStreamHandler} method
 263      *     returns {@code null}, then the list of factories, set through
 264      *     {@linkplain #addURLStreamHandlerFactory(URLStreamHandlerFactory)
 265      *     addURLStreamHandlerFactory} is consulted. The {@code
 266      *     createURLStreamHandler} method of each factory is invoked, in
 267      *     registration order, with the protocol string, until a factory returns
 268      *     non-null, or all the factories in the list have been exhausted.
 269      * <li>If the previous step fails to find a protocol handler, then the
 270      *     {@linkplain java.util.ServiceLoader ServiceLoader} mechanism is used
 271      *     to locate a {@code URLStreamHandlerFactory} provider using the system
 272      *     class loader. The ordering that providers are located is
 273      *     implementation specific, and an implementation is free to cache the
 274      *     located providers. A {@linkplain java.util.ServiceConfigurationError
 275      *     ServiceConfigurationError}, {@code Error} or {@code RuntimeException}
 276      *     thrown from the {@code createURLStreamHandler}, if encountered, will
 277      *     be propagated to the calling thread. The {@code
 278      *     createURLStreamHandler} method of each provider, if instantiated, is
 279      *     invoked, with the protocol string, until a provider returns non-null,
 280      *     or all providers have been exhausted.
 281      * <li>If the previous step fails to find a protocol handler, then the
 282      *     constructor tries to load a built-in protocol handler.
 283      *     If this class does not exist, or if the class exists but it is not a
 284      *     subclass of {@code URLStreamHandler}, then a
 285      *     {@code MalformedURLException} is thrown.
 286      * </ol>
 287      *
 288      * <p>Protocol handlers for the following protocols are guaranteed
 289      * to exist on the search path :-
 290      * <blockquote><pre>
 291      *     http, https, file, and jar
 292      * </pre></blockquote>
 293      * Protocol handlers for additional protocols may also be  available. Some
 294      * protocols, that are fundamental to the platform, may have restrictions
 295      * around when, or if, their built-in handlers can be overridden.
 296      *
 297      * <p>No validation of the inputs is performed by this constructor.
 298      *
 299      * @param      protocol   the name of the protocol to use.
 300      * @param      host       the name of the host.
 301      * @param      port       the port number on the host.
 302      * @param      file       the file on the host
 303      * @exception  MalformedURLException  if an unknown protocol is specified.
 304      * @see        java.lang.System#getProperty(java.lang.String)
 305      * @see        java.net.URL#setURLStreamHandlerFactory(
 306      *                  java.net.URLStreamHandlerFactory)
 307      * @see        java.net.URLStreamHandler
 308      * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
 309      *                  java.lang.String)
 310      */
 311     public URL(String protocol, String host, int port, String file)
 312         throws MalformedURLException
 313     {
 314         this(protocol, host, port, file, null);
 315     }


1066     /**
1067      * Gets the contents of this URL. This method is a shorthand for:
1068      * <blockquote><pre>
1069      *     openConnection().getContent(classes)
1070      * </pre></blockquote>
1071      *
1072      * @param classes an array of Java types
1073      * @return     the content object of this URL that is the first match of
1074      *               the types specified in the classes array.
1075      *               null if none of the requested types are supported.
1076      * @exception  IOException  if an I/O exception occurs.
1077      * @see        java.net.URLConnection#getContent(Class[])
1078      * @since 1.3
1079      */
1080     public final Object getContent(Class<?>[] classes)
1081     throws java.io.IOException {
1082         return openConnection().getContent(classes);
1083     }
1084 
1085     /**
1086      * The Application URLStreamHandler factory.
1087      */
1088     private static volatile URLStreamHandlerFactory factory;
1089 
1090     /** The list of factories. */
1091     private static final CopyOnWriteArrayList<URLStreamHandlerFactory> factoryList =
1092             new CopyOnWriteArrayList<>();
1093 
1094     /**
1095      * Sets an application's {@code URLStreamHandlerFactory}.
1096      * This method can be called at most once in a given Java Virtual
1097      * Machine.
1098      *
1099      *<p> The {@code URLStreamHandlerFactory} instance is used to
1100      *construct a stream protocol handler from a protocol name.
1101      *
1102      * <p> If there is a security manager, this method first calls
1103      * the security manager's {@code checkSetFactory} method
1104      * to ensure the operation is allowed.
1105      * This could result in a SecurityException.
1106      *
1107      * @param      fac   the desired factory.
1108      * @exception  Error  if the application has already set a factory.
1109      * @exception  SecurityException  if a security manager exists and its
1110      *             {@code checkSetFactory} method doesn't allow
1111      *             the operation.
1112      * @see        java.net.URL#URL(java.lang.String, java.lang.String,
1113      *             int, java.lang.String)
1114      * @see        java.net.URLStreamHandlerFactory
1115      * @see        SecurityManager#checkSetFactory
1116      */
1117     public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
1118         synchronized (streamHandlerLock) {
1119             if (factory != null) {
1120                 throw new Error("factory already defined");
1121             }
1122             SecurityManager security = System.getSecurityManager();
1123             if (security != null) {
1124                 security.checkSetFactory();
1125             }
1126             handlers.clear();
1127 




1128             // safe publication of URLStreamHandlerFactory with volatile write
1129             factory = fac;
1130         }
1131     }
1132 
1133     /**
1134      * Adds a {@linkplain URLStreamHandlerFactory}. This method can be called
1135      * multiple times in order to create an effective list of factories.
1136      *
1137      * <p> Factories, added through a call to this method, will have their
1138      * {@code createURLStreamHandler} method called, in the order in which they
1139      * were added, to construct a stream protocol handler from a protocol name.
1140      * A factory that cannot construct a stream protocol handler for a
1141      * particular protocol name should return {@code null}. The next factory in
1142      * the list, if there is one, will then be consulted.
1143      *
1144      * <p> If there is a security manager, this method first calls
1145      * the security manager's {@code checkSetFactory} method
1146      * to ensure the operation is allowed.
1147      * This could result in a SecurityException.
1148      *
1149      * @apiNote
1150      * This method is intended to be used by long running applications, to
1151      * support adding additional system-wide protocol handlers, beyond that of
1152      * the built-in handlers. It can be used in some situations to override
1153      * built-in handlers, that may not be possible to locate using services,
1154      * like {@code jar} for example.
1155      *
1156      * @param  factory the factory
1157      * @throws SecurityException  if a security manager exists and its {@link
1158      *         SecurityManager#checkSetFactory} method doesn't allow the operation
1159      * @throws NullPointerException if {@code factory} is null
1160      * @since 1.9
1161      */
1162     public static void addURLStreamHandlerFactory(URLStreamHandlerFactory factory) {
1163         Objects.requireNonNull(factory);
1164         synchronized (streamHandlerLock) {
1165             SecurityManager security = System.getSecurityManager();
1166             if (security != null) {
1167                 security.checkSetFactory();
1168             }
1169             handlers.clear();
1170 
1171             factoryList.add(factory);
1172         }
1173     }


1174 
1175     private static final URLStreamHandlerFactory defaultFactory = new DefaultFactory();

1176 
1177     private static class DefaultFactory implements URLStreamHandlerFactory {
1178         private static String PREFIX = "sun.net.www.protocol";
1179 
1180         public URLStreamHandler createURLStreamHandler(String protocol) {
1181             String name = PREFIX + "." + protocol + ".Handler";
1182             try {
1183                 Class<?> c = Class.forName(name);
1184                 return (URLStreamHandler)c.newInstance();
1185             } catch (ClassNotFoundException x) {
1186                 // ignore
1187             } catch (Exception e) {
1188                 // For compatibility, all Exceptions are ignored.
1189                 // any number of exceptions can get thrown here
1190             }
1191             return null;
1192         }
1193     }
1194 
1195     private static final URLStreamHandler NULL_HANDLER = new URLStreamHandler() {
1196         public URLConnection openConnection(URL u) { return null; }
1197         public URLConnection openConnection(URL u, Proxy p)  { return null; }
1198     };
1199 
1200     /** Returns a handler instance for the given protocol, null if the factories
1201      *  could not create a handler, or NULL_HANDLER if there are no factories.
1202      */
1203     private static URLStreamHandler handlerFromSettableFactory(String protocol) {
1204         URLStreamHandler handler = NULL_HANDLER;
1205         // Use the factory (if any). Volatile read makes
1206         // URLStreamHandlerFactory appear fully initialized to current thread.
1207         URLStreamHandlerFactory fac = factory;
1208         if (fac != null)
1209             handler = fac.createURLStreamHandler(protocol);
1210 
1211         if (handler == NULL_HANDLER || handler == null) {
1212             for (URLStreamHandlerFactory f : factoryList) {
1213                 handler = f.createURLStreamHandler(protocol);
1214                 if (handler != null)
1215                     return handler;
1216             }
1217         }
1218         return handler;
1219     }
1220 
1221     // installed service providers
1222     private static volatile List<URLStreamHandlerFactory> installedProviders;
1223     private static final Object providersLock = new Object();
1224     private static boolean loadingProviders  = false;
1225 
1226     private static List<URLStreamHandlerFactory> loadInstalledProviders() {
1227         List<URLStreamHandlerFactory> list = new ArrayList<>();
1228         ServiceLoader<URLStreamHandlerFactory> sl = ServiceLoader
1229                 .load(URLStreamHandlerFactory.class, ClassLoader.getSystemClassLoader());
1230         // ServiceConfigurationError may be throw here
1231         for (URLStreamHandlerFactory provider: sl)
1232             list.add(provider);
1233 
1234         return list;
1235     }
1236 
1237     private static List<URLStreamHandlerFactory> installedProviders() {
1238         if (installedProviders == null) {
1239             synchronized (providersLock) {
1240                 if (installedProviders == null) {
1241                     if (loadingProviders) {
1242                         throw new Error(
1243                             "Circular loading of URL stream handler providers detected");
1244                     }
1245                     loadingProviders = true;
1246 
1247                     // do not use a lambda, or method ref here.
1248                     List<URLStreamHandlerFactory> list = AccessController
1249                         .doPrivileged(new PrivilegedAction<List<URLStreamHandlerFactory>>() {
1250                             public List<URLStreamHandlerFactory> run() {
1251                                 return URL.loadInstalledProviders();
1252                             }
1253                         });
1254 
1255                     installedProviders = Collections.unmodifiableList(list);
1256                 }
1257             }
1258         }
1259         return installedProviders;
1260     }
1261 
1262     private static final String SL_SKIP_PROTOCOL = "jar";

1263 
1264     private static URLStreamHandler handlerFromInstalledProviders(String protocol) {
1265         if (protocol.equalsIgnoreCase(SL_SKIP_PROTOCOL))
1266             return null;
1267 
1268         URLStreamHandler handler = null;
1269         for (URLStreamHandlerFactory f : installedProviders()) {
1270             handler = f.createURLStreamHandler(protocol);
1271             if (handler != null)
1272                 return handler;







1273         }
1274         return handler;
1275     }
1276 
1277     private static final String[] UNOVERRIDEABLE_PROTOCOLS = {"file", "jrt"};
1278     private static boolean overrideable(String protocol) {
1279         for (String p : UNOVERRIDEABLE_PROTOCOLS)
1280             if (protocol.equalsIgnoreCase(p))
1281                 return false;
1282         return true;
1283     }
1284 
1285     /**
1286      * A table of protocol handlers.
1287      */
1288     static Hashtable<String,URLStreamHandler> handlers = new Hashtable<>();
1289     private static final Object streamHandlerLock = new Object();
1290 
1291     /**
1292      * Returns the Stream Handler.
1293      * @param protocol the protocol to use
1294      */
1295     static URLStreamHandler getURLStreamHandler(String protocol) {
1296 
1297         URLStreamHandler handler = handlers.get(protocol);
1298 
1299         if (handler != null)
1300             return handler;
1301 
1302         boolean checkedWithFactory = false;
1303 
1304         if (overrideable(protocol)) {
1305             handler = handlerFromSettableFactory(protocol);
1306             if (handler != NULL_HANDLER)
1307                 checkedWithFactory = true;
1308 
1309             if (handler == null || handler == NULL_HANDLER) {
1310                 handler = handlerFromInstalledProviders(protocol);
1311             }
1312         }
1313         if (handler == null) {
1314             // Try the built-in protocol handler
1315             handler = defaultFactory.createURLStreamHandler(protocol);
1316         }
1317 
1318         synchronized (streamHandlerLock) {
1319 
1320             URLStreamHandler handler2 = null;
1321 
1322             // Check again with hashtable just in case another
1323             // thread created a handler since we last checked
1324             handler2 = handlers.get(protocol);
1325 
1326             if (handler2 != null) {
1327                 return handler2;
1328             }
1329 
1330             // Check with factory if another thread set a
1331             // factory since our last check
1332             if (!checkedWithFactory) {
1333                 handler2 = handlerFromSettableFactory(protocol);
1334             }
1335 
1336             if (!(handler2 == null || handler2 == NULL_HANDLER)) {
1337                 // The handler from the factory must be given more
1338                 // importance. Discard the default handler that
1339                 // this thread created.
1340                 handler = handler2;
1341             }
1342 
1343             // Insert this handler into the hashtable
1344             if (handler != null) {
1345                 handlers.put(protocol, handler);
1346             }
1347 
1348         }

1349 
1350         return handler;

1351     }










1352 
1353     /**
1354      * WriteObject is called to save the state of the URL to an
1355      * ObjectOutputStream. The handler is not saved since it is
1356      * specific to this system.
1357      *
1358      * @serialData the default write object value. When read back in,
1359      * the reader must ensure that calling getURLStreamHandler with
1360      * the protocol variable returns a valid URLStreamHandler and
1361      * throw an IOException if it does not.
1362      */
1363     private synchronized void writeObject(java.io.ObjectOutputStream s)
1364         throws IOException
1365     {
1366         s.defaultWriteObject(); // write the fields
1367     }
1368 
1369     /**
1370      * readObject is called to restore the state of the URL from the
1371      * stream.  It reads the components of the URL and finds the local