/*
* A Gradle plugin for the creation of Minecraft mods and MinecraftForge plugins.
* Copyright (C) 2013 Minecraft Forge
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
package net.minecraftforge.gradle.patcher;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;
import net.md_5.specialsource.Jar;
import net.md_5.specialsource.JarMapping;
import net.md_5.specialsource.JarRemapper;
import net.md_5.specialsource.provider.ClassLoaderProvider;
import net.md_5.specialsource.provider.JarProvider;
import net.md_5.specialsource.provider.JointProvider;
import net.minecraftforge.gradle.common.Constants;
import net.minecraftforge.gradle.util.mcp.ReobfExceptor;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
class TaskReobfuscate extends DefaultTask
{
//@formatter:off
@InputFile private Object inJar;
@InputFile private Object preFFJar;
@InputFile private Object srg;
@InputFile private Object exc;
@InputFile private Object methodsCsv;
@InputFile private Object fieldsCsv;
@OutputFile private Object outJar;
//@formatter: on
@Input
private LinkedList<String> extraSrg = new LinkedList<String>();
@InputFiles
private List<Object> libs = Lists.newArrayList();
//@formatter:off
public TaskReobfuscate() { super(); }
//@formatter:on
@TaskAction
public void doTask() throws IOException
{
File inJar = getInJar();
File srg = getSrg();
{
ReobfExceptor exceptor = new ReobfExceptor();
exceptor.toReobfJar = inJar;
exceptor.deobfJar = getPreFFJar();
exceptor.excConfig = getExc();
exceptor.fieldCSV = getFieldsCsv();
exceptor.methodCSV = getMethodsCsv();
File outSrg = new File(this.getTemporaryDir(), "reobf_cls.srg");
exceptor.doFirstThings();
exceptor.buildSrg(srg, outSrg);
srg = outSrg;
}
// append SRG
BufferedWriter writer = new BufferedWriter(new FileWriter(srg, true));
for (String line : extraSrg)
{
writer.write(line);
writer.newLine();
}
writer.flush();
writer.close();
obfuscate(inJar, getLibs(), srg);
}
private void obfuscate(File inJar, FileCollection classpath, File srg) throws FileNotFoundException, IOException
{
// load mapping
JarMapping mapping = new JarMapping();
mapping.loadMappings(Files.newReader(srg, Charset.defaultCharset()), null, null, false);
// make remapper
JarRemapper remapper = new JarRemapper(null, mapping);
// load jar
Jar input = Jar.init(inJar);
// ensure that inheritance provider is used
JointProvider inheritanceProviders = new JointProvider();
inheritanceProviders.add(new JarProvider(input));
if (classpath != null)
inheritanceProviders.add(new ClassLoaderProvider(new URLClassLoader(Constants.toUrls(classpath))));
mapping.setFallbackInheritanceProvider(inheritanceProviders);
File out = getOutJar();
if (!out.getParentFile().exists()) //Needed because SS doesn't create it.
{
out.getParentFile().mkdirs();
}
// remap jar
remapper.remapJar(input, getOutJar());
}
public File getInJar()
{
return getProject().file(inJar);
}
public void setInJar(Object inJar)
{
this.inJar = inJar;
}
public File getOutJar()
{
return getProject().file(outJar);
}
public void setOutJar(Object outJar)
{
this.outJar = outJar;
}
public File getPreFFJar()
{
return getProject().file(preFFJar);
}
public void setPreFFJar(Object preFFJar)
{
this.preFFJar = preFFJar;
}
public File getSrg()
{
return getProject().file(srg);
}
public void setSrg(Object srg)
{
this.srg = srg;
}
public File getExc()
{
return getProject().file(exc);
}
public void setExc(Object exc)
{
this.exc = exc;
}
public File getMethodsCsv()
{
return getProject().file(methodsCsv);
}
public void setMethodsCsv(Object methodsCsv)
{
this.methodsCsv = methodsCsv;
}
public File getFieldsCsv()
{
return getProject().file(fieldsCsv);
}
public void setFieldsCsv(Object fieldsCsv)
{
this.fieldsCsv = fieldsCsv;
}
public LinkedList<String> getExtraSrg()
{
return extraSrg;
}
public void setExtraSrg(LinkedList<String> extraSrg)
{
this.extraSrg = extraSrg;
}
public FileCollection getLibs()
{
FileCollection collection = null;
for (Object o : libs)
{
FileCollection col;
if (o instanceof FileCollection)
{
col = (FileCollection) o;
}
else
{
col = getProject().files(o);
}
if (collection == null)
collection = col;
else
collection = collection.plus(col);
}
return collection;
}
public void addLibs(Object libs)
{
this.libs.add(libs);
}
}