You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2008/11/03 18:15:51 UTC

svn commit: r710105 - /felix/trunk/framework/src/main/java/org/apache/felix/framework/

Author: pauls
Date: Mon Nov  3 09:15:50 2008
New Revision: 710105

URL: http://svn.apache.org/viewvc?rev=710105&view=rev
Log:
Switch URLHandlers to the old behavior of not overriding built-in handlers by default. Overriding can be enabled using a felix.service.urlhandlers.override=true system property. Furthermore, fix a bug that made URLHandlersBundleStreamHandler.openConnection(URL) fail when extending Felix. (FELIX-756, FELIX-800)

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java?rev=710105&r1=710104&r2=710105&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java Mon Nov  3 09:15:50 2008
@@ -66,7 +66,15 @@
 **/
 class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
 {
+    private static final String STREAM_HANDLER_PACKAGE_PROP = "java.protocol.handler.pkgs";
+    private static final String DEFAULT_STREAM_HANDLER_PACKAGE = "sun.net.www.protocol|com.ibm.oti.net.www.protocol|gnu.java.net.protocol|wonka.net|com.acunia.wonka.net|org.apache.harmony.luni.internal.net.www.protocol|weblogic.utils|weblogic.net|javax.net.ssl|COM.newmonics.www.protocols";
+    
+    private static final String CONTENT_HANDLER_PACKAGE_PROP = "java.content.handler.pkgs";
+    private static final String DEFAULT_CONTENT_HANDLER_PACKAGE = "sun.net.www.content|com.ibm.oti.net.www.content|gnu.java.net.content|org.apache.harmony.luni.internal.net.www.content|COM.newmonics.www.content";
+
     private static final SecureAction m_secureAction = new SecureAction();
+    private static final boolean OVERRIDE = m_secureAction.getSystemProperty(
+        "felix.service.urlhandlers.override", "false").equalsIgnoreCase("true");
 
     private static volatile SecurityManagerEx m_sm = null;
     private static volatile URLHandlers m_handler = null;
@@ -77,6 +85,7 @@
 
     // 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;
 
     private static Map m_contentHandlerCache = null;
     private static Map m_streamHandlerCache = null;
@@ -252,7 +261,7 @@
      * @param protocol the protocol for which a stream handler should be returned.
      * @return a stream handler proxy for the specified protocol.
     **/
-    public synchronized URLStreamHandler createURLStreamHandler(String protocol)
+    public URLStreamHandler createURLStreamHandler(String protocol)
     {
         // See if there is a cached stream handler.
         // IMPLEMENTATION NOTE: Caching is not strictly necessary for
@@ -260,13 +269,7 @@
         // performed for code consistency between stream and content
         // handlers and also because caching behavior may not be guaranteed
         // across different JRE implementations.
-        if (m_streamHandlerCache == null)
-        {
-            m_streamHandlerCache = new HashMap();
-        }
-        
-        URLStreamHandler handler = (URLStreamHandler) 
-            m_streamHandlerCache.get(protocol);
+        URLStreamHandler handler = getFromStreamCache(protocol);
         
         if (handler != null)
         {
@@ -277,9 +280,8 @@
         // allowed to deal with it.
         if (protocol.equals(FelixConstants.BUNDLE_URL_PROTOCOL))
         {
-            handler = new URLHandlersBundleStreamHandler(m_secureAction);
-            m_streamHandlerCache.put(protocol, handler);
-            return handler;
+            return addToStreamCache(protocol, 
+                new URLHandlersBundleStreamHandler(m_secureAction));
         }
     
         // If this is the framework's "felix:" extension protocol, then
@@ -289,7 +291,7 @@
         // URLClassloader.
         if (protocol.equals("felix"))
         {
-            handler = new URLStreamHandler()
+            return addToStreamCache(protocol, new URLStreamHandler()
             {
                 protected URLConnection openConnection(URL url)
                     throws IOException
@@ -311,16 +313,54 @@
                         throw new IOException(ex.getMessage());
                     }
                 }
-            };
-            m_streamHandlerCache.put(protocol, handler);
-            return handler;
+            });
         }
 
