summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/mapping/Mappings.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/mapping/Mappings.java')
-rw-r--r--src/main/java/cuchaz/enigma/mapping/Mappings.java268
1 files changed, 0 insertions, 268 deletions
diff --git a/src/main/java/cuchaz/enigma/mapping/Mappings.java b/src/main/java/cuchaz/enigma/mapping/Mappings.java
deleted file mode 100644
index c865079..0000000
--- a/src/main/java/cuchaz/enigma/mapping/Mappings.java
+++ /dev/null
@@ -1,268 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.mapping;
13
14import com.google.common.collect.Lists;
15import com.google.common.collect.Maps;
16import com.google.common.collect.Sets;
17import cuchaz.enigma.analysis.TranslationIndex;
18import cuchaz.enigma.api.EnigmaPlugin;
19import cuchaz.enigma.bytecode.AccessFlags;
20import cuchaz.enigma.mapping.entry.ClassEntry;
21import cuchaz.enigma.mapping.entry.MethodEntry;
22import cuchaz.enigma.throwables.MappingConflict;
23
24import java.io.File;
25import java.io.IOException;
26import java.util.*;
27import java.util.stream.Collectors;
28
29public class Mappings {
30
31 private final FormatType originMapping;
32 protected Map<String, ClassMapping> classesByObf;
33 protected Map<String, ClassMapping> classesByDeobf;
34 private Mappings previousState;
35
36 public Mappings() {
37 this(FormatType.ENIGMA_DIRECTORY);
38 }
39
40 public Mappings(FormatType originMapping) {
41 this.originMapping = originMapping;
42 this.classesByObf = Maps.newHashMap();
43 this.classesByDeobf = Maps.newHashMap();
44 }
45
46 public Collection<ClassMapping> classes() {
47 assert (this.classesByObf.size() >= this.classesByDeobf.size());
48 return this.classesByObf.values();
49 }
50
51 public void addClassMapping(ClassMapping classMapping) throws MappingConflict {
52 if (this.classesByObf.containsKey(classMapping.getObfFullName())) {
53 throw new MappingConflict("class", classMapping.getObfFullName(), this.classesByObf.get(classMapping.getObfFullName()).getObfFullName());
54 }
55 this.classesByObf.put(classMapping.getObfFullName(), classMapping);
56
57 if (classMapping.getDeobfName() != null) {
58 if (this.classesByDeobf.containsKey(classMapping.getDeobfName())) {
59 throw new MappingConflict("class", classMapping.getDeobfName(), this.classesByDeobf.get(classMapping.getDeobfName()).getDeobfName());
60 }
61 this.classesByDeobf.put(classMapping.getDeobfName(), classMapping);
62 }
63 }
64
65 public void removeClassMapping(ClassMapping classMapping) {
66 boolean obfWasRemoved = this.classesByObf.remove(classMapping.getObfFullName()) != null;
67 assert (obfWasRemoved);
68 if (classMapping.getDeobfName() != null) {
69 boolean deobfWasRemoved = this.classesByDeobf.remove(classMapping.getDeobfName()) != null;
70 assert (deobfWasRemoved);
71 }
72 }
73
74 public ClassMapping getClassByObf(ClassEntry entry) {
75 return getClassByObf(entry.getName());
76 }
77
78 public ClassMapping getClassByObf(String obfName) {
79 return this.classesByObf.get(obfName);
80 }
81
82 public ClassMapping getClassByDeobf(ClassEntry entry) {
83 return getClassByDeobf(entry.getName());
84 }
85
86 public ClassMapping getClassByDeobf(String deobfName) {
87 return this.classesByDeobf.get(deobfName);
88 }
89
90 public void setClassDeobfName(ClassMapping classMapping, String deobfName) {
91 if (classMapping.getDeobfName() != null) {
92 boolean wasRemoved = this.classesByDeobf.remove(classMapping.getDeobfName()) != null;
93 assert (wasRemoved);
94 }
95 classMapping.setDeobfName(deobfName);
96 if (deobfName != null) {
97 boolean wasAdded = this.classesByDeobf.put(deobfName, classMapping) == null;
98 assert (wasAdded);
99 }
100 }
101
102 public Translator getTranslator(TranslationDirection direction, TranslationIndex index) {
103 switch (direction) {
104 case DEOBFUSCATING:
105
106 return new DirectionalTranslator(direction, this.classesByObf, index);
107
108 case OBFUSCATING:
109
110 // fill in the missing deobf class entries with obf entries
111 Map<String, ClassMapping> classes = Maps.newHashMap();
112 for (ClassMapping classMapping : classes()) {
113 if (classMapping.getDeobfName() != null) {
114 classes.put(classMapping.getDeobfName(), classMapping);
115 } else {
116 classes.put(classMapping.getObfFullName(), classMapping);
117 }
118 }
119
120 // translate the translation index
121 // NOTE: this isn't actually recursive
122 TranslationIndex deobfIndex = new TranslationIndex(index, getTranslator(TranslationDirection.DEOBFUSCATING, index));
123
124 return new DirectionalTranslator(direction, classes, deobfIndex);
125
126 default:
127 throw new Error("Invalid translation direction!");
128 }
129 }
130
131 @Override
132 public String toString() {
133 StringBuilder buf = new StringBuilder();
134 for (ClassMapping classMapping : this.classesByObf.values()) {
135 buf.append(classMapping);
136 buf.append("\n");
137 }
138 return buf.toString();
139 }
140
141 public void renameObfClass(String oldObfName, String newObfName) {
142 new ArrayList<>(classes()).stream().filter(classMapping -> classMapping.renameObfClass(oldObfName, newObfName)).forEach(classMapping -> {
143 boolean wasRemoved = this.classesByObf.remove(oldObfName) != null;
144 assert (wasRemoved);
145 boolean wasAdded = this.classesByObf.put(newObfName, classMapping) == null;
146 assert (wasAdded);
147 });
148 }
149
150 public Set<String> getAllObfClassNames() {
151 final Set<String> classNames = Sets.newHashSet();
152 for (ClassMapping classMapping : classes()) {
153
154 // add the class name
155 classNames.add(classMapping.getObfFullName());
156
157 // add classes from method signatures
158 for (MethodMapping methodMapping : classMapping.methods()) {
159 for (TypeDescriptor desc : methodMapping.getObfDesc().types()) {
160 if (desc.containsType()) {
161 classNames.add(desc.getTypeEntry().getClassName());
162 }
163 }
164 }
165 }
166 return classNames;
167 }
168
169 public boolean containsDeobfClass(String deobfName) {
170 return this.classesByDeobf.containsKey(deobfName);
171 }
172
173 public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName, TypeDescriptor obfDesc) {
174 ClassMapping classMapping = this.classesByObf.get(obfClassEntry.getName());
175 return classMapping != null && classMapping.containsDeobfField(deobfName, obfDesc);
176 }
177
178 public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName) {
179 ClassMapping classMapping = this.classesByObf.get(obfClassEntry.getName());
180 if (classMapping != null)
181 for (FieldMapping fieldMapping : classMapping.fields())
182 if (deobfName.equals(fieldMapping.getDeobfName()) || deobfName.equals(fieldMapping.getObfName()))
183 return true;
184
185 return false;
186 }
187
188 public boolean containsDeobfMethod(ClassEntry obfClassEntry, String deobfName, MethodDescriptor obfDescriptor) {
189 ClassMapping classMapping = this.classesByObf.get(obfClassEntry.getName());
190 return classMapping != null && classMapping.containsDeobfMethod(deobfName, obfDescriptor);
191 }
192
193 public boolean containsArgument(MethodEntry obfMethodEntry, String name) {
194 ClassMapping classMapping = this.classesByObf.get(obfMethodEntry.getClassName());
195 return classMapping != null && classMapping.containsArgument(obfMethodEntry, name);
196 }
197
198 public List<ClassMapping> getClassMappingChain(ClassEntry obfClass) {
199 List<ClassMapping> mappingChain = Lists.newArrayList();
200 ClassMapping classMapping = null;
201 for (ClassEntry obfClassEntry : obfClass.getClassChain()) {
202 if (mappingChain.isEmpty()) {
203 classMapping = this.classesByObf.get(obfClassEntry.getName());
204 } else if (classMapping != null) {
205 classMapping = classMapping.getInnerClassByObfSimple(obfClassEntry.getInnermostClassName());
206 }
207 mappingChain.add(classMapping);
208 }
209 return mappingChain;
210 }
211
212 public FormatType getOriginMappingFormat() {
213 return originMapping;
214 }
215
216 public void savePreviousState() {
217 this.previousState = new Mappings(this.originMapping);
218 this.previousState.classesByDeobf = new HashMap<>();
219 for (Map.Entry<String, ClassMapping> entry : this.classesByDeobf.entrySet()) {
220 this.previousState.classesByDeobf.put(entry.getKey(), entry.getValue().copy());
221 }
222 this.previousState.classesByObf = new HashMap<>();
223 for (Map.Entry<String, ClassMapping> entry : this.classesByObf.entrySet()) {
224 this.previousState.classesByObf.put(entry.getKey(), entry.getValue().copy());
225 }
226 classesByDeobf.values().forEach(ClassMapping::resetDirty);
227 classesByObf.values().forEach(ClassMapping::resetDirty);
228 }
229
230 public void saveEnigmaMappings(File file, boolean isDirectoryFormat) throws IOException {
231 new MappingsEnigmaWriter().write(file, this, isDirectoryFormat);
232 this.savePreviousState();
233 }
234
235 public void saveSRGMappings(File file) throws IOException {
236 new MappingsSRGWriter().write(file, this);
237 }
238
239 public Mappings getPreviousState() {
240 return previousState;
241 }
242
243 public enum FormatType {
244 ENIGMA_FILE, ENIGMA_DIRECTORY, TINY_FILE, SRG_FILE
245 }
246
247 public enum EntryModifier {
248 UNCHANGED, PUBLIC, PROTECTED, PRIVATE;
249
250 public String getFormattedName() {
251 return " ACC:" + super.toString();
252 }
253
254 public AccessFlags transform(AccessFlags access) {
255 switch (this) {
256 case PUBLIC:
257 return access.setPublic();
258 case PROTECTED:
259 return access.setProtected();
260 case PRIVATE:
261 return access.setPrivate();
262 case UNCHANGED:
263 default:
264 return access;
265 }
266 }
267 }
268}