This is a URL handler I needed for my javafx application in order to allow WebView (WebEngine) find my classpath resources and use relative resources for images, scripts, etc. If you only use WebEngine.loadContent, you cannot use relative resources and your web pages become much less flexible when changing later.
/**
* Handler factory different types of URL handling.
*/
class ConfigurableStreamHandlerFactory extends URLStreamHandlerFactory {
private var handlers = Map[String, URLStreamHandler]()
/**
* Add an instance as a handler.
*/
def addHandler(protocol: String, handler: URLStreamHandler): Unit = {
handlers = handlers + (protocol -> handler)
}
/**
* Add a closure as a handler.
*/
def addHandler(protocol: String, handler: URL => URLConnection): Unit = {
addHandler(protocol, new URLStreamHandler() {
def openConnection(url: URL): URLConnection = {
handler(url)
}
})
}
override def createURLStreamHandler(protocol: String): URLStreamHandler =
handlers.get(protocol).getOrElse(null)
}
/**
* This can only be set once in an application. To use this factory in your
* application you must initialize like below:
* {{{
* URL.setHandlerFactory(ConfigurableStreamHandlerFactory)
* }}}
* The application should register handlers using this singleton object.
*/
object ConfigurableStreamHandlerFactory extends ConfigurableStreamHandlerFactory
/**
* Bucket of functions to create some URL handlers.
*/
object URLProtocolHandlers {
/**
* Create a URL protocol handler based on a classloader. Make sure
* you watch your class loader and thread use!
*/
def handlerForClasspath(classLoader: ClassLoader = Thread.currentThread().getContextClassLoader()) =
(url: URL) => {
val path = url.getPath
classLoader.getResource(if (path.length ==0)
""
else if(path(0) == '/')
path.drop(1)
else
path) match {
case x: URL => x.openConnection()
case _ =>
null
}
}
}