< prev index next >
src/java.base/share/classes/java/net/URLConnection.java
Print this page
*** 26,37 ****
--- 26,41 ----
package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+ import java.security.PrivilegedAction;
import java.util.Hashtable;
import java.util.Date;
+ import java.util.Iterator;
+ import java.util.ServiceConfigurationError;
+ import java.util.ServiceLoader;
import java.util.StringTokenizer;
import java.util.Collections;
import java.util.Map;
import java.util.List;
import java.security.Permission;
*** 105,115 ****
* <li>{@code getContentEncoding}
* <li>{@code getContentLength}
* <li>{@code getContentType}
* <li>{@code getDate}
* <li>{@code getExpiration}
! * <li>{@code getLastModifed}
* </ul>
* <p>
* provide convenient access to these fields. The
* {@code getContentType} method is used by the
* {@code getContent} method to determine the type of the remote
--- 109,119 ----
* <li>{@code getContentEncoding}
* <li>{@code getContentLength}
* <li>{@code getContentType}
* <li>{@code getDate}
* <li>{@code getExpiration}
! * <li>{@code getLastModified}
* </ul>
* <p>
* provide convenient access to these fields. The
* {@code getContentType} method is used by the
* {@code getContent} method to determine the type of the remote
*** 693,712 ****
* Retrieves the contents of this URL connection.
* <p>
* This method first determines the content type of the object by
* calling the {@code getContentType} method. If this is
* the first time that the application has seen that specific content
! * type, a content handler for that content type is created:
* <ol>
* <li>If the application has set up a content handler factory instance
* using the {@code setContentHandlerFactory} method, the
* {@code createContentHandler} method of that instance is called
* with the content type as an argument; the result is a content
* handler for that content type.
! * <li>If no content handler factory has yet been set up, or if the
! * factory's {@code createContentHandler} method returns
! * {@code null}, then this method tries to load a content handler
* class as defined by {@link java.net.ContentHandler ContentHandler}.
* If the class does not exist, or is not a subclass of {@code
* ContentHandler}, then an {@code UnknownServiceException} is thrown.
* </ol>
*
--- 697,730 ----
* Retrieves the contents of this URL connection.
* <p>
* This method first determines the content type of the object by
* calling the {@code getContentType} method. If this is
* the first time that the application has seen that specific content
! * type, a content handler for that content type is created.
! * <p> This is done as follows:
* <ol>
* <li>If the application has set up a content handler factory instance
* using the {@code setContentHandlerFactory} method, the
* {@code createContentHandler} method of that instance is called
* with the content type as an argument; the result is a content
* handler for that content type.
! * <li>If no {@code ContentHandlerFactory} has yet been set up,
! * or if the factory's {@code createContentHandler} method
! * returns {@code null}, then the {@linkplain java.util.ServiceLoader
! * ServiceLoader} mechanism is used to locate {@linkplain
! * java.net.ContentHandlerFactory ContentHandlerFactory}
! * implementations using the system class
! * loader. The order that factories are located is implementation
! * specific, and an implementation is free to cache the located
! * factories. A {@linkplain java.util.ServiceConfigurationError
! * ServiceConfigurationError}, {@code Error} or {@code RuntimeException}
! * thrown from the {@code createContentHandler}, if encountered, will
! * be propagated to the calling thread. The {@code
! * createContentHandler} method of each factory, if instantiated, is
! * invoked, with the content type, until a factory returns non-null,
! * or all factories have been exhausted.
! * <li>Failing that, this method tries to load a content handler
* class as defined by {@link java.net.ContentHandler ContentHandler}.
* If the class does not exist, or is not a subclass of {@code
* ContentHandler}, then an {@code UnknownServiceException} is thrown.
* </ol>
*
*** 853,864 ****
* @throws IllegalStateException if already connected
* @see java.net.URLConnection#doInput
* @see #getDoInput()
*/
public void setDoInput(boolean doinput) {
! if (connected)
! throw new IllegalStateException("Already connected");
doInput = doinput;
}
/**
* Returns the value of this {@code URLConnection}'s
--- 871,881 ----
* @throws IllegalStateException if already connected
* @see java.net.URLConnection#doInput
* @see #getDoInput()
*/
public void setDoInput(boolean doinput) {
! checkConnected();
doInput = doinput;
}
/**
* Returns the value of this {@code URLConnection}'s
*** 883,894 ****
* @param dooutput the new value.
* @throws IllegalStateException if already connected
* @see #getDoOutput()
*/
public void setDoOutput(boolean dooutput) {
! if (connected)
! throw new IllegalStateException("Already connected");
doOutput = dooutput;
}
/**
* Returns the value of this {@code URLConnection}'s
--- 900,910 ----
* @param dooutput the new value.
* @throws IllegalStateException if already connected
* @see #getDoOutput()
*/
public void setDoOutput(boolean dooutput) {
! checkConnected();
doOutput = dooutput;
}
/**
* Returns the value of this {@code URLConnection}'s
*** 909,920 ****
* @param allowuserinteraction the new value.
* @throws IllegalStateException if already connected
* @see #getAllowUserInteraction()
*/
public void setAllowUserInteraction(boolean allowuserinteraction) {
! if (connected)
! throw new IllegalStateException("Already connected");
allowUserInteraction = allowuserinteraction;
}
/**
* Returns the value of the {@code allowUserInteraction} field for
--- 925,935 ----
* @param allowuserinteraction the new value.
* @throws IllegalStateException if already connected
* @see #getAllowUserInteraction()
*/
public void setAllowUserInteraction(boolean allowuserinteraction) {
! checkConnected();
allowUserInteraction = allowuserinteraction;
}
/**
* Returns the value of the {@code allowUserInteraction} field for
*** 972,983 ****
* or not to allow caching
* @throws IllegalStateException if already connected
* @see #getUseCaches()
*/
public void setUseCaches(boolean usecaches) {
! if (connected)
! throw new IllegalStateException("Already connected");
useCaches = usecaches;
}
/**
* Returns the value of this {@code URLConnection}'s
--- 987,997 ----
* or not to allow caching
* @throws IllegalStateException if already connected
* @see #getUseCaches()
*/
public void setUseCaches(boolean usecaches) {
! checkConnected();
useCaches = usecaches;
}
/**
* Returns the value of this {@code URLConnection}'s
*** 998,1009 ****
* @param ifmodifiedsince the new value.
* @throws IllegalStateException if already connected
* @see #getIfModifiedSince()
*/
public void setIfModifiedSince(long ifmodifiedsince) {
! if (connected)
! throw new IllegalStateException("Already connected");
ifModifiedSince = ifmodifiedsince;
}
/**
* Returns the value of this object's {@code ifModifiedSince} field.
--- 1012,1022 ----
* @param ifmodifiedsince the new value.
* @throws IllegalStateException if already connected
* @see #getIfModifiedSince()
*/
public void setIfModifiedSince(long ifmodifiedsince) {
! checkConnected();
ifModifiedSince = ifmodifiedsince;
}
/**
* Returns the value of this object's {@code ifModifiedSince} field.
*** 1053,1068 ****
*
* @param key the keyword by which the request is known
* (e.g., "{@code Accept}").
* @param value the value associated with it.
* @throws IllegalStateException if already connected
! * @throws NullPointerException if key is <CODE>null</CODE>
* @see #getRequestProperty(java.lang.String)
*/
public void setRequestProperty(String key, String value) {
! if (connected)
! throw new IllegalStateException("Already connected");
if (key == null)
throw new NullPointerException ("key is null");
if (requests == null)
requests = new MessageHeader();
--- 1066,1080 ----
*
* @param key the keyword by which the request is known
* (e.g., "{@code Accept}").
* @param value the value associated with it.
* @throws IllegalStateException if already connected
! * @throws NullPointerException if key is {@code null}
* @see #getRequestProperty(java.lang.String)
*/
public void setRequestProperty(String key, String value) {
! checkConnected();
if (key == null)
throw new NullPointerException ("key is null");
if (requests == null)
requests = new MessageHeader();
*** 1082,1093 ****
* @throws NullPointerException if key is null
* @see #getRequestProperties()
* @since 1.4
*/
public void addRequestProperty(String key, String value) {
! if (connected)
! throw new IllegalStateException("Already connected");
if (key == null)
throw new NullPointerException ("key is null");
if (requests == null)
requests = new MessageHeader();
--- 1094,1104 ----
* @throws NullPointerException if key is null
* @see #getRequestProperties()
* @since 1.4
*/
public void addRequestProperty(String key, String value) {
! checkConnected();
if (key == null)
throw new NullPointerException ("key is null");
if (requests == null)
requests = new MessageHeader();
*** 1105,1116 ****
* connection. If key is null, then null is returned.
* @throws IllegalStateException if already connected
* @see #setRequestProperty(java.lang.String, java.lang.String)
*/
public String getRequestProperty(String key) {
! if (connected)
! throw new IllegalStateException("Already connected");
if (requests == null)
return null;
return requests.findValue(key);
--- 1116,1126 ----
* connection. If key is null, then null is returned.
* @throws IllegalStateException if already connected
* @see #setRequestProperty(java.lang.String, java.lang.String)
*/
public String getRequestProperty(String key) {
! checkConnected();
if (requests == null)
return null;
return requests.findValue(key);
*** 1127,1138 ****
* @return a Map of the general request properties for this connection.
* @throws IllegalStateException if already connected
* @since 1.4
*/
public Map<String,List<String>> getRequestProperties() {
! if (connected)
! throw new IllegalStateException("Already connected");
if (requests == null)
return Collections.emptyMap();
return requests.getHeaders(null);
--- 1137,1147 ----
* @return a Map of the general request properties for this connection.
* @throws IllegalStateException if already connected
* @since 1.4
*/
public Map<String,List<String>> getRequestProperties() {
! checkConnected();
if (requests == null)
return Collections.emptyMap();
return requests.getHeaders(null);
*** 1181,1191 ****
}
/**
* The ContentHandler factory.
*/
! static ContentHandlerFactory factory;
/**
* Sets the {@code ContentHandlerFactory} of an
* application. It can be called at most once by an application.
* <p>
--- 1190,1200 ----
}
/**
* The ContentHandler factory.
*/
! private static volatile ContentHandlerFactory factory;
/**
* Sets the {@code ContentHandlerFactory} of an
* application. It can be called at most once by an application.
* <p>
*** 1214,1254 ****
security.checkSetFactory();
}
factory = fac;
}
! private static Hashtable<String, ContentHandler> handlers = new Hashtable<>();
/**
* Gets the Content Handler appropriate for this connection.
*/
! synchronized ContentHandler getContentHandler()
! throws UnknownServiceException
! {
String contentType = stripOffParameters(getContentType());
! ContentHandler handler = null;
! if (contentType == null)
throw new UnknownServiceException("no content-type");
! try {
! handler = handlers.get(contentType);
if (handler != null)
return handler;
- } catch(Exception e) {
- }
! if (factory != null)
handler = factory.createContentHandler(contentType);
! if (handler == null) {
try {
handler = lookupContentHandlerClassFor(contentType);
! } catch(Exception e) {
e.printStackTrace();
handler = UnknownContentHandler.INSTANCE;
}
! handlers.put(contentType, handler);
! }
! return handler;
}
/*
* Media types are in the format: type/subtype*(; parameter).
* For looking up the content handler, we should ignore those
--- 1223,1271 ----
security.checkSetFactory();
}
factory = fac;
}
! private static final Hashtable<String, ContentHandler> handlers = new Hashtable<>();
/**
* Gets the Content Handler appropriate for this connection.
*/
! private ContentHandler getContentHandler() throws UnknownServiceException {
String contentType = stripOffParameters(getContentType());
! if (contentType == null) {
throw new UnknownServiceException("no content-type");
! }
!
! ContentHandler handler = handlers.get(contentType);
if (handler != null)
return handler;
! if (factory != null) {
handler = factory.createContentHandler(contentType);
! if (handler != null)
! return handler;
! }
!
! handler = lookupContentHandlerViaProvider(contentType);
!
! if (handler != null) {
! ContentHandler h = handlers.putIfAbsent(contentType, handler);
! return h != null ? h : handler;
! }
!
try {
handler = lookupContentHandlerClassFor(contentType);
! } catch (Exception e) {
e.printStackTrace();
handler = UnknownContentHandler.INSTANCE;
}
!
! assert handler != null;
!
! ContentHandler h = handlers.putIfAbsent(contentType, handler);
! return h != null ? h : handler;
}
/*
* Media types are in the format: type/subtype*(; parameter).
* For looking up the content handler, we should ignore those
*** 1268,1293 ****
private static final String contentClassPrefix = "sun.net.www.content";
private static final String contentPathProp = "java.content.handler.pkgs";
/**
! * Looks for a content handler in a user-defineable set of places.
! * By default it looks in sun.net.www.content, but users can define a
! * vertical-bar delimited set of class prefixes to search through in
! * addition by defining the java.content.handler.pkgs property.
* The class name must be of the form:
* <pre>
* {package-prefix}.{major}.{minor}
* e.g.
* YoyoDyne.experimental.text.plain
* </pre>
*/
! private ContentHandler lookupContentHandlerClassFor(String contentType)
! throws InstantiationException, IllegalAccessException, ClassNotFoundException {
String contentHandlerClassName = typeToPackageName(contentType);
! String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
StringTokenizer packagePrefixIter =
new StringTokenizer(contentHandlerPkgPrefixes, "|");
while (packagePrefixIter.hasMoreTokens()) {
--- 1285,1309 ----
private static final String contentClassPrefix = "sun.net.www.content";
private static final String contentPathProp = "java.content.handler.pkgs";
/**
! * Looks for a content handler in a user-definable set of places.
! * By default it looks in {@value #contentClassPrefix}, but users can define
! * a vertical-bar delimited set of class prefixes to search through in
! * addition by defining the {@value #contentPathProp} property.
* The class name must be of the form:
* <pre>
* {package-prefix}.{major}.{minor}
* e.g.
* YoyoDyne.experimental.text.plain
* </pre>
*/
! private ContentHandler lookupContentHandlerClassFor(String contentType) {
String contentHandlerClassName = typeToPackageName(contentType);
! String contentHandlerPkgPrefixes = getContentHandlerPkgPrefixes();
StringTokenizer packagePrefixIter =
new StringTokenizer(contentHandlerPkgPrefixes, "|");
while (packagePrefixIter.hasMoreTokens()) {
*** 1303,1323 ****
if (cl != null) {
cls = cl.loadClass(clsName);
}
}
if (cls != null) {
! ContentHandler handler =
! (ContentHandler)cls.newInstance();
! return handler;
! }
! } catch(Exception e) {
}
}
return UnknownContentHandler.INSTANCE;
}
/**
* Utility function to map a MIME content type into an equivalent
* pair of class name components. For example: "text/html" would
* be returned as "text.html"
*/
--- 1319,1368 ----
if (cl != null) {
cls = cl.loadClass(clsName);
}
}
if (cls != null) {
! return (ContentHandler) cls.newInstance();
}
+ } catch(Exception ignored) { }
}
return UnknownContentHandler.INSTANCE;
}
+ private ContentHandler lookupContentHandlerViaProvider(String contentType) {
+ return AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ @Override
+ public ContentHandler run() {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ ServiceLoader<ContentHandlerFactory> sl =
+ ServiceLoader.load(ContentHandlerFactory.class, cl);
+
+ Iterator<ContentHandlerFactory> iterator = sl.iterator();
+
+ ContentHandler handler = null;
+ while (iterator.hasNext()) {
+ ContentHandlerFactory f;
+ try {
+ f = iterator.next();
+ } catch (ServiceConfigurationError e) {
+ if (e.getCause() instanceof SecurityException) {
+ continue;
+ }
+ throw e;
+ }
+ handler = f.createContentHandler(contentType);
+ if (handler != null) {
+ break;
+ }
+ }
+ return handler;
+ }
+ });
+ }
+
/**
* Utility function to map a MIME content type into an equivalent
* pair of class name components. For example: "text/html" would
* be returned as "text.html"
*/
*** 1343,1354 ****
/**
* Returns a vertical bar separated list of package prefixes for potential
* content handlers. Tries to get the java.content.handler.pkgs property
* to use as a set of package prefixes to search. Whether or not
! * that property has been defined, the sun.net.www.content is always
! * the last one on the returned package list.
*/
private String getContentHandlerPkgPrefixes() {
String packagePrefixList = AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(contentPathProp, ""));
--- 1388,1399 ----
/**
* Returns a vertical bar separated list of package prefixes for potential
* content handlers. Tries to get the java.content.handler.pkgs property
* to use as a set of package prefixes to search. Whether or not
! * that property has been defined, the {@value #contentClassPrefix}
! * is always the last one on the returned package list.
*/
private String getContentHandlerPkgPrefixes() {
String packagePrefixList = AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(contentPathProp, ""));
*** 1762,1774 ****
skipped += eachSkip;
}
return skipped;
}
}
-
class UnknownContentHandler extends ContentHandler {
static final ContentHandler INSTANCE = new UnknownContentHandler();
public Object getContent(URLConnection uc) throws IOException {
return uc.getInputStream();
--- 1807,1822 ----
skipped += eachSkip;
}
return skipped;
}
+ private void checkConnected() {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+ }
}
class UnknownContentHandler extends ContentHandler {
static final ContentHandler INSTANCE = new UnknownContentHandler();
public Object getContent(URLConnection uc) throws IOException {
return uc.getInputStream();
< prev index next >