diff --git a/src/main/java/net/md_5/specialsource/CSVMappingTransformer.java b/src/main/java/net/md_5/specialsource/CSVMappingTransformer.java new file mode 100644 index 0000000..ac91ec2 --- /dev/null +++ b/src/main/java/net/md_5/specialsource/CSVMappingTransformer.java @@ -0,0 +1,87 @@ +/** + * 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. + * + * The name of the author may not 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 au.com.bytecode.opencsv.CSVReader; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * For reading a .srg through MCP's fields.csv and methods.csv + * Maps func_### and field_### in input srg to "descriptive" names + */ +public class CSVMappingTransformer extends JarMappingLoadTransformer { + + private final Map fieldMap; + private final Map methodMap; + + public CSVMappingTransformer(File fieldsCsv, File methodsCsv) throws IOException { + fieldMap = new HashMap(); + methodMap = new HashMap(); + + readIntoMap(fieldsCsv, fieldMap); + readIntoMap(methodsCsv, methodMap); + } + + private void readIntoMap(File file, Map map) throws IOException { + CSVReader csvReader = new CSVReader(new FileReader(file)); + String[] line; + + while ((line = csvReader.readNext()) != null) { + if (line.length == 0) { + continue; + } + + if (line.length < 4) { + throw new IllegalArgumentException("Invalid csv line: " + line); + } + + String numericName = line[0]; + String descriptiveName = line[1]; + //String side = line[2]; + //String javadoc = line[3]; + + map.put(numericName, descriptiveName); + } + } + + @Override + public String transformFieldName(String fieldName) { + return fieldMap.get(fieldName); + } + + @Override + public String transformMethodName(String methodName) { + return methodMap.get(methodName); + } +} diff --git a/src/main/java/net/md_5/specialsource/JarMapping.java b/src/main/java/net/md_5/specialsource/JarMapping.java index f42d9fb..8d74a16 100644 --- a/src/main/java/net/md_5/specialsource/JarMapping.java +++ b/src/main/java/net/md_5/specialsource/JarMapping.java @@ -44,7 +44,8 @@ public class JarMapping { public JarMapping() { } - public JarMapping(BufferedReader reader, JarMappingInputTransformer shader) throws IOException { + @Deprecated + public JarMapping(BufferedReader reader, ShadeRelocationSimulator shader) throws IOException { loadMappings(reader, shader); } @@ -106,7 +107,7 @@ public class JarMapping { int n = spec.lastIndexOf('@'); String path; - JarMappingInputTransformer inputTransformer; + JarMappingLoadTransformer inputTransformer; if (n == -1) { path = spec; @@ -118,7 +119,7 @@ public class JarMapping { BufferedReader reader = new BufferedReader(new FileReader(path)); - loadMappings(reader, inputTransformer); + loadMappings(reader, inputTransformer, null); } /** @@ -157,27 +158,43 @@ public class JarMapping { throw new IOException("loadMappingsDir("+dir+"): no joined.srg, client.srg, or client.srg found"); } - // TODO: read through csv mappings + // Read output names through csv mappings, if available File fieldsCsv = new File(dir.getPath() + sep + "fields.csv"); File methodsCsv = new File(dir.getPath() + sep + "methods.csv"); + CSVMappingTransformer outputTransformer; + + if (fieldsCsv.exists() && methodsCsv.exists()) { + // they want descriptive "csv" names + outputTransformer = new CSVMappingTransformer(fieldsCsv, methodsCsv); + } else { + // they want numeric "srg" names, for some reason + outputTransformer = null; + } + for (File srg : srgFiles) { - loadMappings(srg); + loadMappings(new BufferedReader(new FileReader(srg)), null, outputTransformer); } } public void loadMappings(File file) throws IOException { - loadMappings(new BufferedReader(new FileReader(file)), null); + loadMappings(new BufferedReader(new FileReader(file)), null, null); + } + + @Deprecated + public void loadMappings(BufferedReader reader, ShadeRelocationSimulator shader) throws IOException { + loadMappings(reader, (JarMappingLoadTransformer) shader, null); } /** * Load a mapping given a .csrg file * * @param reader Mapping file reader - * @param inputTransformer Transformation to apply to old class names, or null + * @param inputTransformer Transformation to apply on input + * @param outputTransformer Transformation to apply on output * @throws IOException */ - public void loadMappings(BufferedReader reader, JarMappingInputTransformer inputTransformer) throws IOException { + public void loadMappings(BufferedReader reader, JarMappingLoadTransformer inputTransformer, JarMappingLoadTransformer outputTransformer) throws IOException { if (inputTransformer == null) { inputTransformer = ShadeRelocationSimulator.IDENTITY; } @@ -190,10 +207,10 @@ public class JarMapping { if (line.contains(":")) { // standard srg - parseSrgLine(line, inputTransformer); + parseSrgLine(line, inputTransformer, outputTransformer); } else { // better 'compact' srg format - parseCsrgLine(line, inputTransformer); + parseCsrgLine(line, inputTransformer, outputTransformer); } } } @@ -201,12 +218,12 @@ public class JarMapping { /** * Parse a 'csrg' mapping format line and populate the data structures */ - private void parseCsrgLine(String line, JarMappingInputTransformer inputTransformer) throws IOException { + private void parseCsrgLine(String line, JarMappingLoadTransformer inputTransformer, JarMappingLoadTransformer outputTransformer) throws IOException { String[] tokens = line.split(" "); if (tokens.length == 2) { String oldClassName = inputTransformer.transformClassName(tokens[0]); - String newClassName = tokens[1]; + String newClassName = outputTransformer.transformClassName(tokens[1]); if (oldClassName.endsWith("/")) { // Special case: mapping an entire hierarchy of classes @@ -216,14 +233,14 @@ public class JarMapping { } } else if (tokens.length == 3) { String oldClassName = inputTransformer.transformClassName(tokens[0]); - String oldFieldName = tokens[1]; - String newFieldName = tokens[2]; + String oldFieldName = inputTransformer.transformFieldName(tokens[1]); + String newFieldName = outputTransformer.transformFieldName(tokens[2]); fields.put(oldClassName + "/" + oldFieldName, newFieldName); } else if (tokens.length == 4) { String oldClassName = inputTransformer.transformClassName(tokens[0]); - String oldMethodName = tokens[1]; + String oldMethodName = inputTransformer.transformMethodName(tokens[1]); String oldMethodDescriptor = inputTransformer.transformMethodDescriptor(tokens[2]); - String newMethodName = tokens[3]; + String newMethodName = outputTransformer.transformMethodName(tokens[3]); methods.put(oldClassName + "/" + oldMethodName + " " + oldMethodDescriptor, newMethodName); } else { throw new IOException("Invalid csrg file line, token count " + tokens.length + " unexpected in "+line); @@ -233,13 +250,13 @@ public class JarMapping { /** * Parse a standard 'srg' mapping format line and populate the data structures */ - private void parseSrgLine(String line, JarMappingInputTransformer inputTransformer) throws IOException { + private void parseSrgLine(String line, JarMappingLoadTransformer inputTransformer, JarMappingLoadTransformer outputTransformer) throws IOException { String[] tokens = line.split(" "); String kind = tokens[0]; if (kind.equals("CL:")) { String oldClassName = inputTransformer.transformClassName(tokens[1]); - String newClassName = tokens[2]; + String newClassName = outputTransformer.transformClassName(tokens[2]); if (classes.containsKey(oldClassName) && !newClassName.equals(classes.get(oldClassName))) { throw new IllegalArgumentException("Duplicate class mapping: " + oldClassName + " -> " + newClassName + @@ -248,8 +265,8 @@ public class JarMapping { classes.put(oldClassName, newClassName); } else if (kind.equals("PK:")) { - String oldPackageName = tokens[1]; - String newPackageName = tokens[2]; + String oldPackageName = inputTransformer.transformClassName(tokens[1]); + String newPackageName = outputTransformer.transformClassName(tokens[2]); if (packages.containsKey(oldPackageName) && !newPackageName.equals(packages.get(oldPackageName))) { throw new IllegalArgumentException("Duplicate package mapping: " + oldPackageName + " ->" + newPackageName + @@ -270,16 +287,16 @@ public class JarMapping { } String oldClassName = inputTransformer.transformClassName(oldFull.substring(0, splitOld)); - String oldFieldName = oldFull.substring(splitOld + 1); + String oldFieldName = inputTransformer.transformFieldName(oldFull.substring(splitOld + 1)); //String newClassName = newFull.substring(0, splitNew); // redundant and ignored - String newFieldName = newFull.substring(splitNew + 1); + String newFieldName = outputTransformer.transformFieldName(newFull.substring(splitNew + 1)); fields.put(oldClassName + "/" + oldFieldName, newFieldName); } else if (kind.equals("MD:")) { String oldFull = tokens[1]; String oldMethodDescriptor = inputTransformer.transformMethodDescriptor(tokens[2]); String newFull = tokens[3]; - //String newMethodDescriptor = tokens[4]; // redundant and ignored + //String newMethodDescriptor = outputTransformer.transformMethodDescriptor(tokens[4]); // redundant and ignored // Split the qualified field names into their classes and actual names TODO: refactor with above int splitOld = oldFull.lastIndexOf('/'); @@ -290,9 +307,9 @@ public class JarMapping { } String oldClassName = inputTransformer.transformClassName(oldFull.substring(0, splitOld)); - String oldMethodName = oldFull.substring(splitOld + 1); - //String newClassName = newFull.substring(0, splitNew); // redundant and ignored - String newMethodName = newFull.substring(splitNew + 1); + String oldMethodName = inputTransformer.transformMethodName(oldFull.substring(splitOld + 1)); + //String newClassName = outputTransformer.transformClassName(newFull.substring(0, splitNew)); // redundant and ignored + String newMethodName = outputTransformer.transformMethodName(newFull.substring(splitNew + 1)); methods.put(oldClassName + "/" + oldMethodName + " " + oldMethodDescriptor, newMethodName); } else { diff --git a/src/main/java/net/md_5/specialsource/JarMappingInputTransformer.java b/src/main/java/net/md_5/specialsource/JarMappingInputTransformer.java deleted file mode 100644 index d1329e8..0000000 --- a/src/main/java/net/md_5/specialsource/JarMappingInputTransformer.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.md_5.specialsource; - -/** - * Transform mapping files while reading as input - */ -public interface JarMappingInputTransformer { - - public String transformClassName(String className); - - public String transformMethodDescriptor(String oldDescriptor); -} diff --git a/src/main/java/net/md_5/specialsource/JarMappingLoadTransformer.java b/src/main/java/net/md_5/specialsource/JarMappingLoadTransformer.java new file mode 100644 index 0000000..7c96b62 --- /dev/null +++ b/src/main/java/net/md_5/specialsource/JarMappingLoadTransformer.java @@ -0,0 +1,54 @@ +/** + * 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. + * + * The name of the author may not 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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; + +/** + * Transform mapping files while loading (only) + * + * TODO: refactor with JarRemapper? + */ +public abstract class JarMappingLoadTransformer { + + public String transformClassName(String className) { + return className; + } + + public String transformFieldName(String fieldName) { + return fieldName; + } + + public String transformMethodName(String methodName) { + return methodName; + } + + public String transformMethodDescriptor(String oldDescriptor) { + return oldDescriptor; + } + +} diff --git a/src/main/java/net/md_5/specialsource/ShadeRelocationSimulator.java b/src/main/java/net/md_5/specialsource/ShadeRelocationSimulator.java index a08eff4..a739017 100644 --- a/src/main/java/net/md_5/specialsource/ShadeRelocationSimulator.java +++ b/src/main/java/net/md_5/specialsource/ShadeRelocationSimulator.java @@ -34,7 +34,7 @@ import java.util.*; * Simulate a small subset of the maven-shade-plugin class relocation * functionality */ -public class ShadeRelocationSimulator implements JarMappingInputTransformer { +public class ShadeRelocationSimulator extends JarMappingLoadTransformer { public LinkedHashMap relocations = new LinkedHashMap(); // No relocations @@ -77,6 +77,7 @@ public class ShadeRelocationSimulator implements JarMappingInputTransformer { this(Arrays.asList(string.split(","))); } + @Override public String transformClassName(String className) { for (Map.Entry entry : relocations.entrySet()) { String pattern = entry.getKey(); @@ -93,6 +94,7 @@ public class ShadeRelocationSimulator implements JarMappingInputTransformer { return className; } + @Override public String transformMethodDescriptor(String oldDescriptor) { MethodDescriptorTransformer methodDescriptorTransformer = new MethodDescriptorTransformer(relocations, null); return methodDescriptorTransformer.transform(oldDescriptor);