--- /home/tromey/gnu/Nightly/classpath/classpath/java/net/URLConnection.java 2004-11-23 02:24:10.000000000 -0700 +++ java/net/URLConnection.java 2004-09-29 02:16:26.000000000 -0600 @@ -47,8 +47,12 @@ import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; +import java.util.Hashtable; import java.util.Locale; import java.util.Map; +import java.util.StringTokenizer; +import gnu.gcj.io.MimeTypes; + /** * Written using on-line Java Platform 1.2 API Specification, as well @@ -113,6 +117,9 @@ */ private static boolean defaultUseCaches = true; + private static ContentHandlerFactory defaultFactory + = new gnu.java.net.DefaultContentHandlerFactory(); + /** * This variable determines whether or not interaction is allowed with * the user. For example, to prompt for a username and password. @@ -160,6 +167,8 @@ * This is the URL associated with this connection */ protected URL url; + + private static Hashtable handlers = new Hashtable(); private static SimpleDateFormat[] dateFormats; private static boolean dateformats_initialized; @@ -423,8 +432,6 @@ * UnknownServiceException so subclasses are encouraged * to override this method.

* - * @return the content - * * @exception IOException If an error with the connection occurs. * @exception UnknownServiceException If the protocol does not support the * content type at all. @@ -452,8 +459,6 @@ * * @param classes The allowed classes for the content * - * @return the content - * * @exception IOException If an error occurs * @exception UnknownServiceException If the protocol does not support the * content type @@ -890,7 +895,22 @@ */ public static String guessContentTypeFromName(String filename) { - return getFileNameMap().getContentTypeFor(filename.toLowerCase()); + int dot = filename.lastIndexOf("."); + + if (dot != -1) + { + if (dot == filename.length()) + return "application/octet-stream"; + else + filename = filename.substring(dot + 1); + } + + String type = MimeTypes.getMimeTypeFromExtension(filename); + + if (type == null) + return"application/octet-stream"; + + return type; } /** @@ -912,7 +932,10 @@ public static String guessContentTypeFromStream(InputStream is) throws IOException { - return "application/octet-stream"; + is.mark(1024); + // FIXME: Implement this. Use system mimetype informations (like "file"). + is.reset(); + return null; } /** @@ -923,12 +946,8 @@ * * @since 1.2 */ - public static synchronized FileNameMap getFileNameMap() + public static FileNameMap getFileNameMap() { - // Delayed initialization. - if (fileNameMap == null) - fileNameMap = new MimeTypeMapper(); - return fileNameMap; } @@ -943,7 +962,7 @@ * * @since 1.2 */ - public static synchronized void setFileNameMap(FileNameMap map) + public static void setFileNameMap(FileNameMap map) { // Throw an exception if an extant security manager precludes // setting the factory. @@ -960,45 +979,83 @@ if (contentType == null || contentType.equals("")) return null; - ContentHandler handler = null; + ContentHandler handler; + + // 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. if (factory != null) handler = factory.createContentHandler(contentType); - // Then try our default class. - try + // Now try default factory. Using this factory to instantiate built-in + // content handlers is preferable + if (handler == null) + handler = defaultFactory.createContentHandler(contentType); + + // User-set factory has not returned a handler. Use the default search + // algorithm. + if (handler == null) { - String typeClass = contentType.replace('/', '.'); - - // Deal with "Content-Type: text/html; charset=ISO-8859-1". - int parameterBegin = typeClass.indexOf(';'); - if (parameterBegin >= 1) - typeClass = typeClass.substring(0, parameterBegin); - - Class cls = Class.forName("gnu.java.net.content." + typeClass); - Object obj = cls.newInstance(); - - if (obj instanceof ContentHandler) + // 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.java.net.content|sun.net.www.content"; + + // Replace the '/' character in the content type with '.' and + // all other non-alphabetic, non-numeric characters with '_'. + char[] cArray = contentType.toCharArray(); + for (int i = 0; i < cArray.length; i++) { - handler = (ContentHandler) obj; - return handler; + 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. + StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|"); + 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()); } - catch (ClassNotFoundException e) - { - // Ignore. - } - catch (InstantiationException e) - { - // Ignore. - } - catch (IllegalAccessException e) + + // Update the hashtable with the new content handler. + if (handler instanceof ContentHandler) { - // Ignore. + handlers.put(contentType, handler); + return 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; } // We don't put these in a static initializer, because it creates problems