Speed-up URL stream/content handler lookup by using a tracker again. The difference to the previous tracker is that we now create and maintain the trackers inside the framework so don't need to do classloads when using them (FELIX-1138).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@810183 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index fd29299..14ff7e5 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -307,7 +307,7 @@
         {
             // This should not throw an exception, but if so, lets convert it to
             // a runtime exception.
-            throw new RuntimeException(ex);
+            throw new RuntimeException(ex.getMessage());
         }
 
         // Read the boot delegation property and parse it.
@@ -4626,4 +4626,21 @@
             }
         }
     }
+
+    private volatile URLHandlersActivator m_urlHandlersActivator;
+    
+    void setURLHandlersActivator(URLHandlersActivator urlHandlersActivator)
+    {
+        m_urlHandlersActivator = urlHandlersActivator;
+    }
+    
+    Object getStreamHandlerService(String protocol)
+    {
+        return m_urlHandlersActivator.getStreamHandlerService(protocol);
+    }
+    
+    Object getContentHandlerService(String mimeType)
+    {
+        return m_urlHandlersActivator.getContentHandlerService(mimeType);
+    }
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
index 3180aaf..69db16a 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
@@ -18,10 +18,15 @@
  */
 package org.apache.felix.framework;
 
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Map;
+
 import org.apache.felix.framework.util.FelixConstants;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
 
 /**
  * <p>
@@ -34,8 +39,8 @@
 **/
 class URLHandlersActivator implements BundleActivator
 {
-    private Map m_configMap = null;
-    private Felix m_framework = null;
+    private final Map m_configMap;
+    private final Felix m_framework;
 
     public URLHandlersActivator(Map configMap, Felix framework)
     {
@@ -55,11 +60,71 @@
                 FelixConstants.SERVICE_URLHANDLERS_PROP) == null)
                 ? true
                 : !m_configMap.get(FelixConstants.SERVICE_URLHANDLERS_PROP).equals("false");
+
+        if (enable)
+        {
+            m_streamTracker = new ServiceTracker(context, "org.osgi.service.url.URLStreamHandlerService", null);
+            m_contentTracker= new ServiceTracker(context, "java.net.ContentHandler", null);
+            m_streamTracker.open();
+            m_contentTracker.open();
+            m_framework.setURLHandlersActivator(this);
+        }
         URLHandlers.registerFrameworkInstance(m_framework, enable);
     }
 
     public void stop(BundleContext context)
     {
         URLHandlers.unregisterFrameworkInstance(m_framework);
+        m_framework.setURLHandlersActivator(null);
+        if (m_streamTracker != null)
+        {
+            m_streamTracker.close();
+        }
+        if (m_contentTracker != null)
+        {
+            m_contentTracker.close();
+        }
+        m_streamTracker = null;
+        m_contentTracker = null;
+    }
+
+    private volatile ServiceTracker m_streamTracker;
+    private volatile ServiceTracker m_contentTracker;
+    
+    protected Object getStreamHandlerService(String protocol)
+    {
+        return get(m_streamTracker, "url.handler.protocol", protocol);
+    }
+
+    protected Object getContentHandlerService(String mimeType)
+    {
+        return get(m_contentTracker, "url.content.mimetype", mimeType);
+    }
+
+    private Object get(ServiceTracker tracker, String key, String value)
+    {
+    	Object service = null;
+        if (tracker != null)
+        {
+            ServiceReference[] refs = tracker.getServiceReferences();
+
+            if (refs != null)
+            {
+                if (refs.length > 1)
+                {
+                    Arrays.sort(refs, Collections.reverseOrder());
+                }
+
+                for (int i = 0;(i < refs.length) && (service == null);i++)
+                {
+                    if (value.equals(refs[i].getProperty(key)))
+                    {
+                        service = tracker.getService(refs[i]);
+                    }
+                }
+            }
+        }
+
+        return service;
     }
 }
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 35b6e15..4d51311 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
@@ -52,10 +52,7 @@
 **/
 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";
@@ -75,7 +72,6 @@
 
     private final String m_mimeType;
     private final SecureAction m_action;
-    private final Object[] m_filter;
 
     public URLHandlersContentHandlerProxy(String mimeType, SecureAction action, 
         ContentHandlerFactory factory)
@@ -83,10 +79,6 @@
         m_mimeType = mimeType;
         m_action = action;
         m_factory = factory;
-        m_filter = new Object[]{"java.net.ContentHandler", 
-            "(&(objectClass=java.net.ContentHandler)(url.content.mimetype="
-            + mimeType
-            + "))"};
     } 
 
     //
@@ -125,63 +117,19 @@
         }
         try 
         {
-            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) 
+            ContentHandler service;
+            if (framework instanceof Felix)
             {
-                // 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++)
-                {
-                    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)))
-                    {
-                        ref = refs[i];
-                        highestRank = rank;
-                        currentId = idObj.longValue();
-                    }
-                }
+                service = (ContentHandler) ((Felix) framework).getContentHandlerService(m_mimeType);
             }
-            ContentHandler service = null;
-            if (ref != null) 
+            else
             {
-                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});
+                    m_action.getMethod(framework.getClass(), "getContentHandlerService", STRING_TYPES),
+                    framework, new Object[]{m_mimeType});
             }
-        
-            if (service == null)
-            {
-                service = getBuiltIn();
-            }
-            return service;
+            
+            return (service == null) ? getBuiltIn() : service;
         }
         catch (Exception ex)
         {
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 3cb9751..36708c9 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
@@ -28,6 +28,8 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
+import java.util.Collections;
+import java.util.Arrays;
 
 import org.apache.felix.framework.util.SecureAction;
 import org.osgi.service.url.URLStreamHandlerService;
@@ -59,10 +61,7 @@
     implements URLStreamHandlerSetter, InvocationHandler
 {
     private static final Class[] URL_PROXY_CLASS;
-    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;
@@ -129,28 +128,25 @@
     private final SecureAction m_action;
     private final URLStreamHandler m_builtIn;
     private final URL m_builtInURL;
-    private final Object[] m_filter;
+    private final String m_protocol;
 
     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; 
     }
 
     //
@@ -535,57 +531,19 @@
             {
                 return m_builtIn;
             }
-            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) 
-            {
-                // 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++)
-                {
-                    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)))
-                    {
-                        ref = refs[i];
-                        highestRank = rank;
-                        currentId = idObj.longValue();
-                    }
-                }
-            }
+
             Object service = null;
-            if (ref != null) 
+            if (framework instanceof Felix)
             {
-                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});
+                service = ((Felix) framework).getStreamHandlerService(m_protocol);
             }
+            else
+            {
+                m_action.invoke(
+                    m_action.getMethod(framework.getClass(), "getStreamHandlerService", STRING_TYPES), 
+                    framework, new Object[]{m_protocol});
+            }
+
             if (service == null) 
             {
                 return m_builtIn;