/[classpath]/classpath/java/net/URLConnection.java
ViewVC logotype

Diff of /classpath/java/net/URLConnection.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.9 by mkoch, Sat Dec 21 12:37:01 2002 UTC revision 1.10 by mkoch, Tue Mar 11 14:35:20 2003 UTC
# Line 53  import java.util.Map; Line 53  import java.util.Map;
53  import java.util.Locale;  import java.util.Locale;
54    
55  /**  /**
56    * This class models a connection that retrieves the information pointed   * This class models a connection that retrieves the information pointed
57    * to by a URL object.  This is typically a connection to a remote node   * to by a URL object.  This is typically a connection to a remote node
58    * on the network, but could be a simple disk read.   * on the network, but could be a simple disk read.
59    * <p>   * <p>
60    * A URLConnection object is normally created by calling the openConnection()   * A URLConnection object is normally created by calling the openConnection()
61    * method of a URL object.  This method is somewhat misnamed because it does   * method of a URL object.  This method is somewhat misnamed because it does
62    * not actually open the connection.  Instead, it return an unconnected   * not actually open the connection.  Instead, it return an unconnected
63    * instance of this object.  The caller then has the opportunity to set   * instance of this object.  The caller then has the opportunity to set
64    * various connection options prior to calling the actual connect() method.   * various connection options prior to calling the actual connect() method.
65    * <p>   * <p>
66    * After the connection has been opened, there are a number of methods in   * After the connection has been opened, there are a number of methods in
67    * this class that access various attributes of the data, typically   * this class that access various attributes of the data, typically
68    * represented by headers sent in advance of the actual data itself.   * represented by headers sent in advance of the actual data itself.
69    * <p>   * <p>
70    * Also of note are the getInputStream and getContent() methods which allow   * Also of note are the getInputStream and getContent() methods which allow
71    * the caller to retrieve the actual data from the connection.  Note that   * the caller to retrieve the actual data from the connection.  Note that
72    * for some types of connections, writing is also allowed.  The setDoOutput()   * for some types of connections, writing is also allowed.  The setDoOutput()
73    * method must be called prior to connecing in order to enable this, then   * method must be called prior to connecing in order to enable this, then
74    * the getOutputStream method called after the connection in order to   * the getOutputStream method called after the connection in order to
75    * obtain a stream to write the output to.   * obtain a stream to write the output to.
76    * <p>   * <p>
77    * The getContent() method is of particular note.  This method returns an   * The getContent() method is of particular note.  This method returns an
78    * Object that encapsulates the data returned.  There is no way do determine   * Object that encapsulates the data returned.  There is no way do determine
79    * the type of object that will be returned in advance.  This is determined   * the type of object that will be returned in advance.  This is determined
80    * by the actual content handlers as described in the description of that   * by the actual content handlers as described in the description of that
81    * method.   * method.
82    *   *
83    * @version 0.5   * @version 0.5
   *  
   * @author Aaron M. Renn (arenn@urbanophile.com)  
   */  
 public abstract class URLConnection  
 {  
   
 /*************************************************************************/  
   
 /*  
  * Class Variables  
  */  
   
 /**  
   * This is an object that maps filenames to MIME types.  The interface  
   * to do this is implemented by this class, so just create an empty  
   * instance and store it here.  
   */  
 private static FileNameMap fileNameMap = new MimeTypeMapper();  
   
 /**  
   * This is the ContentHandlerFactory set by the caller, if any  
   */  
 private static ContentHandlerFactory factory;  
   
 /**  
   * This is the default value that will be used to determine whether or  
   * not user interaction should be allowed.  
   */  
 private static boolean def_allow_user_inter;  
   
 /**  
   * This is the default flag indicating whether or not to use caches to  
   * store the data returned from a server  
   */  
 private static boolean def_use_caches;  
   
 /**  
   * This is a Hashable for setting default request properties  
   */  
 private static Hashtable def_req_props = new Hashtable();  
   
 /*************************************************************************/  
   
 /*  
  * Instance Variables  
  */  
   
 /**  
   * This variable determines whether or not interaction is allowed with  
   * the user.  For example, to prompt for a username and password.  
   */  
 protected boolean allowUserInteraction;  
   
 /**  
   * Indicates whether or not a connection has been established to the  
   * destination specified in the URL  
   */  
 protected boolean connected;  
   
 /**  
   * Indicates whether or not input can be read from this URL  
   */  
 protected boolean doInput;  
   
 /**  
   * Indicates whether or not output can be sent to this URL  
   */  
 protected boolean doOutput;  
   
 /**  
   * If this flag is set, the protocol is allowed to cache data whenever  
   * it can (caching is not guaranteed). If it is not set, the protocol must a get a fresh copy of  
   * the data.  
   * <p>  
   * This field is set by the setUseCaches method and returned by the  
   * getUseCaches method.  
   *  
   * Its default value is that determined by the last invocation of  
   * setDefaultUseCaches  
   *  
   */  
 protected boolean useCaches;  
   
 /**  
   * If this value is non-zero, then the connection will only attempt to  
   * fetch the document pointed to by the URL if the document has been  
   * modified more recently than the date set in this variable.  That date  
   * should be specified as the number of seconds since 1/1/1970 GMT.  
   */  
 protected long ifModifiedSince;  
   
 /**  
   * This is the URL associated with this connection  
   */  
 protected URL url;  
   
 /**  
   * The list of request properties for this connection  
   */  
 private final Hashtable req_props;  
   
 /*************************************************************************/  
   
 /*  
  * Class Methods  
  */  
   
 /**  
   * Set's the ContentHandlerFactory for an application.  This can be called  
   * once and only once.  If it is called again, then an Error is thrown.  
   * Unlike for other set factory methods, this one does not do a security  
   * check prior to setting the factory.  
   *  
   * @param factory The ContentHandlerFactory for this application  
   *  
   * @error Error If the factory is already set  
   */  
 public static synchronized void  
 setContentHandlerFactory(ContentHandlerFactory fac)  
 {  
   if (factory != null)  
     throw new Error("The ContentHandlerFactory is already set");  
   
   factory = fac;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the default flag for whether or not interaction with a user  
   * is allowed.  This will be used for all connections unless overidden  
   *  
   * @return true if user interaction is allowed, false otherwise  
   */  
 public static boolean  
 getDefaultAllowUserInteraction()  
 {  
   return(def_allow_user_inter);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the default flag for whether or not interaction with a user  
   * is allowed.  This will be used for all connections unless overridden  
   *  
   * @param allow true to allow user interaction, false otherwise  
   */  
 public static synchronized void  
 setDefaultAllowUserInteraction(boolean allow)  
 {  
   def_allow_user_inter = allow;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the default value of a request property.  This will be used  
   * for all connections unless the value of the property is manually  
   * overridden.  
   *  
   * @param key The request property to return the default value of  
   *  
   * @return The default request property  
   */  
 public static String  
 getDefaultRequestProperty(String key)  
 {  
   return((String)def_req_props.get(key.toLowerCase()));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the default value of a request property.  This will be used  
   * for all connections unless the value of the property is manually  
   * overridden.  
   *  
   * @param key The request property name the default is being set for  
   * @param value The value to set the default to  
   */  
 public static synchronized void  
 setDefaultRequestProperty(String key, String value)  
 {  
   def_req_props.put(key.toLowerCase(), value);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the MIME type of a file based on the name of the file.  This  
   * works by searching for the file's extension in a list of file extensions  
   * and returning the MIME type associated with it.  If no type is found,  
   * then a MIME type of "application/octet-stream" will be returned.  
   *  
   * @param filename The filename to determine the MIME type for  
   *  
   * @return The MIME type String  
   *  
   * @specnote public since jdk 1.4  
   */  
 public static String  
 guessContentTypeFromName(String filename)  
 {  
   return(fileNameMap.getContentTypeFor(filename.toLowerCase()));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the MIME type of a stream based on the first few characters  
   * at the beginning of the stream.  This routine can be used to determine  
   * the MIME type if a server is believed to be returning an incorrect  
   * MIME type.  This method returns "application/octet-stream" if it  
   * cannot determine the MIME type.  
   * <p>  
   * NOTE: Overriding MIME types sent from the server can be obnoxious  
   * to user's.  See Internet Exploder 4 if you don't believe me.  
   *  
   * @param is The InputStream to determine the MIME type from  
   *  
   * @return The MIME type  
   *  
   * @exception IOException If an error occurs  
   */  
 public static String  
 guessContentTypeFromStream(InputStream is) throws IOException  
 {  
   return("application/octet-stream");  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method returns the <code>FileNameMap</code> object being used  
   * to decode MIME types by file extension.  
   *  
   * @return The <code>FileNameMap</code>.  
   */  
 public static FileNameMap  
 getFileNameMap()  
 {  
   return(fileNameMap);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method set the <code>FileNameMap</code> object being used  
   * to decode MIME types by file extension.  
   *  
   * @param fileNameMap The <code>FileNameMap</code>.  
   */  
 public static void  
 setFileNameMap(FileNameMap fileNameMap)  
 {  
   URLConnection.fileNameMap = fileNameMap;    
 }  
   
 /*************************************************************************/  
   
 /*  
  * Constructors  
  */  
   
 /**  
   * This constructs a URLConnection from a URL object  
   *  
   * @param url The URL for this connection  
   */  
 protected  
 URLConnection(URL url)  
 {  
   // Set up all our instance variables  
   this.url = url;  
   allowUserInteraction = def_allow_user_inter;  
   useCaches = def_use_caches;  
   
   req_props = new Hashtable(def_req_props);  
 }  
   
 /*************************************************************************/  
   
 /*  
  * Instance Methods  
  */  
   
 /**  
   * Returns the default value used to determine whether or not caching  
   * of documents will be done when possible.  
   *  
   * @return true if caches will be used, false otherwise  
   */  
 public boolean  
 getDefaultUseCaches()  
 {  
   return(def_use_caches);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the default value used to determine whether or not caching  
   * of documents will be done when possible.  
   *  
   * @param use true to use caches if possible by default, false otherwise  
   */  
 public synchronized void  
 setDefaultUseCaches(boolean use)  
 {  
   def_use_caches = use;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns a boolean flag indicating whether or not user interaction is  
   * allowed for this connection.  (For example, in order to prompt for  
   * username and password info.  
   *  
   * @return true if user interaction is allowed, false otherwise  
   */  
 public boolean  
 getAllowUserInteraction()  
 {  
   return(allowUserInteraction);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets a boolean flag indicating whether or not user interaction is  
   * allowed for this connection.  (For example, in order to prompt for  
   * username and password info.  
   *  
   * @param allow true if user interaction should be allowed, false otherwise  
   */  
 public void  
 setAllowUserInteraction(boolean allow)  
 {  
   allowUserInteraction = allow;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of a flag indicating whether or not input is going  
   * to be done for this connection.  This default to true unless the  
   * doOutput flag is set to false, in which case this defaults to false.  
   *  
   * @return true if input is to be done, false otherwise  
   */  
 public boolean  
 getDoInput()  
 {  
   return(doInput);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of a flag indicating whether or not input is going  
   * to be done for this connection.  This default to true unless the  
   * doOutput flag is set to false, in which case this defaults to false.  
   *  
   * @param input true if input is to be done, false otherwise  
   */  
 public void  
 setDoInput(boolean input)  
 {  
   doInput = input;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns a boolean flag indicating whether or not output will be done  
   * on this connection.  This defaults to false.  
   *  
   * @return true if output is to be done, false otherwise  
   */  
 public boolean  
 getDoOutput()  
 {  
   return(doOutput);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns a boolean flag indicating whether or not output will be done  
   * on this connection.  The default value is false, so this method can  
   * be used to override the default  
   *  
   * @param output ture if output is to be done, false otherwise  
   */  
 public void  
 setDoOutput(boolean output)  
 {  
   doOutput = output;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns a boolean flag indicating whether or not caching will be used  
   * (if possible) to store data downloaded via the connection.  
   *  
   * @return true if caching should be used if possible, false otherwise  
   */  
 public boolean  
 getUseCaches()  
 {  
   return(useCaches);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets a boolean flag indicating whether or not caching will be used  
   * (if possible) to store data downloaded via the connection.  
   *  
   * @param use_cache true if caching should be used if possible, false otherwise  
   */  
 public void  
 setUseCaches(boolean use_caches)  
 {  
   useCaches = use_caches;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the ifModified since instance variable.  If this value is non  
   * zero and the underlying protocol supports it, the actual document will  
   * not be fetched unless it has been modified since this time.  The value  
   * returned will be 0 if this feature is disabled or the time expressed  
   * as the number of seconds since midnight 1/1/1970 GMT otherwise  
   *  
   * @return The ifModifiedSince value  
   */  
 public long  
 getIfModifiedSince()  
 {  
   return(ifModifiedSince);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the ifModified since instance variable.  If this value is non  
   * zero and the underlying protocol supports it, the actual document will  
   * not be fetched unless it has been modified since this time.  The value  
   * passed should  be 0 if this feature is to be disabled or the time expressed  
   * as the number of seconds since midnight 1/1/1970 GMT otherwise.  
   *  
   * @param modified_since The new ifModifiedSince value  
   */  
 public void  
 setIfModifiedSince(long modified_since)  
 {  
   ifModifiedSince = modified_since;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of the named request property.  
   *  
   * @param key The name of the property  
   *  
   * @return The value of the property  
   */  
 public String  
 getRequestProperty(String key)  
 {  
   return((String)req_props.get(key.toLowerCase()));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the value of the named request property  
   *  
   * @param key The name of the property  
   * @param value The value of the property  
   */  
 public void  
 setRequestProperty(String key, String value)  
 {  
   req_props.put(key.toLowerCase(), value);  
 }  
   
 /**  
  * Returns an unmodifiable Map containing the request properties.  
84   *   *
85   * @since 1.4   * @author Aaron M. Renn (arenn@urbanophile.com)
86   */   */
87  public Map  public abstract class URLConnection
 getRequestProperties()  
 {  
   return Collections.unmodifiableMap(req_props);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the URL object associated with this connection  
   *  
   * @return The URL for this connection.  
   */  
 public URL  
 getURL()  
 {  
   return(url);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Establishes the actual connection to the URL associated with this  
   * connection object  
   */  
 public abstract void  
 connect() throws IOException;  
   
 /*************************************************************************/  
   
 /**  
   * Returns an InputStream for this connection.  As this default  
   * implementation returns null, subclasses should override this method  
   *  
   * @return An InputStream for this connection  
   *  
   * @exception IOException If an error occurs  
   */  
 public InputStream  
 getInputStream() throws IOException  
 {  
   return(null);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns an OutputStream for this connection.  As this default  
   * implementation returns null, subclasses should override this method  
   *  
   * @return An OutputStream for this connection  
   *  
   * @exception IOException If an error occurs  
   */  
 public OutputStream  
 getOutputStream() throws IOException  
 {  
   return(null);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of the content-encoding field or null if it is not  
   * known or not present.  
   *  
   * @return The content-encoding field  
   */  
 public String  
 getContentEncoding()  
 {  
   return(getHeaderField("content-encoding"));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of the content-length header field or -1 if the value  
   * is not known or not present.  
   *  
   * @return The content-length field  
   */  
 public int  
 getContentLength()  
 {  
   return(getHeaderFieldInt("content-length", -1));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the the content-type of the data pointed to by the URL.  This  
   * method first tries looking for a content-type header.  If that is not  
   * present, it attempts to use the file name to determine the content's  
   * MIME type.  If that is unsuccessful, the method returns null.  The caller  
   * may then still attempt to determine the MIME type by a call to  
   * guessContentTypeFromStream()  
   *  
   * @return The content MIME type  
   */  
 public String  
 getContentType()  
 {  
   String type = getHeaderField("content-type");  
   if (type == null)  
     type = guessContentTypeFromName(getURL().getFile());  
   
   return(type);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the date of the document pointed to by the URL as reported in  
   * the date field of the header or 0 if the value is not present or not  
   * known. If populated, the return value is number of seconds since  
   * midnight on 1/1/1970 GMT.  
   *  
   * @return The document date  
   */  
 public long  
 getDate()  
 {  
   return(getHeaderFieldDate("date", 0));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of the expires header or 0 if not known or present.  
   * If populated, the return value is number of seconds since midnight  
   * on 1/1/1970 GMT.  
   *  
   * @return The expiration time.  
   */  
 public long  
 getExpiration()  
 {  
   return(getHeaderFieldDate("expires", 0));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of the last-modified header field or 0 if not known known  
   * or not present.  If populated, the return value is the number of seconds  
   * since midnight on 1/1/1970.  
   *  
   * @return The last modified time  
   */  
 public long  
 getLastModified()  
 {  
   return(getHeaderFieldDate("last-modified", 0));  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns a String representing the header key at the specified index.  
   * This allows the caller to walk the list of header fields.  The analogous  
   * getHeaderField(int) method allows access to the corresponding value for  
   * this tag.  
   *  
   * @param index The index into the header field list to retrieve the key for.  
   *  
   * @return The header field key or null if index is past the end of the headers  
   */  
 public String  
 getHeaderFieldKey(int index)  
 {  
   return(null);  
 }      
   
 /*************************************************************************/  
   
 /**  
   * Return a String representing the header value at the specified index.  
   * This allows the caller to walk the list of header fields.  The analogous  
   * getHeaderFieldKey(int) method allows access to the corresponding key  
   * for this header field  
   *  
   * @param index The index into the header field list to retrieve the value for  
   *  
   * @return The header value or null if index is past the end of the headers  
   */  
 public String  
 getHeaderField(int index)  
 {  
   return(null);  
 }      
   
 /*************************************************************************/  
   
 /**  
   * Returns a String representing the value of the header field having  
   * the named key.  Returns null if the header field does not exist.  
   *  
   * @param The key of the header field  
   *  
   * @return The value of the header field as a String  
   */  
 public String  
 getHeaderField(String name)  
 {  
   for (int i = 0; ; i++)  
     {  
       String key = getHeaderFieldKey(i);  
       if (key == null)  
         return(null);  
   
       if (key.toLowerCase().equals(name.toLowerCase()))  
         return(getHeaderField(i));  
     }  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the value of the named header field as a date.  This date will  
   * be the number of seconds since midnight 1/1/1970 GMT or the default  
   * value if the field is not present or cannot be converted to a date.  
   *  
   * @param key The header field key to lookup  
   * @param def The default value if the header field is not found or can't be converted  
   */  
 public long  
 getHeaderFieldDate(String key, long def)  
88  {  {
89    String value = getHeaderField(key);    /**
90    if (value == null)     * This is an object that maps filenames to MIME types.  The interface
91      return(def);     * to do this is implemented by this class, so just create an empty
92       * instance and store it here.
93    // This needs to change since Date(String) is deprecated, but DateFormat     */
94    // doesn't seem to be working for some reason    private static FileNameMap fileNameMap = new MimeTypeMapper();
95    //DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, Locale.US);  
96    //df.setLenient(true);    /**
97       * This is the ContentHandlerFactory set by the caller, if any
98       */
99      private static ContentHandlerFactory factory;
100    
101      /**
102       * This is the default value that will be used to determine whether or
103       * not user interaction should be allowed.
104       */
105      private static boolean def_allow_user_inter;
106    
107      /**
108       * This is the default flag indicating whether or not to use caches to
109       * store the data returned from a server
110       */
111      private static boolean def_use_caches;
112    
113      /**
114       * This is a Hashable for setting default request properties
115       */
116      private static Hashtable def_req_props = new Hashtable();
117    
118      /**
119       * This variable determines whether or not interaction is allowed with
120       * the user.  For example, to prompt for a username and password.
121       */
122      protected boolean allowUserInteraction;
123    
124      /**
125       * Indicates whether or not a connection has been established to the
126       * destination specified in the URL
127       */
128      protected boolean connected;
129    
130      /**
131       * Indicates whether or not input can be read from this URL
132       */
133      protected boolean doInput;
134    
135      /**
136       * Indicates whether or not output can be sent to this URL
137       */
138      protected boolean doOutput;
139    
140      /**
141       * If this flag is set, the protocol is allowed to cache data whenever
142       * it can (caching is not guaranteed). If it is not set, the protocol
143       * must a get a fresh copy of the data.
144       * <p>
145       * This field is set by the setUseCaches method and returned by the
146       * getUseCaches method.
147       *
148       * Its default value is that determined by the last invocation of
149       * setDefaultUseCaches
150       *
151       */
152      protected boolean useCaches;
153    
154      /**
155       * If this value is non-zero, then the connection will only attempt to
156       * fetch the document pointed to by the URL if the document has been
157       * modified more recently than the date set in this variable.  That date
158       * should be specified as the number of seconds since 1/1/1970 GMT.
159       */
160      protected long ifModifiedSince;
161    
162      /**
163       * This is the URL associated with this connection
164       */
165      protected URL url;
166    
167      /**
168       * The list of request properties for this connection
169       */
170      private final Hashtable req_props;
171    
172      /**
173       * Set's the ContentHandlerFactory for an application.  This can be called
174       * once and only once.  If it is called again, then an Error is thrown.
175       * Unlike for other set factory methods, this one does not do a security
176       * check prior to setting the factory.
177       *
178       * @param factory The ContentHandlerFactory for this application
179       *
180       * @error Error If the factory is already set
181       */
182      public static synchronized void setContentHandlerFactory
183                                        (ContentHandlerFactory fac)
184      {
185        if (factory != null)
186          throw new Error("The ContentHandlerFactory is already set");
187    
188        factory = fac;
189      }
190    
191      /**
192       * Returns the default flag for whether or not interaction with a user
193       * is allowed.  This will be used for all connections unless overridden
194       *
195       * @return true if user interaction is allowed, false otherwise
196       */
197      public static boolean getDefaultAllowUserInteraction()
198      {
199        return(def_allow_user_inter);
200      }
201    
202      /**
203       * Sets the default flag for whether or not interaction with a user
204       * is allowed.  This will be used for all connections unless overridden
205       *
206       * @param allow true to allow user interaction, false otherwise
207       */
208      public static synchronized void setDefaultAllowUserInteraction(boolean allow)
209      {
210        def_allow_user_inter = allow;
211      }
212    
213      /**
214       * Returns the default value of a request property.  This will be used
215       * for all connections unless the value of the property is manually
216       * overridden.
217       *
218       * @param key The request property to return the default value of
219       *
220       * @return The default request property
221       */
222      public static String getDefaultRequestProperty(String key)
223      {
224        return((String)def_req_props.get(key.toLowerCase()));
225      }
226    
227      /**
228       * Sets the default value of a request property.  This will be used
229       * for all connections unless the value of the property is manually
230       * overridden.
231       *
232       * @param key The request property name the default is being set for
233       * @param value The value to set the default to
234       */
235      public static synchronized void setDefaultRequestProperty (String key,
236                                                                 String value)
237      {
238        def_req_props.put(key.toLowerCase(), value);
239      }
240    
241      /**
242       * Returns the MIME type of a file based on the name of the file.  This
243       * works by searching for the file's extension in a list of file extensions
244       * and returning the MIME type associated with it.  If no type is found,
245       * then a MIME type of "application/octet-stream" will be returned.
246       *
247       * @param filename The filename to determine the MIME type for
248       *
249       * @return The MIME type String
250       *
251       * @specnote public since jdk 1.4
252       */
253      public static String guessContentTypeFromName(String filename)
254      {
255        return(fileNameMap.getContentTypeFor(filename.toLowerCase()));
256      }
257    
258      /**
259       * Returns the MIME type of a stream based on the first few characters
260       * at the beginning of the stream.  This routine can be used to determine
261       * the MIME type if a server is believed to be returning an incorrect
262       * MIME type.  This method returns "application/octet-stream" if it
263       * cannot determine the MIME type.
264       * <p>
265       * NOTE: Overriding MIME types sent from the server can be obnoxious
266       * to user's.  See Internet Exploder 4 if you don't believe me.
267       *
268       * @param is The InputStream to determine the MIME type from
269       *
270       * @return The MIME type
271       *
272       * @exception IOException If an error occurs
273       */
274      public static String guessContentTypeFromStream(InputStream is)
275        throws IOException
276      {
277        return("application/octet-stream");
278      }
279    
280      /**
281       * This method returns the <code>FileNameMap</code> object being used
282       * to decode MIME types by file extension.
283       *
284       * @return The <code>FileNameMap</code>.
285       */
286      public static FileNameMap getFileNameMap()
287      {
288        return(fileNameMap);
289      }
290    
291      /**
292       * This method set the <code>FileNameMap</code> object being used
293       * to decode MIME types by file extension.
294       *
295       * @param fileNameMap The <code>FileNameMap</code>.
296       */
297      public static void setFileNameMap(FileNameMap fileNameMap)
298      {
299        URLConnection.fileNameMap = fileNameMap;  
300      }
301    
302      /**
303       * This constructs a URLConnection from a URL object
304       *
305       * @param url The URL for this connection
306       */
307      protected URLConnection(URL url)
308      {
309        // Set up all our instance variables
310        this.url = url;
311        allowUserInteraction = def_allow_user_inter;
312        useCaches = def_use_caches;
313    
314        req_props = new Hashtable(def_req_props);
315      }
316    
317      /**
318       * Returns the default value used to determine whether or not caching
319       * of documents will be done when possible.
320       *
321       * @return true if caches will be used, false otherwise
322       */
323      public boolean getDefaultUseCaches()
324      {
325        return(def_use_caches);
326      }
327    
328      /**
329       * Sets the default value used to determine whether or not caching
330       * of documents will be done when possible.
331       *
332       * @param use true to use caches if possible by default, false otherwise
333       */
334      public synchronized void setDefaultUseCaches(boolean use)
335      {
336        def_use_caches = use;
337      }
338    
339      /**
340       * Returns a boolean flag indicating whether or not user interaction is
341       * allowed for this connection.  (For example, in order to prompt for
342       * username and password info.
343       *
344       * @return true if user interaction is allowed, false otherwise
345       */
346      public boolean getAllowUserInteraction()
347      {
348        return(allowUserInteraction);
349      }
350    
351      /**
352       * Sets a boolean flag indicating whether or not user interaction is
353       * allowed for this connection.  (For example, in order to prompt for
354       * username and password info.
355       *
356       * @param allow true if user interaction should be allowed, false otherwise.
357       */
358      public void setAllowUserInteraction(boolean allow)
359      {
360        allowUserInteraction = allow;
361      }
362    
363      /**
364       * Returns the value of a flag indicating whether or not input is going
365       * to be done for this connection.  This default to true unless the
366       * doOutput flag is set to false, in which case this defaults to false.
367       *
368       * @return true if input is to be done, false otherwise
369       */
370      public boolean getDoInput()
371      {
372        return(doInput);
373      }
374    
375      /**
376       * Returns the value of a flag indicating whether or not input is going
377       * to be done for this connection.  This default to true unless the
378       * doOutput flag is set to false, in which case this defaults to false.
379       *
380       * @param input true if input is to be done, false otherwise
381       */
382      public void setDoInput(boolean input)
383      {
384        doInput = input;
385      }
386    
387      /**
388       * Returns a boolean flag indicating whether or not output will be done
389       * on this connection.  This defaults to false.
390       *
391       * @return true if output is to be done, false otherwise
392       */
393      public boolean getDoOutput()
394      {
395        return(doOutput);
396      }
397    
398      /**
399       * Returns a boolean flag indicating whether or not output will be done
400       * on this connection.  The default value is false, so this method can
401       * be used to override the default
402       *
403       * @param output ture if output is to be done, false otherwise
404       */
405      public void setDoOutput(boolean output)
406      {
407        doOutput = output;
408      }
409    
410      /**
411       * Returns a boolean flag indicating whether or not caching will be used
412       * (if possible) to store data downloaded via the connection.
413       *
414       * @return true if caching should be used if possible, false otherwise
415       */
416      public boolean getUseCaches()
417      {
418        return(useCaches);
419      }
420    
421      /**
422       * Sets a boolean flag indicating whether or not caching will be used
423       * (if possible) to store data downloaded via the connection.
424       *
425       * @param use_cache true if caching should be used if possible,
426       * false otherwise.
427       */
428      public void setUseCaches(boolean use_caches)
429      {
430        useCaches = use_caches;
431      }
432    
433      /**
434       * Returns the ifModified since instance variable.  If this value is non
435       * zero and the underlying protocol supports it, the actual document will
436       * not be fetched unless it has been modified since this time.  The value
437       * returned will be 0 if this feature is disabled or the time expressed
438       * as the number of seconds since midnight 1/1/1970 GMT otherwise
439       *
440       * @return The ifModifiedSince value
441       */
442      public long getIfModifiedSince()
443      {
444        return(ifModifiedSince);
445      }
446    
447      /**
448       * Sets the ifModified since instance variable.  If this value is non
449       * zero and the underlying protocol supports it, the actual document will
450       * not be fetched unless it has been modified since this time.  The value
451       * passed should  be 0 if this feature is to be disabled or the time expressed
452       * as the number of seconds since midnight 1/1/1970 GMT otherwise.
453       *
454       * @param modified_since The new ifModifiedSince value
455       */
456      public void setIfModifiedSince(long modified_since)
457      {
458        ifModifiedSince = modified_since;
459      }
460    
461      /**
462       * Returns the value of the named request property.
463       *
464       * @param key The name of the property
465       *
466       * @return The value of the property
467       */
468      public String getRequestProperty(String key)
469      {
470        return((String)req_props.get(key.toLowerCase()));
471      }
472    
473      /**
474       * Sets the value of the named request property
475       *
476       * @param key The name of the property
477       * @param value The value of the property
478       */
479      public void setRequestProperty(String key, String value)
480      {
481        req_props.put(key.toLowerCase(), value);
482      }
483    
484      /**
485       * Returns an unmodifiable Map containing the request properties.
486       *
487       * @since 1.4
488       */
489      public Map getRequestProperties()
490      {
491        return Collections.unmodifiableMap(req_props);
492      }
493    
494      /**
495       * Returns the URL object associated with this connection
496       *
497       * @return The URL for this connection.
498       */
499      public URL getURL()
500      {
501        return(url);
502      }
503    
504      /**
505       * Establishes the actual connection to the URL associated with this
506       * connection object
507       */
508      public abstract void connect() throws IOException;
509    
510      /**
511       * Returns an InputStream for this connection.  As this default
512       * implementation returns null, subclasses should override this method
513       *
514       * @return An InputStream for this connection
515       *
516       * @exception IOException If an error occurs
517       */
518      public InputStream getInputStream() throws IOException
519      {
520        return(null);
521      }
522    
523      /**
524       * Returns an OutputStream for this connection.  As this default
525       * implementation returns null, subclasses should override this method
526       *
527       * @return An OutputStream for this connection
528       *
529       * @exception IOException If an error occurs
530       */
531      public OutputStream getOutputStream() throws IOException
532      {
533        return(null);
534      }
535    
536      /**
537       * Returns the value of the content-encoding field or null if it is not
538       * known or not present.
539       *
540       * @return The content-encoding field
541       */
542      public String getContentEncoding()
543      {
544        return(getHeaderField("content-encoding"));
545      }
546    
547      /**
548       * Returns the value of the content-length header field or -1 if the value
549       * is not known or not present.
550       *
551       * @return The content-length field
552       */
553      public int getContentLength()
554      {
555        return(getHeaderFieldInt("content-length", -1));
556      }
557    
558      /**
559       * Returns the the content-type of the data pointed to by the URL.  This
560       * method first tries looking for a content-type header.  If that is not
561       * present, it attempts to use the file name to determine the content's
562       * MIME type.  If that is unsuccessful, the method returns null.  The caller
563       * may then still attempt to determine the MIME type by a call to
564       * guessContentTypeFromStream()
565       *
566       * @return The content MIME type
567       */
568      public String getContentType()
569      {
570        String type = getHeaderField("content-type");
571        if (type == null)
572          type = guessContentTypeFromName(getURL().getFile());
573    
574        return(type);
575      }
576    
577      /**
578       * Returns the date of the document pointed to by the URL as reported in
579       * the date field of the header or 0 if the value is not present or not
580       * known. If populated, the return value is number of seconds since
581       * midnight on 1/1/1970 GMT.
582       *
583       * @return The document date
584       */
585      public long getDate()
586      {
587        return(getHeaderFieldDate("date", 0));
588      }
589    
590      /**
591       * Returns the value of the expires header or 0 if not known or present.
592       * If populated, the return value is number of seconds since midnight
593       * on 1/1/1970 GMT.
594       *
595       * @return The expiration time.
596       */
597      public long getExpiration()
598      {
599        return(getHeaderFieldDate("expires", 0));
600      }
601    
602      /**
603       * Returns the value of the last-modified header field or 0 if not known known
604       * or not present.  If populated, the return value is the number of seconds
605       * since midnight on 1/1/1970.
606       *
607       * @return The last modified time
608       */
609      public long getLastModified()
610      {
611        return(getHeaderFieldDate("last-modified", 0));
612      }
613    
614      /**
615       * Returns a String representing the header key at the specified index.
616       * This allows the caller to walk the list of header fields.  The analogous
617       * getHeaderField(int) method allows access to the corresponding value for
618       * this tag.
619       *
620       * @param index The index into the header field list to retrieve the key for.
621       *
622       * @return The header field key or null if index is past the end
623       * of the headers.
624       */
625      public String getHeaderFieldKey(int index)
626      {
627        return(null);
628      }    
629    
630      /**
631       * Return a String representing the header value at the specified index.
632       * This allows the caller to walk the list of header fields.  The analogous
633       * getHeaderFieldKey(int) method allows access to the corresponding key
634       * for this header field
635       *
636       * @param index The index into the header field list to retrieve the value for
637       *
638       * @return The header value or null if index is past the end of the headers
639       */
640      public String getHeaderField(int index)
641      {
642        return(null);
643      }    
644    
645      /**
646       * Returns a String representing the value of the header field having
647       * the named key.  Returns null if the header field does not exist.
648       *
649       * @param The key of the header field
650       *
651       * @return The value of the header field as a String
652       */
653      public String getHeaderField(String name)
654      {
655        for (int i = 0; ; i++)
656          {
657            String key = getHeaderFieldKey(i);
658            if (key == null)
659              return(null);
660    
661            if (key.toLowerCase().equals(name.toLowerCase()))
662              return(getHeaderField(i));
663          }
664      }
665    
666      /**
667       * Returns the value of the named header field as a date.  This date will
668       * be the number of seconds since midnight 1/1/1970 GMT or the default
669       * value if the field is not present or cannot be converted to a date.
670       *
671       * @param key The header field key to lookup
672       * @param def The default value if the header field is not found
673       * or can't be converted.
674       */
675      public long getHeaderFieldDate(String key, long def)
676      {
677        String value = getHeaderField(key);
678        if (value == null)
679          return(def);
680    
681        // This needs to change since Date(String) is deprecated, but DateFormat
682        // doesn't seem to be working for some reason
683        //DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, Locale.US);
684        //df.setLenient(true);
685    
686    //Date d = df.parse(value, new ParsePosition(0));      //Date d = df.parse(value, new ParsePosition(0));
687    Date d = new Date(value);      Date d = new Date(value);
688    
689    if (d == null)      if (d == null)
690      return(def);        return(def);
691                
692    return(d.getTime() / 1000);      return(d.getTime() / 1000);
693  }    }
694    
695  /*************************************************************************/    /**
696       * Returns the value of the named header field as an int.  If the field
697       * is not present or cannot be parsed as an integer, the default value
698       * will be returned.
699       *
700       * @param key The header field key to lookup
701       * @param def The defaule value if the header field is not found
702       * or can't be parsed.
703       */
704      public int getHeaderFieldInt(String key, int def)
705      {
706        String value = getHeaderField(key);
707        if (value == null)
708          return(def);
709    
710        int retval = def;
711        try
712          {
713            retval = Integer.parseInt(value);
714          }
715        catch (NumberFormatException e)
716          {
717            return(def);
718          }
719    
720        return(retval);
721      }
722    
723      /**
724       * This method returns a <code>Permission</code> object representing the
725       * permissions required to access this URL.  This method returns
726       * <code>java.security.AllPermission</code> by default.  Subclasses should
727       * override it to return a more specific permission.  For example, an
728       * HTTP URL should return an instance of <code>SocketPermission</code>
729       * for the appropriate host and port.
730       * <p>
731       * Note that because of items such as HTTP redirects, the permission
732       * object returned might be different before and after connecting.
733       *
734       * @return A Permission object
735       *
736       * @exception IOException If an error occurs
737       */
738      public Permission getPermission() throws IOException
739      {
740        return(new java.security.AllPermission());
741      }
742    
743      /**
744       * This method returns the content of the document pointed to by the URL
745       * as an Object.  The type of object depends on the MIME type of the
746       * object and particular content hander loaded.  Most text type content
747       * handlers will return a subclass of InputStream.  Images usually return
748       * a class that implements ImageProducer.  There is not guarantee what
749       * type of object will be returned, however.
750       * <p>
751       * This class first determines the MIME type of the content, then creates
752       * a ContentHandler object to process the input.  If the ContentHandlerFactory
753       * is set, then that object is called to load a content handler, otherwise
754       * a class called gnu.java.net.content.<content_type> is tried.
755       * The default class will also be used if the content handler factory returns
756       * a null content handler.
757       *
758       * @exception IOException If an error occurs.
759       */
760      public Object getContent() throws IOException
761      {
762        //  connect();
763        String type = getContentType();
764    
765        // First try the factory
766        ContentHandler ch = null;
767        if (factory != null)
768          ch = factory.createContentHandler(type);
769    
770  /**      if (ch != null)
   * Returns the value of the named header field as an int.  If the field  
   * is not present or cannot be parsed as an integer, the default value  
   * will be returned.  
   *  
   * @param key The header field key to lookup  
   * @param def The defaule value if the header field is not found or can't be parsed  
   */  
 public int  
 getHeaderFieldInt(String key, int def)  
 {  
   String value = getHeaderField(key);  
   if (value == null)  
     return(def);  
   
   int retval = def;  
   try  
     {  
       retval = Integer.parseInt(value);  
     }  
   catch (NumberFormatException e)  
     {  
      return(def);  
     }  
   
   return(retval);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method returns a <code>Permission</code> object representing the  
   * permissions required to access this URL.  This method returns  
   * <code>java.security.AllPermission</code> by default.  Subclasses should  
   * override it to return a more specific permission.  For example, an  
   * HTTP URL should return an instance of <code>SocketPermission</code>  
   * for the appropriate host and port.  
   * <p>  
   * Note that because of items such as HTTP redirects, the permission  
   * object returned might be different before and after connecting.  
   *  
   * @return A Permission object  
   *  
   * @exception IOException If an error occurs  
   */  
 public Permission  
 getPermission() throws IOException  
 {  
   return(new java.security.AllPermission());  
 }  
   
 /*************************************************************************/  
   
 /**  
   * This method returns the content of the document pointed to by the URL  
   * as an Object.  The type of object depends on the MIME type of the  
   * object and particular content hander loaded.  Most text type content  
   * handlers will return a subclass of InputStream.  Images usually return  
   * a class that implements ImageProducer.  There is not guarantee what  
   * type of object will be returned, however.  
   * <p>  
   * This class first determines the MIME type of the content, then creates  
   * a ContentHandler object to process the input.  If the ContentHandlerFactory  
   * is set, then that object is called to load a content handler, otherwise  
   * a class called gnu.java.net.content.<content_type> is tried.  
   * The default class will also be used if the content handler factory returns  
   * a null content handler.  
   *  
   * @exception IOException If an error occurs.  
   */  
 public Object  
 getContent() throws IOException  
 {  
 //  connect();  
   String type = getContentType();  
   
   // First try the factory  
   ContentHandler ch = null;  
   if (factory != null)  
     ch = factory.createContentHandler(type);  
   
   if (ch != null)  
     return(ch.getContent(this));  
   
   // Then try our default class  
   try  
     {  
       Class cls = Class.forName("gnu.java.net.content." +  
                                  type.replace('/', '.'));  
       
       Object obj = cls.newInstance();  
       if (!(obj instanceof ContentHandler))  
         throw new UnknownServiceException(type);  
   
       ch = (ContentHandler)obj;  
771        return(ch.getContent(this));        return(ch.getContent(this));
     }  
   catch (ClassNotFoundException e) { ; }  
   catch (InstantiationException e) { ; }  
   catch (IllegalAccessException e) { ; }  
   
   throw new UnknownServiceException(type);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * The methods prints the value of this object as a String by calling the  
   * toString() method of its associated URL.  Overrides Object.toString()  
   *  
   * @return A String representation of this object  
   */  
 public String  
 toString()  
 {  
   return(url.toString());  
 }  
772    
773        // Then try our default class
774        try
775          {
776            Class cls = Class.forName("gnu.java.net.content." +
777                                      type.replace('/', '.'));
778        
779            Object obj = cls.newInstance();
780            if (!(obj instanceof ContentHandler))
781              throw new UnknownServiceException(type);
782    
783            ch = (ContentHandler)obj;
784            return(ch.getContent(this));
785          }
786        catch (ClassNotFoundException e)
787          {
788          }
789        catch (InstantiationException e)
790          {
791          }
792        catch (IllegalAccessException e)
793          {
794          }
795    
796        throw new UnknownServiceException(type);
797      }
798    
799      /**
800       * The methods prints the value of this object as a String by calling the
801       * toString() method of its associated URL.  Overrides Object.toString()
802       *
803       * @return A String representation of this object
804       */
805      public String toString()
806      {
807        return(url.toString());
808      }
809  } // class URLConnection  } // class URLConnection
810    

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26