Java tutorial
/* * 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 static net.minecraftforge.gradle.common.Constants.NEWLINE; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import net.minecraftforge.gradle.common.Constants; import org.gradle.api.DefaultTask; import org.gradle.api.Project; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.OutputFiles; import org.gradle.api.tasks.TaskAction; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.io.Files; import com.google.common.io.Resources; class TaskGenSubprojects extends DefaultTask { //@formatter:off @Input private String javaLevel; private Object workspaceDir; @Input private final String resource; @Input private final List<Repo> repositories = Lists.newArrayList(); @Input private final List<String> dependencies = Lists.newArrayList(); private final Map<String, DevProject> projects = Maps.newHashMap(); private static final String INDENT = " "; // 4 spaces //@formatter:on public TaskGenSubprojects() throws IOException { super(); resource = Resources.toString(Resources.getResource(TaskGenSubprojects.class, "globalGradle"), Constants.CHARSET); } @TaskAction public void executeTask() throws IOException { File workspace = getWorkspaceDir(); workspace.mkdirs(); // make run dir just in case new File(workspace, "run").mkdirs(); generateRootBuild(new File(workspace, "build.gradle")); generateRootSettings(new File(workspace, "settings.gradle"), projects.keySet()); URI workspaceUri = workspace.toURI(); for (DevProject project : projects.values()) { File projectDir = project.getProjectDir(workspace); projectDir.mkdirs(); generateProjectBuild(workspaceUri, new File(projectDir, "build.gradle"), project); } } private void generateRootBuild(File output) throws IOException { int repoStart, repoEnd; int depStart, depEnd; int jLevelStart, jLevelEnd; { int startIndex = resource.indexOf("@@"); int endIndex = resource.indexOf("@@", startIndex + 2); //System.out.println("start: "+startIndex + " end: "+endIndex); repoStart = startIndex; repoEnd = endIndex + 3; // account for the ending newline and @@ startIndex = resource.indexOf("@@", endIndex + 2); endIndex = resource.indexOf("@@", startIndex + 2); //System.out.println("start: "+startIndex + " end: "+endIndex); depStart = startIndex; depEnd = endIndex + 3; // account for the ending newline and @@ startIndex = resource.indexOf("@@", endIndex + 2); endIndex = resource.indexOf("@@", startIndex + 2); //System.out.println("start: "+startIndex + " end: "+endIndex); jLevelStart = startIndex; jLevelEnd = endIndex + 2; // keep the line ending this time, only account for @@ } StringBuilder builder = new StringBuilder(); builder.append(resource.subSequence(0, repoStart)); // repositories for (Repo repo : repositories) { lines(builder, 2, "maven {", " name '" + repo.name + "'", " url '" + repo.url + "'", "}"); } builder.append(resource.subSequence(repoEnd, depStart)); // dependencies for (String dep : dependencies) { append(builder, INDENT, INDENT, dep, NEWLINE); } builder.append(resource.subSequence(depEnd, jLevelStart)); builder.append(getJavaLevel()); builder.append(resource.subSequence(jLevelEnd, resource.length())); Files.write(builder.toString(), output, Constants.CHARSET); } private static void generateRootSettings(File output, Collection<String> projects) throws IOException { StringBuilder builder = new StringBuilder(); builder.append("include '"); Joiner.on("', '").appendTo(builder, projects); builder.append("'"); Files.write(builder.toString(), output, Constants.CHARSET); } private static void generateProjectBuild(URI workspace, File output, DevProject project) throws IOException { StringBuilder builder = new StringBuilder(); File src = project.getExternalSrcDir(); File res = project.getExternalResDir(); File testSrc = project.getExternalTestSrcDir(); File testRes = project.getExternalTestResDir(); // @formatter:off // why use relatvie paths? so the eclipse hack below can work correctly. // add extra sourceDirs append(builder, "sourceSets {", NEWLINE); append(builder, INDENT, "main.java.srcDir 'src/main/start'", NEWLINE); // add start dir to gradle sources if (src != null) append(builder, INDENT, "main.java.srcDir '", relative(workspace, src), "'", NEWLINE); if (res != null) append(builder, INDENT, "main.resources.srcDir '", relative(workspace, res), "'", NEWLINE); if (testSrc != null) append(builder, INDENT, "test.java.srcDir '", relative(workspace, testSrc), "'", NEWLINE); if (testRes != null) append(builder, INDENT, "test.resources.srcDir '", relative(workspace, testRes), "'", NEWLINE); append(builder, "}"); // @formatter:on // write Files.write(builder.toString(), output, Constants.CHARSET); } private static void lines(StringBuilder out, int indentLevel, CharSequence... lines) { String indent = Strings.repeat(INDENT, indentLevel); for (CharSequence line : lines) { out.append(indent).append(line).append(NEWLINE); } } private static void append(StringBuilder out, CharSequence... things) { for (CharSequence str : things) { out.append(str); } } private static String relative(URI base, File src) { String relative = base.relativize(src.toURI()).getPath().replace('\\', '/'); if (!relative.endsWith("/")) relative += "/"; return relative; } @SuppressWarnings("serial") private static class Repo implements Serializable { public final String name, url; public Repo(String name, String url) { super(); this.name = name; this.url = url; } } @SuppressWarnings("serial") private static class DevProject implements Serializable { //@formatter:off private final transient Project project; private final String name; private final Object externalSrcDir, externalResDir; private final Object externalTestSrcDir, externalTestResDir; //@formatter:on public DevProject(Project project, String name, Object externalSrcDir, Object externalResDir, Object externalTestSrcDir, Object externalTestResDir) { super(); this.project = project; this.name = name; this.externalSrcDir = externalSrcDir; this.externalResDir = externalResDir; this.externalTestSrcDir = externalTestSrcDir; this.externalTestResDir = externalTestResDir; } public File getProjectDir(File root) { return new File(root, name); } public File getExternalSrcDir() { return externalSrcDir == null ? null : project.file(externalSrcDir); } public File getExternalResDir() { return externalResDir == null ? null : project.file(externalResDir); } public File getExternalTestSrcDir() { return externalTestSrcDir == null ? null : project.file(externalTestSrcDir); } public File getExternalTestResDir() { return externalTestResDir == null ? null : project.file(externalTestResDir); } } public String getJavaLevel() { return javaLevel; } public void setJavaLevel(String javaLevel) { this.javaLevel = javaLevel; } public void addCompileDep(String depString) { dependencies.add("compile '" + depString + "'"); } public void addTestCompileDep(String depString) { dependencies.add("testCompile '" + depString + "'"); } public void addRepo(String name, String url) { repositories.add(new Repo(name, url)); } @OutputFiles public List<File> getGeneratedFiles() { List<File> files = new ArrayList<File>(2 + projects.size()); File workspace = getWorkspaceDir(); files.add(new File(workspace, "build.gradle")); files.add(new File(workspace, "settings.gradle")); for (DevProject p : projects.values()) { files.add(new File(p.getProjectDir(workspace) + "/build.gradle")); } return files; } public void putProject(String name, Object externalSrcDir, Object externalResDir, Object externalTestSrcDir, Object externalTestResDir) { projects.put(name, new DevProject(getProject(), name, externalSrcDir, externalResDir, externalTestSrcDir, externalTestResDir)); } public void removeProject(String name) { projects.remove(name); } public File getWorkspaceDir() { return getProject().file(workspaceDir); } public void setWorkspaceDir(Object workspaceDir) { this.workspaceDir = workspaceDir; } }