Hi Bernd,

On 02/01/2015 01:14 AM, Bernd wrote:

Hello,

What about simply rejecting overlapping programmatic registrations,


This can't work by registering URLStreamHandlerFactory objects as they don't announce their supported protocols. Perhaps registering URLStreamHandler objects directly would be an option as in:

public static void setURLStreamHandler(String protocol, URLStreamHandler urlStreamHandler) throws IllegalStateException

But this per-protocol registration (or any programmatic registration that overrides previous defaults) has a drawback that you can end up with URL instances for the same protocol but different URLStreamHandler, depending on when they are constructed, so it can happen that URL("http://www.google.com/";) is not equal to URL("http://www.google.com/";). Sometimes you actually want that (see Alan's note about loading a "jar" URLStreamHandler deployed in a jar file), but otherwise it gives you a very fragile system that depends on initialization order. Programmatic registration should be reserved for the master of the universe (to be performed before the universe is born). Otherwise, special protocol handlers are better registered declaratively.

and for the service loader using the natural order (class loader search order). I guess most extensions register new schemes only, as it was not easy before in such a central shared system component. an ordering api might not really help. Its might be better to allow specific versions like a factory or even something thread local? (Similar to jndi enc)


If you want to have multiple universes in the same VM where each has it's own view of per-protocol URLStreamHandlers, then you must ensure that URL instances constructed in each universe, don't come in contact with each other or you will be subjected to similar issues as when two Class objects with same class name are not equal to each other, because each is loaded by different ClassLoader.

Regards, Peter

Bernd

Am 01.02.2015 00:48 schrieb "Peter Levart" <peter.lev...@gmail.com <mailto:peter.lev...@gmail.com>>:

    Hi Alan,

    On 01/31/2015 10:33 PM, Alan Bateman wrote:
    On 31/01/2015 19:42, Peter Levart wrote:
    Hi Chris,

    I looked at your solution to make URLStreamHandlerFactory
    interface a service provider using ServiceLoader API and in
    addition adding new URL static method to programmaticaly
    register URLStreamHandlerFactories. There are a couple of issues
    with your approach I'd like to discuss.

    The programmatic approach using static URL method does give you
    some means of order in which registered
    URLStreamHandlerFactories are tried to create URLStreamHandler
    for particular protocol - the registration order. It means that
    this method should only be called by one "party" in the VM or
    else it is hard to control the order of registration.

    ServiceLoader is a declarative approach, but does not give you
    order by default. Also, your ServiceLoader approach gives a way
    for URLStreamHandlerFactories to register in the system without
    security checks. If a particular
    META-INF/services/java.net.URLStreamHandlerFactory is found,
    it's content is used to load a class and instantiate a factory
    which is used in URL constructors then. Previously, one had to
    have a "setFactory" permission to set the
    URLStreamHandlerFactory or appropriate PropertyPermission for
    seting the package prefix property. This can be fixed.

    :

    Anyway, I think there is an alternative to programmatic
    registration approach of URLStreamHandlerFactories. Using just
    ServiceLoader and a new default method on
    URLStreamHandlerFactory interface to provide order. Here's what
    I'm thinking about:

    
http://cr.openjdk.java.net/~plevart/jdk9-dev/URLStreamHandlerFactory/webrev.01/
    
<http://cr.openjdk.java.net/%7Eplevart/jdk9-dev/URLStreamHandlerFactory/webrev.01/>

    I don't think we should we expose ordering values in
    URLStreamHandlerFactory, it looks a bit odd and not clear how an
    implementation can choose a useful value. There is a general
    issue that ServiceLoader doesn't currently support a means to
    order service providers but I think we can re-examine that when
    we move to modules and and linking. That is, have a consistent
    way to configure ordering that we can use everywhere that
    ServiceLoader is used rather than doing one-off solutions.

    I agree. Putting the order on the SPI API is not the right
    solution. The order should be configured in one place. But there
    needs to be some kind of handle each service exposes for order
    configuration to reference. So one idea how to extend the
    ServiceLoader mechanism is this:

    create a special class-scope runtime annotation...

    public @interface ServiceProvider {
            String name();
    }

    ...with which service implementation classes can optionally be
    annotated. This could enable ServiceLoader API extension like:

        public static <S> ServiceLoader<S> load(Class<S> service,
    String serviceProviderName)

    that would return an Iterable over implementations that are
    annotated with a particular @ServiceProvider(name = ...)
    annotation (similar to security Providers but simpler).

    In addition one could specify a system property with the key being
    prefixed by service interface FQ class name, like:

    
java.net.URLStreamHandlerFactory.serviceLoaderOrder=providerName1,providerName2,providerName3,...




    The other thing is that it's not clear how this would work for a
    factory for the jar protocol that is itself deployed in a JAR
    file on the class path. This is important for containers that
    want to do their own caching and they want their jar protocol
    handler configured system-wide before starting any applications.
    It's also part of the motive for the addURLStreamHandlerFactory
    in the original proposal.

    I see. But isn't URL.setURLStreamHandlerFactory() enough for that
    purpose? It can only be set once, but there can only be *one*
    container that wants it's jar protocol handler configured system-wide.

    Regards, Peter


    I think you have good point with the setFactory permission, that
    does need to be looked at.

    -Alan.


Reply via email to