gcc/libjava/java/net/URLConnection.java
Tom Tromey ee9dd3721b Initial revision
From-SVN: r26263
1999-04-07 14:42:40 +00:00

424 lines
11 KiB
Java

// URLConnection.java - Superclass of all communications links between
// an application and a URL.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.net;
import java.io.*;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date March 5, 1999.
*/
/**
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* Status: Two guessContentTypeFrom... methods not implemented.
* getContent method assumes content type from response; see comment there.
*/
public abstract class URLConnection
{
protected URL url;
protected boolean doInput = true;
protected boolean doOutput = false;
protected boolean allowUserInteraction;
protected boolean useCaches;
protected long ifModifiedSince = 0L;
protected boolean connected = false;
private static boolean defaultAllowUserInteraction = false;
private static boolean defaultUseCaches = true;
private static FileNameMap fileNameMap; // Set by the URLConnection subclass.
private static ContentHandlerFactory factory;
private static ContentHandler contentHandler;
private static Hashtable handlers = new Hashtable();
private static Locale locale = new Locale("En", "Us", "Unix");
private static SimpleDateFormat dateFormat1 =
new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'", locale);
private static SimpleDateFormat dateFormat2 =
new SimpleDateFormat("EEEE, dd-MMM-yy hh:mm:ss 'GMT'", locale);
private static SimpleDateFormat dateFormat3 =
new SimpleDateFormat("EEE MMM d hh:mm:ss yyyy", locale);
protected URLConnection(URL url)
{
this.url = url;
allowUserInteraction = defaultAllowUserInteraction;
useCaches = defaultUseCaches;
}
public abstract void connect() throws IOException;
public URL getURL()
{
return url;
}
public int getContentLength()
{
return getHeaderFieldInt("content-length", -1);
}
public String getContentType()
{
return getHeaderField("content-type");
}
public String getContentEncoding()
{
return getHeaderField("content-encoding");
}
public long getExpiration()
{
return getHeaderFieldDate("expiration", 0L);
}
public long getDate()
{
return getHeaderFieldDate("date", 0L);
}
public long getLastModified()
{
return getHeaderFieldDate("last-modified", 0L);
}
public String getHeaderField(int n)
{
// Subclasses for specific protocols override this.
return null;
}
public String getHeaderField(String name)
{
// Subclasses for specific protocols override this.
return null;
}
public int getHeaderFieldInt(String name, int val)
{
String str = getHeaderField(name);
try
{
if (str != null)
val = Integer.parseInt(str);
}
catch (NumberFormatException e)
{
; // Do nothing; val is the default.
}
return val;
}
public long getHeaderFieldDate(String name, long val)
{
String str = getHeaderField(name);
if (str != null)
{
Date date;
if ((date = dateFormat1.parse(str, new ParsePosition(0))) != null)
val = date.getTime();
else if ((date = dateFormat2.parse(str, new ParsePosition(0))) != null)
val = date.getTime();
else if ((date = dateFormat3.parse(str, new ParsePosition(0))) != null)
val = date.getTime();
}
return val;
}
public String getHeaderFieldKey(int n)
{
// Subclasses for specific protocols override this.
return null;
}
public Object getContent() throws IOException
{
// FIXME: Doc indicates that other criteria should be applied as
// heuristics to determine the true content type, e.g. see
// guessContentTypeFromName() and guessContentTypeFromStream methods
// as well as FileNameMap class & fileNameMap field & get/set methods.
String cType = getContentType();
contentHandler = setContentHandler(cType);
if (contentHandler == null)
return getInputStream();
return contentHandler.getContent(this);
}
// TODO12: public Permission getPermission() throws IOException
// {
// // Subclasses may override this.
// return java.security.AllPermission;
// }
public InputStream getInputStream() throws IOException
{
// Subclasses for specific protocols override this.
throw new UnknownServiceException("Protocol " + url.getProtocol() +
" does not support input.");
}
public OutputStream getOutputStream() throws IOException
{
// Subclasses for specific protocols override this.
throw new UnknownServiceException("Protocol " + url.getProtocol() +
" does not support output.");
}
public String toString()
{
return this.getClass().getName() + ":" + url.toString();
}
public void setDoInput(boolean doinput)
{
if (connected)
throw new IllegalAccessError("Already connected");
doInput = doinput;
}
public boolean getDoInput()
{
return doInput;
}
public void setDoOutput(boolean dooutput)
{
if (connected)
throw new IllegalAccessError("Already connected");
doOutput = dooutput;
if (doOutput)
doInput = false;
}
public boolean getDoOutput()
{
return doOutput;
}
public void setAllowUserInteraction(boolean allowuserinteraction)
{
if (connected)
throw new IllegalAccessError("Already connected");
allowUserInteraction = allowuserinteraction;
}
public boolean getAllowUserInteraction()
{
return allowUserInteraction;
}
public static void
setDefaultAllowUserInteraction(boolean defaultallowuserinteraction)
{
defaultAllowUserInteraction = defaultallowuserinteraction;
}
public static boolean getDefaultAllowUserInteraction()
{
return defaultAllowUserInteraction;
}
public void setUseCaches(boolean usecaches)
{
if (connected)
throw new IllegalAccessError("Already connected");
useCaches = usecaches;
}
public boolean getUseCaches()
{
return useCaches;
}
public void setIfModifiedSince(long ifmodifiedsince)
{
if (connected)
throw new IllegalAccessError("Already connected");
ifModifiedSince = ifmodifiedsince;
}
public long getIfModifiedSince()
{
return ifModifiedSince;
}
public boolean getDefaultUseCaches()
{
return defaultUseCaches;
}
public void setDefaultUseCaches(boolean defaultusecaches)
{
defaultUseCaches = defaultusecaches;
}
public void setRequestProperty(String key, String value)
{
// Do nothing unless overridden by subclasses that support setting
// header fields in the request.
}
public String getRequestProperty(String key)
{
// Overridden by subclasses that support reading header fields from the
// request.
return null;
}
public static void setDefaultRequestProperty(String key, String value)
{
// Do nothing unless overridden by subclasses that support setting
// default request properties.
}
public static String getDefaultRequestProperty(String key)
{
// Overridden by subclasses that support default request properties.
return null;
}
public static void setContentHandlerFactory(ContentHandlerFactory fac)
{
if (factory != null)
throw new Error("ContentHandlerFactory already set");
// Throw an exception if an extant security mgr precludes
// setting the factory.
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkSetFactory();
factory = fac;
}
// TODO: protected static String guessContentTypeFromName(String fname)
// {
// }
// TODO: public static String guessContentTypeFromStream(InputStream is)
// throws IOException
// {
// }
// TODO12: protected void parseURL(URL u, String spec, int start, int limit)
// JDK1.2
public static FileNameMap getFileNameMap()
{
return fileNameMap;
}
// JDK1.2
public static void setFileNameMap(FileNameMap map)
{
// Throw an exception if an extant security mgr precludes
// setting the factory.
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkSetFactory();
fileNameMap = map;
}
private ContentHandler setContentHandler(String contentType)
{
ContentHandler handler;
// No content type so just handle it as the default.
if (contentType == null || contentType == "")
return null;
// See if a handler has been cached for this content type.
// For efficiency, if a content type has been searched for but not
// found, it will be in the hash table but as the contentType String
// instead of a ContentHandler.
if ((handler = (ContentHandler) handlers.get(contentType)) != null)
if (handler instanceof ContentHandler)
return handler;
else
return null;
// If a non-default factory has been set, use it to find the content type.
if (factory != null)
handler = factory.createContentHandler(contentType);
// Non-default factory may have returned null or a factory wasn't set.
// Use the default search algorithm to find a handler for this content type.
if (handler == null)
{
// Get the list of packages to check and append our default handler
// to it, along with the JDK specified default as a last resort.
// Except in very unusual environments the JDK specified one shouldn't
// ever be needed (or available).
String propVal = System.getProperty("java.content.handler.pkgs");
propVal = (propVal == null) ? "" : (propVal + "|");
propVal = propVal + "gnu.gcj.content|sun.net.www.content";
// Replace the '/' character in the content type with '.' and
// all other non-alphabetic, non-numeric characters with '_'.
StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|");
char[] cArray = contentType.toCharArray();
for (int i = 0; i < cArray.length; i++)
{
if (cArray[i] == '/')
cArray[i] = '.';
else if (! ((cArray[i] >= 'A' && cArray[i] <= 'Z') ||
(cArray[i] >= 'a' && cArray[i] <= 'z') ||
(cArray[i] >= '0' && cArray[i] <= '9')))
cArray[i] = '_';
}
String contentClass = new String(cArray);
// See if a class of this content type exists in any of the packages.
do
{
String facName = pkgPrefix.nextToken() + "." + contentClass;
try
{
handler =
(ContentHandler) Class.forName(facName).newInstance();
}
catch (Exception e)
{
// Can't instantiate; handler still null, go on to next element.
}
} while ((handler == null ||
! (handler instanceof ContentHandler)) &&
pkgPrefix.hasMoreTokens());
}
// Update the hashtable with the new content handler.
if (handler != null && handler instanceof ContentHandler)
{
handlers.put(contentType, handler);
return handler;
}
// For efficiency on subsequent searches, put a dummy entry in the hash
// table for content types that don't have a non-default ContentHandler.
handlers.put(contentType, contentType);
return null;
}
}