[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[equinox-dev] URL Handlers service

I'm trying to gather up, clean up and to some degree analyze the various approaches for the URL Handlers Service in environments where the URLStreamHandlerFactory and ContentHandlerFactory singletons have already been set.
This is fairly long, but if you can have a read and send feedback it would be much appreciated.
Tom sent me a possible option that looks promising so let's start with that.
Instead of giving up when URL.setURLStreamHandlerFactory fails maybe we can use reflection to replace the static field 'factory' in URL with out own URLStreamHandlerFactory which first proxies to the original URLStreamHandlerFactory.  Then we could always make sure our factory is in place.  For this to work our factory would have to do the following (non-inclusive list)

1)  All calls to createURLStreamHandler on our factory would proxy to the original createURLStreamHandler.  If that returns non-null then we return it else we try our own method of lookup (using services etc)

2)  We would not want to replace the 'factory' field in URL if the factory is already an instance of our own factory.  If the factory is already an instance of our own then we can register an instance of the framework with that factory and start doing the fancy stuff that felix is doing for multiple frameworks running.

3)  The reflection will be kind of tricky.  We would have to search all static fields of the URL class for a Field of type URLStreamHandlerFactory, this is needed because we do not know what the name of the field across all VM implementations.  Then we would have to set the accessible bit on the field (by calling Field.setAccessible(true)).  And then calling Field.set to set the Field with our own factory.

I think the same approach can be done for the ContentHandlerFactory on URLConnection.  I must admit I woke up with this idea in my head and have not thought it all the way through.  What are your thoughts?

[After Jeff's comment a week ago I figured this approach was coming... ]
A bit naughty perhaps, but certainly the net result is pretty clean.
There's a bit more per VM work to do for synchronization but it looks workable.
The implementation is pretty complex but perhaps it's small enough to not worry.
The only real problem I see is the Security Permission required when a SecurityManager is active.
In my experience, if we can state the required "permission" precisely this is not a huge deal for customers.
I like it. 
I'm very interested in what everyone else thinks?
I've also been thinking a bit about the very real but unwritten dependencies implied when you use an internal protocol.
(By internal protocols I mean: bundleentry, bundleresource, reference, and platform)
When you use one of these protocols directly (meaning you are the URL creator) you're not really asking for any implementation of the protocol; you instead want a specific implementation. For that reason I think it's reasonable to make mandatory the specifying of the URLStreamHandler (perhaps indirectly through a factory) and establish a code dependency.
I think that it's also reasonable to not have these protocols discoverable through the URLHandlerService - but perhaps not practical for compatibility reasons.
So, what I'm getting at is you really should be able to run Equinox without the URLHandlerService without creating any new dependencies that are not already implicit.
URL creation might be a little less convenient for built-in URL types but nothing an InternalFactory can't fix.
For external URLs exposed by the URLHandlerService you can use the Services directly to create URLs without requiring the singleton sets.
Using internal URLs in this fashion also has the added benefit of being able to selectively control who can create certain types of URLs without having to resort to Access Control checks.
... I'm just saying this because I think that an internal URL based approach is workable. The caveat is that the URL <--> String representation is not symmetric.
So with that said, (and a little reworking of what I had before)
The approaches I see are:
1) Internal URL creation approach
- does not require the singletons sets, but as a result URL <--> String representation is not symmetric
- requires no new API (maybe something for convenience)
- requires exposing "reference" URLHandler
- requires code changes for existing plug-ins that create internal URL types directly from String[s]
- URL <--> String representation is not symmetric
2) URLHandlerService support through a URLFactory
- does not require the singletons sets, but as a result URL <--> String representation is not symmetric
- requires a new approach for creating URLs - e.g. all URLs created with URLFactory.createURL(...) - easy to map and suitable for byte-code weaving
A (Code Time)
- requires code changes for existing plug-ins that create URLs directly from String[s] - [Current approach]
B (Load Time)
- requires a run time byte-weaving tool (ASM is probably as good as it gets - 33K) to substitute URLFactory.createURL(...)  for URL construction
- Class parse time is approx. 60% slower
- requires work in EclipseClassLoader to support transform
C (Build Time)
- requires a build time byte-weaving tool to substitute URLFactory.createURL(...)  for URL construction
- Net result of A but existing code can continue creating URLs normally.
- Requires build support
D (Deploy Time)
- requires System Bundle pre-built with URLFactory support
- Might be very complex with jar verifiers - at the very least double up bundles on disk (e.g. original + transformed)
3) URLStreamHandlerFactory wrap
- possible Security concerns
- requires per VM work
- requires a multiplexing URLStreamHandlerFactory for multiple instances.
After writing out this list I have to admit approach 3 really looks pretty good so long as it works.
The trade-offs seem bearable. If it works (and is palatable) the approach might be usable for other similar problems as Tom states.

That being said I think the other approaches with the possible exception of 2D (deploy-time) are also workable.
       This message may contain privileged and/or confidential information.  If you have received this e-mail in error or are not the intended recipient, you may not use, copy, disseminate or distribute it; do not open any attachments, delete it immediately from your system and notify the sender promptly by e-mail that you have done so.  Thank you.