Rework stream handler proxies to not do classloads when looking up the URLHandler services (FELIX-1035).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@765971 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 812bc7f..9b49a59 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -20,19 +20,16 @@
 
 import java.net.ContentHandler;
 import java.net.ContentHandlerFactory;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
 import java.net.URLStreamHandlerFactory;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 
-import org.apache.felix.framework.searchpolicy.ModuleImpl.ModuleClassLoader;
 import org.apache.felix.framework.util.FelixConstants;
 import org.apache.felix.framework.util.SecureAction;
 import org.apache.felix.framework.util.SecurityManagerEx;
@@ -79,6 +76,10 @@
 **/
 class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
 {
+    private static final Class[] CLASS_TYPE = new Class[]{Class.class};
+
+    private static final Class URLHANDLERS_CLASS = URLHandlers.class;
+
     private static final SecureAction m_secureAction = new SecureAction();
 
     private static volatile SecurityManagerEx m_sm = null;
@@ -122,7 +123,7 @@
         {
             m_handlerToURL.put(getBuiltInStreamHandler(protocol, null), new URL(protocol + ":") );
         }
-        catch (MalformedURLException ex)
+        catch (Throwable ex)
         {
             ex.printStackTrace();
             // Ignore, this is a best effort (maybe log it or something).
@@ -143,7 +144,15 @@
         init("ftp");
         init("http");
         init("https");
-        getBuiltInStreamHandler("jar", null);
+        try 
+        {
+            getBuiltInStreamHandler("jar", null);
+        }
+        catch (Throwable ex)
+        {
+            ex.printStackTrace();
+            // Ignore, this is a best effort (maybe log it or something)
+        }
         m_sm = new SecurityManagerEx();
         synchronized (URL.class)
         {
@@ -160,18 +169,18 @@
                     // there already is a factory set so try to swap it with ours.
                     m_streamHandlerFactory = (URLStreamHandlerFactory)
                         m_secureAction.swapStaticFieldIfNotClass(URL.class, 
-                        URLStreamHandlerFactory.class, URLHandlers.class, "streamHandlerLock");
+                        URLStreamHandlerFactory.class, URLHANDLERS_CLASS, "streamHandlerLock");
                     
                     if (m_streamHandlerFactory == null)
                     {
                         throw err;
                     }
-                    if (!m_streamHandlerFactory.getClass().getName().equals(URLHandlers.class.getName()))
+                    if (!m_streamHandlerFactory.getClass().getName().equals(URLHANDLERS_CLASS.getName()))
                     {
                         URL.setURLStreamHandlerFactory(this);
                         m_rootURLHandlers = this;
                     }
-                    else if (URLHandlers.class != m_streamHandlerFactory.getClass())
+                    else if (URLHANDLERS_CLASS != m_streamHandlerFactory.getClass())
                     {
                         try
                         {
@@ -179,7 +188,7 @@
                                 m_secureAction.getDeclaredMethod(m_streamHandlerFactory.getClass(), 
                                 "registerFrameworkListsForContextSearch", 
                                 new Class[]{ClassLoader.class, List.class}), 
-                                m_streamHandlerFactory, new Object[]{ URLHandlers.class.getClassLoader(), 
+                                m_streamHandlerFactory, new Object[]{ URLHANDLERS_CLASS.getClassLoader(), 
                                     m_frameworks });
                             m_rootURLHandlers = m_streamHandlerFactory;
                         }
@@ -208,13 +217,13 @@
                     m_contentHandlerFactory = (ContentHandlerFactory) 
                         m_secureAction.swapStaticFieldIfNotClass(
                             URLConnection.class, ContentHandlerFactory.class, 
-                            URLHandlers.class, null);
+                            URLHANDLERS_CLASS, null);
                     if (m_contentHandlerFactory == null)
                     {
                         throw err;
                     }
                     if (!m_contentHandlerFactory.getClass().getName().equals(
-                        URLHandlers.class.getName()))
+                        URLHANDLERS_CLASS.getName()))
                     {
                         URLConnection.setContentHandlerFactory(this);
                     }
@@ -226,7 +235,7 @@
             }
         }
         // are we not the new root?
