diff --git a/cache/src/main/scala/coursier/Cache.scala b/cache/src/main/scala/coursier/Cache.scala index 90e815fc4..d733f2486 100644 --- a/cache/src/main/scala/coursier/Cache.scala +++ b/cache/src/main/scala/coursier/Cache.scala @@ -1,7 +1,7 @@ package coursier import java.math.BigInteger -import java.net.{ HttpURLConnection, URL, URLConnection, URLStreamHandler } +import java.net.{ HttpURLConnection, URL, URLConnection, URLStreamHandler, URLStreamHandlerFactory } import java.nio.channels.{ OverlappingFileLockException, FileLock } import java.nio.file.{ StandardCopyOption, Files => NioFiles } import java.security.MessageDigest @@ -243,21 +243,24 @@ object Cache { Option(handlerClsCache.get(protocol)) match { case None => val clsName = s"coursier.cache.protocol.${protocol.capitalize}Handler" - val clsOpt = - try Some(Thread.currentThread().getContextClassLoader.loadClass(clsName)) + def clsOpt(loader: ClassLoader) = + try Some(loader.loadClass(clsName)) catch { case _: ClassNotFoundException => None } + val clsOpt0 = clsOpt(Thread.currentThread().getContextClassLoader) + .orElse(clsOpt(getClass.getClassLoader)) + def printError(e: Exception): Unit = scala.Console.err.println( s"Cannot instantiate $clsName: $e${Option(e.getMessage).fold("")(" ("+_+")")}" ) - val handlerOpt = clsOpt.flatMap { + val handlerFactoryOpt = clsOpt0.flatMap { cls => - try Some(cls.newInstance().asInstanceOf[URLStreamHandler]) + try Some(cls.newInstance().asInstanceOf[URLStreamHandlerFactory]) catch { case e: InstantiationException => printError(e) @@ -271,6 +274,18 @@ object Cache { } } + val handlerOpt = handlerFactoryOpt.flatMap { + factory => + try Some(factory.createURLStreamHandler(protocol)) + catch { + case NonFatal(e) => + scala.Console.err.println( + s"Cannot get handler for $protocol from $clsName: $e${Option(e.getMessage).fold("")(" ("+_+")")}" + ) + None + } + } + val prevOpt = Option(handlerClsCache.putIfAbsent(protocol, handlerOpt)) prevOpt.getOrElse(handlerOpt) diff --git a/tests/jvm/src/test/scala/coursier/cache/protocol/TestprotocolHandler.scala b/tests/jvm/src/test/scala/coursier/cache/protocol/TestprotocolHandler.scala index 7f5094dfc..a9f667f96 100644 --- a/tests/jvm/src/test/scala/coursier/cache/protocol/TestprotocolHandler.scala +++ b/tests/jvm/src/test/scala/coursier/cache/protocol/TestprotocolHandler.scala @@ -1,19 +1,22 @@ package coursier.cache.protocol -import java.net.{ URL, URLConnection, URLStreamHandler } +import java.net.{ URL, URLConnection, URLStreamHandler, URLStreamHandlerFactory } -class TestprotocolHandler extends URLStreamHandler { - protected def openConnection(url: URL): URLConnection = { - val resPath = "/test-repo/http/abc.com" + url.getPath - val resURLOpt = Option(getClass.getResource(resPath)) +class TestprotocolHandler extends URLStreamHandlerFactory { - resURLOpt match { - case None => - new URLConnection(url) { - def connect() = throw new NoSuchElementException(s"Resource $resPath") - } - case Some(resURL) => - resURL.openConnection() + def createURLStreamHandler(protocol: String): URLStreamHandler = new URLStreamHandler { + protected def openConnection(url: URL): URLConnection = { + val resPath = "/test-repo/http/abc.com" + url.getPath + val resURLOpt = Option(getClass.getResource(resPath)) + + resURLOpt match { + case None => + new URLConnection(url) { + def connect() = throw new NoSuchElementException(s"Resource $resPath") + } + case Some(resURL) => + resURL.openConnection() + } } } }