summaryrefslogtreecommitdiff
path: root/project/JarJar.scala
diff options
context:
space:
mode:
Diffstat (limited to 'project/JarJar.scala')
-rw-r--r--project/JarJar.scala83
1 files changed, 83 insertions, 0 deletions
diff --git a/project/JarJar.scala b/project/JarJar.scala
new file mode 100644
index 0000000000..64281f23c1
--- /dev/null
+++ b/project/JarJar.scala
@@ -0,0 +1,83 @@
+import org.pantsbuild.jarjar
+import org.pantsbuild.jarjar._
+import org.pantsbuild.jarjar.util._
+import scala.collection.JavaConverters._
+import java.util.jar._
+import java.io._
+import sbt._
+
+object JarJar {
+ sealed abstract class JarJarConfig {
+ def toPatternElement: PatternElement
+ }
+ object JarJarConfig {
+ case class Rule(pattern: String, result: String) extends JarJarConfig {
+ def toPatternElement: PatternElement = {
+ val rule = new jarjar.Rule
+ rule.setPattern(pattern)
+ rule.setResult(result)
+ rule
+ }
+ }
+ case class Keep(pattern: String) extends JarJarConfig {
+ def toPatternElement: PatternElement = {
+ val keep = new jarjar.Keep
+ keep.setPattern(pattern)
+ keep
+ }
+ }
+ }
+
+ sealed abstract class Entry {
+ def name: String
+ def time: Long
+ def data: Array[Byte]
+ }
+
+ case class JarEntryInput(jarFile: JarFile, entry: JarEntry) extends Entry {
+ def name = entry.getName
+ def time = entry.getTime
+ def data = sbt.IO.readBytes(jarFile.getInputStream(entry))
+ }
+ case class FileInput(base: File, file: File) extends Entry {
+ def name = file.relativeTo(base).get.getPath
+ def time = file.lastModified
+ def data = sbt.IO.readBytes(file)
+ }
+
+ private def newMainProcessor(patterns: java.util.List[PatternElement], verbose: Boolean, skipManifest: Boolean): JarProcessor = {
+ val cls = Class.forName("org.pantsbuild.jarjar.MainProcessor")
+ val constructor = cls.getConstructor(classOf[java.util.List[_]], java.lang.Boolean.TYPE, java.lang.Boolean.TYPE)
+ constructor.setAccessible(true)
+ constructor.newInstance(patterns, Boolean.box(verbose), Boolean.box(skipManifest)).asInstanceOf[JarProcessor]
+ }
+
+ def apply(in: Iterator[Entry], outdir: File,
+ config: Seq[JarJarConfig], verbose: Boolean = false): Seq[File] = {
+ val patterns = config.map(_.toPatternElement).asJava
+ val processor: JarProcessor = newMainProcessor(patterns, verbose, false)
+ def process(e: Entry): Option[File] = {
+ val struct = new EntryStruct()
+ struct.name = e.name
+ struct.time = e.time
+ struct.data = e.data
+ if (processor.process(struct)) {
+ if (struct.name.endsWith("/")) None
+ else {
+ val f = outdir / struct.name
+ try {
+ f.getParentFile.mkdirs()
+ sbt.IO.write(f, struct.data)
+ } catch {
+ case ex: Exception =>
+ throw new IOException(s"Failed to write ${e.name} / ${f.getParentFile} / ${f.getParentFile.exists}", ex)
+ }
+ Some(f)
+ }
+ }
+ else None
+ }
+ in.flatMap(entry => process(entry)).toList
+
+ }
+}