summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/ClassRenamer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/bytecode/ClassRenamer.java')
-rw-r--r--src/cuchaz/enigma/bytecode/ClassRenamer.java110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/bytecode/ClassRenamer.java b/src/cuchaz/enigma/bytecode/ClassRenamer.java
new file mode 100644
index 0000000..a5fea92
--- /dev/null
+++ b/src/cuchaz/enigma/bytecode/ClassRenamer.java
@@ -0,0 +1,110 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import java.util.Map;
14import java.util.Set;
15
16import javassist.ClassMap;
17import javassist.CtClass;
18import javassist.bytecode.ConstPool;
19import javassist.bytecode.Descriptor;
20import javassist.bytecode.InnerClassesAttribute;
21
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
24
25import cuchaz.enigma.mapping.ClassEntry;
26
27public class ClassRenamer {
28
29 public static void renameClasses(CtClass c, Map<ClassEntry,ClassEntry> map) {
30
31 // build the map used by javassist
32 ClassMap nameMap = new ClassMap();
33 for (Map.Entry<ClassEntry,ClassEntry> entry : map.entrySet()) {
34 nameMap.put(entry.getKey().getName(), entry.getValue().getName());
35 }
36
37 c.replaceClassName(nameMap);
38
39 // replace simple names in the InnerClasses attribute too
40 ConstPool constants = c.getClassFile().getConstPool();
41 InnerClassesAttribute attr = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag);
42 if (attr != null) {
43 for (int i = 0; i < attr.tableLength(); i++) {
44 ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i)));
45 if (attr.innerNameIndex(i) != 0) {
46 attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnerClassName()));
47 }
48
49 /* DEBUG
50 System.out.println(String.format("\tDEOBF: %s-> ATTR: %s,%s,%s", classEntry, attr.outerClass(i), attr.innerClass(i), attr.innerName(i)));
51 */
52 }
53 }
54 }
55
56 public static Set<ClassEntry> getAllClassEntries(final CtClass c) {
57
58 // get the classes that javassist knows about
59 final Set<ClassEntry> entries = Sets.newHashSet();
60 ClassMap map = new ClassMap() {
61 @Override
62 public Object get(Object obj) {
63 if (obj instanceof String) {
64 String str = (String)obj;
65
66 // javassist throws a lot of weird things at this map
67 // I either have to implement my on class scanner, or just try to filter out the weirdness
68 // I'm opting to filter out the weirdness for now
69
70 // skip anything with generic arguments
71 if (str.indexOf('<') >= 0 || str.indexOf('>') >= 0 || str.indexOf(';') >= 0) {
72 return null;
73 }
74
75 // convert path/to/class.inner to path/to/class$inner
76 str = str.replace('.', '$');
77
78 // remember everything else
79 entries.add(new ClassEntry(str));
80 }
81 return null;
82 }
83
84 private static final long serialVersionUID = -202160293602070641L;
85 };
86 c.replaceClassName(map);
87
88 return entries;
89 }
90
91 public static void moveAllClassesOutOfDefaultPackage(CtClass c, String newPackageName) {
92 Map<ClassEntry,ClassEntry> map = Maps.newHashMap();
93 for (ClassEntry classEntry : ClassRenamer.getAllClassEntries(c)) {
94 if (classEntry.isInDefaultPackage()) {
95 map.put(classEntry, new ClassEntry(newPackageName + "/" + classEntry.getName()));
96 }
97 }
98 ClassRenamer.renameClasses(c, map);
99 }
100
101 public static void moveAllClassesIntoDefaultPackage(CtClass c, String oldPackageName) {
102 Map<ClassEntry,ClassEntry> map = Maps.newHashMap();
103 for (ClassEntry classEntry : ClassRenamer.getAllClassEntries(c)) {
104 if (classEntry.getPackageName().equals(oldPackageName)) {
105 map.put(classEntry, new ClassEntry(classEntry.getSimpleName()));
106 }
107 }
108 ClassRenamer.renameClasses(c, map);
109 }
110}