aiai.ai.core.ExecProcessService.java Source code

Java tutorial

Introduction

Here is the source code for aiai.ai.core.ExecProcessService.java

Source

/*
 AiAi, Copyright (C) 2017 - 2018, Serge Maslyukov
    
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 This program 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 General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <https://www.gnu.org/licenses/>.
    
 */
package aiai.ai.core;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

@Service
@Slf4j
public class ExecProcessService {

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Result {
        public boolean isOk;
        public int exitCode;
        public String console;
    }

    private static class StreamHolder {
        private InputStream is;
    }

    // TODO 2018-10-30 need to implement for station side
    /*
        private final LogDataRepository logDataRepository;
        
        public ProcessService(LogDataRepository logDataRepository) {
    this.logDataRepository = logDataRepository;
        }
    */

    public Result execCommand(List<String> cmd, File execDir, File consoleLogFile)
            throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder();
        pb.command(cmd);
        pb.directory(execDir);
        pb.redirectErrorStream(true);
        final Process process = pb.start();

        final StreamHolder streamHolder = new StreamHolder();
        int exitCode;
        try (final FileOutputStream fos = new FileOutputStream(consoleLogFile);
                BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            final Thread reader = new Thread(() -> {
                try {
                    streamHolder.is = process.getInputStream();
                    int c;
                    while ((c = streamHolder.is.read()) != -1) {
                        bos.write(c);
                    }
                } catch (IOException e) {
                    log.error("Error collect data from output stream", e);
                }
            });
            reader.start();

            exitCode = process.waitFor();
            reader.join();
        } finally {
            try {
                if (streamHolder.is != null) {
                    streamHolder.is.close();
                }
            } catch (Throwable th) {
                log.warn("Error with closing InputStream", th);
            }
        }

        log.info("Any errors of execution? {}", (exitCode == 0 ? "No" : "Yes"));
        log.debug("'\tcmd: {}", cmd);
        log.debug("'\texecDir: {}", execDir.getPath());
        String console = readLastLines(500, consoleLogFile);
        log.debug("'\tconsole output:\n{}", console);

        return new Result(exitCode == 0, exitCode, console);
    }

    private String readLastLines(int maxSize, File consoleLogFile) throws IOException {
        LinkedList<String> lines = new LinkedList<>();
        String inputLine;
        try (FileReader fileReader = new FileReader(consoleLogFile);
                BufferedReader in = new BufferedReader(fileReader)) {
            while ((inputLine = in.readLine()) != null) {
                inputLine = inputLine.trim();
                if (lines.size() == maxSize) {
                    lines.removeFirst();
                }
                lines.add(inputLine);
            }
        }
        StringBuilder sb = new StringBuilder();
        for (String line : lines) {
            sb.append(line).append('\n');
        }
        return sb.toString();
    }

}