-
-
Save colestanfield/fac042d3108b0c06e952 to your computer and use it in GitHub Desktop.
// Create a new MergeStrategy for aop.xml files | |
val aopMerge: MergeStrategy = new MergeStrategy { | |
val name = "aopMerge" | |
import scala.xml._ | |
import scala.xml.dtd._ | |
def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]] = { | |
val dt = DocType("aspectj", PublicID("-//AspectJ//DTD//EN", "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"), Nil) | |
val file = MergeStrategy.createMergeTarget(tempDir, path) | |
val xmls: Seq[Elem] = files.map(XML.loadFile) | |
val aspectsChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "aspects" \ "_") | |
val weaverChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "weaver" \ "_") | |
val options: String = xmls.map(x => (x \\ "aspectj" \ "weaver" \ "@options").text).mkString(" ").trim | |
val weaverAttr = if (options.isEmpty) Null else new UnprefixedAttribute("options", options, Null) | |
val aspects = new Elem(null, "aspects", Null, TopScope, false, aspectsChildren: _*) | |
val weaver = new Elem(null, "weaver", weaverAttr, TopScope, false, weaverChildren: _*) | |
val aspectj = new Elem(null, "aspectj", Null, TopScope, false, aspects, weaver) | |
XML.save(file.toString, aspectj, "UTF-8", xmlDecl = false, dt) | |
IO.append(file, IO.Newline.getBytes(IO.defaultCharset)) | |
Right(Seq(file -> path)) | |
} | |
} | |
// Use defaultMergeStrategy with a case for aop.xml | |
// I like this better than the inline version mentioned in assembly's README | |
val customMergeStrategy: String => MergeStrategy = { | |
case PathList("META-INF", "aop.xml") => | |
aopMerge | |
case s => | |
defaultMergeStrategy(s) | |
} | |
// Use the customMergeStrategy in your settings | |
mergeStrategy in assembly := customMergeStrategy |
I tried to add this to my 'project/assembly.sbt' file, which only contained the line below:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
I also deleted the blank line after "import scala.xml.dtd._".
But when I try to load sbt it says:
error: not found: type MergeStrategy
Thanks, very nice!
@tuler - import sbtassembly.MergeStrategy at the top of your assembly.sbt file.
Tried this and when running the app it could not find aspectj-weaver...
It seems like your application was not started with the -javaagent:/path-to-aspectj-weaver.jar option but Kamon detected the following modules which require AspectJ to work properly:
kamon-akka, kamon-spray, kamon-scala
If you need help on setting up the aspectj weaver go to http://kamon.io/introduction/get-started/ for more info. On the other hand, if you are sure that you do not need or do not want to use the weaver then you can disable this error message by changing the kamon.show-aspectj-missing-warning setting in your configuration file.
I tried downloading the jar separately and pointing my java command at it, but to no avail. Anyone know anything about this?
Thank you @colestanfield. I had a
case "META-INF/aop.xml" => MergeStrategy.first
and it wouldn't work. Your aopMerge strategy works just fine!
Thanks @colestanfield... this works great! I would modify the first line to
val aopMerge = new sbtassembly.MergeStrategy {
so folks don't need to import MergeStrategy.
ok first of all: major kudos to @colestanfield! 'found this thread because i ran into the same issue with aop.xml with Kamon libraries ...this is probably a stupid question: i copied the defaultMergeStrategy
from the sbt-assembly README file because of missing reference to this function error...am i supposed to do that or am i supposed to add some import?
I wasn't too thrilled about putting this code in build.sbt
...you can't add this to any .sbt file under project
folder because sbt
don't allow imports (at least for the current 0.13.11 version)...also, with the autoPlugins support...having a separate .sbt file (except for specific plugins that don't support autoplugin trait) is actually discouraged (i.e. you add sbt-assembly
plugin in the plugins.sbt
).
anyway, so i created a project/AssemblyMergeStrategies.scala
and import that in the build.sbt
file so i can use the assemblyMergeStrategy in assembly := customMergeStrategy
line
BTW mergeStrategy
is already deprecated; use assemblyMergeStrategy
instead
It worked .. thanks @colestanfield for nice finding
I've tried using this snippet and for some reason sbt assembly
suspends while trying to read an XML file from a directory target/streams/$global
making us unable to use that - does anyone knows what may be causing this to try and read this directory or why is it created?
Hello @colestanfield
I notice that with sbt 1.4.9
this cause some problem
The error message during the build is
org.xml.sax.SAXParseExceptionpublicId: -//AspectJ//DTD//EN; systemId: http://www.eclipse.org/aspectj/dtd/aspectj.dtd; lineNumber: 1; columnNumber: 2; The markup declarations contained or pointed to by the document type declaration must be well-formed.
With sbt 1.10.11 and sbt-assembly 2.3.1 this can be
lazy val aopMerge = CustomMergeStrategy("aopMerge") { (conflicts: Vector[Dependency]) =>
import scala.xml.*
import scala.xml.dtd.*
val parser = {
val factory = javax.xml.parsers.SAXParserFactory.newInstance
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
factory.newSAXParser
}
val xmls: Seq[Elem] = conflicts.map { conflict =>
Using.resource((dependency: Dependency) => dependency.stream())(conflict) { is: InputStream =>
XML.loadXML(Source.fromInputStream(is), parser)
// XML.load(is)
}
}
val dt = DocType("aspectj", PublicID("-//AspectJ//DTD//EN", "https://www.eclipse.org/aspectj/dtd/aspectj.dtd"), Nil)
val aspectsChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "aspects" \ "_")
val weaverChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "weaver" \ "_")
val options: String = xmls.map(x => (x \\ "aspectj" \ "weaver" \ "@options").text).mkString(" ").trim
val weaverAttr = if (options.isEmpty) Null else new UnprefixedAttribute("options", options, Null)
val aspects = new Elem(null, "aspects", Null, TopScope, false, aspectsChildren: _*)
val weaver = new Elem(null, "weaver", weaverAttr, TopScope, false, weaverChildren: _*)
val aspectj = new Elem(null, "aspectj", Null, TopScope, false, aspects, weaver)
val bytes = scala.util.Using.resource(new CharArrayWriter()) { writer =>
XML.write(writer, aspectj, "UTF-8", xmlDecl = false, dt)
(writer.toString + IO.Newline).getBytes(IO.defaultCharset)
}
Right(Vector(JarEntry(conflicts.head.target, () => new java.io.ByteArrayInputStream(bytes))))
}
This is very helpful for people trying to get Kamon (or anything with multiple aop.xml) working with sbt-assembly. Thanks!