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