io.macgyver.server.Startup.java Source code

Java tutorial

Introduction

Here is the source code for io.macgyver.server.Startup.java

Source

/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.macgyver.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.io.CharStreams;
import com.google.common.io.Files;
import com.google.common.collect.Lists;

import groovy.lang.Writable;
import groovy.text.SimpleTemplateEngine;
import groovy.text.Template;

@Component
public class Startup implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    ApplicationContext applicationContext;

    Logger logger = LoggerFactory.getLogger(Startup.class);

    File tempDir;

    File targetDir = new File(".");
    File targetLibDir = new File(targetDir, "lib");

    JsonNode pluginDescriptor;

    List<String> dependencies = Lists.newArrayList();

    public Startup() {
        super();

        tempDir = Files.createTempDir();
        logger.info("temp dir: {}", tempDir);

        targetLibDir = new File(targetDir, "lib");
    }

    protected void readPlugins() throws IOException, JsonProcessingException {
        File pluginsFile = new File("./config/plugins.json");

        ObjectMapper mapper = new ObjectMapper();

        pluginDescriptor = mapper.readTree(pluginsFile);

        String version = pluginDescriptor.path("version").asText("1.1.1");

        pluginDescriptor.path("plugins").forEach(it -> {
            if (it.path("enabled").asBoolean(true)) {
                String group = it.path("group").asText("io.macgyver");
                String name = it.path("name").asText();
                String v = it.path("version").asText(version);

                String val = group + ":" + name + ":" + v;
                dependencies.add(val);
            }
        });

        if (!dependencies.stream().anyMatch(it -> it.startsWith("io.macgyver:macgyver-core:"))) {
            dependencies.add("io.macgyver:macgyver-core:" + version);
        }
    }

    protected void copyResource(String source, File target) throws IOException {
        target.getParentFile().mkdirs();
        logger.info("writing {} to {}", source, target);
        try (InputStream is = applicationContext.getResource(source).getInputStream()) {
            java.nio.file.Files.copy(is, target.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }

    }

    public void copyPluginsJson() throws IOException {
        File target = new File(targetDir, "config/plugins.json");
        if (!target.exists()) {
            copyResource("classpath:templates/plugins.json", target);
        }
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {

        try {
            copyPluginsJson();
            readPlugins();
            Resource resource = applicationContext.getResource("classpath:templates/build.gradle.template");

            File buildGradleFile = new File(tempDir, "build.gradle");
            SimpleTemplateEngine ste = new SimpleTemplateEngine();
            Template template = ste.createTemplate(new InputStreamReader(resource.getInputStream()));
            FileWriter fw = new FileWriter(buildGradleFile);

            Map<String, Object> x = Maps.newConcurrentMap();
            x.put("dependencies", dependencies);
            template.make(x).writeTo(fw);

            fw.close();

            logger.info("resource: {}", resource);

            ProjectConnection connect = GradleConnector.newConnector().forProjectDirectory(tempDir).connect();

            logger.info("{}", connect);
            BuildLauncher launcher = connect.newBuild();
            launcher.setStandardOutput(System.out);
            launcher.forTasks("fetch").run();

            targetLibDir.mkdirs();

            Arrays.asList(targetLibDir.listFiles()).forEach(it -> {
                it.delete();
            });

            Arrays.asList(new File(tempDir, "jars").listFiles()).forEach(it -> {
                try {
                    File targetFile = new File(targetLibDir, it.getName());
                    logger.info("using {}", targetFile.getName());
                    Files.copy(it, targetFile);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });

            connect.close();

            File logbackFile = new File(targetDir, "config/logback.xml");

            if (!logbackFile.exists()) {
                logbackFile.getParentFile().mkdirs();
                try (FileOutputStream fos = new FileOutputStream(logbackFile)) {
                    ByteStreams.copy(
                            applicationContext.getResource("classpath:templates/logback.xml").getInputStream(),
                            fos);
                }
            }

            File targetFile = new File(targetDir, "bin/macgyverctl");
            targetFile.getParentFile().mkdirs();

            try (FileOutputStream fos = new FileOutputStream(targetFile)) {
                ByteStreams.copy(applicationContext.getResource("classpath:templates/macgyverctl").getInputStream(),
                        fos);
            }

            targetFile.setExecutable(true);

            String[] env = new String[] { "JAVA_HOME=" + System.getProperty("java.home") };

            Process p = Runtime.getRuntime().exec(targetFile.getAbsolutePath(), env);

            int rc = p.waitFor();
            logger.info("return code from start script: {}", rc);

        } catch (IOException | InterruptedException e) {
            logger.error("problem", e);
        }

    }

}