Reputation: 630
I have a sbt-web project with some webjar and common jar dependencies. I want to get resource file from one of my jar dependency and use it in concatenation task. But I don't know how refer to the resource inside dependent jar in my build.sbt.
Upvotes: 4
Views: 2882
Reputation: 2847
The other answers didn't work for me, I think because they're on older versions of SBT. I've been banging my head against this for a while but I finally got something to work. Here's the full script that will do this resource copying before an arbitrary Compile task (mine is guardrail
) on SBT v1.5.5:
lazy val myDep = "my-dep-project"
lazy val myFilename = "someDir/myFile.yaml"
val copyResourcesFromJars =
TaskKey[Unit]("copyResourcesFromJars", "Copy specific resources to be used by this project")
copyResourcesFromJars := {
def copyResourceFromJar(classpathEntry: Attributed[File], jarName: String, resourceName: String): Unit = {
classpathEntry.get(artifact.key) match {
case Some(entryArtifact) =>
// searching artifact
if (entryArtifact.name.startsWith(jarName)) {
// unpack artifact's jar to tmp directory
val jarFile = classpathEntry.data
IO.withTemporaryDirectory { tmpDir =>
IO.unzip(jarFile, tmpDir)
// copy to project's target directory
// Instead of copying you can do any other stuff here
IO.copyFile(
tmpDir / resourceName,
baseDirectory.value / s"target/$resourceName"
)
}
}
case _ =>
}
}
(Compile / dependencyClasspath).value.foreach(entry =>
copyResourceFromJar(entry, myDep, myFilename)
)
}
Compile / guardrail := (Compile / guardrail dependsOn copyResourcesFromJars).value
(project in file(".")).settings(
...
Compile / guardrailTasks := List(
ScalaServer(
baseDirectory.value / s"target/$myFilename",
pkg = "my.pkg.guardrail"
)
)
)
Upvotes: 1
Reputation: 630
I finally find the solution with this docs. The main idea is to find the right jar in the classpath dependencies, unzip it to temprorary folder and do what you need with this files. In my case I copy it to my target directory and use it in concatenation task.
I end up with this code:
def copyResourceFromJar(classpathEntry: Attributed[File], jarName: String, resourceName: String) = {
classpathEntry.get(artifact.key) match {
case Some(entryArtifact) => {
// searching artifact
if (entryArtifact.name.startsWith(jarName)) {
// unpack artifact's jar to tmp directory
val jarFile = classpathEntry.data
IO.withTemporaryDirectory { tmpDir =>
IO.unzip(jarFile, tmpDir)
// copy to project's target directory
// Instead of copying you can do any other stuff here
IO.copyFile(
tmpDir / resourceName,
(WebKeys.webJarsDirectory in Assets).value / resourceName
)
}
}
}
case _ =>
}
}
for(entry <- (dependencyClasspath in Compile).value) yield {
copyResourceFromJar(entry, "firstJar", "firstFile.js")
copyResourceFromJar(entry, "secondJar", "some/path/secondFile.js")
}
This code should be placed in the task. For example:
val copyResourcesFromJar = TaskKey[Unit]("copyResourcesFromJar", "Copy resources from jar dependencies")
copyResourcesFromJar := {
//your task code here
}
copyResourcesFromJar <<= copyResourcesFromJar dependsOn (dependencyClasspath in Compile)
And don't forget to add this task as dependcy to your build task. In my case it looks like this:
concat <<= concat dependsOn copyResourcesFromJar
Upvotes: 9
Reputation: 10894
Normally getResourceAsStream works:
getClass.getResourceAsStream("/path/to/resource/in/jar")
It is important to read the resource as a Stream getClass.getResource will not work.
Upvotes: 0