Initial commit.
This commit is contained in:
commit
e5af484c54
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Eclipse stuff
|
||||||
|
/.classpath
|
||||||
|
/.project
|
||||||
|
/.settings
|
||||||
|
|
||||||
|
# netbeans
|
||||||
|
/nbproject
|
||||||
|
/nbactions.xml
|
||||||
|
/nb-configuration.xml
|
||||||
|
|
||||||
|
# we use maven!
|
||||||
|
/build.xml
|
||||||
|
|
||||||
|
# maven
|
||||||
|
/target
|
||||||
|
/dependency-reduced-pom.xml
|
||||||
|
|
||||||
|
# vim
|
||||||
|
.*.sw[a-p]
|
||||||
|
|
||||||
|
# various other potential build files
|
||||||
|
/build
|
||||||
|
/bin
|
||||||
|
/dist
|
||||||
|
/manifest.mf
|
||||||
|
|
||||||
|
# Mac filesystem dust
|
||||||
|
/.DS_Store
|
||||||
|
|
||||||
|
# intellij
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# other files
|
||||||
|
*.csv
|
||||||
|
*.jar
|
||||||
|
*.log
|
||||||
|
*.rg
|
||||||
|
*.srg
|
||||||
|
*.txt
|
24
LICENSE
Normal file
24
LICENSE
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Copyright (c) 2012, md_5
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the <organization> nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
4
README.md
Normal file
4
README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Special Source
|
||||||
|
==============
|
||||||
|
|
||||||
|
Automatic generator and renamer of jar obfuscation mappings.
|
126
pom.xml
Normal file
126
pom.xml
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.sonatype.oss</groupId>
|
||||||
|
<artifactId>oss-parent</artifactId>
|
||||||
|
<version>7</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>SpecialSource</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>SpecialSource</name>
|
||||||
|
<description>A jar compare and renaming engine designed for comparing and remapping 2 jars of differnent obfuscation mappings. Can also be useful for reobfuscation.</description>
|
||||||
|
<url>https://github.com/md-5/SpecialSource</url>
|
||||||
|
<inceptionYear>2012</inceptionYear>
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>The BSD 3-Clause License</name>
|
||||||
|
<url>http://opensource.org/licenses/BSD-3-Clause</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>md_5</id>
|
||||||
|
<name>Michael Dardis</name>
|
||||||
|
<email>md_5@live.com.au</email>
|
||||||
|
<timezone>+10</timezone>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:git@github.com:md-5/SpecialSource.git</connection>
|
||||||
|
<developerConnection>scm:git:git@github.com:md-5/SpecialSource.git</developerConnection>
|
||||||
|
<url>git@github.com:md-5/SpecialSource.git</url>
|
||||||
|
</scm>
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/md-5/SpecialSource/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
<artifactId>asm-all</artifactId>
|
||||||
|
<version>4.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>0.11.6</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.mycila.maven-license-plugin</groupId>
|
||||||
|
<artifactId>maven-license-plugin</artifactId>
|
||||||
|
<version>1.10.b1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>clean</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>format</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<strictCheck>true</strictCheck>
|
||||||
|
<header>${basedir}/LICENSE</header>
|
||||||
|
<includes>
|
||||||
|
<include>src/**</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.7</source>
|
||||||
|
<target>1.7</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestEntries>
|
||||||
|
<Main-Class>${main.class}</Main-Class>
|
||||||
|
</manifestEntries>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<minimizeJar>true</minimizeJar>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
104
src/main/java/net/md_5/specialsource/Jar.java
Normal file
104
src/main/java/net/md_5/specialsource/Jar.java
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class wraps a {@link JarFile} enabling quick access to the jar's main
|
||||||
|
* class, as well as the ability to get the {@link InputStream} of a class file,
|
||||||
|
* and speedy lookups to see if the jar contains the specified class.
|
||||||
|
*/
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class Jar {
|
||||||
|
|
||||||
|
public final JarFile file;
|
||||||
|
public final String main;
|
||||||
|
private final Set<String> contains = new HashSet<>();
|
||||||
|
private final Map<String, ClassNode> classes = new HashMap<>();
|
||||||
|
|
||||||
|
public boolean containsClass(String clazz) {
|
||||||
|
return contains.contains(clazz) ? true : getClass(clazz) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getClass(String clazz) {
|
||||||
|
try {
|
||||||
|
ZipEntry e = file.getEntry(clazz + ".class");
|
||||||
|
if (e != null) {
|
||||||
|
contains.add(clazz);
|
||||||
|
}
|
||||||
|
return e == null ? null : file.getInputStream(e);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNode getNode(String clazz) {
|
||||||
|
try {
|
||||||
|
ClassNode cache = classes.get(clazz);
|
||||||
|
if (cache != null) {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
InputStream is = getClass(clazz);
|
||||||
|
if (is != null) {
|
||||||
|
ClassReader cr = new ClassReader(getClass(clazz));
|
||||||
|
ClassNode node = new ClassNode();
|
||||||
|
cr.accept(node, 0);
|
||||||
|
classes.put(clazz, node);
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
System.out.println(clazz);
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Jar init(String jar) throws IOException {
|
||||||
|
File file = new File(jar);
|
||||||
|
JarFile jarFile = new JarFile(file);
|
||||||
|
String main = jarFile.getManifest().getMainAttributes().getValue("Main-Class").replace('.', '/');
|
||||||
|
return new Jar(jarFile, main);
|
||||||
|
}
|
||||||
|
}
|
126
src/main/java/net/md_5/specialsource/JarComparer.java
Normal file
126
src/main/java/net/md_5/specialsource/JarComparer.java
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.FieldVisitor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
public class JarComparer extends ClassVisitor {
|
||||||
|
|
||||||
|
private final MethodReferenceFinder methodVisitor = new MethodReferenceFinder();
|
||||||
|
public final Jar jar;
|
||||||
|
private String myName;
|
||||||
|
public int iterDepth;
|
||||||
|
public NoDupeList<String> classes = new NoDupeList<>();
|
||||||
|
public NoDupeList<Ownable> fields = new NoDupeList<>();
|
||||||
|
public NoDupeList<Ownable> methods = new NoDupeList<>();
|
||||||
|
|
||||||
|
private void visitType(Type type) {
|
||||||
|
// FIXME: Scan arrays too!
|
||||||
|
if (type.getSort() == Type.OBJECT) {
|
||||||
|
String name = type.getInternalName();
|
||||||
|
if (jar.containsClass(name)) {
|
||||||
|
classes.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarComparer(Jar jar) {
|
||||||
|
super(Opcodes.ASM4);
|
||||||
|
this.jar = jar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||||
|
myName = name;
|
||||||
|
// FIXME: Scan the super class too!
|
||||||
|
for (String implement : interfaces) {
|
||||||
|
if (jar.containsClass(implement)) {
|
||||||
|
classes.add(implement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
|
||||||
|
Ownable field = new Ownable(NodeType.FIELD, myName, name, desc);
|
||||||
|
fields.add(field);
|
||||||
|
return null; // No need to get more info about a field!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||||
|
// Check for initializers
|
||||||
|
if (!name.equals("<init>") && !name.equals("<clinit>")) {
|
||||||
|
Ownable method = new Ownable(NodeType.METHOD, myName, name, desc);
|
||||||
|
methods.add(method);
|
||||||
|
}
|
||||||
|
// FIXME: Scan return types too!
|
||||||
|
for (Type t : Type.getArgumentTypes(desc)) {
|
||||||
|
visitType(t);
|
||||||
|
}
|
||||||
|
return methodVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MethodReferenceFinder extends MethodVisitor {
|
||||||
|
|
||||||
|
public MethodReferenceFinder() {
|
||||||
|
super(Opcodes.ASM4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||||
|
if (jar.containsClass(owner)) {
|
||||||
|
classes.add(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitLdcInsn(Object cst) {
|
||||||
|
if (cst instanceof Type) {
|
||||||
|
visitType((Type) cst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||||
|
if (jar.containsClass(owner)) {
|
||||||
|
classes.add(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTypeInsn(int opcode, String type) {
|
||||||
|
if (jar.containsClass(type)) {
|
||||||
|
classes.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
188
src/main/java/net/md_5/specialsource/JarRemapper.java
Normal file
188
src/main/java/net/md_5/specialsource/JarRemapper.java
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.commons.Remapper;
|
||||||
|
import org.objectweb.asm.commons.RemappingClassAdapter;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.FieldNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
|
public class JarRemapper extends Remapper {
|
||||||
|
|
||||||
|
private static final int CLASS_LEN = ".class".length();
|
||||||
|
private static final String HEADER = ""
|
||||||
|
+ "# THESE ARE AUTOMATICALLY GENERATED MAPPINGS BETWEEN {0} and {1}\n"
|
||||||
|
+ "# THEY WERE GENERATED ON {2} USING Special Source (c) md_5 2012.\n"
|
||||||
|
+ "# PLEASE DO NOT REMOVE THIS HEADER OR DISTRIBUTE THIS FILE WITHOUT PERMISSION!\n";
|
||||||
|
private final JarComparer oldJar;
|
||||||
|
private final JarComparer newJar;
|
||||||
|
private final Jar self;
|
||||||
|
private final Map<String, String> classes = new HashMap<>();
|
||||||
|
private final Map<String, String> fields = new HashMap<>();
|
||||||
|
private final Map<String, String> methods = new HashMap<>();
|
||||||
|
|
||||||
|
private JarRemapper(JarComparer oldJar, JarComparer newJar, Jar self, File logfile) throws IOException {
|
||||||
|
SpecialSource.validate(oldJar, newJar);
|
||||||
|
this.oldJar = oldJar;
|
||||||
|
this.newJar = newJar;
|
||||||
|
this.self = self;
|
||||||
|
|
||||||
|
List<String> searge = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < oldJar.classes.size(); i++) {
|
||||||
|
String oldClass = oldJar.classes.get(i);
|
||||||
|
String newClass = newJar.classes.get(i);
|
||||||
|
classes.put(oldClass, newClass);
|
||||||
|
if (!Objects.equals(oldClass, newClass)) {
|
||||||
|
searge.add("CL: " + oldClass + " " + newClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < oldJar.fields.size(); i++) {
|
||||||
|
Ownable oldField = oldJar.fields.get(i);
|
||||||
|
Ownable newField = newJar.fields.get(i);
|
||||||
|
fields.put(oldField.owner + "/" + oldField.name, newField.name);
|
||||||
|
if (!Objects.equals(oldField, newField)) {
|
||||||
|
searge.add("FD: " + oldField.owner + "/" + oldField.name + " " + newField.owner + "/" + newField.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < oldJar.methods.size(); i++) {
|
||||||
|
Ownable oldMethod = oldJar.methods.get(i);
|
||||||
|
Ownable newMethod = newJar.methods.get(i);
|
||||||
|
methods.put(oldMethod.owner + "/" + oldMethod.name + " " + oldMethod.descriptor, newMethod.name);
|
||||||
|
if (!Objects.equals(oldMethod, newMethod)) {
|
||||||
|
searge.add("MD: " + oldMethod.owner + "/" + oldMethod.name + " " + oldMethod.descriptor + " " + newMethod.owner + "/" + newMethod.name + " " + newMethod.descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(searge);
|
||||||
|
try (PrintWriter out = new PrintWriter(logfile)) {
|
||||||
|
out.println(MessageFormat.format(HEADER, oldJar.jar.file.getName(), newJar.jar.file.getName(), new Date()));
|
||||||
|
for (String s : searge) {
|
||||||
|
out.println(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String map(String typeName) {
|
||||||
|
int index = typeName.indexOf('$');
|
||||||
|
String key = (index == -1) ? typeName : typeName.substring(0, index);
|
||||||
|
String mapped = classes.get(key);
|
||||||
|
return mapped != null ? mapped + (index == -1 ? "" : typeName.substring(index, typeName.length())) : typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String mapFieldName(String owner, String name, String desc) {
|
||||||
|
String mapped = tryClimb(fields, NodeType.FIELD, owner, name);
|
||||||
|
return mapped == null ? name : mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String tryClimb(Map<String, String> map, NodeType type, String owner, String name) {
|
||||||
|
String key = owner + "/" + name;
|
||||||
|
if (key.contains("findNearestMapFeature")) {
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
String mapped = map.get(key);
|
||||||
|
if (mapped == null) {
|
||||||
|
ClassNode node = self.getNode(owner);
|
||||||
|
if (node != null) {
|
||||||
|
for (String iface : (List<String>) node.interfaces) {
|
||||||
|
mapped = tryClimb(map, type, iface, name);
|
||||||
|
if (mapped != null) {
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tryClimb(map, type, node.superName, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String mapMethodName(String owner, String name, String desc) {
|
||||||
|
String mapped = tryClimb(methods, NodeType.METHOD, owner, name + " " + desc);
|
||||||
|
return mapped == null ? name : mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renameJar(Jar jar, File target, JarComparer oldNames, JarComparer newNames) throws IOException {
|
||||||
|
try (JarOutputStream out = new JarOutputStream(new FileOutputStream(target))) {
|
||||||
|
JarRemapper self = new JarRemapper(oldNames, newNames, jar, new File(target.getPath() + ".srg"));
|
||||||
|
for (Enumeration<JarEntry> entr = jar.file.entries(); entr.hasMoreElements();) {
|
||||||
|
JarEntry entry = entr.nextElement();
|
||||||
|
try (InputStream is = jar.file.getInputStream(entry)) {
|
||||||
|
String name = entry.getName();
|
||||||
|
byte[] data;
|
||||||
|
if (name.endsWith(".class")) {
|
||||||
|
name = name.substring(0, name.length() - CLASS_LEN);
|
||||||
|
|
||||||
|
ClassReader reader = new ClassReader(is);
|
||||||
|
ClassWriter wr = new ClassWriter(0);
|
||||||
|
RemappingClassAdapter mapper = new RemappingClassAdapter(wr, self);
|
||||||
|
reader.accept(mapper, ClassReader.EXPAND_FRAMES);
|
||||||
|
data = wr.toByteArray();
|
||||||
|
String newName = self.map(name);
|
||||||
|
|
||||||
|
entry = new JarEntry(newName == null ? name : newName + ".class");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
int n;
|
||||||
|
byte[] b = new byte[1 << 15]; // Max class file size, arbritrary number
|
||||||
|
while ((n = is.read(b, 0, b.length)) != -1) {
|
||||||
|
buffer.write(b, 0, n);
|
||||||
|
}
|
||||||
|
buffer.flush();
|
||||||
|
data = buffer.toByteArray();
|
||||||
|
}
|
||||||
|
entry.setTime(0);
|
||||||
|
out.putNextEntry(entry);
|
||||||
|
out.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
src/main/java/net/md_5/specialsource/NoDupeList.java
Normal file
69
src/main/java/net/md_5/specialsource/NoDupeList.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pseudo class implementing the {@link List} like, but does not allow
|
||||||
|
* duplicates. Is backed by an {@link ArrayList} and {@link HashSet} for speedy
|
||||||
|
* contains lookups.
|
||||||
|
*
|
||||||
|
* @param <E> the type of elements contained in this 'list'
|
||||||
|
*/
|
||||||
|
public class NoDupeList<E> implements Iterable<E> {
|
||||||
|
|
||||||
|
private final Set<E> set = new HashSet<>();
|
||||||
|
private final List<E> backing = new ArrayList<>();
|
||||||
|
|
||||||
|
public boolean add(E e) {
|
||||||
|
if (set.contains(e)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
set.add(e);
|
||||||
|
backing.add(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public E get(int index) {
|
||||||
|
return backing.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return backing.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<E> iterator() {
|
||||||
|
return backing.iterator();
|
||||||
|
}
|
||||||
|
}
|
32
src/main/java/net/md_5/specialsource/NodeType.java
Normal file
32
src/main/java/net/md_5/specialsource/NodeType.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
public enum NodeType {
|
||||||
|
|
||||||
|
FIELD, METHOD;
|
||||||
|
}
|
42
src/main/java/net/md_5/specialsource/Ownable.java
Normal file
42
src/main/java/net/md_5/specialsource/Ownable.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class which can be used to represent a field, method, or anything else
|
||||||
|
* which has an owner, a name and a descriptor.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Ownable {
|
||||||
|
|
||||||
|
final NodeType type;
|
||||||
|
final String owner;
|
||||||
|
final String name;
|
||||||
|
final String descriptor;
|
||||||
|
}
|
46
src/main/java/net/md_5/specialsource/Pair.java
Normal file
46
src/main/java/net/md_5/specialsource/Pair.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class representing a set of 2 objects as defined by the type parameters.
|
||||||
|
*
|
||||||
|
* @param <T1> First type
|
||||||
|
* @param <T2> Second type
|
||||||
|
*/
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Pair<T1, T2> {
|
||||||
|
|
||||||
|
public final T1 first;
|
||||||
|
public final T2 second;
|
||||||
|
}
|
100
src/main/java/net/md_5/specialsource/SpecialSource.java
Normal file
100
src/main/java/net/md_5/specialsource/SpecialSource.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2012, md_5
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
|
||||||
|
public class SpecialSource {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
args = new String[]{"jars/1.4.5/bukkit.jar", "jars/1.4.5/vanilla.jar", "jars/1.4.5/craftbukkit-1.4.5-R0.3-SNAPSHOT.jar"};
|
||||||
|
if (args.length != 3) {
|
||||||
|
System.err.println("SpecialSource takes 3 arguments. It will take 2 jars to generate a difference between, and a 3rd jar based on the first jar to rename to the second jar.");
|
||||||
|
System.err.println("Usage: java -jar SpecialSource.jar <first jar> <second jar> <jar of first names>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Reading jars");
|
||||||
|
Jar jar1 = Jar.init(args[0]);
|
||||||
|
Jar jar2 = Jar.init(args[1]);
|
||||||
|
|
||||||
|
System.out.println("Creating jar compare");
|
||||||
|
JarComparer visitor1 = new JarComparer(jar1);
|
||||||
|
JarComparer visitor2 = new JarComparer(jar2);
|
||||||
|
visit(new Pair<>(jar1, jar2), new Pair<>(visitor1, visitor2), new Pair<>(jar1.main, jar2.main));
|
||||||
|
|
||||||
|
System.out.println("Checking vailidity");
|
||||||
|
if (visitor1.classes.size() != 1004 || visitor2.classes.size() != 1004) {
|
||||||
|
throw new IllegalStateException("classes");
|
||||||
|
}
|
||||||
|
if (visitor1.fields.size() != 3582 || visitor2.fields.size() != 3582) {
|
||||||
|
throw new IllegalStateException("fields");
|
||||||
|
}
|
||||||
|
if (visitor1.methods.size() != 6531 + 4 || visitor2.methods.size() != 6531 + 4) { // 3 broken enums (EnumEntitySize, EnumFacing, EnumGameType), and 1 main method
|
||||||
|
throw new IllegalStateException("methods");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Renaming final jar");
|
||||||
|
JarRemapper.renameJar(Jar.init(args[2]), new File("out.jar"), visitor1, visitor2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void visit(Pair<Jar, Jar> jars, Pair<JarComparer, JarComparer> visitors, Pair<String, String> classes) throws IOException {
|
||||||
|
JarComparer visitor1 = visitors.first;
|
||||||
|
JarComparer visitor2 = visitors.second;
|
||||||
|
|
||||||
|
ClassReader clazz1 = new ClassReader(jars.first.getClass(classes.first));
|
||||||
|
ClassReader clazz2 = new ClassReader(jars.second.getClass(classes.second));
|
||||||
|
clazz1.accept(visitor1, 0);
|
||||||
|
clazz2.accept(visitor2, 0);
|
||||||
|
|
||||||
|
validate(visitor1, visitor2);
|
||||||
|
|
||||||
|
while (visitor1.iterDepth < visitor1.classes.size()) {
|
||||||
|
String className1 = visitor1.classes.get(visitor1.iterDepth);
|
||||||
|
String className2 = visitor2.classes.get(visitor1.iterDepth);
|
||||||
|
Pair<String, String> pair = new Pair<>(className1, className2);
|
||||||
|
visitor1.iterDepth++;
|
||||||
|
visit(jars, visitors, pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validate(JarComparer visitor1, JarComparer visitor2) {
|
||||||
|
if (visitor1.classes.size() != visitor2.classes.size()) {
|
||||||
|
throw new IllegalStateException("classes");
|
||||||
|
}
|
||||||
|
if (visitor1.fields.size() != visitor2.fields.size()) {
|
||||||
|
throw new IllegalStateException("fields");
|
||||||
|
}
|
||||||
|
if (visitor1.methods.size() != visitor2.methods.size()) {
|
||||||
|
throw new IllegalStateException("methods");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user