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/10/31 20:21:22 UTC

svn commit: r709541 - in /felix/trunk/framework/src/main/java/org/apache/felix/framework: URLHandlers.java URLHandlersContentHandlerProxy.java URLHandlersStreamHandlerProxy.java

Author: pauls
Date: Fri Oct 31 12:21:22 2008
New Revision: 709541

URL: http://svn.apache.org/viewvc?rev=709541&view=rev
Log:
In certain cases it might be desirable to override built-in URLStreamHandlers with services provided by bundles. We will first see whether there is a service for the protocol and if so use that one else, we try to lookup a built-in one as we do now. This includes the possibility to add locations to the default locations. What changes is that we first look at the services. (FELIX-756)

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.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=709541&r1=709540&r2=709541&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 Fri Oct 31 12:21:22 2008
@@ -66,15 +66,10 @@
 **/
 class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
 {
-    private static final String STREAM_HANDLER_PACKAGE_PROP = "java.protocol.handler.pkgs";
-    private static final String CONTENT_HANDLER_PACKAGE_PROP = "java.content.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 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 SecurityManagerEx m_sm = null;
-    private static URLHandlers m_handler = null;
+    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 
     // their frameworks.
@@ -257,7 +252,7 @@
      * @param protocol the protocol for which a stream handler should be returned.
      * @return a stream handler proxy for the specified protocol.
     **/
-    public URLStreamHandler createURLStreamHandler(String protocol)
+    public synchronized URLStreamHandler createURLStreamHandler(String protocol)
     {
         // See if there is a cached stream handler.
         // IMPLEMENTATION NOTE: Caching is not strictly necessary for
@@ -265,7 +260,13 @@
         // performed for code consistency between stream and content
         // handlers and also because caching behavior may not be guaranteed
         // across different JRE implementations.
-        URLStreamHandler handler = getFromStreamCache(protocol);
+        if (m_streamHandlerCache == null)
+        {
+            m_streamHandlerCache = new HashMap();
+        }
+        
+        URLStreamHandler handler = (URLStreamHandler) 
+            m_streamHandlerCache.get(protocol);
         
         if (handler != null)
         {
@@ -276,8 +277,9 @@
         // allowed to deal with it.
         if (protocol.equals(FelixConstants.BUNDLE_URL_PROTOCOL))
         {
-            return addToStreamCache(protocol, 
-                new URLHandlersBundleStreamHandler(m_secureAction));
+            handler = new URLHandlersBundleStreamHandler(m_secureAction);
+            m_streamHandlerCache.put(protocol, handler);
+            return handler;
         }
     
         // If this is the framework's "felix:" extension protocol, then
@@ -287,7 +289,7 @@
         // URLClassloader.
         if (protocol.equals("felix"))
         {
-            return addToStreamCache(protocol, new URLStreamHandler()
+            handler = new URLStreamHandler()
             {
                 protected URLConnection openConnection(URL url)
                     throws IOException
@@ -309,50 +311,16 @@
                         throw new IOException(ex.getMessage());
                     }
                 }
-            });
+            };
+            m_streamHandlerCache.put(protocol, handler);
+            return handler;
         }
 
-        // 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));
+        // 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;
     }
 
     /**
@@ -365,112 +333,19 @@
      * @param mimeType the mime type for which a content handler should be returned.
      * @return a content handler proxy for the specified mime type.
     **/
-    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 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));
-    }
-
-    private synchronized ContentHandler addToContentCache(String mimeType, ContentHandler handler)
+    public synchronized ContentHandler createContentHandler(String mimeType)
     {
         if (m_contentHandlerCache == null)
         {
             m_contentHandlerCache = new HashMap();
         }
-        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)
+        if (m_contentHandlerCache.containsKey(mimeType))
         {
-            cache.put(key, value);
-            result = value;
+            return (ContentHandler) m_contentHandlerCache.get(mimeType);
         }
+        ContentHandler result = new URLHandlersContentHandlerProxy(mimeType, m_secureAction,
+            (m_contentHandlerFactory != this) ? m_contentHandlerFactory : null);
+        m_contentHandlerCache.put(mimeType, result);
         return result;
     }
 

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=709541&r1=709540&r2=709541&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 Fri Oct 31 12:21:22 2008
@@ -20,9 +20,11 @@
 
 import java.io.IOException;
 import java.net.ContentHandler;