-        // If built-in or unknown content handler, then create a proxy handler.
-        handler = new URLHandlersStreamHandlerProxy(protocol, m_secureAction, 
-            (m_streamHandlerFactory != this) ? m_streamHandlerFactory : null);
-        m_streamHandlerCache.put(protocol, handler);
-        return handler;
+        if (!OVERRIDE)
+        {
+            // If there was a custom factory then try to get the handler form it
+            if (m_streamHandlerFactory != this)
+            {
+                handler = 
+                    addToStreamCache(protocol, m_streamHandlerFactory.createURLStreamHandler(protocol));
+    
+                if (handler != null)
+                {
+                    return handler;
+                }
+            }
+            // Check for built-in handlers for the protocol.
+            String pkgs = m_secureAction.getSystemProperty(STREAM_HANDLER_PACKAGE_PROP, "");
+            pkgs = (pkgs.equals(""))
+                ? DEFAULT_STREAM_HANDLER_PACKAGE
+                : pkgs + "|" + DEFAULT_STREAM_HANDLER_PACKAGE;
+    
+            // Iterate over built-in packages.
+            StringTokenizer pkgTok = new StringTokenizer(pkgs, "| ");
+            while (pkgTok.hasMoreTokens())
+            {
+                String pkg = pkgTok.nextToken().trim();
+                String className = pkg + "." + protocol + ".Handler";
+                try
+                {
+                    // If a built-in handler is found then let the
+                    // JRE handle it.
+                    if (m_secureAction.forName(className) != null)
+                    {
+                        return null;
+                    }
+                }
+                catch (Exception 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.
+                }
+            }
+        }
+        // If built-in content handler, then create a proxy handler.
+        return addToStreamCache(protocol, new URLHandlersStreamHandlerProxy(protocol, m_secureAction, 
+            (m_streamHandlerFactory != this) ? m_streamHandlerFactory : null, OVERRIDE));
     }
 
     /**
@@ -333,19 +373,116 @@
      * @param mimeType the mime type for which a content handler should be returned.
      * @return a content handler proxy for the specified mime type.
     **/
-    public synchronized ContentHandler createContentHandler(String mimeType)
+    public ContentHandler createContentHandler(String mimeType)
+    {
+        // See if there is a cached stream handler.
+        // IMPLEMENTATION NOTE: Caching is not strictly necessary for
+        // stream handlers since the Java runtime caches them. Caching is
+        // performed for code consistency between stream and content
+        // handlers and also because caching behavior may not be guaranteed
+        // across different JRE implementations.
+        ContentHandler handler = getFromContentCache(mimeType);
+        
+        if (handler != null)
+        {
+            return handler;
+        }
+        if (!OVERRIDE)
+        {
+            // If there was a custom factory then try to get the handler form it
+            if (m_contentHandlerFactory != this)
+            {
+                handler = addToContentCache(mimeType, 
+                    m_contentHandlerFactory.createContentHandler(mimeType));
+                
+                if (handler != null)
+                {
+                    return handler;
+                }
+            }
+    
+            // Check for built-in handlers for the mime type.
+            String pkgs = m_secureAction.getSystemProperty(CONTENT_HANDLER_PACKAGE_PROP, "");
+            pkgs = (pkgs.equals(""))
+                ? DEFAULT_CONTENT_HANDLER_PACKAGE
+                : pkgs + "|" + DEFAULT_CONTENT_HANDLER_PACKAGE;
+    
+            // Remove periods, slashes, and dashes from mime type.
+            String fixedType = mimeType.replace('.', '_').replace('/', '.').replace('-', '_');
+    
+            // Iterate over built-in packages.
+            StringTokenizer pkgTok = new StringTokenizer(pkgs, "| ");
+            while (pkgTok.hasMoreTokens())
+            {
+                String pkg = pkgTok.nextToken().trim();
+                String className = pkg + "." + fixedType;
+                try
+                {
+                    // If a built-in handler is found then let the
+                    // JRE handle it.
+                    if (m_secureAction.forName(className) != null)
+                    {
+                        return null;
+                    }
+                }
+                catch (Exception 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.
+                }
+            }
+        }
+            
+        return addToContentCache(mimeType, 
+            new URLHandlersContentHandlerProxy(mimeType, m_secureAction, 
+            (m_contentHandlerFactory != this) ? m_contentHandlerFactory : null, OVERRIDE));
+    }
+
+    private synchronized ContentHandler addToContentCache(String mimeType, ContentHandler handler)
     {
         if (m_contentHandlerCache == null)
         {
             m_contentHandlerCache = new HashMap();
         }
-        if (m_contentHandlerCache.containsKey(mimeType))
+        return (ContentHandler) addToCache(m_contentHandlerCache, mimeType, handler);
+    }
+    
+    private synchronized ContentHandler getFromContentCache(String mimeType)
+    {
+        return (ContentHandler) ((m_contentHandlerCache != null) ? 
+            m_contentHandlerCache.get(mimeType) : null);
+    }
+
+    private synchronized URLStreamHandler addToStreamCache(String protocol, URLStreamHandler handler)
+    {
+        if (m_streamHandlerCache == null)
+        {
+            m_streamHandlerCache = new HashMap();
+        }
+        return (URLStreamHandler) addToCache(m_streamHandlerCache, protocol, handler);
+    }
+    
+    private synchronized URLStreamHandler getFromStreamCache(String protocol)
+    {
+        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)
         {
-            return (ContentHandler) m_contentHandlerCache.get(mimeType);
+            cache.put(key, value);
+            result = value;
         }
