net.minecraftforge.gradle.patcher.TaskGenSubprojects.java Source code

Java tutorial

Introduction

Here is the source code for net.minecraftforge.gradle.patcher.TaskGenSubprojects.java

Source

/*
 * 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;
    }
}