简体   繁体   中英

Is it a good idea to replace java.net.URL URLStreamHandlerFactory using reflection?

In Java we can register a custom protocol handler in at least two ways:

  1. by setting system property 'java.protocol.handler.pkgs'
  2. using URL.setURLStreamHandlerFactory

For more details please check http://accu.org/index.php/journals/1434

I can not go with the first option, as i would have to add a lot of jar files to the server (tomcat) classpath, to make the handler implementaion visible for bootstrap classloader. Moreover some initialization is needed, which has to be done in an application context.

The problem with the second option is that the Factory can be registered only once (check java.net.URL#setURLStreamHandlerFactory), and unfortunately it is done by Tomcat.

What i can do is to create a decorator factory which will extend the existing one by my protocol handler. Than using relfection set the static field URL#factory to null and register (again?) my "decoratorFactory" in a standard way using URL#setURLStreamHandlerFactory. I'm just wondering if it is a good idea to use the reflection here...? How about the security?

I would like to do something like that:

try {
        Field factoryField = URL.class.getDeclaredField("factory");
        factoryField.setAccessible(true);
        //  get current factory
        Object currentFactory = factoryField.get(null);
        //  define a decorator factory
        MyFactoryDecorator mfd = new MyFactoryDecorator(currentFactory);
        //  set the factory to null and register MyFactoryDecorator using URL#setURLStreamHandlerFactory.
        factoryField.set(null, null);
        URL.setURLStreamHandlerFactory(mfd);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

Idk if this would work, but what if you create a new URLStreamHandlerFactory that doesn't actually contain the implementation? It just sits there and then instantiates the real implementation at runtime when it is called via an app context lookup. Then in theory you can instantiate this new proxy handler via the system property at the beginning, but also use the one you want when it is actually called.

UPDATE:

Actually, I think your link above mentions this strategy:

Another approach is to use the factory registration, but to provide a factory class that itself supports registration of multiple different stream handlers using different names.

This approach supports code using the java.net.URL class but it does require a registration call for each protocol and so hence changes are needed to an application before it can make use of the new URLs. However the approach gets around the problems discussed above with multiple class loaders since the factory is loaded by the user code class loader rather than by the class loader for the URL class.

I'm not super familiar with what all you're doing and how the registration works, so this could be more or less complicated depending on what you're doing. Idk if you even need the extra registration or not, but it sounds like it might solve the .jar/app context problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM