Use jarjar library from pants (WIP) (#102)

Seems more maintained than https://github.com/shevek/jarjar
This commit is contained in:
Alexandre Archambault 2019-07-12 10:03:59 +02:00 committed by GitHub
parent 759d0bff9a
commit 0400b537f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 127 additions and 24 deletions

View File

@ -133,19 +133,13 @@ lazy val `sbt-pgp-coursier` = project
lazy val `sbt-shading` = project
.in(file("modules/sbt-shading"))
.enablePlugins(ScriptedPlugin, ShadingPlugin)
.enablePlugins(ScriptedPlugin)
.dependsOn(`sbt-coursier`)
.settings(
plugin,
shading,
libraryDependencies += "io.get-coursier.jarjar" % "jarjar-core" % "1.0.1-coursier-1" % "shaded",
// dependencies of jarjar-core - directly depending on these so that they don't get shaded
libraryDependencies ++= Seq(
"com.google.code.findbugs" % "jsr305" % "3.0.2",
"org.ow2.asm" % "asm-commons" % "7.0",
"org.ow2.asm" % "asm-util" % "7.0",
"org.slf4j" % "slf4j-api" % "1.7.26"
),
libraryDependencies += ("org.pantsbuild" % "jarjar" % "1.7.2")
.exclude("org.apache.maven", "maven-plugin-api")
.exclude("org.apache.ant", "ant"),
scriptedDependencies := {
scriptedDependencies.value
// TODO Get dependency projects automatically

View File

@ -0,0 +1,74 @@
package org.pantsbuild.jarjar.util;
// adapted from https://github.com/pantsbuild/jarjar/blob/57845dc73d3e2c9b916ae4a788cfa12114fd7df1/src/main/java/org/pantsbuild/jarjar/util/StandaloneJarProcessor.java
// - made it accepted a List<File> rather than a single File
// - added argument ignoreDuplicateEntries
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.Enumeration;
import java.io.*;
import java.util.*;
public class CoursierJarProcessor
{
public static void run(File[] from, File to, JarProcessor proc, boolean ignoreDuplicateEntries) throws IOException {
byte[] buf = new byte[0x2000];
final File tmpTo = File.createTempFile("jarjar", ".jar");
Set<String> entries = new HashSet<>();
FileOutputStream fos = null;
JarOutputStream out = null;
try {
fos = new FileOutputStream(tmpTo);
BufferedOutputStream buffered = new BufferedOutputStream(fos);
out = new JarOutputStream(buffered);
for (File from0 : from) {
JarFile in = null;
try {
in = new JarFile(from0);
Enumeration<JarEntry> e = in.entries();
while (e.hasMoreElements()) {
EntryStruct struct = new EntryStruct();
JarEntry entry = e.nextElement();
struct.name = entry.getName();
struct.time = entry.getTime();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IoUtil.pipe(in.getInputStream(entry), baos, buf);
struct.data = baos.toByteArray();
if (proc.process(struct)) {
if (entries.add(struct.name)) {
entry = new JarEntry(struct.name);
entry.setTime(struct.time);
entry.setCompressedSize(-1);
out.putNextEntry(entry);
out.write(struct.data);
} else if (struct.name.endsWith("/")) {
// TODO(chrisn): log
} else if (!ignoreDuplicateEntries) {
throw new DuplicateJarEntryException(from0.getAbsolutePath(), struct.name);
}
}
}
} finally {
if (in != null)
in.close();
}
}
} finally {
if (out != null)
out.close();
if (fos != null)
fos.close();
}
// delete the empty directories
IoUtil.copyZipWithoutEmptyDirectories(tmpTo, to);
tmpTo.delete();
}
}

View File

@ -4,12 +4,9 @@ import java.io.{File, FileInputStream}
import java.util.jar.JarInputStream
import java.util.zip.{ZipEntry, ZipInputStream}
import com.tonicsystems.jarjar.classpath.ClassPath
import com.tonicsystems.jarjar.transform.JarTransformer
import com.tonicsystems.jarjar.transform.config.ClassRename
import com.tonicsystems.jarjar.transform.jar.DefaultJarProcessor
import coursier.core.{Configuration, Orders}
import sbt.file
import org.pantsbuild.jarjar._
import org.pantsbuild.jarjar.util.CoursierJarProcessor
object Shading {
@ -191,17 +188,22 @@ object Shading {
baseJar.getName.stripSuffix(".jar") + "-shading.jar"
)
val processor = new DefaultJarProcessor
def rename(from: String, to: String): Rule = {
val rule = new Rule
rule.setPattern(from)
rule.setResult(to)
rule
}
for (namespace <- shadeNamespaces)
processor.addClassRename(new ClassRename(namespace + ".**", shadingNamespace + ".@0"))
val nsRules = shadeNamespaces.toVector.sorted.map { namespace =>
rename(namespace + ".**", shadingNamespace + ".@0")
}
val clsRules = toShadeClasses.map { cls =>
rename(cls, shadingNamespace + ".@0")
}
for (cls <- toShadeClasses)
processor.addClassRename(new ClassRename(cls, shadingNamespace + ".@0"))
val transformer = new JarTransformer(outputJar, processor)
val cp = new ClassPath(file(sys.props("user.dir")), (baseJar +: toShadeJars).toArray)
transformer.transform(cp)
val processor = JJProcessor(nsRules ++ clsRules, verbose = true, skipManifest = false)
CoursierJarProcessor.run((baseJar +: toShadeJars).toArray, outputJar, processor.proc, true)
outputJar
}

View File

@ -0,0 +1,33 @@
package org.pantsbuild.jarjar
// from https://github.com/sbt/sbt-assembly/blob/17786404117889e5a8225c97b9b7639160fb91e8/src/main/scala/org/pantsbuild/jarjar/JJProcessor.scala
import org.pantsbuild.jarjar.util.{EntryStruct, JarProcessor}
import scala.collection.JavaConverters._
class JJProcessor(val proc: JarProcessor) {
def process(entry: EntryStruct): Boolean = proc.process(entry)
def getExcludes(): Set[String] = {
val field = proc.getClass().getDeclaredField("kp")
field.setAccessible(true)
val keepProcessor = field.get(proc)
if (keepProcessor == null) Set()
else {
val method = proc.getClass().getDeclaredMethod("getExcludes")
method.setAccessible(true)
method.invoke(proc).asInstanceOf[java.util.Set[String]].asScala.toSet
}
}
}
object JJProcessor {
def apply(patterns: Seq[PatternElement], verbose: Boolean, skipManifest: Boolean): JJProcessor =
new JJProcessor(new MainProcessor(patterns.asJava, verbose, skipManifest))
}