Skip to content

Instantly share code, notes, and snippets.

@colestanfield
Created August 8, 2014 22:55
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save colestanfield/fac042d3108b0c06e952 to your computer and use it in GitHub Desktop.
Save colestanfield/fac042d3108b0c06e952 to your computer and use it in GitHub Desktop.
sbt-assembly merge strategy for aop.xml files
// 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
@wulftone
Copy link

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?

@arlequin-nyc
Copy link

Thank you @colestanfield. I had a

case "META-INF/aop.xml"                                            => MergeStrategy.first

and it wouldn't work. Your aopMerge strategy works just fine!

@velvia
Copy link

velvia commented Jun 23, 2016

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.

@dalegaspi
Copy link

dalegaspi commented Jun 25, 2016

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

@asethia
Copy link

asethia commented Sep 13, 2016

It worked .. thanks @colestanfield for nice finding

@gidgid
Copy link

gidgid commented Jul 10, 2017

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?

@paoloSrc
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment