--- /home/cpdev/src/classpath/java/net/URLConnection.java	2005-07-02 21:03:36.000000000 +0000
+++ java/net/URLConnection.java	2005-07-15 05:34:10.000000000 +0000
@@ -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;
 
@@ -890,7 +899,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 +936,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 +950,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 +966,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.
@@ -962,43 +985,86 @@
 
     ContentHandler handler = 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.
+    {
+      Object cachedHandler;
+      if ((cachedHandler = handlers.get(contentType)) != null)
+	{
+	  if (cachedHandler instanceof ContentHandler)
+	    return (ContentHandler)cachedHandler;
+	  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
