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)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@709541 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 281b803..20906eb 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -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)
+ if (m_contentHandlerCache.containsKey(mimeType))
{
- m_streamHandlerCache = new HashMap();
+ return (ContentHandler) m_contentHandlerCache.get(mimeType);
}
- 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)
- {
- 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;
}
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 a8f06b9..6e7dd0a 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersContentHandlerProxy.java
@@ -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
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 ec431e5..1e9fe12 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
@@ -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