Skip to content

Commit

Permalink
fix: improve workaround for Scala3 bug 18248 (#1349)
Browse files Browse the repository at this point in the history
Towards #325
  • Loading branch information
raboof authored Jun 4, 2024
1 parent 92b38e7 commit 6721173
Showing 1 changed file with 30 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,44 +38,43 @@ private[pekko] trait ExtensionsImpl extends Extensions { self: ActorSystem[_] wi
* Hook for ActorSystem to load extensions on startup
*/
def loadExtensions(): Unit = {
loadExtensionsFor("pekko.actor.typed.library-extensions", throwOnLoadFail = true)
loadExtensionsFor("pekko.actor.typed.extensions", throwOnLoadFail = false)
}

/*
* @param throwOnLoadFail Throw exception when an extension fails to load (needed for backwards compatibility)
*/
def loadExtensionsFor(key: String, throwOnLoadFail: Boolean): Unit = {

settings.config.getStringList(key).asScala.foreach { extensionIdFQCN =>
// it is either a Scala object or it is a Java class with a static singleton accessor
val idTry = dynamicAccess.getObjectFor[AnyRef](extensionIdFQCN).recoverWith {
case _ => idFromJavaSingletonAccessor(extensionIdFQCN)
}
/*
* @param throwOnLoadFail Throw exception when an extension fails to load (needed for backwards compatibility)
*/
private def loadExtensionsFor(key: String, throwOnLoadFail: Boolean): Unit = {

idTry match {
case Success(id: ExtensionId[_]) => registerExtension(id)
case Success(_) =>
if (!throwOnLoadFail) log.error("[{}] is not an 'ExtensionId', skipping...", extensionIdFQCN)
else throw new RuntimeException(s"[$extensionIdFQCN] is not an 'ExtensionId'")
case Failure(problem) =>
if (!throwOnLoadFail)
log.error(s"While trying to load extension $extensionIdFQCN, skipping...", problem)
else throw new RuntimeException(s"While trying to load extension [$extensionIdFQCN]", problem)
}
settings.config.getStringList(key).asScala.foreach { extensionIdFQCN =>
// it is either a Scala object or it is a Java class with a static singleton accessor
val idTry = dynamicAccess.getObjectFor[AnyRef](extensionIdFQCN).recoverWith {
case _ => idFromJavaSingletonAccessor(extensionIdFQCN)
}
}

def idFromJavaSingletonAccessor(extensionIdFQCN: String): Try[ExtensionId[Extension]] =
dynamicAccess.getClassFor[ExtensionId[Extension]](extensionIdFQCN).flatMap[ExtensionId[Extension]] {
(clazz: Class[_]) =>
Try {
val singletonAccessor = clazz.getDeclaredMethod("getInstance")
singletonAccessor.invoke(null).asInstanceOf[ExtensionId[Extension]]
}
idTry match {
case Success(id: ExtensionId[_]) => registerExtension(id)
case Success(_) =>
if (!throwOnLoadFail) log.error("[{}] is not an 'ExtensionId', skipping...", extensionIdFQCN)
else throw new RuntimeException(s"[$extensionIdFQCN] is not an 'ExtensionId'")
case Failure(problem) =>
if (!throwOnLoadFail)
log.error(s"While trying to load extension $extensionIdFQCN, skipping...", problem)
else throw new RuntimeException(s"While trying to load extension [$extensionIdFQCN]", problem)
}

loadExtensionsFor("pekko.actor.typed.library-extensions", throwOnLoadFail = true)
loadExtensionsFor("pekko.actor.typed.extensions", throwOnLoadFail = false)
}
}

private def idFromJavaSingletonAccessor(extensionIdFQCN: String): Try[ExtensionId[Extension]] =
dynamicAccess.getClassFor[ExtensionId[Extension]](extensionIdFQCN).flatMap[ExtensionId[Extension]] {
(clazz: Class[_]) =>
Try {
val singletonAccessor = clazz.getDeclaredMethod("getInstance")
singletonAccessor.invoke(null).asInstanceOf[ExtensionId[Extension]]
}
}

final override def hasExtension(ext: ExtensionId[_ <: Extension]): Boolean = findExtension(ext) != null

final override def extension[T <: Extension](ext: ExtensionId[T]): T = findExtension(ext) match {
Expand Down

0 comments on commit 6721173

Please sign in to comment.