All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avito.utils.RealProcessRunner.kt Maven / Gradle / Ivy

Go to download

Collection of infrastructure libraries and gradle plugins of Avito Android project

There is a newer version: 2023.22
Show newest version
package com.avito.utils

import com.avito.android.Result
import org.apache.tools.ant.types.Commandline
import org.gradle.internal.impldep.com.google.common.annotations.VisibleForTesting
import java.io.File
import java.time.Duration
import java.util.concurrent.ExecutorService
import java.util.concurrent.SynchronousQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

internal class RealProcessRunner(
    private val workingDirectory: File?,
    private val cliOutputReaderThreadPool: ExecutorService =
        ThreadPoolExecutor(0, 300, 30, TimeUnit.SECONDS, SynchronousQueue())
) : ProcessRunner {

    override fun run(
        command: String,
        timeout: Duration
    ): Result {
        return runCommand(
            command = command,
            workingDirectory = workingDirectory,
            timeout = timeout
        )
    }

    override fun spawn(command: String, outputTo: File?): Process {
        return spawnProcess(command, workingDirectory, outputTo)
    }

    /**
     * [ProcessBuilder] expects command as an arguments list, arguments could be separated by space
     */
    @VisibleForTesting
    internal fun splitCommand(source: String): Array = Commandline.translateCommandline(source)

    private fun spawnProcess(
        command: String,
        workingDirectory: File? = null,
        outputTo: File? = null
    ): Process {
        return ProcessBuilder(*splitCommand(command))
            .redirectErrorStream(true)
            .also { builder ->
                if (workingDirectory != null) {
                    builder.directory(workingDirectory)
                }
                if (outputTo != null) {
                    builder.redirectOutput(outputTo)
                }
            }
            .start()
    }

    private fun runCommand(
        command: String,
        workingDirectory: File? = null,
        timeout: Duration
    ): Result = try {
        val process = spawnProcess(
            command = command,
            workingDirectory = workingDirectory
        )
        val outputFuture = cliOutputReaderThreadPool.submit(
            CLIOutputReaderTask(
                stdout = process.inputStream
            )
        )

        process.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS)
        val output = outputFuture.get(timeout.toMillis(), TimeUnit.MILLISECONDS)

        if (process.exitValue() != 0) {
            Result.Failure(Throwable("Unknown error: exit code=[${process.exitValue()}]; output=$output"))
        } else {
            Result.Success(output)
        }
    } catch (t: Throwable) {
        Result.Failure(t)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy