From c4970cc4addedd4565cf8c3ed9ea92b6a4487e0c Mon Sep 17 00:00:00 2001 From: Thomas Guillemard Date: Fri, 12 Aug 2016 19:23:54 +0200 Subject: Implement Enigma directory format (#1) Others changes: ~ Rework File menu ~ Force UTF-8 for all I/O operations ~ Enigma now detect the original file format and use the correct one when you save a mapping--- src/main/java/cuchaz/enigma/CommandMain.java | 4 +- src/main/java/cuchaz/enigma/Deobfuscator.java | 3 +- src/main/java/cuchaz/enigma/Main.java | 2 +- .../bytecode/accessors/ConstInfoAccessor.java | 7 +- src/main/java/cuchaz/enigma/gui/Gui.java | 33 +++-- src/main/java/cuchaz/enigma/gui/GuiController.java | 35 +++-- .../java/cuchaz/enigma/gui/elements/MenuBar.java | 85 +++++++----- .../enigma/gui/filechooser/FileChooserAny.java | 11 ++ src/main/java/cuchaz/enigma/mapping/Mappings.java | 19 ++- .../enigma/mapping/MappingsEnigmaReader.java | 153 +++++++++++++++++++++ .../enigma/mapping/MappingsEnigmaWriter.java | 137 ++++++++++++++++++ .../cuchaz/enigma/mapping/MappingsJsonReader.java | 120 ++++++++++++++++ .../cuchaz/enigma/mapping/MappingsJsonWriter.java | 101 ++++++++++++++ .../cuchaz/enigma/mapping/MappingsOldWriter.java | 88 ------------ .../java/cuchaz/enigma/mapping/MappingsReader.java | 121 ---------------- .../cuchaz/enigma/mapping/MappingsReaderOld.java | 127 ----------------- .../cuchaz/enigma/mapping/MappingsSRGWriter.java | 7 +- .../java/cuchaz/enigma/mapping/MappingsWriter.java | 102 -------------- src/test/java/cuchaz/enigma/TestTranslator.java | 10 +- 19 files changed, 647 insertions(+), 518 deletions(-) create mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java create mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java create mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java create mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsJsonReader.java create mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsJsonWriter.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsOldWriter.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsReader.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsReaderOld.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsWriter.java diff --git a/src/main/java/cuchaz/enigma/CommandMain.java b/src/main/java/cuchaz/enigma/CommandMain.java index d7967b46..4e3f4479 100644 --- a/src/main/java/cuchaz/enigma/CommandMain.java +++ b/src/main/java/cuchaz/enigma/CommandMain.java @@ -15,7 +15,7 @@ import java.util.jar.JarFile; import cuchaz.enigma.Deobfuscator.ProgressListener; import cuchaz.enigma.mapping.Mappings; -import cuchaz.enigma.mapping.MappingsReader; +import cuchaz.enigma.mapping.MappingsJsonReader; public class CommandMain { @@ -119,7 +119,7 @@ public class CommandMain { Deobfuscator deobfuscator = new Deobfuscator(jar); if (fileMappings != null) { System.out.println("Reading mappings..."); - Mappings mappings = new MappingsReader().read(fileMappings); + Mappings mappings = new MappingsJsonReader().read(fileMappings); deobfuscator.setMappings(mappings); } return deobfuscator; diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index d22260fb..8cd80bef 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java @@ -10,6 +10,7 @@ ******************************************************************************/ package cuchaz.enigma; +import com.google.common.base.Charsets; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -277,7 +278,7 @@ public class Deobfuscator { // write the file File file = new File(dirOut, deobfClassEntry.getName().replace('.', '/') + ".java"); file.getParentFile().mkdirs(); - try (FileWriter out = new FileWriter(file)) { + try (OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8)) { out.write(source); } } catch (Throwable t) { diff --git a/src/main/java/cuchaz/enigma/Main.java b/src/main/java/cuchaz/enigma/Main.java index d52e390a..0be1d90c 100644 --- a/src/main/java/cuchaz/enigma/Main.java +++ b/src/main/java/cuchaz/enigma/Main.java @@ -28,7 +28,7 @@ public class Main { gui.getController().openJar(new JarFile(getFile(args[0]))); } if (args.length >= 2) { - gui.getController().openMappings(getFile(args[1])); + gui.getController().openJsonMappings(getFile(args[1])); } // DEBUG diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java index 0ea2d02b..474a3ef0 100644 --- a/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java +++ b/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java @@ -11,10 +11,13 @@ package cuchaz.enigma.bytecode.accessors; import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; +import com.google.common.base.Charsets; import cuchaz.enigma.bytecode.InfoType; public class ConstInfoAccessor { @@ -56,12 +59,12 @@ public class ConstInfoAccessor { public String toString() { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); - PrintWriter out = new PrintWriter(buf); + PrintWriter out = new PrintWriter(new OutputStreamWriter(buf, Charsets.UTF_8)); Method print = this.item.getClass().getMethod("print", PrintWriter.class); print.setAccessible(true); print.invoke(this.item, out); out.close(); - return buf.toString().replace("\n", ""); + return buf.toString("UTF-8").replace("\n", ""); } catch (Exception ex) { throw new Error(ex); } diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java index 5b0b599f..22694760 100644 --- a/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/src/main/java/cuchaz/enigma/gui/Gui.java @@ -34,6 +34,7 @@ import cuchaz.enigma.analysis.*; import cuchaz.enigma.gui.dialog.CrashDialog; import cuchaz.enigma.gui.elements.MenuBar; import cuchaz.enigma.gui.elements.PopupMenuBar; +import cuchaz.enigma.gui.filechooser.FileChooserAny; import cuchaz.enigma.gui.filechooser.FileChooserFile; import cuchaz.enigma.gui.filechooser.FileChooserFolder; import cuchaz.enigma.gui.highlight.DeobfuscatedHighlightPainter; @@ -78,8 +79,8 @@ public class Gui { public EntryReference m_reference; public JFileChooser jarFileChooser; - public JFileChooser mappingsFileChooser; - public JFileChooser oldMappingsFileChooser; + public JFileChooser jsonMappingsFileChooser; + public JFileChooser enigmaMappingsFileChooser; public JFileChooser exportSourceFileChooser; public JFileChooser exportJarFileChooser; @@ -106,10 +107,10 @@ public class Gui { // init file choosers this.jarFileChooser = new FileChooserFile(); - this.mappingsFileChooser = new FileChooserFolder(); + this.jsonMappingsFileChooser = new FileChooserFolder(); - this.oldMappingsFileChooser = new FileChooserFile(); + this.enigmaMappingsFileChooser = new FileChooserAny(); this.exportSourceFileChooser = new FileChooserFolder(); this.exportJarFileChooser = new FileChooserFile(); @@ -315,11 +316,12 @@ public class Gui { // update menu this.menuBar.closeJarMenu.setEnabled(true); - this.menuBar.openOldMappingsMenu.setEnabled(true); - this.menuBar.openMappingsMenu.setEnabled(true); + this.menuBar.openEnigmaMappingsMenu.setEnabled(true); + this.menuBar.openMappingsJsonMenu.setEnabled(true); this.menuBar.saveMappingsMenu.setEnabled(false); - this.menuBar.saveMappingsAsMenu.setEnabled(true); - this.menuBar.saveMappingsOldMenu.setEnabled(true); + this.menuBar.saveMappingsJsonMenu.setEnabled(true); + this.menuBar.saveMappingEnigmaFileMenu.setEnabled(true); + this.menuBar.saveMappingEnigmaDirectoryMenu.setEnabled(true); this.menuBar.saveMappingsSrgMenu.setEnabled(true); this.menuBar.closeMappingsMenu.setEnabled(true); this.menuBar.exportSourceMenu.setEnabled(true); @@ -338,11 +340,12 @@ public class Gui { // update menu this.menuBar.closeJarMenu.setEnabled(false); - this.menuBar.openOldMappingsMenu.setEnabled(false); - this.menuBar.openMappingsMenu.setEnabled(false); + this.menuBar.openEnigmaMappingsMenu.setEnabled(false); + this.menuBar.openMappingsJsonMenu.setEnabled(false); this.menuBar.saveMappingsMenu.setEnabled(false); - this.menuBar.saveMappingsAsMenu.setEnabled(false); - this.menuBar.saveMappingsOldMenu.setEnabled(false); + this.menuBar.saveMappingsJsonMenu.setEnabled(false); + this.menuBar.saveMappingEnigmaFileMenu.setEnabled(false); + this.menuBar.saveMappingEnigmaDirectoryMenu.setEnabled(false); this.menuBar.saveMappingsSrgMenu.setEnabled(false); this.menuBar.closeMappingsMenu.setEnabled(false); this.menuBar.exportSourceMenu.setEnabled(false); @@ -360,7 +363,7 @@ public class Gui { } public void setMappingsFile(File file) { - this.mappingsFileChooser.setSelectedFile(file); + this.jsonMappingsFileChooser.setSelectedFile(file); this.menuBar.saveMappingsMenu.setEnabled(file != null); } @@ -721,9 +724,9 @@ public class Gui { JOptionPane.QUESTION_MESSAGE, null, options, options[2]); switch (response) { case JOptionPane.YES_OPTION: // save and exit - if (this.mappingsFileChooser.getSelectedFile() != null || this.mappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION) { + if (this.jsonMappingsFileChooser.getSelectedFile() != null || this.jsonMappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION) { try { - this.controller.saveMappings(this.mappingsFileChooser.getCurrentDirectory()); + this.controller.saveMappings(this.jsonMappingsFileChooser.getCurrentDirectory()); this.frame.dispose(); } catch (IOException ex) { throw new Error(ex); diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java index fe7d0978..d416345b 100644 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/src/main/java/cuchaz/enigma/gui/GuiController.java @@ -16,7 +16,6 @@ import com.google.common.collect.Queues; import com.strobel.decompiler.languages.java.ast.CompilationUnit; import java.io.File; -import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Collection; @@ -65,18 +64,16 @@ public class GuiController { this.gui.onCloseJar(); } - public void openOldMappings(File file) throws IOException, MappingParseException { - FileReader in = new FileReader(file); - this.deobfuscator.setMappings(new MappingsReaderOld().read(in)); - in.close(); + public void openEnigmaMappings(File file) throws IOException, MappingParseException { + this.deobfuscator.setMappings(new MappingsEnigmaReader().read(file)); this.isDirty = false; this.gui.setMappingsFile(file); refreshClasses(); refreshCurrentClass(); } - public void openMappings(File file) throws IOException { - this.deobfuscator.setMappings(new MappingsReader().read(file)); + public void openJsonMappings(File file) throws IOException { + this.deobfuscator.setMappings(new MappingsJsonReader().read(file)); this.isDirty = false; this.gui.setMappingsFile(file); refreshClasses(); @@ -84,13 +81,29 @@ public class GuiController { } public void saveMappings(File file) throws IOException { - new MappingsWriter().write(file, this.deobfuscator.getMappings()); + Mappings mappings = this.deobfuscator.getMappings(); + switch (mappings.getOriginMappingFormat()) + { + case SRG_FILE: + saveSRGMappings(file); + break; + case JSON_DIRECTORY: + saveJsonMappings(file); + break; + default: + saveEnigmaMappings(file, Mappings.FormatType.ENIGMA_FILE != mappings.getOriginMappingFormat()); + break; + } + + } + + public void saveJsonMappings(File file) throws IOException { + new MappingsJsonWriter().write(file, this.deobfuscator.getMappings()); this.isDirty = false; } - public void saveOldMappings(File file) throws IOException { - FileWriter out = new FileWriter(file); - new MappingsOldWriter().write(out, this.deobfuscator.getMappings()); + public void saveEnigmaMappings(File file, boolean isDirectoryFormat) throws IOException { + new MappingsEnigmaWriter().write(file, this.deobfuscator.getMappings(), isDirectoryFormat); this.isDirty = false; } diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java index e79476bb..e988d74c 100644 --- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java @@ -17,12 +17,13 @@ public class MenuBar extends JMenuBar { public final JMenuItem closeJarMenu; - public final JMenuItem openMappingsMenu; - public final JMenuItem openOldMappingsMenu; + public final JMenuItem openMappingsJsonMenu; + public final JMenuItem openEnigmaMappingsMenu; public final JMenuItem saveMappingsMenu; - public final JMenuItem saveMappingsAsMenu; - public final JMenuItem saveMappingsOldMenu; + public final JMenuItem saveMappingsJsonMenu; + public final JMenuItem saveMappingEnigmaFileMenu; + public final JMenuItem saveMappingEnigmaDirectoryMenu; public final JMenuItem saveMappingsSrgMenu; public final JMenuItem closeMappingsMenu; @@ -62,43 +63,44 @@ public class MenuBar extends JMenuBar { this.closeJarMenu = item; } menu.addSeparator(); + JMenu openMenu = new JMenu("Open Mappings..."); { - JMenuItem item = new JMenuItem("Open Mappings..."); - menu.add(item); + JMenuItem item = new JMenuItem("Enigma"); + openMenu.add(item); item.addActionListener(event -> { - if (this.gui.mappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { try { - this.gui.getController().openMappings(this.gui.mappingsFileChooser.getSelectedFile()); + this.gui.getController().openEnigmaMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile()); } catch (IOException ex) { throw new Error(ex); + } catch (MappingParseException ex) { + JOptionPane.showMessageDialog(this.gui.getFrame(), ex.getMessage()); } } }); - this.openMappingsMenu = item; + this.openEnigmaMappingsMenu = item; } + menu.add(openMenu); { - JMenuItem item = new JMenuItem("Open Old Mappings..."); - menu.add(item); + JMenuItem item = new JMenuItem("JSON (directory)"); + openMenu.add(item); item.addActionListener(event -> { - if (this.gui.oldMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + if (this.gui.jsonMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { try { - this.gui.getController().openOldMappings(this.gui.oldMappingsFileChooser.getSelectedFile()); + this.gui.getController().openJsonMappings(this.gui.jsonMappingsFileChooser.getSelectedFile()); } catch (IOException ex) { throw new Error(ex); - } catch (MappingParseException ex) { - JOptionPane.showMessageDialog(this.gui.getFrame(), ex.getMessage()); } } }); - this.openOldMappingsMenu = item; + this.openMappingsJsonMenu = item; } - menu.addSeparator(); { JMenuItem item = new JMenuItem("Save Mappings"); menu.add(item); item.addActionListener(event -> { try { - this.gui.getController().saveMappings(this.gui.mappingsFileChooser.getSelectedFile()); + this.gui.getController().saveMappings(this.gui.jsonMappingsFileChooser.getSelectedFile()); } catch (IOException ex) { throw new Error(ex); } @@ -106,29 +108,29 @@ public class MenuBar extends JMenuBar { item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); this.saveMappingsMenu = item; } + JMenu saveMenu = new JMenu("Save Mappings As..."); { - JMenuItem item = new JMenuItem("Save Mappings As..."); - menu.add(item); + JMenuItem item = new JMenuItem("Enigma (single file)"); + saveMenu.add(item); item.addActionListener(event -> { - if (this.gui.mappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + if (this.gui.jsonMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { try { - this.gui.getController().saveMappings(this.gui.mappingsFileChooser.getSelectedFile()); + this.gui.getController().saveEnigmaMappings(this.gui.jsonMappingsFileChooser.getSelectedFile(), false); this.saveMappingsMenu.setEnabled(true); } catch (IOException ex) { throw new Error(ex); } } }); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); - this.saveMappingsAsMenu = item; + this.saveMappingEnigmaFileMenu = item; } { - JMenuItem item = new JMenuItem("Save Mappings as Enigma"); - menu.add(item); + JMenuItem item = new JMenuItem("Enigma (directory)"); + saveMenu.add(item); item.addActionListener(event -> { - if (this.gui.mappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + if (this.gui.jsonMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { try { - this.gui.getController().saveOldMappings(this.gui.mappingsFileChooser.getSelectedFile()); + this.gui.getController().saveEnigmaMappings(this.gui.jsonMappingsFileChooser.getSelectedFile(), true); this.saveMappingsMenu.setEnabled(true); } catch (IOException ex) { throw new Error(ex); @@ -136,22 +138,37 @@ public class MenuBar extends JMenuBar { } }); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); - this.saveMappingsOldMenu = item; + this.saveMappingEnigmaDirectoryMenu = item; } + menu.add(saveMenu); { - JMenuItem item = new JMenuItem("Save Mappings as SRG"); - menu.add(item); + JMenuItem item = new JMenuItem("JSON (directory)"); + saveMenu.add(item); item.addActionListener(event -> { - if (this.gui.mappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + if (this.gui.jsonMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { try { - this.gui.getController().saveSRGMappings(this.gui.mappingsFileChooser.getSelectedFile()); + this.gui.getController().saveJsonMappings(this.gui.jsonMappingsFileChooser.getSelectedFile()); + this.saveMappingsMenu.setEnabled(true); + } catch (IOException ex) { + throw new Error(ex); + } + } + }); + this.saveMappingsJsonMenu = item; + } + { + JMenuItem item = new JMenuItem("SRG"); + saveMenu.add(item); + item.addActionListener(event -> { + if (this.gui.jsonMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + try { + this.gui.getController().saveSRGMappings(this.gui.jsonMappingsFileChooser.getSelectedFile()); this.saveMappingsMenu.setEnabled(true); } catch (IOException ex) { throw new Error(ex); } } }); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); this.saveMappingsSrgMenu = item; } { diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java new file mode 100644 index 00000000..23393347 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java @@ -0,0 +1,11 @@ +package cuchaz.enigma.gui.filechooser; + +import javax.swing.*; + +public class FileChooserAny extends JFileChooser +{ + public FileChooserAny() { + this.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + this.setAcceptAllFileFilterUsed(false); + } +} \ No newline at end of file diff --git a/src/main/java/cuchaz/enigma/mapping/Mappings.java b/src/main/java/cuchaz/enigma/mapping/Mappings.java index b51e1a4c..1f4ca02c 100644 --- a/src/main/java/cuchaz/enigma/mapping/Mappings.java +++ b/src/main/java/cuchaz/enigma/mapping/Mappings.java @@ -24,8 +24,15 @@ public class Mappings { protected Map classesByObf; protected Map classesByDeobf; + private final FormatType originMapping; - public Mappings() { + public Mappings() + { + this(FormatType.ENIGMA_DIRECTORY); + } + + public Mappings(FormatType originMapping) { + this.originMapping = originMapping; this.classesByObf = Maps.newHashMap(); this.classesByDeobf = Maps.newHashMap(); } @@ -145,4 +152,14 @@ public class Mappings { } return mappingChain; } + + public FormatType getOriginMappingFormat() + { + return originMapping; + } + + public enum FormatType + { + JSON_DIRECTORY, ENIGMA_FILE, ENIGMA_DIRECTORY, SRG_FILE + } } diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java new file mode 100644 index 00000000..70f3f184 --- /dev/null +++ b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java @@ -0,0 +1,153 @@ +package cuchaz.enigma.mapping; + +import com.google.common.base.Charsets; +import com.google.common.collect.Queues; +import cuchaz.enigma.throwables.MappingConflict; +import cuchaz.enigma.throwables.MappingParseException; + +import java.io.*; +import java.util.Deque; + +public class MappingsEnigmaReader +{ + + public Mappings read(File file) throws IOException, MappingParseException { + Mappings mappings; + + // Multiple file + if (file.isDirectory()) + { + mappings = new Mappings(Mappings.FormatType.ENIGMA_DIRECTORY); + readDirectory(mappings, file); + } + else + { + mappings = new Mappings(); + readFile(mappings, new BufferedReader(new InputStreamReader(new FileInputStream(file), Charsets.UTF_8))); + } + return mappings; + } + + public void readDirectory(Mappings mappings, File directory) throws IOException, MappingParseException { + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isFile()) + readFile(mappings, new BufferedReader(new InputStreamReader(new FileInputStream(file), Charsets.UTF_8))); + else if (file.isDirectory()) + readDirectory(mappings, file.getAbsoluteFile()); + } + } + else + throw new IOException("Cannot access directory" + directory.getAbsolutePath()); + } + + public Mappings readFile(Mappings mappings, BufferedReader in) throws IOException, MappingParseException { + + Deque mappingStack = Queues.newArrayDeque(); + + int lineNumber = 0; + String line; + while ((line = in.readLine()) != null) { + lineNumber++; + + // strip comments + int commentPos = line.indexOf('#'); + if (commentPos >= 0) { + line = line.substring(0, commentPos); + } + + // skip blank lines + if (line.trim().length() <= 0) { + continue; + } + + // get the indent of this line + int indent = 0; + for (int i = 0; i < line.length(); i++) { + if (line.charAt(i) != '\t') { + break; + } + indent++; + } + + // handle stack pops + while (indent < mappingStack.size()) { + mappingStack.pop(); + } + + String[] parts = line.trim().split("\\s"); + try { + // read the first token + String token = parts[0]; + + if (token.equalsIgnoreCase("CLASS")) { + ClassMapping classMapping; + if (indent <= 0) { + // outer class + classMapping = readClass(parts); + mappings.addClassMapping(classMapping); + } else { + + // inner class + if (!(mappingStack.peek() instanceof ClassMapping)) { + throw new MappingParseException(lineNumber, "Unexpected CLASS entry here!"); + } + + classMapping = readClass(parts); + ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); + } + mappingStack.push(classMapping); + } else if (token.equalsIgnoreCase("FIELD")) { + if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { + throw new MappingParseException(lineNumber, "Unexpected FIELD entry here!"); + } + ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); + } else if (token.equalsIgnoreCase("METHOD")) { + if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { + throw new MappingParseException(lineNumber, "Unexpected METHOD entry here!"); + } + MethodMapping methodMapping = readMethod(parts); + ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); + mappingStack.push(methodMapping); + } else if (token.equalsIgnoreCase("ARG")) { + if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { + throw new MappingParseException(lineNumber, "Unexpected ARG entry here!"); + } + ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); + } + } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { + throw new MappingParseException(lineNumber, "Malformed line:\n" + line); + } catch (MappingConflict e) { + e.printStackTrace(); + } + } + in.close(); + return mappings; + } + + private ArgumentMapping readArgument(String[] parts) { + return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]); + } + + private ClassMapping readClass(String[] parts) { + if (parts.length == 2) { + return new ClassMapping(parts[1]); + } else { + return new ClassMapping(parts[1], parts[2]); + } + } + + /* TEMP */ + protected FieldMapping readField(String[] parts) { + return new FieldMapping(parts[1], new Type(parts[3]), parts[2]); + } + + private MethodMapping readMethod(String[] parts) { + if (parts.length == 3) { + return new MethodMapping(parts[1], new Signature(parts[2])); + } else { + return new MethodMapping(parts[1], new Signature(parts[3]), parts[2]); + } + } +} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java new file mode 100644 index 00000000..a3b0616e --- /dev/null +++ b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.mapping; + +import com.google.common.base.Charsets; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MappingsEnigmaWriter { + + public void write(File out, Mappings mappings, boolean isDirectoryFormat) throws IOException { + if (!isDirectoryFormat) + { + PrintWriter outputWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(out), Charsets.UTF_8)); + write(outputWriter, mappings); + outputWriter.close(); + } + else + writeAsDirectory(out, mappings); + } + + public void writeAsDirectory(File target, Mappings mappings) throws IOException { + if (!target.exists() && !target.mkdirs()) + throw new IOException("Cannot create mapping directory!"); + + for (ClassMapping classMapping : sorted(mappings.classes())) { + File obFile = new File(target, classMapping.getObfFullName() + ".mapping"); + File result; + if (classMapping.getDeobfName() == null) + result = obFile; + else + { + // Make sure that old version of the file doesn't exist + if (obFile.exists()) + obFile.delete(); + result = new File(target, classMapping.getDeobfName() + ".mapping"); + } + + if (!result.getParentFile().exists()) + result.getParentFile().mkdirs(); + result.createNewFile(); + PrintWriter outputWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(result), Charsets.UTF_8)); + write(outputWriter, classMapping, 0); + outputWriter.close(); + } + + // Remove empty directories + File[] fileList = target.listFiles(); + if (fileList != null) + { + for (File file : fileList) + { + if (file.isDirectory()) + { + File[] childFiles = file.listFiles(); + if (childFiles != null && childFiles.length == 0) + file.delete(); + } + } + } + + } + + public void write(PrintWriter out, Mappings mappings) throws IOException { + for (ClassMapping classMapping : sorted(mappings.classes())) { + write(out, classMapping, 0); + } + } + + private void write(PrintWriter out, ClassMapping classMapping, int depth) throws IOException { + if (classMapping.getDeobfName() == null) { + out.format("%sCLASS %s\n", getIndent(depth), classMapping.getObfFullName()); + } else { + out.format("%sCLASS %s %s\n", getIndent(depth), classMapping.getObfFullName(), classMapping.getDeobfName()); + } + + for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { + write(out, innerClassMapping, depth + 1); + } + + for (FieldMapping fieldMapping : sorted(classMapping.fields())) { + write(out, fieldMapping, depth + 1); + } + + for (MethodMapping methodMapping : sorted(classMapping.methods())) { + write(out, methodMapping, depth + 1); + } + } + + private void write(PrintWriter out, FieldMapping fieldMapping, int depth) throws IOException { + out.format("%sFIELD %s %s %s\n", getIndent(depth), fieldMapping.getObfName(), fieldMapping.getDeobfName(), fieldMapping.getObfType().toString()); + } + + private void write(PrintWriter out, MethodMapping methodMapping, int depth) throws IOException { + if (methodMapping.getDeobfName() == null) { + out.format("%sMETHOD %s %s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getObfSignature()); + } else { + out.format("%sMETHOD %s %s %s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getDeobfName(), methodMapping.getObfSignature()); + } + + for (ArgumentMapping argumentMapping : sorted(methodMapping.arguments())) { + write(out, argumentMapping, depth + 1); + } + } + + private void write(PrintWriter out, ArgumentMapping argumentMapping, int depth) throws IOException { + out.format("%sARG %d %s\n", getIndent(depth), argumentMapping.getIndex(), argumentMapping.getName()); + } + + private > List sorted(Iterable classes) { + List out = new ArrayList(); + for (T t : classes) { + out.add(t); + } + Collections.sort(out); + return out; + } + + private String getIndent(int depth) { + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < depth; i++) { + buf.append("\t"); + } + return buf.toString(); + } +} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsJsonReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsJsonReader.java new file mode 100644 index 00000000..8f5bde33 --- /dev/null +++ b/src/main/java/cuchaz/enigma/mapping/MappingsJsonReader.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.mapping; + +import com.google.common.base.Charsets; +import com.google.common.io.Files; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.*; + +import cuchaz.enigma.json.JsonClass; +import cuchaz.enigma.throwables.MappingConflict; + +public class MappingsJsonReader { + + public Mappings read(File in) throws IOException { + Mappings mappings = new Mappings(Mappings.FormatType.JSON_DIRECTORY); + readDirectory(mappings, in); + return mappings; + } + + public void readDirectory(Mappings mappings, File in) throws IOException { + File[] fList = in.listFiles(); + if (fList != null) { + for (File file : fList) { + if (file.isFile() && Files.getFileExtension(file.getName()).equalsIgnoreCase("json")) { + readFile(mappings, new BufferedReader(new InputStreamReader(new FileInputStream(file), + Charsets.UTF_8))); + } else if (file.isDirectory()) { + readDirectory(mappings, file.getAbsoluteFile()); + } + } + } + } + + public void readFile(Mappings mappings, BufferedReader in) throws IOException { + StringBuilder buf = new StringBuilder(); + String line; + while ((line = in.readLine()) != null) { + buf.append(line); + } + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + JsonClass jsonClass = gson.fromJson(buf.toString(), JsonClass.class); + try { + load(null, jsonClass, mappings); + } catch (MappingConflict e) { + e.printStackTrace(); + } + in.close(); + } + + public void load(ClassMapping parent, JsonClass jsonClass, Mappings mappings) throws MappingConflict { + ClassMapping classMapping = readClass(jsonClass.getObf(), jsonClass.getName()); + if (parent != null) { + parent.addInnerClassMapping(classMapping); + } else { + mappings.addClassMapping(classMapping); + } + jsonClass.getField().forEach(jsonField -> classMapping.addFieldMapping(readField(jsonField.getObf(), jsonField.getName(), jsonField.getType()))); + + jsonClass.getConstructors().forEach(jsonConstructor -> { + MethodMapping methodMapping = readMethod(jsonConstructor.isStatics() ? "" : "", null, jsonConstructor.getSignature()); + jsonConstructor.getArgs().forEach(jsonArgument -> { + try { + methodMapping.addArgumentMapping(readArgument(jsonArgument.getIndex(), jsonArgument.getName())); + } catch (MappingConflict e) { + e.printStackTrace(); + } + }); + classMapping.addMethodMapping(methodMapping); + }); + + jsonClass.getMethod().forEach(jsonMethod -> { + MethodMapping methodMapping = readMethod(jsonMethod.getObf(), jsonMethod.getName(), jsonMethod.getSignature()); + jsonMethod.getArgs().forEach(jsonArgument -> { + try { + methodMapping.addArgumentMapping(readArgument(jsonArgument.getIndex(), jsonArgument.getName())); + } catch (MappingConflict e) { + e.printStackTrace(); + } + }); + classMapping.addMethodMapping(methodMapping); + }); + + jsonClass.getInnerClass().forEach(jsonInnerClasses -> { + try { + load(classMapping, jsonInnerClasses, mappings); + } catch (MappingConflict e) { + e.printStackTrace(); + } + }); + } + + private ArgumentMapping readArgument(int index, String name) { + return new ArgumentMapping(index, name); + } + + private ClassMapping readClass(String obf, String deobf) { + return new ClassMapping("none/" + obf, deobf); + } + + /* TEMP */ + protected FieldMapping readField(String obf, String deobf, String sig) { + return new FieldMapping(obf, new Type(sig), deobf); + } + + private MethodMapping readMethod(String obf, String deobf, String sig) { + return new MethodMapping(obf, new Signature(sig), deobf); + } +} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsJsonWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsJsonWriter.java new file mode 100644 index 00000000..db95322b --- /dev/null +++ b/src/main/java/cuchaz/enigma/mapping/MappingsJsonWriter.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.mapping; + +import com.google.common.base.Charsets; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import cuchaz.enigma.json.*; + +public class MappingsJsonWriter { + + public void write(File file, Mappings mappings) throws IOException { + if (!file.isDirectory()) { + return; + } + + String[] entries = file.list(); + for (String s : entries) { + File currentFile = new File(file.getPath(), s); + deleteDirectory(currentFile); + } + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + for (ClassMapping classMapping : sorted(mappings.classes())) { + if (classMapping.getDeobfName() != null && !classMapping.getDeobfName().equalsIgnoreCase("") && !classMapping.getDeobfName().equalsIgnoreCase("null")) { + JsonClass jsonClass = new JsonClass(classMapping.getObfSimpleName(), classMapping.getDeobfName()); + write(jsonClass, classMapping); + + File f = new File(file, jsonClass.getName() + ".json"); + f.getParentFile().mkdirs(); + f.createNewFile(); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(f), Charsets.UTF_8)); + writer.write(gson.toJson(jsonClass)); + writer.close(); + } + } + } + + private void write(JsonClass jsonClass, ClassMapping classMapping) { + for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { + JsonClass innerClass = new JsonClass(classMapping.getObfSimpleName() + "$" + innerClassMapping.getObfSimpleName().replace("nome/", ""), innerClassMapping.getDeobfName()); + write(innerClass, innerClassMapping); + jsonClass.addInnerClass(innerClass); + } + + for (FieldMapping fieldMapping : sorted(classMapping.fields())) { + jsonClass.addField(new JsonField(fieldMapping.getObfName(), fieldMapping.getDeobfName(), fieldMapping.getObfType().toString())); + } + + for (MethodMapping methodMapping : sorted(classMapping.methods())) { + List args = new ArrayList<>(); + for (ArgumentMapping argumentMapping : sorted(methodMapping.arguments())) { + args.add(new JsonArgument(argumentMapping.getIndex(), argumentMapping.getName())); + } + if (methodMapping.getObfName().contains("") || methodMapping.getObfName().contains("")) { + jsonClass.addConstructor(new JsonConstructor(methodMapping.getObfSignature().toString(), args, methodMapping.getObfName().contains(""))); + } else { + jsonClass.addMethod(new JsonMethod(methodMapping.getObfName(), methodMapping.getDeobfName(), methodMapping.getObfSignature().toString(), args)); + } + } + } + + private > List sorted(Iterable classes) { + List out = new ArrayList<>(); + for (T t : classes) { + out.add(t); + } + Collections.sort(out); + return out; + } + + public static boolean deleteDirectory(File directory) { + if (directory.exists()) { + File[] files = directory.listFiles(); + if (null != files) { + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + deleteDirectory(files[i]); + } else { + files[i].delete(); + } + } + } + } + return (directory.delete()); + } +} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsOldWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsOldWriter.java deleted file mode 100644 index 8b766a31..00000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsOldWriter.java +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - * - * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.mapping; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class MappingsOldWriter { - - public void write(Writer out, Mappings mappings) throws IOException { - write(new PrintWriter(out), mappings); - } - - public void write(PrintWriter out, Mappings mappings) throws IOException { - for (ClassMapping classMapping : sorted(mappings.classes())) { - write(out, classMapping, 0); - } - } - - private void write(PrintWriter out, ClassMapping classMapping, int depth) throws IOException { - if (classMapping.getDeobfName() == null) { - out.format("%sCLASS %s\n", getIndent(depth), classMapping.getObfFullName()); - } else { - out.format("%sCLASS %s %s\n", getIndent(depth), classMapping.getObfFullName(), classMapping.getDeobfName()); - } - - for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { - write(out, innerClassMapping, depth + 1); - } - - for (FieldMapping fieldMapping : sorted(classMapping.fields())) { - write(out, fieldMapping, depth + 1); - } - - for (MethodMapping methodMapping : sorted(classMapping.methods())) { - write(out, methodMapping, depth + 1); - } - } - - private void write(PrintWriter out, FieldMapping fieldMapping, int depth) throws IOException { - out.format("%sFIELD %s %s %s\n", getIndent(depth), fieldMapping.getObfName(), fieldMapping.getDeobfName(), fieldMapping.getObfType().toString()); - } - - private void write(PrintWriter out, MethodMapping methodMapping, int depth) throws IOException { - if (methodMapping.getDeobfName() == null) { - out.format("%sMETHOD %s %s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getObfSignature()); - } else { - out.format("%sMETHOD %s %s %s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getDeobfName(), methodMapping.getObfSignature()); - } - - for (ArgumentMapping argumentMapping : sorted(methodMapping.arguments())) { - write(out, argumentMapping, depth + 1); - } - } - - private void write(PrintWriter out, ArgumentMapping argumentMapping, int depth) throws IOException { - out.format("%sARG %d %s\n", getIndent(depth), argumentMapping.getIndex(), argumentMapping.getName()); - } - - private > List sorted(Iterable classes) { - List out = new ArrayList(); - for (T t : classes) { - out.add(t); - } - Collections.sort(out); - return out; - } - - private String getIndent(int depth) { - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < depth; i++) { - buf.append("\t"); - } - return buf.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsReader.java deleted file mode 100644 index b2b6d09c..00000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsReader.java +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.mapping; - -import com.google.common.io.Files; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; - -import cuchaz.enigma.json.JsonClass; -import cuchaz.enigma.throwables.MappingConflict; - -public class MappingsReader { - - public Mappings read(File in) throws IOException { - Mappings mappings = new Mappings(); - readDirectory(mappings, in); - return mappings; - } - - public void readDirectory(Mappings mappings, File in) throws IOException { - File[] fList = in.listFiles(); - if (fList != null) { - for (File file : fList) { - if (file.isFile() && Files.getFileExtension(file.getName()).equalsIgnoreCase("json")) { - readFile(mappings, new BufferedReader(new FileReader(file))); - } else if (file.isDirectory()) { - readDirectory(mappings, file.getAbsoluteFile()); - } - } - } - } - - public void readFile(Mappings mappings, BufferedReader in) throws IOException { - StringBuilder buf = new StringBuilder(); - String line; - while ((line = in.readLine()) != null) { - buf.append(line); - } - - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - JsonClass jsonClass = gson.fromJson(buf.toString(), JsonClass.class); - try { - load(null, jsonClass, mappings); - } catch (MappingConflict e) { - e.printStackTrace(); - } - in.close(); - } - - public void load(ClassMapping parent, JsonClass jsonClass, Mappings mappings) throws MappingConflict { - ClassMapping classMapping = readClass(jsonClass.getObf(), jsonClass.getName()); - if (parent != null) { - parent.addInnerClassMapping(classMapping); - } else { - mappings.addClassMapping(classMapping); - } - jsonClass.getField().forEach(jsonField -> classMapping.addFieldMapping(readField(jsonField.getObf(), jsonField.getName(), jsonField.getType()))); - - jsonClass.getConstructors().forEach(jsonConstructor -> { - MethodMapping methodMapping = readMethod(jsonConstructor.isStatics() ? "" : "", null, jsonConstructor.getSignature()); - jsonConstructor.getArgs().forEach(jsonArgument -> { - try { - methodMapping.addArgumentMapping(readArgument(jsonArgument.getIndex(), jsonArgument.getName())); - } catch (MappingConflict e) { - e.printStackTrace(); - } - }); - classMapping.addMethodMapping(methodMapping); - }); - - jsonClass.getMethod().forEach(jsonMethod -> { - MethodMapping methodMapping = readMethod(jsonMethod.getObf(), jsonMethod.getName(), jsonMethod.getSignature()); - jsonMethod.getArgs().forEach(jsonArgument -> { - try { - methodMapping.addArgumentMapping(readArgument(jsonArgument.getIndex(), jsonArgument.getName())); - } catch (MappingConflict e) { - e.printStackTrace(); - } - }); - classMapping.addMethodMapping(methodMapping); - }); - - jsonClass.getInnerClass().forEach(jsonInnerClasses -> { - try { - load(classMapping, jsonInnerClasses, mappings); - } catch (MappingConflict e) { - e.printStackTrace(); - } - }); - } - - private ArgumentMapping readArgument(int index, String name) { - return new ArgumentMapping(index, name); - } - - private ClassMapping readClass(String obf, String deobf) { - return new ClassMapping("none/" + obf, deobf); - } - - /* TEMP */ - protected FieldMapping readField(String obf, String deobf, String sig) { - return new FieldMapping(obf, new Type(sig), deobf); - } - - private MethodMapping readMethod(String obf, String deobf, String sig) { - return new MethodMapping(obf, new Signature(sig), deobf); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsReaderOld.java b/src/main/java/cuchaz/enigma/mapping/MappingsReaderOld.java deleted file mode 100644 index 776d9083..00000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsReaderOld.java +++ /dev/null @@ -1,127 +0,0 @@ -package cuchaz.enigma.mapping; - -import com.google.common.collect.Queues; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.util.Deque; - -import cuchaz.enigma.throwables.MappingConflict; -import cuchaz.enigma.throwables.MappingParseException; - -public class MappingsReaderOld { - - public Mappings read(Reader in) throws IOException, MappingParseException { - return read(new BufferedReader(in)); - } - - public Mappings read(BufferedReader in) throws IOException, MappingParseException { - Mappings mappings = new Mappings(); - Deque mappingStack = Queues.newArrayDeque(); - - int lineNumber = 0; - String line; - while ((line = in.readLine()) != null) { - lineNumber++; - - // strip comments - int commentPos = line.indexOf('#'); - if (commentPos >= 0) { - line = line.substring(0, commentPos); - } - - // skip blank lines - if (line.trim().length() <= 0) { - continue; - } - - // get the indent of this line - int indent = 0; - for (int i = 0; i < line.length(); i++) { - if (line.charAt(i) != '\t') { - break; - } - indent++; - } - - // handle stack pops - while (indent < mappingStack.size()) { - mappingStack.pop(); - } - - String[] parts = line.trim().split("\\s"); - try { - // read the first token - String token = parts[0]; - - if (token.equalsIgnoreCase("CLASS")) { - ClassMapping classMapping; - if (indent <= 0) { - // outer class - classMapping = readClass(parts); - mappings.addClassMapping(classMapping); - } else { - - // inner class - if (!(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(lineNumber, "Unexpected CLASS entry here!"); - } - - classMapping = readClass(parts); - ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); - } - mappingStack.push(classMapping); - } else if (token.equalsIgnoreCase("FIELD")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(lineNumber, "Unexpected FIELD entry here!"); - } - ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); - } else if (token.equalsIgnoreCase("METHOD")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(lineNumber, "Unexpected METHOD entry here!"); - } - MethodMapping methodMapping = readMethod(parts); - ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); - mappingStack.push(methodMapping); - } else if (token.equalsIgnoreCase("ARG")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { - throw new MappingParseException(lineNumber, "Unexpected ARG entry here!"); - } - ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); - } - } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { - throw new MappingParseException(lineNumber, "Malformed line:\n" + line); - } catch (MappingConflict e) { - e.printStackTrace(); - } - } - - return mappings; - } - - private ArgumentMapping readArgument(String[] parts) { - return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]); - } - - private ClassMapping readClass(String[] parts) { - if (parts.length == 2) { - return new ClassMapping(parts[1]); - } else { - return new ClassMapping(parts[1], parts[2]); - } - } - - /* TEMP */ - protected FieldMapping readField(String[] parts) { - return new FieldMapping(parts[1], new Type(parts[3]), parts[2]); - } - - private MethodMapping readMethod(String[] parts) { - if (parts.length == 3) { - return new MethodMapping(parts[1], new Signature(parts[2])); - } else { - return new MethodMapping(parts[1], new Signature(parts[3]), parts[2]); - } - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java index 64da7091..a05b9158 100644 --- a/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java +++ b/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java @@ -1,10 +1,9 @@ package cuchaz.enigma.mapping; +import com.google.common.base.Charsets; import cuchaz.enigma.Deobfuscator; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -22,7 +21,7 @@ public class MappingsSRGWriter { Mappings mappings = deobfuscator.getMappings(); - FileWriter writer = new FileWriter(file); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8)); List fieldMappings = new ArrayList<>(); List methodMappings = new ArrayList<>(); for (ClassMapping classMapping : sorted(mappings.classes())) { diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsWriter.java deleted file mode 100644 index 47931662..00000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsWriter.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.mapping; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import cuchaz.enigma.json.*; - -public class MappingsWriter { - - public void write(File file, Mappings mappings) throws IOException { - if (!file.isDirectory()) { - return; - } - - String[] entries = file.list(); - for (String s : entries) { - File currentFile = new File(file.getPath(), s); - deleteDirectory(currentFile); - } - - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - for (ClassMapping classMapping : sorted(mappings.classes())) { - if (classMapping.getDeobfName() != null && !classMapping.getDeobfName().equalsIgnoreCase("") && !classMapping.getDeobfName().equalsIgnoreCase("null")) { - JsonClass jsonClass = new JsonClass(classMapping.getObfSimpleName(), classMapping.getDeobfName()); - write(jsonClass, classMapping); - - File f = new File(file, jsonClass.getName() + ".json"); - f.getParentFile().mkdirs(); - f.createNewFile(); - FileWriter writer = new FileWriter(f); - writer.write(gson.toJson(jsonClass)); - writer.close(); - } - } - } - - private void write(JsonClass jsonClass, ClassMapping classMapping) { - for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { - JsonClass innerClass = new JsonClass(classMapping.getObfSimpleName() + "$" + innerClassMapping.getObfSimpleName().replace("nome/", ""), innerClassMapping.getDeobfName()); - write(innerClass, innerClassMapping); - jsonClass.addInnerClass(innerClass); - } - - for (FieldMapping fieldMapping : sorted(classMapping.fields())) { - jsonClass.addField(new JsonField(fieldMapping.getObfName(), fieldMapping.getDeobfName(), fieldMapping.getObfType().toString())); - } - - for (MethodMapping methodMapping : sorted(classMapping.methods())) { - List args = new ArrayList<>(); - for (ArgumentMapping argumentMapping : sorted(methodMapping.arguments())) { - args.add(new JsonArgument(argumentMapping.getIndex(), argumentMapping.getName())); - } - if (methodMapping.getObfName().contains("") || methodMapping.getObfName().contains("")) { - jsonClass.addConstructor(new JsonConstructor(methodMapping.getObfSignature().toString(), args, methodMapping.getObfName().contains(""))); - } else { - jsonClass.addMethod(new JsonMethod(methodMapping.getObfName(), methodMapping.getDeobfName(), methodMapping.getObfSignature().toString(), args)); - } - } - } - - private > List sorted(Iterable classes) { - List out = new ArrayList<>(); - for (T t : classes) { - out.add(t); - } - Collections.sort(out); - return out; - } - - public static boolean deleteDirectory(File directory) { - if (directory.exists()) { - File[] files = directory.listFiles(); - if (null != files) { - for (int i = 0; i < files.length; i++) { - if (files[i].isDirectory()) { - deleteDirectory(files[i]); - } else { - files[i].delete(); - } - } - } - } - return (directory.delete()); - } -} diff --git a/src/test/java/cuchaz/enigma/TestTranslator.java b/src/test/java/cuchaz/enigma/TestTranslator.java index dcdced01..dddfb704 100644 --- a/src/test/java/cuchaz/enigma/TestTranslator.java +++ b/src/test/java/cuchaz/enigma/TestTranslator.java @@ -11,20 +11,12 @@ package cuchaz.enigma; import static cuchaz.enigma.TestEntryFactory.*; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.jar.JarFile; import org.junit.BeforeClass; import org.junit.Test; import cuchaz.enigma.mapping.Entry; import cuchaz.enigma.mapping.Mappings; -import cuchaz.enigma.mapping.MappingsReader; -import cuchaz.enigma.mapping.TranslationDirection; import cuchaz.enigma.mapping.Translator; @@ -41,7 +33,7 @@ public class TestTranslator { //TODO FIx //m_deobfuscator = new Deobfuscator(new JarFile("build/test-obf/translation.jar")); //try (InputStream in = TestTranslator.class.getResourceAsStream("/cuchaz/enigma/resources/translation.mappings")) { - // m_mappings = new MappingsReader().read(new InputStreamReader(in)); + // m_mappings = new MappingsJsonReader().read(new InputStreamReader(in)); // m_deobfuscator.setMappings(m_mappings); // m_deobfTranslator = m_deobfuscator.getTranslator(TranslationDirection.Deobfuscating); // m_obfTranslator = m_deobfuscator.getTranslator(TranslationDirection.Obfuscating); -- cgit v1.2.3