Skip to content

Commit

Permalink
Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
cdkrot committed Jan 27, 2024
1 parent 9d0eb03 commit 87d7d05
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 38 deletions.
2 changes: 1 addition & 1 deletion core/src/main/scala/com/eed3si9n/jarjar/JJProcessor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class JJProcessor(
processors += new ZapProcessor(zapList.asJava)
processors += misplacedClassProcessor
processors += new JarTransformerChain(
Array[RemappingClassTransformer](new RemappingClassTransformer(pr))
Array[RemappingClassTransformer](new RemappingClassTransformer()), pr
)

val renamer: String => Option[String] = {
Expand Down
4 changes: 2 additions & 2 deletions jarjar/src/main/java/com/eed3si9n/jarjar/MainProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ public MainProcessor(List<PatternElement> patterns, boolean verbose, boolean ski
processors.add(new ZapProcessor(zapList));
processors.add(misplacedClassProcessor);
processors.add(new JarTransformerChain(new RemappingClassTransformer[] {
new RemappingClassTransformer(pr)
}));
new RemappingClassTransformer()
}, pr));
processors.add(new MethodSignatureProcessor(pr));
processors.add(new ResourceProcessor(pr));
chain = new JarProcessorChain(processors.toArray(new JarProcessor[processors.size()]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import com.eed3si9n.jarjar.util.RemappingJarProcessor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
Expand All @@ -20,7 +22,7 @@
* being renamed. Method signatures are more difficult to detect so this class keeps track of which
* methods definitely take method signatures and remaps those explicitly.
*/
public class MethodSignatureProcessor implements JarProcessor {
public class MethodSignatureProcessor extends RemappingJarProcessor {

/**
* List of method names which take a method signature as their parameter.
Expand All @@ -30,14 +32,12 @@ public class MethodSignatureProcessor implements JarProcessor {
private static final Set<String> METHOD_NAMES_WITH_PARAMS_TO_REWRITE =
new HashSet<String>(Arrays.asList("getImplMethodSignature"));

private final Remapper remapper;

public MethodSignatureProcessor(Remapper remapper) {
this.remapper = remapper;
public MethodSignatureProcessor(TracingRemapper remapper) {
super(remapper);
}

@Override
public boolean process(final EntryStruct struct) throws IOException {
public boolean processImpl(EntryStruct struct, Remapper remapper) throws IOException {
if (!struct.name.endsWith(".class") || struct.skipTransform) {
return true;
}
Expand All @@ -50,12 +50,14 @@ public boolean process(final EntryStruct struct) throws IOException {
e.printStackTrace();
return true;
}
reader.accept(new MethodSignatureRemapperClassVisitor(classWriter), ClassReader.EXPAND_FRAMES);
reader.accept(new MethodSignatureRemapperClassVisitor(classWriter, remapper), ClassReader.EXPAND_FRAMES);
struct.data = classWriter.toByteArray();
return true;
}

private class MethodSignatureRemapperClassVisitor extends ClassVisitor {
private static class MethodSignatureRemapperClassVisitor extends ClassVisitor {

private final Remapper remapper;

private class MethodSignatureRemapperMethodVisitor extends MethodVisitor {

Expand Down Expand Up @@ -96,8 +98,9 @@ public void visitLdcInsn(Object value) {
}
}

public MethodSignatureRemapperClassVisitor(ClassVisitor classVisitor) {
public MethodSignatureRemapperClassVisitor(ClassVisitor classVisitor, Remapper remapper) {
super(Opcodes.ASM9, classVisitor);
this.remapper = remapper;
}

@Override
Expand Down
21 changes: 19 additions & 2 deletions jarjar/src/main/java/com/eed3si9n/jarjar/PackageRemapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,33 @@
import java.util.*;
import java.util.regex.Pattern;

class PackageRemapper extends Remapper
class PackageRemapper extends TracingRemapper
{
private static final String RESOURCE_SUFFIX = "RESOURCE";

private static final Pattern ARRAY_FOR_NAME_PATTERN
= Pattern.compile("\\[L[\\p{javaJavaIdentifierPart}\\.]+?;");

private final List<Wildcard> wildcards;
private final List<Rule> ruleList;
private final Map<String, String> typeCache = new HashMap<String, String>();
private final Map<String, String> pathCache = new HashMap<String, String>();
private final Map<Object, String> valueCache = new HashMap<Object, String>();
private final boolean verbose;
private boolean modified = false;


public PackageRemapper(List<Rule> ruleList, boolean verbose) {
this.verbose = verbose;
this.ruleList = ruleList;
wildcards = PatternElement.createWildcards(ruleList);
}

@Override
public TracingRemapper copy() {
return new PackageRemapper(this.ruleList, this.verbose);
}

// also used by KeepProcessor
static boolean isArrayForName(String value) {
return ARRAY_FOR_NAME_PATTERN.matcher(value).matches();
Expand Down Expand Up @@ -130,9 +139,17 @@ public String mapInnerClassName(
private String replaceHelper(String value) {
for (Wildcard wildcard : wildcards) {
String test = wildcard.replace(value);
if (test != null)
if (test != null) {
if (!test.equals(value))
this.modified = true;
return test;
}
}
return value;
}

@Override
public boolean hasChanges() {
return modified;
}
}
15 changes: 15 additions & 0 deletions jarjar/src/main/java/com/eed3si9n/jarjar/TracingRemapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.eed3si9n.jarjar;

import org.objectweb.asm.commons.Remapper;

public abstract class TracingRemapper extends Remapper {
/**
* Obtain the fresh copy of this object.
*/
public abstract TracingRemapper copy();

/**
* Check if this instance remapped something already.
*/
public abstract boolean hasChanges();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@ public class EntryStruct {
public String name;
public long time;
public boolean skipTransform;

public EntryStruct copy() {
EntryStruct result = new EntryStruct();
result.data = data;
result.name = name;
result.time = time;
result.skipTransform = skipTransform;
return result;
}
}
15 changes: 11 additions & 4 deletions jarjar/src/main/java/com/eed3si9n/jarjar/util/JarTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@
import java.io.*;

import static com.eed3si9n.jarjar.misplaced.MisplacedClassProcessor.VERSIONED_CLASS_FOLDER;

import com.eed3si9n.jarjar.TracingRemapper;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.Remapper;

abstract public class JarTransformer extends RemappingJarProcessor {

abstract public class JarTransformer implements JarProcessor {
public JarTransformer(TracingRemapper remapper) {
super(remapper);
}

public boolean process(EntryStruct struct) throws IOException {
public boolean processImpl(EntryStruct struct, Remapper remapper) throws IOException {
if (struct.name.endsWith(".class") && !struct.skipTransform) {
ClassReader reader;
try {
Expand All @@ -38,7 +45,7 @@ public boolean process(EntryStruct struct) throws IOException {

GetNameClassWriter w = new GetNameClassWriter(ClassWriter.COMPUTE_MAXS);
try {
reader.accept(transform(w), ClassReader.EXPAND_FRAMES);
reader.accept(transform(w, remapper), ClassReader.EXPAND_FRAMES);
} catch (RuntimeException e) {
throw new IOException("Unable to transform " + struct.name, e);
}
Expand All @@ -51,7 +58,7 @@ public boolean process(EntryStruct struct) throws IOException {
return true;
}

abstract protected ClassVisitor transform(ClassVisitor v);
abstract protected ClassVisitor transform(ClassVisitor v, Remapper remapper);

private static String pathFromName(String className) {
return className.replace('.', '/') + ".class";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@

package com.eed3si9n.jarjar.util;

import com.eed3si9n.jarjar.TracingRemapper;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.commons.Remapper;

public class JarTransformerChain extends JarTransformer
{
private final RemappingClassTransformer[] chain;

public JarTransformerChain(RemappingClassTransformer[] chain) {
public JarTransformerChain(RemappingClassTransformer[] chain, TracingRemapper remapper) {
super(remapper);
this.chain = chain.clone();
for (int i = chain.length - 1; i > 0; i--) {
chain[i - 1].setTarget(chain[i]);
}
}

protected ClassVisitor transform(ClassVisitor v) {
chain[chain.length - 1].setTarget(v);
return chain[0];
protected ClassVisitor transform(ClassVisitor parent, Remapper remapper) {
for (int i = chain.length - 1; i >= 0; i--) {
chain[i] = chain[i].update(remapper, parent);
parent = chain[i];
}
return parent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@

public class RemappingClassTransformer extends ClassRemapper
{
public RemappingClassTransformer(Remapper pr) {
public RemappingClassTransformer() {
this(null, null);
}

public RemappingClassTransformer(Remapper pr, ClassVisitor parent) {
super(new EmptyClassVisitor(), pr);
this.cv = parent;
}
public void setTarget(ClassVisitor target) {
cv = target;

public RemappingClassTransformer update(Remapper pr, ClassVisitor target) {
return new RemappingClassTransformer(pr, target);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.eed3si9n.jarjar.util;


import com.eed3si9n.jarjar.TracingRemapper;
import org.objectweb.asm.commons.Remapper;

import java.io.IOException;

/**
* Extension of JarProcessor for building processors around TracingRemapper.
*
* This class will track if TracingRemapper recorded doing any changes, and if it didn't,
* it will make sure that the underlying bytes are unmodified.
*
* This helps to avoid bytecode modifications when there was no actual changes
* to do.
*/
public abstract class RemappingJarProcessor implements JarProcessor {
private TracingRemapper remapper;

public RemappingJarProcessor(TracingRemapper remapper) {
this.remapper = remapper;
}

public final boolean process(EntryStruct struct) throws IOException {
TracingRemapper structRemapper = remapper.copy();
EntryStruct origStruct = struct.copy();

if (!processImpl(struct, structRemapper)) {
return false;
}

if (!structRemapper.hasChanges()) {
struct.data = origStruct.data;
}

return true;
}

protected abstract boolean processImpl(EntryStruct struct, Remapper remapper) throws IOException;
}
5 changes: 3 additions & 2 deletions jarjar/src/test/java/com/eed3si9n/jarjar/GenericsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ public void testTransform() throws Exception {
Rule rule = new Rule();
rule.setPattern("java.lang.String");
rule.setResult("com.tonicsystems.String");
RemappingClassTransformer t = new RemappingClassTransformer(new PackageRemapper(Arrays.asList(rule), false));
t.setTarget(new EmptyClassVisitor());
RemappingClassTransformer t = new RemappingClassTransformer(
new PackageRemapper(Arrays.asList(rule), false), new EmptyClassVisitor()
);
ClassReader reader = new ClassReader(getClass().getResourceAsStream("/Generics.class"));
reader.accept(t, 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public MethodVisitor visitMethod(
}
}

private static byte[] readInputStream(InputStream inputStream) throws IOException {
protected static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buf = new byte[0x2000];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IoUtil.pipe(inputStream, baos, buf);
Expand Down
35 changes: 35 additions & 0 deletions jarjar/src/test/java/com/eed3si9n/jarjar/UnmodifiedTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.eed3si9n.jarjar;

import com.eed3si9n.jarjar.util.EntryStruct;
import org.junit.Assert;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

import static com.eed3si9n.jarjar.MethodRewriterTest.readInputStream;

public class UnmodifiedTest {
@Test
public void testNotModified() throws Exception {
Rule rule = new Rule();
rule.setPattern("com.abc");
rule.setResult("com.def");

MainProcessor mp = new MainProcessor(Arrays.asList(rule), false, false, "move");

EntryStruct entryStruct = new EntryStruct();
entryStruct.name = "BigtableIO$Write.class";
entryStruct.skipTransform = false;
entryStruct.time = 0;
entryStruct.data =
readInputStream(
getClass().getResourceAsStream("/com/eed3si9n/jarjar/BigtableIO$Write.class"));

EntryStruct orig = entryStruct.copy();

mp.process(entryStruct);

Assert.assertEquals(entryStruct.data, orig.data);
}
}
15 changes: 9 additions & 6 deletions jarjar/src/test/java/com/eed3si9n/jarjar/VersionedClassTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.junit.Test;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand Down Expand Up @@ -37,13 +38,15 @@ public void testVersionPrefixIsPreserved() throws IOException {
String expectedName = Example.class.getName().replace("jarjar", "jarjarabrams");
struct.name = MisplacedClassProcessor.VERSIONED_CLASS_FOLDER + "9/" + toClassPath(originalName);
struct.data = getClassBytes(originalName);
JarTransformer transformer = new JarTransformer() {

Rule rule = new Rule();
rule.setPattern(originalName);
rule.setResult(expectedName);
PackageRemapper remapper = new PackageRemapper(Arrays.asList(rule), false);

JarTransformer transformer = new JarTransformer(remapper) {
@Override
protected ClassVisitor transform(ClassVisitor v) {
Rule rule = new Rule();
rule.setPattern(originalName);
rule.setResult(expectedName);
PackageRemapper remapper = new PackageRemapper(Arrays.asList(rule), false);
protected ClassVisitor transform(ClassVisitor v, Remapper remapper) {
return new ClassRemapper(v, remapper);
}
};
Expand Down

0 comments on commit 87d7d05

Please # to comment.