+import java.net.ContentHandlerFactory;
 import java.net.URLConnection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.StringTokenizer;
 
 import org.apache.felix.framework.util.SecureAction;
 import org.osgi.service.url.URLConstants;
@@ -51,21 +53,29 @@
 **/
 class URLHandlersContentHandlerProxy extends ContentHandler
 {
+    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 Map m_builtIn = new HashMap();
+    private final ContentHandlerFactory m_factory;
+
     private final Map m_trackerMap = new HashMap();
     private final String m_mimeType;
     private final SecureAction m_action;
 
-    public URLHandlersContentHandlerProxy(String mimeType, SecureAction action)
+    public URLHandlersContentHandlerProxy(String mimeType, SecureAction action, 
+        ContentHandlerFactory factory)
     {
         m_mimeType = mimeType;
         m_action = action;
+        m_factory = factory;
     }
 
     //
     // ContentHandler interface method.
     //
 
-    public synchronized Object getContent(URLConnection urlc) throws IOException
+    public Object getContent(URLConnection urlc) throws IOException
     {
         ContentHandler svc = getContentHandlerService();
         if (svc == null)
@@ -91,15 +101,17 @@
         // Get the framework instance associated with call stack.
         Object framework = URLHandlers.getFrameworkFromContext();
 
-        // If the framework has disabled the URL Handlers service,
-        // then it will not be found so just return null.
         if (framework == null)
         {
-            return null;
+            return getBuiltIn();
         }
 
         // Get the service tracker for the framework instance or create one.
-        Object tracker = m_trackerMap.get(framework);
+        Object tracker;
+        synchronized (m_trackerMap)
+        {
+            tracker = m_trackerMap.get(framework);
+        }
         try
         {
             if (tracker == null)
@@ -120,11 +132,26 @@
                     new Class[]{framework.getClass(), String.class}), 
                     new Object[]{framework, filter});
                 // Cache the simple service tracker.
-                m_trackerMap.put(framework, tracker);
+                synchronized (m_trackerMap) 
+                {
+                    if (!m_trackerMap.containsKey(framework))
+                    {
+                        m_trackerMap.put(framework, tracker);
+                    }
+                    else
+                    {
+                        tracker = m_trackerMap.get(framework);
+                    }
+                }
             }
-            return (ContentHandler) m_action.invoke(
+            ContentHandler result = (ContentHandler) m_action.invoke(
                 m_action.getMethod(tracker.getClass(), "getService", null), 
                 tracker, null);
+            if (result == null)
+            {
+                return getBuiltIn();
+            }
+            return result;
         }
         catch (Exception ex)
         {
@@ -133,4 +160,66 @@
             return null;
         }
     }
+
+    private ContentHandler getBuiltIn()
+    {
+        synchronized (m_builtIn)
+        {
+            if (m_builtIn.containsKey(m_mimeType))
+            {
+                return (ContentHandler) m_builtIn.get(m_mimeType);
+            }
+        }
+        if (m_factory != null)
+        {
+            ContentHandler result = m_factory.createContentHandler(m_mimeType);
+            if (result != null)
+            {
+                return addToCache(m_mimeType, result);
+            }
+        }
+        // Check for built-in handlers for the mime type.
+        String pkgs = m_action.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 = m_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 cache and return it
+                Class handler = m_action.forName(className); 
+                if (handler != null)
+                {
+                    return addToCache(m_mimeType, 
+                        (ContentHandler) handler.newInstance());
+                }
+            }
+            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 addToCache(m_mimeType, null);
+    }
+
+    private synchronized ContentHandler addToCache(String mimeType, ContentHandler handler)
+    {
+        if (!m_builtIn.containsKey(mimeType))
+        {
+            m_builtIn.put(mimeType, handler);
+            return handler;
+        }
+        return (ContentHandler) m_builtIn.get(mimeType);
+    }
 }
\ No newline at end of file

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=709541&r1=709540&r2=709541&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 Fri Oct 31 12:21:22 2008
@@ -25,6 +25,7 @@
 import java.net.*;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.StringTokenizer;
 
 import org.apache.felix.framework.util.SecureAction;
 import org.osgi.service.url.URLConstants;
@@ -56,16 +57,24 @@
 public 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 Map m_builtIn = new HashMap();
+    private final URLStreamHandlerFactory m_factory;
+    
     private final Map m_trackerMap = new HashMap();
     private final String m_protocol;
     private final Object m_service;
     private final SecureAction m_action;
 
-    public URLHandlersStreamHandlerProxy(String protocol, SecureAction action)
+    public URLHandlersStreamHandlerProxy(String protocol, SecureAction action, 
+        URLStreamHandlerFactory factory)
     {
         m_protocol = protocol;
         m_service = null;
         m_action = action;
+        m_factory = factory;
     }
     
     private URLHandlersStreamHandlerProxy(Object service, SecureAction action)
@@ -73,96 +82,211 @@
         m_protocol = null;
         m_service = service;
         m_action = action;
+        m_factory = null;
     }
 
     //
     // URLStreamHandler interface methods.
     //
 
-    protected synchronized boolean equals(URL url1, URL url2)
+    protected boolean equals(URL url1, URL url2)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url1.getProtocol());
         }
-        return svc.equals(url1, url2);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).equals(url1, url2);
+        }
+        try 
+        {
+            return ((Boolean) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, "equals", 
+                new Class[]{URL.class, URL.class}), svc, new Object[]{url1, url2})).booleanValue();
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
-    protected synchronized int getDefaultPort()
+    protected int getDefaultPort()
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException("Stream handler unavailable.");
         }
-        return svc.getDefaultPort();
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).getDefaultPort();
+        }
+        try 
+        {
+            return ((Integer) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "getDefaultPort", null), svc, null)).intValue();
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
-    protected synchronized InetAddress getHostAddress(URL url)
+    protected InetAddress getHostAddress(URL url)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url.getProtocol());
         }
-        return svc.getHostAddress(url);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).getHostAddress(url);
+        }
+        try 
+        {
+            return (InetAddress) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "getHostAddress", new Class[]{URL.class}), svc, new Object[]{url});
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
-    protected synchronized int hashCode(URL url)
+    protected int hashCode(URL url)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url.getProtocol());
         }
-        return svc.hashCode(url);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).hashCode(url);
+        }
+        try 
+        {
+            return ((Integer) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "hashCode", new Class[]{URL.class}), svc, new Object[]{url})).intValue();
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
-    protected synchronized boolean hostsEqual(URL url1, URL url2)
+    protected boolean hostsEqual(URL url1, URL url2)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url1.getProtocol());
         }
-        return svc.hostsEqual(url1, url2);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).hostsEqual(url1, url2);
+        }
+        try 
+        {
+            return ((Boolean) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "hostsEqual", new Class[]{URL.class, URL.class}), svc, new Object[]{url1, url2})).booleanValue();
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
-    protected synchronized URLConnection openConnection(URL url) throws IOException
+    protected URLConnection openConnection(URL url) throws IOException
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new MalformedURLException("Unknown protocol: " + url.toString());
         }
-        return svc.openConnection(url);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).openConnection(url);
+        }
+        try 
+        {
+            return (URLConnection) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "openConnection", new Class[]{URL.class}), svc, new Object[]{url});
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
-    protected synchronized void parseURL(URL url, String spec, int start, int limit)
+    protected void parseURL(URL url, String spec, int start, int limit)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        System.out.println("parse");
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url.getProtocol());
         }
-        svc.parseURL(this, url, spec, start, limit);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            ((URLStreamHandlerService) svc).parseURL(this, url, spec, start, limit);
+        }
+        else
+        {
+            try 
+            {
+                URL test = new URL(null, url.toExternalForm(), (URLStreamHandler) svc);
+                
+                m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                    "parseURL", new Class[]{URL.class, String.class, Integer.TYPE, Integer.TYPE}), 
+                    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());
+            } 
+            catch (Exception ex)  
+            {
+                ex.printStackTrace();
+                throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+            }
+        }
     }
 
-    protected synchronized boolean sameFile(URL url1, URL url2)
+    protected boolean sameFile(URL url1, URL url2)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url1.getProtocol());
         }
