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 2732</a>;
232 * However, the literal IPv6 address format defined in <a
233 * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 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 * <<i>package</i>>.<<i>protocol</i>>.Handler
262 * </pre></blockquote>
263 * where <<i>package</i>> is replaced by the name of the package
264 * and <<i>protocol</i>> 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 2732</a>;
242 * However, the literal IPv6 address format defined in <a
243 * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 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
|