diff options
Diffstat (limited to 'libjava/java/net/URLConnection.java')
-rw-r--r-- | libjava/java/net/URLConnection.java | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/libjava/java/net/URLConnection.java b/libjava/java/net/URLConnection.java new file mode 100644 index 00000000000..12e8a8b4cc6 --- /dev/null +++ b/libjava/java/net/URLConnection.java @@ -0,0 +1,423 @@ +// 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; + } +} |