Fix felix on android >= 4.1. The problem is that starting with 4.1 on android the built-in handlers are renamed and moved -- hence, not following the normal pattern for url handler classnames. This makes us unable to for e.g., open file/http/ftp/https/jar urls. Works now.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1380214 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlers.java b/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
index 1d02695..c7d69b7 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -85,11 +85,11 @@
     private static volatile SecurityManagerEx m_sm = null;
     private static volatile URLHandlers m_handler = null;
 
-    // This maps classloaders of URLHandlers in other classloaders to lists of 
+    // This maps classloaders of URLHandlers in other classloaders to lists of
     // their frameworks.
     private static Map m_classloaderToFrameworkLists = new HashMap();
 
-    // The list to hold all enabled frameworks registered with this handlers 
+    // The list to hold all enabled frameworks registered with this handlers
     private static final List m_frameworks = new ArrayList();
     private static int m_counter = 0;
 
@@ -104,8 +104,8 @@
     private static final String m_streamPkgs;
     private static final Map m_builtIn = new HashMap();
     private static final boolean m_loaded;
-    
-    static 
+
+    static
     {
         String pkgs = new SecureAction().getSystemProperty(STREAM_HANDLER_PACKAGE_PROP, "");
         m_streamPkgs = (pkgs.equals(""))
@@ -115,7 +115,7 @@
             (null != URLHandlersContentHandlerProxy.class) && (null != URLStreamHandlerService.class);
     }
 
-    
+
     private static final Map m_handlerToURL = new HashMap();
     private void init(String protocol, URLStreamHandlerFactory factory)
     {
@@ -133,14 +133,14 @@
             // Ignore, this is a best effort (maybe log it or something).
         }
     }
-    
+
     /**
      * <p>
-     * Only one instance of this class is created per classloader 
+     * Only one instance of this class is created per classloader
      * and that one instance is registered as the stream and content handler
      * factories for the JVM. Unless, we already register one from a different
      * classloader. In this case we attach to this root.
-     * </p> 
+     * </p>
     **/
     private URLHandlers()
     {
@@ -157,7 +157,7 @@
             {
                 // Ignore, this is a best effort (maybe log it or something)
             }
-    
+
             init("file", currentFactory);
             init("ftp", currentFactory);
             init("http", currentFactory);
@@ -170,7 +170,7 @@
             {
                 // Ignore, this is a best effort (maybe log it or something)
             }
-    
+
             if (currentFactory != null)
             {
                 try
@@ -182,7 +182,7 @@
                     // Ignore, this is a best effort (maybe log it or something)
                 }
             }