-        ContentHandler result = new URLHandlersContentHandlerProxy(mimeType, m_secureAction,
-            (m_contentHandlerFactory != this) ? m_contentHandlerFactory : null);
-        m_contentHandlerCache.put(mimeType, result);
         return result;
     }
 
@@ -376,6 +513,7 @@
                 }
                 m_frameworks.add(framework);
             }
+            m_counter++;
         }
     }
 
@@ -391,6 +529,7 @@
     {
         synchronized (m_frameworks)
         {
+            m_counter--;
             if (m_frameworks.remove(framework) && m_frameworks.isEmpty())
             {
                 if (m_handler.m_streamHandlerFactory.getClass().getName().equals(
@@ -429,6 +568,20 @@
     **/
     public static Object getFrameworkFromContext()
     {
+        // This is a hack. The idea is to return the only registered framework
+        synchronized (m_classloaderToFrameworkLists)
+        {
+            if (m_classloaderToFrameworkLists.isEmpty())
+            {
+                synchronized (m_frameworks)
+                {
+                    if ((m_counter == 1) && (m_frameworks.size() == 1))
+                    {
+                        return m_frameworks.get(0);
+                    }
+                }
+            }
+        }
         // get the current class call stack.
         Class[] stack = m_sm.getClassContext();
         // Find the first class that is loaded from a bundle.

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java?rev=710105&r1=710104&r2=710105&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java Mon Nov  3 09:15:50 2008
@@ -51,15 +51,18 @@
         
         if (framework != null)
         {
-            // TODO: optimize this to not use reflection if not needed
+            if (framework instanceof Felix)
+            {
+                return new URLHandlersBundleURLConnection(url, (Felix) framework);
+            }
             try
             {
                 Class targetClass = framework.getClass().getClassLoader().loadClass(
                     URLHandlersBundleURLConnection.class.getName());
                 
                 return (URLConnection) m_action.invoke(m_action.getConstructor(targetClass, 
-                    new Class[]{URL.class, framework.getClass()}),
-                    new Object[]{url, framework});
+                    new Class[]{URL.class, framework.getClass().getClassLoader().loadClass(
+                    Felix.class.getName())}), new Object[]{url, framework});
             }
             catch (Exception ex)
             {

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java?rev=710105&r1=710104&r2=710105&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java Mon Nov  3 09:15:50 2008
@@ -52,7 +52,11 @@
         // one from the call context.
         if (m_framework == null)
         {
-            m_framework = (Felix) URLHandlers.getFrameworkFromContext();
+            Object tmp = URLHandlers.getFrameworkFromContext();
+            if (tmp instanceof Felix)
+            {
+                m_framework = (Felix) framework;
+            }
         }
 
         // If there is still no framework, then error.

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java?rev=710105&r1=710104&r2=710105&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java Mon Nov  3 09:15:50 2008
@@ -62,13 +62,15 @@
     private final Map m_trackerMap = new HashMap();
     private final String m_mimeType;
     private final SecureAction m_action;
+    private final boolean m_override;
 
     public URLHandlersContentHandlerProxy(String mimeType, SecureAction action, 
-        ContentHandlerFactory factory)
+        ContentHandlerFactory factory, boolean override)
     {
         m_mimeType = mimeType;
         m_action = action;
         m_factory = factory;
+        m_override = override;
     }
 
     //
@@ -101,9 +103,9 @@
         // Get the framework instance associated with call stack.
         Object framework = URLHandlers.getFrameworkFromContext();
 
-        if (framework == null)
+        if (framework == null) 
         {
-            return getBuiltIn();
+            return m_override ? getBuiltIn() : null;
         }
 
         // Get the service tracker for the framework instance or create one.
@@ -129,7 +131,8 @@
                 tracker = m_action.invoke(m_action.getConstructor(
                     framework.getClass().getClassLoader().loadClass(
                     URLHandlersServiceTracker.class.getName()),
-                    new Class[]{framework.getClass(), String.class}), 
+                    new Class[]{framework.getClass().getClassLoader().loadClass(
+                    Felix.class.getName()), String.class}), 
                     new Object[]{framework, filter});
                 // Cache the simple service tracker.
                 synchronized (m_trackerMap) 
@@ -144,12 +147,21 @@
                     }
                 }
             }
-            ContentHandler result = (ContentHandler) m_action.invoke(
-                m_action.getMethod(tracker.getClass(), "getService", null), 
-                tracker, null);
-            if (result == null)
+            ContentHandler result;
+            if (tracker instanceof URLHandlersServiceTracker)
             {
-                return getBuiltIn();
+                result = (ContentHandler) 
+                    ((URLHandlersServiceTracker) tracker).getService();
+            }
+            else
+            {
+                result = (ContentHandler) m_action.invoke(
+                    m_action.getMethod(tracker.getClass(), "getService", null), 
+                    tracker, null);
+            }
+            if ((result == null) && m_override)
+            {
+                result = getBuiltIn();
             }
             return result;
         }

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java?rev=710105&r1=710104&r2=710105&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java Mon Nov  3 09:15:50 2008
@@ -32,10 +32,10 @@
 **/
 class URLHandlersServiceTracker
 {
-    private BundleContext m_context = null;
-    private String m_filter = null;
+    private final BundleContext m_context;
+    private final String m_filter;
     private ServiceReference m_ref = null;
-    private Object m_svcObj = null;
+    private volatile Object m_svcObj = null;
     private long m_id = -1;
     private int m_rank = -1;
 
@@ -126,7 +126,7 @@
      * service before selecting the best available service.
      * </p>
     **/
-    private void selectBestService()
+    private synchronized void selectBestService()
     {
         // If there is an existing service, then unget it.
         if (m_ref != null)

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java?rev=710105&r1=710104&r2=710105&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java Mon Nov  3 09:15:50 2008
@@ -54,11 +54,49 @@
  * stream handler service at any given time.
  * </p>
 **/
-public class URLHandlersStreamHandlerProxy extends URLStreamHandler
+public final class URLHandlersStreamHandlerProxy extends URLStreamHandler
     implements URLStreamHandlerSetter, InvocationHandler
 {
     private static final String STREAM_HANDLER_PACKAGE_PROP = "java.protocol.handler.pkgs";
     private static final String DEFAULT_STREAM_HANDLER_PACKAGE = "sun.net.www.protocol|com.ibm.oti.net.www.protocol|gnu.java.net.protocol|wonka.net|com.acunia.wonka.net|org.apache.harmony.luni.internal.net.www.protocol|weblogic.utils|weblogic.net|javax.net.ssl|COM.newmonics.www.protocols";
+    
+    private static final Method EQUALS;
+    private static final Method GET_DEFAULT_PORT;
+    private static final Method GET_HOST_ADDRESS;
+    private static final Method HASH_CODE;
+    private static final Method HOSTS_EQUAL;
+    private static final Method OPEN_CONNECTION;
+    private static final Method PARSE_URL;
+    private static final Method SAME_FILE;
+    private static final Method TO_EXTERNAL_FORM;
+    
+    static {
+        try
+        {
+            EQUALS = URLStreamHandler.class.getDeclaredMethod("equals", 
+                new Class[]{URL.class, URL.class});
+            GET_DEFAULT_PORT = URLStreamHandler.class.getDeclaredMethod("getDefaultPort", null);
+            GET_HOST_ADDRESS = URLStreamHandler.class.getDeclaredMethod(
+                    "getHostAddress", new Class[]{URL.class});
+            HASH_CODE = URLStreamHandler.class.getDeclaredMethod( 
+                    "hashCode", new Class[]{URL.class});
+            HOSTS_EQUAL = URLStreamHandler.class.getDeclaredMethod(
+                    "hostsEqual", new Class[]{URL.class, URL.class});
+            OPEN_CONNECTION = URLStreamHandler.class.getDeclaredMethod(
+                    "openConnection", new Class[]{URL.class});
+            PARSE_URL = URLStreamHandler.class.getDeclaredMethod( 
+                    "parseURL", new Class[]{URL.class, String.class, Integer.TYPE, Integer.TYPE});
+            SAME_FILE = URLStreamHandler.class.getDeclaredMethod(
+                    "sameFile", new Class[]{URL.class, URL.class});
+            TO_EXTERNAL_FORM = URLStreamHandler.class.getDeclaredMethod( 
+                   "toExternalForm", new Class[]{URL.class});
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
 
     private static final Map m_builtIn = new HashMap();
     private final URLStreamHandlerFactory m_factory;
@@ -67,14 +105,16 @@
     private final String m_protocol;
     private final Object m_service;
     private final SecureAction m_action;
+    private final boolean m_override;
 
     public URLHandlersStreamHandlerProxy(String protocol, SecureAction action, 
-        URLStreamHandlerFactory factory)
+        URLStreamHandlerFactory factory, boolean override)
     {
         m_protocol = protocol;
         m_service = null;
         m_action = action;
         m_factory = factory;
+        m_override = override;
     }
     
     private URLHandlersStreamHandlerProxy(Object service, SecureAction action)
@@ -83,12 +123,12 @@
         m_service = service;
         m_action = action;
         m_factory = null;
+        m_override = false;
     }
 
     //
     // URLStreamHandler interface methods.
     //
-
     protected boolean equals(URL url1, URL url2)
     {
         Object svc = getStreamHandlerService();
@@ -103,8 +143,7 @@
         }
         try 
         {
-            return ((Boolean) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, "equals", 
-                new Class[]{URL.class, URL.class}), svc, new Object[]{url1, url2})).booleanValue();
+            return ((Boolean) m_action.invoke(EQUALS, svc, new Object[]{url1, url2})).booleanValue();
         } 
         catch (Exception ex)  
         {
@@ -126,8 +165,7 @@
         }
         try 
         {
-            return ((Integer) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "getDefaultPort", null), svc, null)).intValue();
+            return ((Integer) m_action.invoke(GET_DEFAULT_PORT, svc, null)).intValue();
         } 
         catch (Exception ex)  
         {
@@ -150,8 +188,7 @@
         }
         try 
         {
-            return (InetAddress) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "getHostAddress", new Class[]{URL.class}), svc, new Object[]{url});
+            return (InetAddress) m_action.invoke(GET_HOST_ADDRESS, svc, new Object[]{url});
         } 
         catch (Exception ex)  
         {
@@ -174,8 +211,7 @@
         }
         try 
         {
-            return ((Integer) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "hashCode", new Class[]{URL.class}), svc, new Object[]{url})).intValue();
+            return ((Integer) m_action.invoke(HASH_CODE, svc, new Object[]{url})).intValue();
         } 
         catch (Exception ex)  
         {
@@ -198,8 +234,7 @@
         }
         try 
         {
-            return ((Boolean) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "hostsEqual", new Class[]{URL.class, URL.class}), svc, new Object[]{url1, url2})).booleanValue();
+            return ((Boolean) m_action.invoke(HOSTS_EQUAL, svc, new Object[]{url1, url2})).booleanValue();
         } 
         catch (Exception ex)  
         {
@@ -221,8 +256,7 @@
         }
         try 
         {
-            return (URLConnection) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "openConnection", new Class[]{URL.class}), svc, new Object[]{url});
+            return (URLConnection) m_action.invoke(OPEN_CONNECTION, svc, new Object[]{url});
         } 
         catch (Exception ex)  
         {
@@ -247,10 +281,9 @@
         {
             try 
             {
-                URL test = new URL(null, url.toExternalForm(), (URLStreamHandler) svc);
+                URL test = new URL(null, toExternalForm(url, svc), (URLStreamHandler) svc);
                 
-                m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                    "parseURL", new Class[]{URL.class, String.class, Integer.TYPE, Integer.TYPE}), 
+                m_action.invoke(PARSE_URL, 
                     svc, new Object[]{test, spec, new Integer(start), new Integer(limit)});
                 super.setURL(url, test.getProtocol(), test.getHost(), test.getPort(),test.getAuthority(), 
                         test.getUserInfo(), test.getPath(), test.getQuery(), test.getRef());
@@ -277,8 +310,7 @@
         }
         try 
         {
-            return ((Boolean) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "sameFile", new Class[]{URL.class, URL.class}), 
+            return ((Boolean) m_action.invoke(SAME_FILE, 
                 svc, new Object[]{url1, url2})).booleanValue();
         } 
         catch (Exception ex)  
@@ -303,7 +335,11 @@
 
     protected String toExternalForm(URL url)
     {
-        Object svc = getStreamHandlerService();
+        return toExternalForm(url, getStreamHandlerService());
+    }
+    
+    private String toExternalForm(URL url, Object svc)
+    {
         if (svc == null)
         {
             throw new IllegalStateException(
@@ -315,8 +351,7 @@
         }
         try 
         {
-            return (String) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
-                "toExternalForm", new Class[]{URL.class}), 
+            return (String) m_action.invoke(TO_EXTERNAL_FORM, 
                 svc, new Object[]{url});
         } 
         catch (Exception ex)  
@@ -342,9 +377,9 @@
         // Get the framework instance associated with call stack.
         Object framework = URLHandlers.getFrameworkFromContext();
 
-        if (framework == null)
+        if (framework == null) 
         {
-            return getBuiltIn();
+            return m_override ? getBuiltIn() : null;
         }
 
         // Get the service tracker for the framework instance or create one.
@@ -370,7 +405,8 @@
                 tracker = m_action.invoke(m_action.getConstructor(
                     framework.getClass().getClassLoader().loadClass(
                     URLHandlersServiceTracker.class.getName()), 
-                    new Class[]{framework.getClass(), String.class}), 
+                    new Class[]{framework.getClass().getClassLoader().loadClass(
+                    Felix.class.getName()), String.class}), 
                     new Object[]{framework, filter});
 
                 // Cache the simple service tracker.
@@ -386,11 +422,19 @@
                     }
                 }
             }
-            Object service = m_action.invoke(m_action.getMethod(
-                tracker.getClass(), "getService", null), tracker, null);
-            if (service == null)
+            Object service;
+            if (tracker instanceof URLHandlersServiceTracker)
+            {
+                service = ((URLHandlersServiceTracker) tracker).getService();
+            }
+            else
+            {
+                service = m_action.invoke(m_action.getMethod(
+                    tracker.getClass(), "getService", null), tracker, null);
+            }
+            if (service == null) 
             {
-                return getBuiltIn();
+                return m_override ? getBuiltIn() : null;
             }
             if (service instanceof URLStreamHandlerService)
             {