/*
 *  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.Date;
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;

/**
 * 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.
 */
public abstract class URLConnection {

    /**
     * The URL which represents the remote target of this {@code URLConnection}.
     */
    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.
     */
    protected long ifModifiedSince;

    /**
     * Specifies whether the using of caches is enabled or the data has to be
     * recent for every request.
     */
    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.
     */
    protected boolean connected;

    /**
     * Specifies whether this {@code URLConnection} allows sending data.
     */
    protected boolean doOutput;

    /**
     * Specifies whether this {@code URLConnection} allows receiving data.
     */
    protected boolean doInput = true;

    /**
     * Specifies whether this {@code URLConnection} allows user interaction as
     * it is needed for authentication purposes.
     */
    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.
     */
    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.
     */
    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
     */
    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.
     */
    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.
     */
    // 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}.
     */
    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);
            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 {
                                // Try looking up AWT image content handlers
                                String className = "org.apache.harmony.awt.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}.
     */
    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}.
     */
    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.
     */
    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
     */
    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}
     */
    @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
     */
    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
     */
    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
     */
    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}.
     */
    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.
     */
    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.
        synchronized (URLConnection.class) {
            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}.
     */
    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 1.4
     */
    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 1.4
     */
    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 1.4
     */
    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.
     */
    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.
     */
    @SuppressWarnings("deprecation")
    public long getHeaderFieldDate(String field, long defaultValue) {
        String date = getHeaderField(field);
        if (date == null) {
            return defaultValue;
        }
        try {
            return Date.parse(date);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 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.
     */
    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.
     */
    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
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    @SuppressWarnings("nls")
    public static String guessContentTypeFromStream(InputStream is)
            throws IOException {

        if (!is.markSupported()) {
            return null;
        }
        // Look ahead up to 64 bytes for the longest encoded header
        is.mark(64);
        byte[] bytes = new byte[64];
        int length = is.read(bytes);
        is.reset();

        // Check for Unicode BOM encoding indicators
        String encoding = "ASCII";
        int start = 0;
        if (length > 1) {
            if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)) {
                encoding = "UTF-16LE";
                start = 2;
                length -= length & 1;
            }
            if ((bytes[0] == (byte) 0xFE) && (bytes[1] == (byte) 0xFF)) {
                encoding = "UTF-16BE";
                start = 2;
                length -= length & 1;
            }
            if (length > 2) {
                if ((bytes[0] == (byte) 0xEF) && (bytes[1] == (byte) 0xBB)
                        && (bytes[2] == (byte) 0xBF)) {
                    encoding = "UTF-8";
                    start = 3;
                }
                if (length > 3) {
                    if ((bytes[0] == (byte) 0x00) && (bytes[1] == (byte) 0x00)
                            && (bytes[2] == (byte) 0xFE)
                            && (bytes[3] == (byte) 0xFF)) {
                        encoding = "UTF-32BE";
                        start = 4;
                        length -= length & 3;
                    }
                    if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)
                            && (bytes[2] == (byte) 0x00)
                            && (bytes[3] == (byte) 0x00)) {
                        encoding = "UTF-32LE";
                        start = 4;
                        length -= length & 3;
                    }
                }
            }
        }

        String header = new String(bytes, start, length - start, encoding);

        // Check binary types
        if (header.startsWith("PK")) {
            return "application/zip";
        }
        if (header.startsWith("GI")) {
            return "image/gif";
        }

        // Check text types
        String textHeader = header.trim().toUpperCase();
        if (textHeader.startsWith("<!DOCTYPE HTML") ||
                textHeader.startsWith("<HTML") ||
                textHeader.startsWith("<HEAD") ||
                textHeader.startsWith("<BODY") ||
                textHeader.startsWith("<HEAD")) {
            return "text/html";
        }

        if (textHeader.startsWith("<?XML")) {
            return "application/xml";
        }

        // Give up
        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) {
        StringBuilder typeStringBuffer = new StringBuilder(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
     */
    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.
     */
    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
     */
    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.
     */
    @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
     */
    public void setDefaultUseCaches(boolean newValue) {
        if (connected) {
            throw new IllegalAccessError(Msg.getString("K0037")); //$NON-NLS-1$
        }
        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
     */
    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
     */
    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.
     */
    public static void setFileNameMap(FileNameMap map) {
        SecurityManager manager = System.getSecurityManager();
        if (manager != null) {
            manager.checkSetFactory();
        }
        synchronized (URLConnection.class) {
            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
     */
    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}.
     */
    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
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.
     */
    @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();
        }
    }
}