-            
+
             try
             {
                 URL.setURLStreamHandlerFactory(this);
@@ -204,9 +204,9 @@
                 {
                     // there already is a factory set so try to swap it with ours.
                     m_streamHandlerFactory = (URLStreamHandlerFactory)
-                        m_secureAction.swapStaticFieldIfNotClass(URL.class, 
+                        m_secureAction.swapStaticFieldIfNotClass(URL.class,
                         URLStreamHandlerFactory.class, URLHANDLERS_CLASS, "streamHandlerLock");
-                    
+
                     if (m_streamHandlerFactory == null)
                     {
                         throw err;
@@ -221,10 +221,10 @@
                         try
                         {
                             m_secureAction.invoke(
-                                m_secureAction.getDeclaredMethod(m_streamHandlerFactory.getClass(), 
-                                "registerFrameworkListsForContextSearch", 
-                                new Class[]{ClassLoader.class, List.class}), 
-                                m_streamHandlerFactory, new Object[]{ URLHANDLERS_CLASS.getClassLoader(), 
+                                m_secureAction.getDeclaredMethod(m_streamHandlerFactory.getClass(),
+                                "registerFrameworkListsForContextSearch",
+                                new Class[]{ClassLoader.class, List.class}),
+                                m_streamHandlerFactory, new Object[]{ URLHANDLERS_CLASS.getClassLoader(),
                                     m_frameworks });
                             m_rootURLHandlers = m_streamHandlerFactory;
                         }
@@ -239,7 +239,7 @@
                     throw err;
                 }
             }
-            
+
             try
             {
                 URLConnection.setContentHandlerFactory(this);
@@ -258,10 +258,10 @@
             {
                 // there already is a factory set so try to swap it with ours.
                 try
-                {   
-                    m_contentHandlerFactory = (ContentHandlerFactory) 
+                {
+                    m_contentHandlerFactory = (ContentHandlerFactory)
                         m_secureAction.swapStaticFieldIfNotClass(
-                            URLConnection.class, ContentHandlerFactory.class, 
+                            URLConnection.class, ContentHandlerFactory.class,
                             URLHANDLERS_CLASS, null);
                     if (m_contentHandlerFactory == null)
                     {
@@ -289,7 +289,7 @@
         }
     }
 
-    static void registerFrameworkListsForContextSearch(ClassLoader index, 
+    static void registerFrameworkListsForContextSearch(ClassLoader index,
         List frameworkLists)
     {
         synchronized (URL.class)
@@ -316,7 +316,7 @@
                         {
                             try
                             {
-                                m_secureAction.swapStaticFieldIfNotClass(URL.class, 
+                                m_secureAction.swapStaticFieldIfNotClass(URL.class,
                                     URLStreamHandlerFactory.class, null, "streamHandlerLock");
                             }
                             catch (Exception ex)
@@ -324,7 +324,7 @@
                                 // TODO log this
                                 ex.printStackTrace();
                             }
-                            
+
                             if (m_streamHandlerFactory.getClass() != URLHANDLERS_CLASS)
                             {
                                 URL.setURLStreamHandlerFactory(m_streamHandlerFactory);
@@ -332,7 +332,7 @@
                             try
                             {
                                 m_secureAction.swapStaticFieldIfNotClass(
-                                    URLConnection.class, ContentHandlerFactory.class, 
+                                    URLConnection.class, ContentHandlerFactory.class,
                                     null, null);
                             }
                             catch (Exception ex)
@@ -340,7 +340,7 @@
                                 // TODO log this
                                 ex.printStackTrace();
                             }
-                            
+
                             if (m_contentHandlerFactory.getClass() != URLHANDLERS_CLASS)
                             {
                                 URLConnection.setContentHandlerFactory(m_contentHandlerFactory);
@@ -388,7 +388,48 @@
             try
             {
                 // If a built-in handler is found then cache and return it
-                Class handler = m_secureAction.forName(className, classLoader); 
+                Class handler = m_secureAction.forName(className, classLoader);
+                if (handler != null)
+                {
+                    return (URLStreamHandler) handler.newInstance();
+                }
+            }
+            catch (Throwable ex)
+            {
+                // This could be a class not found exception or an
+                // instantiation exception, not much we can do in either
+                // case other than ignore it.
+            }
+        }
+        // This is a workaround for android - Starting with 4.1 the built-in core handler
+        // are not following the normal naming nore package schema :-(
+        String androidHandler = null;
+        if ("file".equalsIgnoreCase(protocol))
+        {
+            androidHandler = "libcore.net.url.FileHandler";
+        }
+        else if ("ftp".equalsIgnoreCase(protocol))
+        {
+            androidHandler = "libcore.net.url.FtpHandler";
+        }
+        else if ("http".equalsIgnoreCase(protocol))
+        {
+            androidHandler = "libcore.net.http.HttpHandler";
+        }
+        else if ("https".equalsIgnoreCase(protocol))
+        {
+            androidHandler = "libcore.net.http.HttpsHandler";
+        }
+        else if ("jar".equalsIgnoreCase(protocol))
+        {
+            androidHandler = "libcore.net.url.JarHandler";
+        }
+        if (androidHandler != null)
+        {
+            try
+            {
+                // If a built-in handler is found then cache and return it
+                Class handler = m_secureAction.forName(androidHandler, classLoader);
                 if (handler != null)
                 {
                     return (URLStreamHandler) handler.newInstance();
@@ -413,7 +454,7 @@
             }
         return (URLStreamHandler) m_builtIn.get(protocol);
     }
-    
+
     /**
      * <p>
      * This is a method implementation for the <tt>URLStreamHandlerFactory</tt>
@@ -433,7 +474,7 @@
         // handlers and also because caching behavior may not be guaranteed
         // across different JRE implementations.
         URLStreamHandler handler = getFromStreamCache(protocol);
-        
+
         if (handler != null)
         {
             return handler;
@@ -443,16 +484,16 @@
         // allowed to deal with it.
         if (protocol.equals(FelixConstants.BUNDLE_URL_PROTOCOL))
         {
-            return addToStreamCache(protocol, 
+            return addToStreamCache(protocol,
                 new URLHandlersBundleStreamHandler(m_secureAction));
         }
 
-       handler = getBuiltInStreamHandler(protocol, 
+       handler = getBuiltInStreamHandler(protocol,
            (m_streamHandlerFactory != this) ? m_streamHandlerFactory : null);
 
         // If built-in content handler, then create a proxy handler.
-        return addToStreamCache(protocol, 
-            new URLHandlersStreamHandlerProxy(protocol, m_secureAction, 
+        return addToStreamCache(protocol,
+            new URLHandlersStreamHandlerProxy(protocol, m_secureAction,
                 handler, (URL) m_handlerToURL.get(handler)));
     }
 
@@ -475,14 +516,14 @@
         // handlers and also because caching behavior may not be guaranteed
         // across different JRE implementations.
         ContentHandler handler = getFromContentCache(mimeType);
-        
+
         if (handler != null)
         {
             return handler;
         }
 
-        return addToContentCache(mimeType, 
-            new URLHandlersContentHandlerProxy(mimeType, m_secureAction, 
+        return addToContentCache(mimeType,
+            new URLHandlersContentHandlerProxy(mimeType, m_secureAction,
             (m_contentHandlerFactory != this) ? m_contentHandlerFactory : null));
     }
 
@@ -494,10 +535,10 @@
         }
         return (ContentHandler) addToCache(m_contentHandlerCache, mimeType, handler);
     }
-    
+
     private synchronized ContentHandler getFromContentCache(String mimeType)
     {
-        return (ContentHandler) ((m_contentHandlerCache != null) ? 
+        return (ContentHandler) ((m_contentHandlerCache != null) ?
             m_contentHandlerCache.get(mimeType) : null);
     }
 
@@ -509,22 +550,22 @@
         }
         return (URLStreamHandler) addToCache(m_streamHandlerCache, protocol, handler);
     }
-    
+
     private synchronized URLStreamHandler getFromStreamCache(String protocol)
     {
-        return (URLStreamHandler) ((m_streamHandlerCache != null) ? 
+        return (URLStreamHandler) ((m_streamHandlerCache != null) ?
             m_streamHandlerCache.get(protocol) : null);
     }
-    
+
     private Object addToCache(Map cache, String key, Object value)
     {
         if (value == null)
         {
             return null;
         }
-        
+
         Object result = cache.get(key);
-            
+
         if (result == null)
         {
             cache.put(key, value);
@@ -579,7 +620,7 @@
         {
             m_counter--;
             if (m_frameworks.remove(framework))
-            {    
+            {
                 if (m_frameworks.isEmpty())
                 {
                     unregister = true;
@@ -592,9 +633,9 @@
              try
              {
                  m_secureAction.invoke(m_secureAction.getDeclaredMethod(
-                     m_rootURLHandlers.getClass(), 
-                     "unregisterFrameworkListsForContextSearch", 
-                     new Class[]{ ClassLoader.class}), 
+                     m_rootURLHandlers.getClass(),
+                     "unregisterFrameworkListsForContextSearch",
+                     new Class[]{ ClassLoader.class}),
                      m_rootURLHandlers,
                      new Object[] {URLHANDLERS_CLASS.getClassLoader()});
              }
@@ -639,7 +680,7 @@
         Class targetClass = null;
         for (int i = 0; i < stack.length; i++)
         {
-            if (stack[i].getClassLoader() != null) 
+            if (stack[i].getClassLoader() != null)
             {
                 String name = stack[i].getClassLoader().getClass().getName();
                 if (name.startsWith("org.apache.felix.framework.ModuleImpl$ModuleClassLoader")
@@ -651,7 +692,7 @@
                 }
             }
         }
-        
+
         // If we found a class loaded from a bundle, then iterate
         // over the framework instances and see which framework owns
         // the bundle that loaded the class.
@@ -660,11 +701,11 @@
             synchronized (m_classloaderToFrameworkLists)
             {
                 ClassLoader index = targetClass.getClassLoader().getClass().getClassLoader();
-                
+
                 List frameworks = (List) m_classloaderToFrameworkLists.get(
                     index);
-                
-                if ((frameworks == null) && (index == URLHANDLERS_CLASS.getClassLoader())) 
+
+                if ((frameworks == null) && (index == URLHANDLERS_CLASS.getClassLoader()))
                 {
                     frameworks = m_frameworks;
                 }
@@ -679,7 +720,7 @@
                             try
                             {
                                 if (m_secureAction.invoke(
-                                    m_secureAction.getDeclaredMethod(framework.getClass(), 
+                                    m_secureAction.getDeclaredMethod(framework.getClass(),
                                     "getBundle", CLASS_TYPE),
                                     framework, new Object[]{targetClass}) != null)
                                 {
@@ -688,7 +729,7 @@
                             }
                             catch (Exception ex)
                             {
-                                // This should not happen but if it does there is 
+                                // This should not happen but if it does there is
                                 // not much we can do other then ignore it.
                                 // Maybe log this or something.
                                 ex.printStackTrace();