-        if (!((m_streamHandlerFactory == this) || !URLHandlers.class.getName().equals(
+        if (!((m_streamHandlerFactory == this) || !URLHANDLERS_CLASS.getName().equals(
             m_streamHandlerFactory.getClass().getName())))
         {
             m_sm = null;
@@ -271,7 +280,7 @@
                                 ex.printStackTrace();
                             }
                             
-                            if (m_streamHandlerFactory.getClass() != URLHandlers.class)
+                            if (m_streamHandlerFactory.getClass() != URLHANDLERS_CLASS)
                             {
                                 URL.setURLStreamHandlerFactory(m_streamHandlerFactory);
                             }
@@ -287,7 +296,7 @@
                                 ex.printStackTrace();
                             }
                             
-                            if (m_contentHandlerFactory.getClass() != URLHandlers.class)
+                            if (m_contentHandlerFactory.getClass() != URLHANDLERS_CLASS)
                             {
                                 URLConnection.setContentHandlerFactory(m_contentHandlerFactory);
                             }
@@ -471,31 +480,6 @@
         return result;
     }
 
-    synchronized void flush()
-    {
-        if (m_streamHandlerCache != null)
-        {
-            for (Iterator iter = m_streamHandlerCache.values().iterator();iter.hasNext();)
-            {
-                Object proxy = iter.next();
-                if (proxy instanceof URLHandlersStreamHandlerProxy)
-                {
-                    ((URLHandlersStreamHandlerProxy) proxy).flush();
-                }
-            }
-        }
-        if (m_contentHandlerCache != null)
-        {
-            for (Iterator iter = m_contentHandlerCache.values().iterator();iter.hasNext();)
-            {
-                Object proxy = iter.next();
-                if (proxy instanceof URLHandlersContentHandlerProxy)
-                {
-                    ((URLHandlersContentHandlerProxy) proxy).flush();
-                }
-            }
-        }
-    }
     /**
      * <p>
      * Static method that adds a framework instance to the centralized
@@ -542,18 +526,6 @@
             m_counter--;
             if (m_frameworks.remove(framework))
             {    
-                try
-                {
-                    m_secureAction.invoke(m_secureAction.getDeclaredMethod(
-                        m_rootURLHandlers.getClass(), 
-                       "flush", null), 
-                       m_rootURLHandlers, null);
-                }
-                catch (Exception e)
-                {
-                    // TODO: this should not happen
-                    e.printStackTrace();
-                }
                 if (m_frameworks.isEmpty())
                 {
                     try
@@ -563,7 +535,7 @@
                             "unregisterFrameworkListsForContextSearch", 
                             new Class[]{ ClassLoader.class}), 
                             m_rootURLHandlers,
-                            new Object[] {URLHandlers.class.getClassLoader()});
+                            new Object[] {URLHANDLERS_CLASS.getClassLoader()});
                     }
                     catch (Exception e)
                     {
@@ -610,7 +582,7 @@
         for (int i = 0; i < stack.length; i++)
         {
             if ((stack[i].getClassLoader() != null) && 
-                ModuleClassLoader.class.getName().equals(
+                "org.apache.felix.framework.searchpolicy.ModuleImpl.ModuleClassLoader".equals(
                 stack[i].getClassLoader().getClass().getName()))
             {
                 targetClass = stack[i];
@@ -630,7 +602,7 @@
                 List frameworks = (List) m_classloaderToFrameworkLists.get(
                     index);
                 
-                if ((frameworks == null) && (index == URLHandlers.class.getClassLoader())) 
+                if ((frameworks == null) && (index == URLHANDLERS_CLASS.getClassLoader())) 
                 {
                     frameworks = m_frameworks;
                 }
@@ -646,7 +618,7 @@
                             {
                                 if (m_secureAction.invoke(
                                     m_secureAction.getDeclaredMethod(framework.getClass(), 
-                                    "getBundle", new Class[]{Class.class}),
+                                    "getBundle", CLASS_TYPE),
                                     framework, new Object[]{targetClass}) != null)
                                 {
                                     return framework;
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
index f9c6ecd..35b6e15 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
@@ -23,12 +23,10 @@
 import java.net.ContentHandlerFactory;
 import java.net.URLConnection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.StringTokenizer;
 
 import org.apache.felix.framework.util.SecureAction;
-import org.osgi.service.url.URLConstants;
 
 /**
  * <p>
@@ -54,6 +52,11 @@
 **/
 class URLHandlersContentHandlerProxy extends ContentHandler
 {
+    private static final Object[] SERVICE_RANKING_PARAMS = new Object[]{"service.ranking"};
+    private static final Object[] SERVICE_ID_PARAMS = new Object[]{"service.id"};
+    private static final Class[] STRING_TYPES = new Class[]{String.class};
+    private static final Class[] STRING_STRING_TYPES = new Class[]{String.class, String.class};
+
     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";
     
@@ -70,9 +73,9 @@
 
     private final ContentHandlerFactory m_factory;
 
-    private final Map m_trackerMap = new HashMap();
     private final String m_mimeType;
     private final SecureAction m_action;
+    private final Object[] m_filter;
 
     public URLHandlersContentHandlerProxy(String mimeType, SecureAction action, 
         ContentHandlerFactory factory)
@@ -80,7 +83,11 @@
         m_mimeType = mimeType;
         m_action = action;
         m_factory = factory;
-    }
+        m_filter = new Object[]{"java.net.ContentHandler", 
+            "(&(objectClass=java.net.ContentHandler)(url.content.mimetype="
+            + mimeType
+            + "))"};
+    } 
 
     //
     // ContentHandler interface method.
