summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/net/URLConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/net/URLConnection.java')
-rw-r--r--luni/src/main/java/java/net/URLConnection.java1056
1 files changed, 1056 insertions, 0 deletions
diff --git a/luni/src/main/java/java/net/URLConnection.java b/luni/src/main/java/java/net/URLConnection.java
new file mode 100644
index 0000000..6c1a192
--- /dev/null
+++ b/luni/src/main/java/java/net/URLConnection.java
@@ -0,0 +1,1056 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.harmony.luni.internal.net.www.MimeTable;
+import org.apache.harmony.luni.util.Msg;
+import org.apache.harmony.luni.util.PriviAction;
+import org.apache.harmony.luni.util.Util;
+
+/**
+ * Concrete implementations of the abstract {@code URLConnection} class provide
+ * a communication link to a URL for exchanging data with a specific protocol
+ * type. A {@code URLConnection} can only be set up after the instantiation but
+ * before connecting to the remote resource.
+ *
+ * @since Android 1.0
+ */
+public abstract class URLConnection {
+
+ /**
+ * The URL which represents the remote target of this {@code URLConnection}.
+ *
+ * @since Android 1.0
+ */
+ protected URL url;
+
+ private String contentType;
+
+ private static boolean defaultAllowUserInteraction;
+
+ private static boolean defaultUseCaches = true;
+
+ ContentHandler defaultHandler = new DefaultContentHandler();
+
+ private long lastModified = -1;
+
+ /**
+ * The data must be modified more recently than this time in milliseconds
+ * since January 1, 1970, GMT to be transmitted.
+ *
+ * @since Android 1.0
+ */
+ protected long ifModifiedSince;
+
+ /**
+ * Specifies whether the using of caches is enabled or the data has to be
+ * recent for every request.
+ *
+ * @since Android 1.0
+ */
+ protected boolean useCaches = defaultUseCaches;
+
+ /**
+ * Specifies whether this {@code URLConnection} is already connected to the
+ * remote resource. If this field is set to {@code true} the flags for
+ * setting up the connection are not changeable anymore.
+ *
+ * @since Android 1.0
+ */
+ protected boolean connected;
+
+ /**
+ * Specifies whether this {@code URLConnection} allows sending data.
+ *
+ * @since Android 1.0
+ */
+ protected boolean doOutput;
+
+ /**
+ * Specifies whether this {@code URLConnection} allows receiving data.
+ *
+ * @since Android 1.0
+ */
+ protected boolean doInput = true;
+
+ /**
+ * Specifies whether this {@code URLConnection} allows user interaction as
+ * it is needed for authentication purposes.
+ *
+ * @since Android 1.0
+ */
+ protected boolean allowUserInteraction = defaultAllowUserInteraction;
+
+ private static ContentHandlerFactory contentHandlerFactory;
+
+ private int readTimeout = 0;
+
+ private int connectTimeout = 0;
+
+ /**
+ * Cache for storing content handler
+ */
+ static Hashtable<String, Object> contentHandlers = new Hashtable<String, Object>();
+
+ /**
+ * A hashtable that maps the filename extension (key) to a MIME-type
+ * (element)
+ */
+ private static FileNameMap fileNameMap;
+
+ /**
+ * Creates a new {@code URLConnection} instance pointing to the resource
+ * specified by the given URL.
+ *
+ * @param url
+ * the URL which represents the resource this {@code
+ * URLConnection} will point to.
+ * @since Android 1.0
+ */
+ protected URLConnection(URL url) {
+ this.url = url;
+ }
+
+ /**
+ * Establishes the connection to the earlier configured resource. The
+ * connection can only be set up before this method has been called.
+ *
+ * @throws IOException
+ * if an error occurs while connecting to the resource.
+ * @since Android 1.0
+ */
+ public abstract void connect() throws IOException;
+
+ /**
+ * Gets the option value which indicates whether user interaction is allowed
+ * on this {@code URLConnection}.
+ *
+ * @return the value of the option {@code allowUserInteraction}.
+ * @see #allowUserInteraction
+ * @since Android 1.0
+ */
+ public boolean getAllowUserInteraction() {
+ return allowUserInteraction;
+ }
+
+ /**
+ * Gets an object representing the content of the resource this {@code
+ * URLConnection} is connected to. First, it attempts to get the content
+ * type from the method {@code getContentType()} which looks at the response
+ * header field "Content-Type". If none is found it will guess the content
+ * type from the filename extension. If that fails the stream itself will be
+ * used to guess the content type.
+ *
+ * @return the content representing object.
+ * @throws IOException
+ * if an error occurs obtaining the content.
+ * @since Android 1.0
+ */
+ public Object getContent() throws java.io.IOException {
+ if (!connected) {
+ connect();
+ }
+
+ if ((contentType = getContentType()) == null) {
+ if ((contentType = guessContentTypeFromName(url.getFile())) == null) {
+ contentType = guessContentTypeFromStream(getInputStream());
+ }
+ }
+ if (contentType != null) {
+ return getContentHandler(contentType).getContent(this);
+ }
+ return null;
+ }
+
+ /**
+ * Gets an object representing the content of the resource this {@code
+ * URLConnection} is connected to. First, it attempts to get the content
+ * type from the method {@code getContentType()} which looks at the response
+ * header field "Content-Type". If none is found it will guess the content
+ * type from the filename extension. If that fails the stream itself will be
+ * used to guess the content type. The content type must match with one of
+ * the list {@code types}.
+ *
+ * @param types
+ * the list of acceptable content types.
+ * @return the content representing object or {@code null} if the content
+ * type does not match with one of the specified types.
+ * @throws IOException
+ * if an error occurs obtaining the content.
+ * @since Android 1.0
+ */
+ // Param is not generic in spec
+ @SuppressWarnings("unchecked")
+ public Object getContent(Class[] types) throws IOException {
+ if (!connected) {
+ connect();
+ }
+
+ if ((contentType = getContentType()) == null) {
+ if ((contentType = guessContentTypeFromName(url.getFile())) == null) {
+ contentType = guessContentTypeFromStream(getInputStream());
+ }
+ }
+ if (contentType != null) {
+ return getContentHandler(contentType).getContent(this, types);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the content encoding type specified by the response header field
+ * {@code content-encoding} or {@code null} if this field is not set.
+ *
+ * @return the value of the response header field {@code content-encoding}.
+ * @since Android 1.0
+ */
+ public String getContentEncoding() {
+ return getHeaderField("Content-Encoding"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the specific ContentHandler that will handle the type {@code
+ * contentType}.
+ *
+ * @param type
+ * The type that needs to be handled
+ * @return An instance of the Content Handler
+ */
+ private ContentHandler getContentHandler(String type) throws IOException {
+ // Replace all non-alphanumeric character by '_'
+ final String typeString = parseTypeString(type.replace('/', '.'));
+
+ // if there's a cached content handler, use it
+ Object cHandler = contentHandlers.get(type);
+ if (cHandler != null) {
+ return (ContentHandler) cHandler;
+ }
+
+ if (contentHandlerFactory != null) {
+ cHandler = contentHandlerFactory.createContentHandler(type);
+ if (!(cHandler instanceof ContentHandler)) {
+ throw new UnknownServiceException();
+ }
+ contentHandlers.put(type, cHandler);
+ return (ContentHandler) cHandler;
+ }
+
+ // search through the package list for the right class for the Content
+ // Type
+ String packageList = AccessController
+ .doPrivileged(new PriviAction<String>(
+ "java.content.handler.pkgs")); //$NON-NLS-1$
+ if (packageList != null) {
+ final StringTokenizer st = new StringTokenizer(packageList, "|"); //$NON-NLS-1$
+ while (st.countTokens() > 0) {
+ try {
+ Class<?> cl = Class.forName(st.nextToken() + "." //$NON-NLS-1$
+ + typeString, true, ClassLoader
+ .getSystemClassLoader());
+ cHandler = cl.newInstance();
+ } catch (ClassNotFoundException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InstantiationException e) {
+ }
+ }
+ }
+
+ if (cHandler == null) {
+ cHandler = AccessController
+ .doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ try {
+ String className = "org.apache.harmony.luni.internal.net.www.content." //$NON-NLS-1$
+ + typeString;
+ return Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InstantiationException e) {
+ }
+ return null;
+ }
+ });
+ }
+ if (cHandler != null) {
+ if (!(cHandler instanceof ContentHandler)) {
+ throw new UnknownServiceException();
+ }
+ contentHandlers.put(type, cHandler); // if we got the handler,
+ // cache it for next time
+ return (ContentHandler) cHandler;
+ }
+
+ return defaultHandler;
+ }
+
+ /**
+ * Gets the content length in bytes specified by the response header field
+ * {@code content-length} or {@code -1} if this field is not set.
+ *
+ * @return the value of the response header field {@code content-length}.
+ * @since Android 1.0
+ */
+ public int getContentLength() {
+ return getHeaderFieldInt("Content-Length", -1); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the MIME-type of the content specified by the response header field
+ * {@code content-type} or {@code null} if type is unknown.
+ *
+ * @return the value of the response header field {@code content-type}.
+ * @since Android 1.0
+ */
+ public String getContentType() {
+ return getHeaderField("Content-Type"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the timestamp when this response has been sent as a date in
+ * milliseconds since January 1, 1970 GMT or {@code 0} if this timestamp is
+ * unknown.
+ *
+ * @return the sending timestamp of the current response.
+ * @since Android 1.0
+ */
+ public long getDate() {
+ return getHeaderFieldDate("Date", 0); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the default setting whether this connection allows user interaction.
+ *
+ * @return the value of the default setting {@code
+ * defaultAllowUserInteraction}.
+ * @see #allowUserInteraction
+ * @since Android 1.0
+ */
+ public static boolean getDefaultAllowUserInteraction() {
+ return defaultAllowUserInteraction;
+ }
+
+ /**
+ * Gets the default value for the specified request {@code field} or {@code
+ * null} if the field could not be found. The current implementation of this
+ * method returns always {@code null}.
+ *
+ * @param field
+ * the request field whose default value shall be returned.
+ * @return the default value for the given field.
+ * @deprecated Use {@link #getRequestProperty}
+ * @since Android 1.0
+ */
+ @Deprecated
+ public static String getDefaultRequestProperty(String field) {
+ return null;
+ }
+
+ /**
+ * Gets the default setting whether this connection allows using caches.
+ *
+ * @return the value of the default setting {@code defaultUseCaches}.
+ * @see #useCaches
+ * @since Android 1.0
+ */
+ public boolean getDefaultUseCaches() {
+ return defaultUseCaches;
+ }
+
+ /**
+ * Gets the value of the option {@code doInput} which specifies whether this
+ * connection allows to receive data.
+ *
+ * @return {@code true} if this connection allows input, {@code false}
+ * otherwise.
+ * @see #doInput
+ * @since Android 1.0
+ */
+ public boolean getDoInput() {
+ return doInput;
+ }
+
+ /**
+ * Gets the value of the option {@code doOutput} which specifies whether
+ * this connection allows to send data.
+ *
+ * @return {@code true} if this connection allows output, {@code false}
+ * otherwise.
+ * @see #doOutput
+ * @since Android 1.0
+ */
+ public boolean getDoOutput() {
+ return doOutput;
+ }
+
+ /**
+ * Gets the timestamp when this response will be expired in milliseconds
+ * since January 1, 1970 GMT or {@code 0} if this timestamp is unknown.
+ *
+ * @return the value of the response header field {@code expires}.
+ * @since Android 1.0
+ */
+ public long getExpiration() {
+ return getHeaderFieldDate("Expires", 0); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the table which is used by all {@code URLConnection} instances to
+ * determine the MIME-type according to a file extension.
+ *
+ * @return the file name map to determine the MIME-type.
+ * @since Android 1.0
+ */
+ public static FileNameMap getFileNameMap() {
+ // Must use lazy initialization or there is a bootstrap problem
+ // trying to load the MimeTable resource from a .jar before
+ // JarURLConnection has finished initialization.
+ if (fileNameMap == null) {
+ fileNameMap = new MimeTable();
+ }
+ return fileNameMap;
+ }
+
+ /**
+ * Gets the header value at the field position {@code pos} or {@code null}
+ * if the header has fewer than {@code pos} fields. The current
+ * implementation of this method returns always {@code null}.
+ *
+ * @param pos
+ * the field position of the response header.
+ * @return the value of the field at position {@code pos}.
+ * @since Android 1.0
+ */
+ public String getHeaderField(int pos) {
+ return null;
+ }
+
+ /**
+ * Gets an unchangeable map of the response-header fields and values. The
+ * response-header field names are the key values of the map. The map values
+ * are lists of header field values associated with a particular key name.
+ *
+ * @return the response-header representing generic map.
+ * @since Android 1.0
+ */
+ public Map<String, List<String>> getHeaderFields() {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Gets an unchangeable map of general request properties used by this
+ * connection. The request property names are the key values of the map. The
+ * map values are lists of property values of the corresponding key name.
+ *
+ * @return the request-property representing generic map.
+ * @since Android 1.0
+ */
+ public Map<String, List<String>> getRequestProperties() {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Adds the given property to the request header. Existing properties with
+ * the same name will not be overwritten by this method.
+ *
+ * @param field
+ * the request property field name to add.
+ * @param newValue
+ * the value of the property which is to add.
+ * @throws IllegalStateException
+ * if the connection has been already established.
+ * @throws NullPointerException
+ * if the property name is {@code null}.
+ * @since Android 1.0
+ */
+ public void addRequestProperty(String field, String newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ if (field == null) {
+ throw new NullPointerException(Msg.getString("KA007")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Gets the value of the header field specified by {@code key} or {@code
+ * null} if there is no field with this name. The current implementation of
+ * this method returns always {@code null}.
+ *
+ * @param key
+ * the name of the header field.
+ * @return the value of the header field.
+ * @since Android 1.0
+ */
+ public String getHeaderField(String key) {
+ return null;
+ }
+
+ /**
+ * Gets the specified header value as a date in milliseconds since January
+ * 1, 1970 GMT. Returns the {@code defaultValue} if no such header field
+ * could be found.
+ *
+ * @param field
+ * the header field name whose value is needed.
+ * @param defaultValue
+ * the default value if no field has been found.
+ * @return the value of the specified header field as a date in
+ * milliseconds.
+ * @since Android 1.0
+ */
+ public long getHeaderFieldDate(String field, long defaultValue) {
+ String date = getHeaderField(field);
+ if (date == null) {
+ return defaultValue;
+ }
+ return Util.parseDate(date);
+ }
+
+ /**
+ * Gets the specified header value as a number. Returns the {@code
+ * defaultValue} if no such header field could be found or the value could
+ * not be parsed as an {@code Integer}.
+ *
+ * @param field
+ * the header field name whose value is needed.
+ * @param defaultValue
+ * the default value if no field has been found.
+ * @return the value of the specified header field as a number.
+ * @since Android 1.0
+ */
+ public int getHeaderFieldInt(String field, int defaultValue) {
+ try {
+ return Integer.parseInt(getHeaderField(field));
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Gets the name of the header field at the given position {@code posn} or
+ * {@code null} if there are fewer than {@code posn} fields. The current
+ * implementation of this method returns always {@code null}.
+ *
+ * @param posn
+ * the position of the header field which has to be returned.
+ * @return the header field name at the given position.
+ * @since Android 1.0
+ */
+ public String getHeaderFieldKey(int posn) {
+ return null;
+ }
+
+ /**
+ * Gets the point of time since when the data must be modified to be
+ * transmitted. Some protocols transmit data only if it has been modified
+ * more recently than a particular time.
+ *
+ * @return the time in milliseconds since January 1, 1970 GMT.
+ * @see #ifModifiedSince
+ * @since Android 1.0
+ */
+ public long getIfModifiedSince() {
+ return ifModifiedSince;
+ }
+
+ /**
+ * Gets an {@code InputStream} for reading data from the resource pointed by
+ * this {@code URLConnection}. It throws an UnknownServiceException by
+ * default. This method must be overridden by its subclasses.
+ *
+ * @return the InputStream to read data from.
+ * @throws IOException
+ * if no InputStream could be created.
+ * @since Android 1.0
+ */
+ public InputStream getInputStream() throws IOException {
+ throw new UnknownServiceException(Msg.getString("K004d")); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the value of the response header field {@code last-modified} or
+ * {@code 0} if this value is not set.
+ *
+ * @return the value of the {@code last-modified} header field.
+ * @since Android 1.0
+ */
+ public long getLastModified() {
+ if (lastModified != -1) {
+ return lastModified;
+ }
+ return lastModified = getHeaderFieldDate("Last-Modified", 0); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets an {@code OutputStream} for writing data to this {@code
+ * URLConnection}. It throws an {@code UnknownServiceException} by default.
+ * This method must be overridden by its subclasses.
+ *
+ * @return the OutputStream to write data.
+ * @throws IOException
+ * if no OutputStream could be created.
+ * @since Android 1.0
+ */
+ public OutputStream getOutputStream() throws IOException {
+ throw new UnknownServiceException(Msg.getString("K005f")); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets a {@code Permission} object representing all needed permissions to
+ * open this connection. The returned permission object depends on the state
+ * of the connection and will be {@code null} if no permissions are
+ * necessary. By default, this method returns {@code AllPermission}.
+ * Subclasses should overwrite this method to return an appropriate
+ * permission object.
+ *
+ * @return the permission object representing the needed permissions to open
+ * this connection.
+ * @throws IOException
+ * if an I/O error occurs while creating the permission object.
+ * @since Android 1.0
+ */
+ public java.security.Permission getPermission() throws IOException {
+ return new java.security.AllPermission();
+ }
+
+ /**
+ * Gets the value of the request header property specified by {code field}
+ * or {@code null} if there is no field with this name. The current
+ * implementation of this method returns always {@code null}.
+ *
+ * @param field
+ * the name of the request header property.
+ * @return the value of the property.
+ * @throws IllegalStateException
+ * if the connection has been already established.
+ * @since Android 1.0
+ */
+ public String getRequestProperty(String field) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Gets the URL represented by this {@code URLConnection}.
+ *
+ * @return the URL of this connection.
+ * @since Android 1.0
+ */
+ public URL getURL() {
+ return url;
+ }
+
+ /**
+ * Gets the value of the flag which specifies whether this {@code
+ * URLConnection} allows to use caches.
+ *
+ * @return {@code true} if using caches is allowed, {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean getUseCaches() {
+ return useCaches;
+ }
+
+ /**
+ * Determines the MIME-type of the given resource {@code url} by resolving
+ * the filename extension with the internal FileNameMap. Any fragment
+ * identifier is removed before processing.
+ *
+ * @param url
+ * the URL with the filename to get the MIME type.
+ * @return the guessed content type or {@code null} if the type could not be
+ * determined.
+ * @since Android 1.0
+ */
+ public static String guessContentTypeFromName(String url) {
+ return getFileNameMap().getContentTypeFor(url);
+ }
+
+ /**
+ * Determines the MIME-type of the resource represented by the input stream
+ * {@code is} by reading its first few characters.
+ *
+ * @param is
+ * the resource representing input stream to determine the
+ * content type.
+ * @return the guessed content type or {@code null} if the type could not be
+ * determined.
+ * @throws IOException
+ * if an I/O error occurs while reading from the input stream.
+ * @since Android 1.0
+ */
+ public static String guessContentTypeFromStream(InputStream is)
+ throws IOException {
+ if (!is.markSupported()) {
+ return null;
+ }
+ is.mark(4);
+ char[] chars = new char[4];
+ for (int i = 0; i < chars.length; i++) {
+ chars[i] = (char) is.read();
+ }
+ is.reset();
+ if ((chars[0] == 'P') && (chars[1] == 'K')) {
+ return "application/zip"; //$NON-NLS-1$
+ }
+ if ((chars[0] == 'G') && (chars[1] == 'I')) {
+ return "image/gif"; //$NON-NLS-1$
+ }
+ if (new String(chars).trim().startsWith("<")) { //$NON-NLS-1$
+ return "text/html"; //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Performs any necessary string parsing on the input string such as
+ * converting non-alphanumeric character into underscore.
+ *
+ * @param typeString
+ * the parsed string
+ * @return the string to be parsed
+ */
+ private String parseTypeString(String typeString) {
+ StringBuffer typeStringBuffer = new StringBuffer(typeString);
+ for (int i = 0; i < typeStringBuffer.length(); i++) {
+ // if non-alphanumeric, replace it with '_'
+ char c = typeStringBuffer.charAt(i);
+ if (!(Character.isLetter(c) || Character.isDigit(c) || c == '.')) {
+ typeStringBuffer.setCharAt(i, '_');
+ }
+ }
+ return typeStringBuffer.toString();
+ }
+
+ /**
+ * Sets the flag indicating whether this connection allows user interaction
+ * or not. This method can only be called prior to the connection
+ * establishment.
+ *
+ * @param newValue
+ * the value of the flag to be set.
+ * @throws IllegalStateException
+ * if this method attempts to change the flag after the
+ * connection has been established.
+ * @see #allowUserInteraction
+ * @since Android 1.0
+ */
+ public void setAllowUserInteraction(boolean newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ this.allowUserInteraction = newValue;
+ }
+
+ /**
+ * Sets the internally used content handler factory. The content factory can
+ * only be set if it is allowed by the security manager and only once during
+ * the lifetime of the application.
+ *
+ * @param contentFactory
+ * the content factory to be set.
+ * @throws Error
+ * if the security manager does not allow to set the content
+ * factory or it has been already set earlier ago.
+ * @since Android 1.0
+ */
+ public static synchronized void setContentHandlerFactory(
+ ContentHandlerFactory contentFactory) {
+ if (contentHandlerFactory != null) {
+ throw new Error(Msg.getString("K004e")); //$NON-NLS-1$
+ }
+ SecurityManager sManager = System.getSecurityManager();
+ if (sManager != null) {
+ sManager.checkSetFactory();
+ }
+ contentHandlerFactory = contentFactory;
+ }
+
+ /**
+ * Sets the default value for the flag indicating whether this connection
+ * allows user interaction or not. Existing {@code URLConnection}s are
+ * unaffected.
+ *
+ * @param allows
+ * the default value of the flag to be used for new connections.
+ * @see #defaultAllowUserInteraction
+ * @see #allowUserInteraction
+ * @since Android 1.0
+ */
+ public static void setDefaultAllowUserInteraction(boolean allows) {
+ defaultAllowUserInteraction = allows;
+ }
+
+ /**
+ * Sets the default value of the specified request header field. This value
+ * will be used for the specific field of every newly created connection.
+ * The current implementation of this method does nothing.
+ *
+ * @param field
+ * the request header field to be set.
+ * @param value
+ * the default value to be used.
+ * @deprecated Use {@link #setRequestProperty} of an existing {@code
+ * URLConnection} instance.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public static void setDefaultRequestProperty(String field, String value) {
+ }
+
+ /**
+ * Sets the default value for the flag indicating whether this connection
+ * allows to use caches. Existing {@code URLConnection}s are unaffected.
+ *
+ * @param newValue
+ * the default value of the flag to be used for new connections.
+ * @see #defaultUseCaches
+ * @see #useCaches
+ * @since Android 1.0
+ */
+ public void setDefaultUseCaches(boolean newValue) {
+ // BEGIN android-removed
+ // Setting the default doesn't concern the current connection.
+ // if (connected) {
+ // throw new IllegalAccessError(Msg.getString("K0037")); //$NON-NLS-1$
+ // }
+ // END android-removed
+ defaultUseCaches = newValue;
+ }
+
+ /**
+ * Sets the flag indicating whether this {@code URLConnection} allows input.
+ * It cannot be set after the connection is established.
+ *
+ * @param newValue
+ * the new value for the flag to be set.
+ * @throws IllegalAccessError
+ * if this method attempts to change the value after the
+ * connection has been already established.
+ * @see #doInput
+ * @since Android 1.0
+ */
+ public void setDoInput(boolean newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ this.doInput = newValue;
+ }
+
+ /**
+ * Sets the flag indicating whether this {@code URLConnection} allows
+ * output. It cannot be set after the connection is established.
+ *
+ * @param newValue
+ * the new value for the flag to be set.
+ * @throws IllegalAccessError
+ * if this method attempts to change the value after the
+ * connection has been already established.
+ * @see #doOutput
+ * @since Android 1.0
+ */
+ public void setDoOutput(boolean newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ this.doOutput = newValue;
+ }
+
+ /**
+ * Sets the internal map which is used by all {@code URLConnection}
+ * instances to determine the MIME-type according to a filename extension.
+ *
+ * @param map
+ * the MIME table to be set.
+ * @since Android 1.0
+ */
+ public static void setFileNameMap(FileNameMap map) {
+ SecurityManager manager = System.getSecurityManager();
+ if (manager != null) {
+ manager.checkSetFactory();
+ }
+ fileNameMap = map;
+ }
+
+ /**
+ * Sets the point of time since when the data must be modified to be
+ * transmitted. Some protocols transmit data only if it has been modified
+ * more recently than a particular time. The data will be transmitted
+ * regardless of its timestamp if this option is set to {@code 0}.
+ *
+ * @param newValue
+ * the time in milliseconds since January 1, 1970 GMT.
+ * @throws IllegalStateException
+ * if this {@code URLConnection} has already been connected.
+ * @see #ifModifiedSince
+ * @since Android 1.0
+ */
+ public void setIfModifiedSince(long newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ this.ifModifiedSince = newValue;
+ }
+
+ /**
+ * Sets the value of the specified request header field. The value will only
+ * be used by the current {@code URLConnection} instance. This method can
+ * only be called before the connection is established.
+ *
+ * @param field
+ * the request header field to be set.
+ * @param newValue
+ * the new value of the specified property.
+ * @throws IllegalStateException
+ * if the connection has been already established.
+ * @throws NullPointerException
+ * if the parameter {@code field} is {@code null}.
+ * @since Android 1.0
+ */
+ public void setRequestProperty(String field, String newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ if (field == null) {
+ throw new NullPointerException(Msg.getString("KA007")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets the flag indicating whether this connection allows to use caches or
+ * not. This method can only be called prior to the connection
+ * establishment.
+ *
+ * @param newValue
+ * the value of the flag to be set.
+ * @throws IllegalStateException
+ * if this method attempts to change the flag after the
+ * connection has been established.
+ * @see #useCaches
+ * @since Android 1.0
+ */
+ public void setUseCaches(boolean newValue) {
+ if (connected) {
+ throw new IllegalStateException(Msg.getString("K0037")); //$NON-NLS-1$
+ }
+ this.useCaches = newValue;
+ }
+
+ /**
+ * Sets the timeout value in milliseconds for establishing the connection to
+ * the resource pointed by this {@code URLConnection} instance. A {@code
+ * SocketTimeoutException} is thrown if the connection could not be
+ * established in this time. Default is {@code 0} which stands for an
+ * infinite timeout.
+ *
+ * @param timeout
+ * the connecting timeout in milliseconds.
+ * @throws IllegalArgumentException
+ * if the parameter {@code timeout} is less than zero.
+ * @since Android 1.0
+ */
+ public void setConnectTimeout(int timeout) {
+ if (0 > timeout) {
+ throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
+ }
+ this.connectTimeout = timeout;
+ }
+
+ /**
+ * Gets the configured connecting timeout.
+ *
+ * @return the connecting timeout value in milliseconds.
+ * @since Android 1.0
+ */
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ /**
+ * Sets the timeout value in milliseconds for reading from the input stream
+ * of an established connection to the resource. A {@code
+ * SocketTimeoutException} is thrown if the connection could not be
+ * established in this time. Default is {@code 0} which stands for an
+ * infinite timeout.
+ *
+ * @param timeout
+ * the reading timeout in milliseconds.
+ * @throws IllegalArgumentException
+ * if the parameter {@code timeout} is less than zero.
+ * @since Android 1.0
+ */
+ public void setReadTimeout(int timeout) {
+ if (0 > timeout) {
+ throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
+ }
+ this.readTimeout = timeout;
+ }
+
+ /**
+ * Gets the configured timeout for reading from the input stream of an
+ * established connection to the resource.
+ *
+ * @return the reading timeout value in milliseconds.
+ * @since Android 1.0
+ */
+ public int getReadTimeout() {
+ return readTimeout;
+ }
+
+ /**
+ * Returns the string representation containing the name of this class and
+ * the URL.
+ *
+ * @return the string representation of this {@code URLConnection} instance.
+ * @since Android 1.0
+ */
+ @Override
+ public String toString() {
+ return getClass().getName() + ":" + url.toString(); //$NON-NLS-1$
+ }
+
+ static class DefaultContentHandler extends java.net.ContentHandler {
+
+ /**
+ * @param u
+ * the URL connection
+ *
+ * @see java.net.ContentHandler#getContent(java.net.URLConnection)
+ */
+ @Override
+ public Object getContent(URLConnection u) throws IOException {
+ return u.getInputStream();
+ }
+ }
+}