URLクラスのsetrURLStreamHandlerFactoryが複数のfactoryをサポートする方法
以前、hadoopのurlをサポートする必要があるという問題がありましたが、javaのURLクラスのsetrURLStreamHandlerFactoryメソッドはfactoryを1つしかセットできません.
サポートできるようにネットで検索してみました(https://stackoverflow.com/questions/41696088/register-custom-urlstreamhandler-in-spring-web-application-tomcat)を使用して、既存のfactoryをnullに設定し、新しいurlタイプと互換性のある新しいfactoryを装飾モードで設定できます.例は次のとおりです.
public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
synchronized (streamHandlerLock) {
if (factory != null) {
throw new Error("factory already defined");
}
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSetFactory();
}
handlers.clear();
factory = fac;
}
}
サポートできるようにネットで検索してみました(https://stackoverflow.com/questions/41696088/register-custom-urlstreamhandler-in-spring-web-application-tomcat)を使用して、既存のfactoryをnullに設定し、新しいurlタイプと互換性のある新しいfactoryを装飾モードで設定できます.例は次のとおりです.
/**
* factory, , factory hdfs factory ,
*
* @param fsUrlStreamHandlerFactory
* @throws Exception
*/
private static void registerFactory(final FsUrlStreamHandlerFactory fsUrlStreamHandlerFactory)
throws Exception {
log.info("registerFactory : " + fsUrlStreamHandlerFactory.getClass().getName());
final Field factoryField = URL.class.getDeclaredField("factory");
factoryField.setAccessible(true);
final Field lockField = URL.class.getDeclaredField("streamHandlerLock");
lockField.setAccessible(true);
// use same lock as in java.net.URL.setURLStreamHandlerFactory
synchronized (lockField.get(null)) {
final URLStreamHandlerFactory originalUrlStreamHandlerFactory = (URLStreamHandlerFactory) factoryField.get(null);
// Reset the value to prevent Error due to a factory already defined
factoryField.set(null, null);
URL.setURLStreamHandlerFactory(protocol -> {
if (protocol.equals("hdfs")) {
return fsUrlStreamHandlerFactory.createURLStreamHandler(protocol);
} else {
return originalUrlStreamHandlerFactory.createURLStreamHandler(protocol);
}
});
}
}