@@ -116,63 +123,65 @@
         {
             return getBuiltIn();
         }
-
-        // Get the service tracker for the framework instance or create one.
-        Object tracker;
-        synchronized (m_trackerMap)
+        try 
         {
-            tracker = m_trackerMap.get(framework);
-        }
-        try
-        {
-            if (tracker == null)
+            Object context = m_action.invoke(
+                    m_action.getMethod(framework.getClass(), "getBundleContext", null),framework, null);
+                
+            Class contextClass = context.getClass();
+            
+            Object[] refs = (Object[]) m_action.invoke(
+                m_action.getMethod(contextClass, "getServiceReferences", STRING_STRING_TYPES), 
+                context, m_filter);
+            
+            Object ref = null;
+            int highestRank = -1;
+            long currentId = -1;
+            if (refs != null) 
             {
-                // Create a filter for the mime type.
-                String filter = 
-                    "(&(objectClass="
-                    + ContentHandler.class.getName()
-                    + ")("
-                    + URLConstants.URL_CONTENT_MIMETYPE
-                    + "="
-                    + m_mimeType
-                    + "))";
-                // Create a simple service tracker for the framework.
-                tracker = m_action.invoke(m_action.getConstructor(
-                    framework.getClass().getClassLoader().loadClass(
-                    URLHandlersServiceTracker.class.getName()),
-                    new Class[]{framework.getClass().getClassLoader().loadClass(
-                    Felix.class.getName()), String.class}), 
-                    new Object[]{framework, filter});
-                // Cache the simple service tracker.
-                synchronized (m_trackerMap) 
+                // Loop through all service references and select the reference
+                // with the highest ranking and lower service identifier.
+                for (int i = 0; (refs != null) && (i < refs.length); i++)
                 {
-                    if (!m_trackerMap.containsKey(framework))
+                    Class refClass = refs[i].getClass();
+                    Long idObj = (Long) m_action.invoke(m_action.getMethod(refClass, 
+                        "getProperty", STRING_TYPES), refs[i], SERVICE_ID_PARAMS);
+                    Integer rankObj = (Integer)  m_action.invoke(m_action.getMethod(refClass, 
+                    "getProperty", STRING_TYPES), refs[i], SERVICE_RANKING_PARAMS);
+                    // Ranking value defaults to zero.
+                    int rank = (rankObj == null) ? 0 : rankObj.intValue();
+                    if ((rank > highestRank) ||
+                        ((rank == highestRank) && (idObj.longValue() < currentId)))
                     {
-                        m_trackerMap.put(framework, tracker);
-                    }
-                    else
-                    {
-                        tracker = m_trackerMap.get(framework);
+                        ref = refs[i];
+                        highestRank = rank;
+                        currentId = idObj.longValue();
                     }
                 }
             }
-            ContentHandler result;
-            if (tracker instanceof URLHandlersServiceTracker)
+            ContentHandler service = null;
+            if (ref != null) 
             {
-                result = (ContentHandler) 
-                    ((URLHandlersServiceTracker) tracker).getService();
+                Class serviceRef = null;
+                Class[] interfaces = ref.getClass().getInterfaces();
+                for (int i = 0;i < interfaces.length; i++) 
+                {
+                    if ("org.osgi.framework.ServiceReference".equals(interfaces[i].getName()))
+                    {
+                        serviceRef = interfaces[i];
+                        break;
+                    }
+                }
+                service = (ContentHandler) m_action.invoke(
+                    m_action.getMethod(contextClass, "getService", new Class[]{serviceRef}), 
+                    context, new Object[]{ref});
             }
-            else
+        
+            if (service == null)
             {
-                result = (ContentHandler) m_action.invokeDirect(
-                    m_action.getMethod(tracker.getClass(), "getService", null), 
-                    tracker, null);
+                service = getBuiltIn();
             }
-            if (result == null)
-            {
-                result = getBuiltIn();
-            }
-            return result;
+            return service;
         }
         catch (Exception ex)
         {
@@ -182,38 +191,6 @@
         }
     }
 