-        return svc.sameFile(url1, url2);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).sameFile(url1, url2);
+        }
+        try 
+        {
+            return ((Boolean) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "sameFile", new Class[]{URL.class, URL.class}), 
+                svc, new Object[]{url1, url2})).booleanValue();
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
     public void setURL(
@@ -178,15 +302,29 @@
         super.setURL(url, protocol, host, port, null, null, file, null, ref);
     }
 
-    protected synchronized String toExternalForm(URL url)
+    protected String toExternalForm(URL url)
     {
-        URLStreamHandlerService svc = getStreamHandlerService();
+        Object svc = getStreamHandlerService();
         if (svc == null)
         {
             throw new IllegalStateException(
                 "Unknown protocol: " + url.getProtocol());
         }
-        return svc.toExternalForm(url);
+        if (svc instanceof URLStreamHandlerService)
+        {
+            return ((URLStreamHandlerService) svc).toExternalForm(url);
+        }
+        try 
+        {
+            return (String) m_action.invoke(m_action.getDeclaredMethod(URLStreamHandler.class, 
+                "toExternalForm", new Class[]{URL.class}), 
+                svc, new Object[]{url});
+        } 
+        catch (Exception ex)  
+        {
+            ex.printStackTrace();
+            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage());
+        }
     }
 
     /**
@@ -200,20 +338,22 @@
      *         associated with the current call stack or <tt>null</tt>
      *         is no service is available.
     **/
-    private URLStreamHandlerService getStreamHandlerService()
+    private Object getStreamHandlerService()
     {
         // Get the framework instance associated with call stack.
         Object framework = URLHandlers.getFrameworkFromContext();
 
-        // If the framework has disabled the URL Handlers service,
-        // then it will not be found so just return null.
         if (framework == null)
         {
-            return null;
+            return getBuiltIn();
         }
 
         // Get the service tracker for the framework instance or create one.
-        Object tracker = m_trackerMap.get(framework);
+        Object tracker;
+        synchronized (m_trackerMap)
+        {
+            tracker = m_trackerMap.get(framework);
+        }
         try
         {
             if (tracker == null)
@@ -235,13 +375,23 @@
                     new Object[]{framework, filter});
 
                 // Cache the simple service tracker.
-                m_trackerMap.put(framework, tracker);
+                synchronized (m_trackerMap) 
+                {
+                    if (!m_trackerMap.containsKey(framework))
+                    {
+                        m_trackerMap.put(framework, tracker);
+                    }
+                    else
+                    {
+                        tracker = m_trackerMap.get(framework);
+                    }
+                }
             }
             Object service = m_action.invoke(m_action.getMethod(
                 tracker.getClass(), "getService", null), tracker, null);
             if (service == null)
             {
-                return null;
+                return getBuiltIn();
             }
             if (service instanceof URLStreamHandlerService)
             {
@@ -259,6 +409,65 @@
             return null;
         }
     }
+    
+    private URLStreamHandler getBuiltIn()
+    {
+        synchronized (m_builtIn)
+        {
+            if (m_builtIn.containsKey(m_protocol))
+            {
+                return (URLStreamHandler) m_builtIn.get(m_protocol);
+            }
+        }
+        if (m_factory != null)
+        {
+            URLStreamHandler result = m_factory.createURLStreamHandler(m_protocol);
+            if (result != null)
+            {
+                return addToCache(m_protocol, result);
+            }
+        }
+        // Check for built-in handlers for the mime type.
+        String pkgs = m_action.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 + "." + m_protocol + ".Handler";
+            try
+            {
+                // If a built-in handler is found then cache and return it
+                Class handler = m_action.forName(className); 
+                if (handler != null)
+                {
+                    return addToCache(m_protocol, 
+                        (URLStreamHandler) handler.newInstance());
+                }
+            }
+            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 addToCache(m_protocol, null);
+    }
+
+    private synchronized URLStreamHandler addToCache(String protocol, URLStreamHandler result)
+    {
+        if (!m_builtIn.containsKey(protocol))
+        {
+            m_builtIn.put(protocol, result);
+            return result;
+        }
+        return (URLStreamHandler) m_builtIn.get(protocol);
+    }
 
     public Object invoke(Object obj, Method method, Object[] params)
         throws Throwable