summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping/Mappings.java
diff options
context:
space:
mode:
authorGravatar jeff2015-02-03 22:00:53 -0500
committerGravatar jeff2015-02-03 22:00:53 -0500
commit52ab426d8fad3dbee7e728f523a35af94facebda (patch)
tree146fadfd8e639a909d6c1d6a193e7eddeab0be4a /src/cuchaz/enigma/mapping/Mappings.java
downloadenigma-fork-52ab426d8fad3dbee7e728f523a35af94facebda.tar.gz
enigma-fork-52ab426d8fad3dbee7e728f523a35af94facebda.tar.xz
enigma-fork-52ab426d8fad3dbee7e728f523a35af94facebda.zip
oops, don't depend on local procyon project
Diffstat (limited to 'src/cuchaz/enigma/mapping/Mappings.java')
-rw-r--r--src/cuchaz/enigma/mapping/Mappings.java213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java
new file mode 100644
index 0000000..cc560a8
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/Mappings.java
@@ -0,0 +1,213 @@
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.mapping;
12
13import java.io.IOException;
14import java.io.InputStream;
15import java.io.ObjectInputStream;
16import java.io.Serializable;
17import java.util.ArrayList;
18import java.util.Collection;
19import java.util.Map;
20import java.util.Set;
21import java.util.zip.GZIPInputStream;
22
23import com.google.common.collect.Maps;
24import com.google.common.collect.Sets;
25
26import cuchaz.enigma.Util;
27import cuchaz.enigma.analysis.TranslationIndex;
28import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater;
29
30public class Mappings implements Serializable {
31
32 private static final long serialVersionUID = 4649790259460259026L;
33
34 protected Map<String,ClassMapping> m_classesByObf;
35 protected Map<String,ClassMapping> m_classesByDeobf;
36
37 public Mappings() {
38 m_classesByObf = Maps.newHashMap();
39 m_classesByDeobf = Maps.newHashMap();
40 }
41
42 public Mappings(Iterable<ClassMapping> classes) {
43 this();
44
45 for (ClassMapping classMapping : classes) {
46 m_classesByObf.put(classMapping.getObfName(), classMapping);
47 if (classMapping.getDeobfName() != null) {
48 m_classesByDeobf.put(classMapping.getDeobfName(), classMapping);
49 }
50 }
51 }
52
53 public static Mappings newFromResource(String resource) throws IOException {
54 InputStream in = null;
55 try {
56 in = Mappings.class.getResourceAsStream(resource);
57 return newFromStream(in);
58 } finally {
59 Util.closeQuietly(in);
60 }
61 }
62
63 public Collection<ClassMapping> classes() {
64 assert (m_classesByObf.size() >= m_classesByDeobf.size());
65 return m_classesByObf.values();
66 }
67
68 public void addClassMapping(ClassMapping classMapping) {
69 if (m_classesByObf.containsKey(classMapping.getObfName())) {
70 throw new Error("Already have mapping for " + classMapping.getObfName());
71 }
72 boolean obfWasAdded = m_classesByObf.put(classMapping.getObfName(), classMapping) == null;
73 assert (obfWasAdded);
74 if (classMapping.getDeobfName() != null) {
75 if (m_classesByDeobf.containsKey(classMapping.getDeobfName())) {
76 throw new Error("Already have mapping for " + classMapping.getDeobfName());
77 }
78 boolean deobfWasAdded = m_classesByDeobf.put(classMapping.getDeobfName(), classMapping) == null;
79 assert (deobfWasAdded);
80 }
81 }
82
83 public void removeClassMapping(ClassMapping classMapping) {
84 boolean obfWasRemoved = m_classesByObf.remove(classMapping.getObfName()) != null;
85 assert (obfWasRemoved);
86 if (classMapping.getDeobfName() != null) {
87 boolean deobfWasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
88 assert (deobfWasRemoved);
89 }
90 }
91
92 public ClassMapping getClassByObf(ClassEntry entry) {
93 return getClassByObf(entry.getName());
94 }
95
96 public ClassMapping getClassByObf(String obfName) {
97 return m_classesByObf.get(obfName);
98 }
99
100 public ClassMapping getClassByDeobf(ClassEntry entry) {
101 return getClassByDeobf(entry.getName());
102 }
103
104 public ClassMapping getClassByDeobf(String deobfName) {
105 return m_classesByDeobf.get(deobfName);
106 }
107
108 public Translator getTranslator(TranslationDirection direction, TranslationIndex index) {
109 switch (direction) {
110 case Deobfuscating:
111
112 return new Translator(direction, m_classesByObf, index);
113
114 case Obfuscating:
115
116 // fill in the missing deobf class entries with obf entries
117 Map<String,ClassMapping> classes = Maps.newHashMap();
118 for (ClassMapping classMapping : classes()) {
119 if (classMapping.getDeobfName() != null) {
120 classes.put(classMapping.getDeobfName(), classMapping);
121 } else {
122 classes.put(classMapping.getObfName(), classMapping);
123 }
124 }
125
126 // translate the translation index
127 // NOTE: this isn't actually recursive
128 TranslationIndex deobfIndex = new TranslationIndex(index, getTranslator(TranslationDirection.Deobfuscating, index));
129
130 return new Translator(direction, classes, deobfIndex);
131
132 default:
133 throw new Error("Invalid translation direction!");
134 }
135 }
136
137 public static Mappings newFromStream(InputStream in) throws IOException {
138 try {
139 return (Mappings)new ObjectInputStream(new GZIPInputStream(in)).readObject();
140 } catch (ClassNotFoundException ex) {
141 throw new Error(ex);
142 }
143 }
144
145 @Override
146 public String toString() {
147 StringBuilder buf = new StringBuilder();
148 for (ClassMapping classMapping : m_classesByObf.values()) {
149 buf.append(classMapping.toString());
150 buf.append("\n");
151 }
152 return buf.toString();
153 }
154
155 public void renameObfClass(String oldObfName, String newObfName) {
156 for (ClassMapping classMapping : new ArrayList<ClassMapping>(classes())) {
157 if (classMapping.renameObfClass(oldObfName, newObfName)) {
158 boolean wasRemoved = m_classesByObf.remove(oldObfName) != null;
159 assert (wasRemoved);
160 boolean wasAdded = m_classesByObf.put(newObfName, classMapping) == null;
161 assert (wasAdded);
162 }
163 }
164 }
165
166 public Set<String> getAllObfClassNames() {
167 final Set<String> classNames = Sets.newHashSet();
168 for (ClassMapping classMapping : classes()) {
169 // add the class name
170 classNames.add(classMapping.getObfName());
171
172 // add classes from method signatures
173 for (MethodMapping methodMapping : classMapping.methods()) {
174 SignatureUpdater.update(methodMapping.getObfSignature(), new ClassNameUpdater() {
175 @Override
176 public String update(String className) {
177 classNames.add(className);
178 return className;
179 }
180 });
181 }
182 }
183 return classNames;
184 }
185
186 public boolean containsDeobfClass(String deobfName) {
187 return m_classesByDeobf.containsKey(deobfName);
188 }
189
190 public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName) {
191 ClassMapping classMapping = m_classesByObf.get(obfClassEntry.getName());
192 if (classMapping != null) {
193 return classMapping.containsDeobfField(deobfName);
194 }
195 return false;
196 }
197
198 public boolean containsDeobfMethod(ClassEntry obfClassEntry, String deobfName, String deobfSignature) {
199 ClassMapping classMapping = m_classesByObf.get(obfClassEntry.getName());
200 if (classMapping != null) {
201 return classMapping.containsDeobfMethod(deobfName, deobfSignature);
202 }
203 return false;
204 }
205
206 public boolean containsArgument(BehaviorEntry obfBehaviorEntry, String name) {
207 ClassMapping classMapping = m_classesByObf.get(obfBehaviorEntry.getClassName());
208 if (classMapping != null) {
209 return classMapping.containsArgument(obfBehaviorEntry, name);
210 }
211 return false;
212 }
213}