-    void flush()
-    {
-        synchronized (m_trackerMap)
-        {
-            for (Iterator iter = m_trackerMap.values().iterator(); iter.hasNext();)
-            {
-                unregister(iter.next());
-            }
-            m_trackerMap.clear();
-        }
-    }
-
-    private void unregister(Object tracker)
-    {
-        if (tracker instanceof URLHandlersServiceTracker)
-        {
-            ((URLHandlersServiceTracker) tracker).unregister();
-        }
-        else
-        {
-            try
-            {
-                m_action.invokeDirect(m_action.getMethod(tracker.getClass(), 
-                    "unregister", null), tracker, null);
-            }
-            catch (Exception e)
-            {
-                // Not much we can do - log this or something
-            }
-        }
-    }
-
     private ContentHandler getBuiltIn()
     {
         synchronized (m_builtIn)
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
deleted file mode 100644
index a832056..0000000
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/* 
- * 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
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import org.apache.felix.framework.util.FelixConstants;
-import org.osgi.framework.*;
-
-/**
- * <p>
- * This class implements a simple service tracker that maintains a
- * service object reference to the "best" service available at any
- * given time that matches the filter associated with the tracker.
- * The best service is the one with the one with the highest ranking
- * and lowest service identifier.
- *</p>
-**/
-public class URLHandlersServiceTracker implements ServiceListener
-{
-    private final BundleContext m_context;
-    private final String m_filter;
-    private ServiceReference m_ref = null;
-    private volatile Object m_svcObj = null;
-    private long m_id = -1;
-    private int m_rank = -1;
-
-    /**
-     * <p>
-     * Creates a simple service tracker associated with the specified bundle
-     * context for services matching the specified filter.
-     * </p>
-     * @param context the bundle context used for tracking services.
-     * @param filter the filter used for matching services.
-    **/
-    public URLHandlersServiceTracker(Felix framework, String filter)
-    {
-        m_context = ((BundleImpl) framework).getBundleContext();
-        m_filter = filter;
-
-        synchronized (this)
-        {
-            // Add a service listener to track service changes
-            // for services matching the specified filter.
-            try
-            {
-                m_context.addServiceListener(this, m_filter);
-            }
-            catch (InvalidSyntaxException ex)
-            {
-                System.out.println("Cannot add service listener." + ex);
-            }
-
-            // Select the best service object.
-            selectBestService();
-
-        } // End of synchronized block.
-    }
-
-    public void unregister()
-    {
-        m_context.removeServiceListener(this);
-    }
-
-    public Object getService()
-    {
-        return m_svcObj;
-    }
-    
-    public void serviceChanged(ServiceEvent event)
-    {
-        ServiceReference eventRef = event.getServiceReference();
-        if ((event.getType() == ServiceEvent.REGISTERED) ||
-            (event.getType() == ServiceEvent.MODIFIED))
-        {
-            synchronized (URLHandlersServiceTracker.this)
-            {
-                Long idObj = (Long) eventRef.getProperty(FelixConstants.SERVICE_ID);
-                Integer rankObj = (Integer) eventRef.getProperty(FelixConstants.SERVICE_RANKING);
-                int rank = (rankObj == null) ? 0 : rankObj.intValue();
-                if ((rank > m_rank) ||
-                    ((rank == m_rank) && (idObj.longValue() < m_id)))
-                {
-                    if (m_ref != null)
-                    {
-                        m_context.ungetService(m_ref);
-                    }
-                    m_ref = eventRef;
-                    m_rank = rank;
-                    m_id = idObj.longValue();
-                    m_svcObj = m_context.getService(m_ref);
-                }
-            }
-        }
-        else if (event.getType() == ServiceEvent.UNREGISTERING)
-        {
-            synchronized (URLHandlersServiceTracker.this)
-            {
-                if (eventRef == m_ref)
-                {
-                    selectBestService();
-                }
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * This method selects the highest ranking service object with the
-     * lowest service identifier out of the services selected by the
-     * service filter associated with this proxy. This method is called
-     * to initialize the proxy and any time when the service object
-     * being used is unregistered. If there is an existing service
-     * selected when this method is called, it will unget the existing
-     * service before selecting the best available service.
-     * </p>
-    **/
-    private synchronized void selectBestService()
-    {
-        // If there is an existing service, then unget it.
-        if (m_ref != null)
-        {
-            m_context.ungetService(m_ref);
-            m_ref = null;
-            m_svcObj = null;
-            m_id = -1;
-            m_rank = -1;
-        }
-
-        try
-        {
-            // Get all service references matching the service filter
-            // associated with this proxy.
-            ServiceReference[] refs = m_context.getServiceReferences(null, m_filter);
-            // Loop through all service references and select the reference
-            // with the highest ranking and lower service identifier.
-            for (int i = 0; (refs != null) && (i < refs.length); i++)
-            {
-                Long idObj = (Long) refs[i].getProperty(FelixConstants.SERVICE_ID);
-                Integer rankObj = (Integer) refs[i].getProperty(FelixConstants.SERVICE_RANKING);
-                // Ranking value defaults to zero.
-                int rank = (rankObj == null) ? 0 : rankObj.intValue();
-                if ((rank > m_rank) ||
-                    ((rank == m_rank) && (idObj.longValue() < m_id)))
-                {
-                    m_ref = refs[i];
-                    m_rank = rank;
-                    m_id = idObj.longValue();
-                }
-            }
-
-            // If a service reference was selected, then
-            // get its service object.
-            if (m_ref != null)
-            {
-                m_svcObj = m_context.getService(m_ref);
-            }
-        }
-        catch (InvalidSyntaxException ex)
-        {
-//TODO: LOGGER.
-            System.err.println("URLHandlersServiceTracker: " + ex);
-        }
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
index b905ab5..b62d830 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
@@ -23,13 +23,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.net.*;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.StringTokenizer;
-
 import org.apache.felix.framework.util.SecureAction;
-import org.osgi.service.url.URLConstants;
 import org.osgi.service.url.URLStreamHandlerService;
 import org.osgi.service.url.URLStreamHandlerSetter;
 
@@ -58,6 +52,10 @@
 public final class URLHandlersStreamHandlerProxy extends URLStreamHandler
     implements URLStreamHandlerSetter, InvocationHandler
 {
+    private static final Object[] SERVICE_RANKING_PARAMS = new Object[]{"service.ranking"};
+    private static final Object[] SERVICE_ID_PARAMS = new Object[]{"service.id"};
+    private static final Class[] STRING_TYPES = new Class[]{String.class};
+    private static final Class[] STRING_STRING_TYPES = new Class[]{String.class, String.class};
     private static final Method EQUALS;
     private static final Method GET_DEFAULT_PORT;
     private static final Method GET_HOST_ADDRESS;
@@ -102,31 +100,33 @@
             throw new RuntimeException(ex.getMessage());
         }
     }
-    
-    private final Map m_trackerMap = new HashMap();
-    private final String m_protocol;
+
     private final Object m_service;
     private final SecureAction m_action;
     private final URLStreamHandler m_builtIn;
     private final URL m_builtInURL;
+    private final Object[] m_filter;
 
     public URLHandlersStreamHandlerProxy(String protocol, 
         SecureAction action, URLStreamHandler builtIn, URL builtInURL)
     {
-        m_protocol = protocol;
         m_service = null;
         m_action = action;
         m_builtIn = builtIn;
         m_builtInURL = builtInURL;
+        m_filter = new Object[]{"org.osgi.service.url.URLStreamHandlerService", 
+            "(&(objectClass=org.osgi.service.url.URLStreamHandlerService)(url.handler.protocol="
+            + protocol
+            + "))"};
     }
     
     private URLHandlersStreamHandlerProxy(Object service, SecureAction action)
     {
-        m_protocol = null;
         m_service = service;
         m_action = action;
         m_builtIn = null;
         m_builtInURL = null;
+        m_filter = null;
     }
 
     //
@@ -416,55 +416,56 @@
             {
                 return m_builtIn;
             }
-    
-            // Get the service tracker for the framework instance or create one.
-            Object tracker;
-            synchronized (m_trackerMap)
+            Object context = m_action.invoke(
+                m_action.getMethod(framework.getClass(), "getBundleContext", null),framework, null);
+            
+            Class contextClass = context.getClass();
+            
+            Object[] refs = (Object[]) m_action.invoke(
+                m_action.getMethod(contextClass, "getServiceReferences", STRING_STRING_TYPES), 
+                context, m_filter);
+            
+            Object ref = null;
+            int highestRank = -1;
+            long currentId = -1;
+            if (refs != null) 
             {
-                tracker = m_trackerMap.get(framework);
-            }
-            if (tracker == null)
-            {
-                // Create a filter for the protocol.
-                String filter = 
-                    "(&(objectClass="
-                    + URLStreamHandlerService.class.getName()
-                    + ")("
-                    + URLConstants.URL_HANDLER_PROTOCOL
-                    + "="
-                    + m_protocol
-                    + "))";
-                // Create a simple service tracker for the framework.
-                tracker = m_action.invoke(m_action.getConstructor(
-                    framework.getClass().getClassLoader().loadClass(
-                    "org.apache.felix.framework.URLHandlersServiceTracker"), 
-                    new Class[]{framework.getClass().getClassLoader().loadClass(
-                    "org.apache.felix.framework.Felix"), String.class}), 
-                    new Object[]{framework, filter});
-
-                // Cache the simple service tracker.
-                synchronized (m_trackerMap) 
+                // Loop through all service references and select the reference
+                // with the highest ranking and lower service identifier.
+                for (int i = 0; (refs != null) && (i < refs.length); i++)
                 {
-                    if (!m_trackerMap.containsKey(framework))
+                    Class refClass = refs[i].getClass();
+                    Long idObj = (Long) m_action.invoke(m_action.getMethod(refClass, 
+                        "getProperty", STRING_TYPES), refs[i], SERVICE_ID_PARAMS);
+                    Integer rankObj = (Integer)  m_action.invoke(m_action.getMethod(refClass, 
+                        "getProperty", STRING_TYPES), refs[i], SERVICE_RANKING_PARAMS);
+                    // Ranking value defaults to zero.
+                    int rank = (rankObj == null) ? 0 : rankObj.intValue();
+                    if ((rank > highestRank) ||
+                        ((rank == highestRank) && (idObj.longValue() < currentId)))
                     {
-                        m_trackerMap.put(framework, tracker);
-                    }
-                    else
-                    {
-                        unregister(tracker);
-                        tracker = m_trackerMap.get(framework);
+                        ref = refs[i];
+                        highestRank = rank;
+                        currentId = idObj.longValue();
                     }
                 }
             }
-            Object service;
-            if (tracker instanceof URLHandlersServiceTracker)
+            Object service = null;
+            if (ref != null) 
             {
-                service = ((URLHandlersServiceTracker) tracker).getService();
-            }
-            else
-            {
-                service = m_action.invokeDirect(m_action.getMethod(
-                    tracker.getClass(), "getService", null), tracker, null);
+                Class serviceRef = null;
+                Class[] interfaces = ref.getClass().getInterfaces();
+                for (int i = 0;i < interfaces.length; i++) 
+                {
+                    if ("org.osgi.framework.ServiceReference".equals(interfaces[i].getName()))
+                    {
+                        serviceRef = interfaces[i];
+                        break;
+                    }
+                }
+                service = m_action.invoke(
+                    m_action.getMethod(contextClass, "getService", new Class[]{serviceRef}), 
+                    context, new Object[]{ref});
             }
             if (service == null) 
             {
@@ -485,43 +486,10 @@
         }
         catch (Throwable t)
         {
-         //   t.printStackTrace();
             return m_builtIn;
         }
     }
 
-    void flush()
-    {
-        synchronized (m_trackerMap)
-        {
-            for (Iterator iter = m_trackerMap.values().iterator(); iter.hasNext();)
-            {
-                unregister(iter.next());
-            }
-            m_trackerMap.clear();
-        }
-    }
-
-    private void unregister(Object tracker)
-    {
-        if (tracker instanceof URLHandlersServiceTracker)
-        {
-            ((URLHandlersServiceTracker) tracker).unregister();
-        }
-        else
-        {
-            try
-            {
-                m_action.invokeDirect(m_action.getMethod(tracker.getClass(), 
-                    "unregister", null), tracker, null);
-            }
-            catch (Exception e)
-            {
-                // Not much we can do - log this or something
-            }
-        }
-    }
-
     public Object invoke(Object obj, Method method, Object[] params)
         throws Throwable
     {
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
index 62d55f0..0fdc861 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
@@ -18,7 +18,6 @@
  */
 package org.apache.felix.framework.searchpolicy;
 
-import java.lang.reflect.InvocationTargetException;
 import org.apache.felix.moduleloader.*;
 import java.io.IOException;
 import java.io.InputStream;