Process.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024, 2026 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package platform.independent.osservices;

import avt.io.*;
import platform.dependent.*;
import platform.independent.filesystem.*;

public class Process(Object)
{
    public static final int MIN_PRIORITY  = 1;
    public static final int LOW_PRIORITY  = 3;
    public static final int NORM_PRIORITY = 5;
    public static final int HIGH_PRIORITY = 7;
    public static final int MAX_PRIORITY  = 9;

    public static final int STILL_ACTIVE = 259;

    public static boolean hasInstance() { return PlatformServices.getInstance().isCurrentProcessHasInstance(); }

    public static ByteStream createPipe() { return PlatformServices.getInstance().newPipe(); }

    public static Process current() { return PlatformServices.getInstance().getCurrentProcess(); }

    protected int fldPriority;
    protected String[] fldCommandLine;
    protected String fldWorkingDirectory;
    private boolean fldStarting;
    private long2 fldProcessDs;
    private ByteReader fldStandardInput;
    private ByteWriter fldStandardOutput;
    private ByteWriter fldStandardError;
    private final Environment fldEnvironment;

    public () {
        Process current = Process.current();
        Environment environment = createEnvironment();
        if(environment == null) environment = new Environment();
        fldPriority = NORM_PRIORITY;
        fldEnvironment = environment;
        if(current == null) return;
        environment.assign(current.fldEnvironment);
        fldWorkingDirectory = current.fldWorkingDirectory;
        fldStandardInput = current.fldStandardInput;
        fldStandardOutput = current.fldStandardOutput;
        fldStandardError = current.fldStandardError;
    }

    public void start() throws DirectoryNotFoundException, FileNotFoundException, IOException {
        if(isStarting())
        {
            throw new IllegalProcessStateException(package.getResourceString("illegal-state.process"));
        }
        try
        {
            long2 procDs = fldProcessDs;
            PlatformServices services = PlatformServices.getInstance();
            if(procDs != 0 && !services.isProcessTerminated(procDs))
            {
                throw new IllegalProcessStateException(package.getResourceString("illegal-state.process.already-started"));
            }
            String[] procArg = getCommandLine();
            if(procArg == null || procArg.length <= 0)
            {
                throw new IllegalProcessStateException(package.getResourceString("illegal-state.process.command-line"));
            }
            char[][] procEnv;
            with(fldEnvironment)
            {
                Mutex operation = operation;
                operation.lock();
                try
                {
                    EnvironmentTable variables = variables;
                    int length = variables.length;
                    procEnv = new char[length][];
                    for(int index = 0; index < length; index++)
                    {
                        String name = variables[index];
                        String value = variables[name];
                        int nlength = name.length;
                        int vlength = value.length;
                        char[] component = new char[nlength + vlength + 1];
                        name.getChars(0, nlength, component, 0);
                        value.getChars(0, vlength, component, nlength + 1);
                        component[nlength] = '=';
                        procEnv[index] = component;
                    }
                } finally
                {
                    operation.unlock();
                }
            }
            ProcessParameters procPrm = new ProcessParameters() {
                priority = fldPriority,
                environment = procEnv,
                arguments = procArg,
                workingDirectory = fldWorkingDirectory,
                standardInput = fldStandardInput,
                standardOutput = fldStandardOutput,
                standardError = fldStandardError
            };
            fldProcessDs = services.startProcess(procPrm);
            if(procDs != 0) services.closeProcessDescriptor(procDs);
        } finally
        {
            clearStarting();
        }
    }

    public void join(long timeInMillis, int timeInNanos) {
        long2 procDs = fldProcessDs;
        if(procDs == 0)
        {
            throw new IllegalProcessStateException(package.getResourceString("illegal-state.process"));
        }
        if(timeInMillis < 0)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument.negative"), new Object[] { "timeInMillis" }));
        }
        if(timeInNanos < 0 || timeInNanos > 999999)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument.out-of-range"), new Object[] { "timeInNanos" }));
        }
        PlatformServices.getInstance().joinProcess(procDs, timeInMillis, timeInNanos);
    }

    public boolean isTerminated() {
        long2 procDs = fldProcessDs;
        return procDs != 0 && PlatformServices.getInstance().isProcessTerminated(procDs);
    }

    public int getExitCode() {
        long2 procDs = fldProcessDs;
        return procDs == 0 ? 0 : PlatformServices.getInstance().getProcessExitCode(procDs);
    }

    public final void join(long timeInMillis) { join(timeInMillis, 0); }

    public final void join() { join(0, 0); }

    public final int priority { read = getPriority, write = setPriority }

    public final String[] commandLine { read = getCommandLine, write = setCommandLine }

    public final String workingDirectory { read = getWorkingDirectory, write = setWorkingDirectory }

    public final Environment environment { read = fldEnvironment, write = setEnvironment }

    public final ByteReader standardInput { read = fldStandardInput, write = setStandardInput }

    public final ByteWriter standardOutput { read = fldStandardOutput, write = setStandardOutput }

    public final ByteWriter standardError { read = fldStandardError, write = setStandardError }

    protected void beforeDestruction() {
        long2 procDs = fldProcessDs;
        if(procDs != 0) PlatformServices.getInstance().closeProcessDescriptor(procDs);
    }

    protected void setPriority(int newPriority) {
        if(newPriority < MIN_PRIORITY) newPriority = MIN_PRIORITY;
        if(newPriority > MAX_PRIORITY) newPriority = MAX_PRIORITY;
        fldPriority = newPriority;
    }

    protected void setCommandLine(String[] newCommandLine) {
        if(newCommandLine == null)
        {
            fldCommandLine = null;
            return;
        }
        int length = newCommandLine.length;
        String[] locCommandLine = new String[length];
        for(int index = 0; index < length; index++)
        {
            String component = newCommandLine[index];
            if(component == null || component.indexOf(0) >= 0 || component.indexOf('\"') >= 0)
            {
                throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "commandLine" }));
            }
            if(index == 0 && !PlatformServices.getInstance().isInternalPathFull(component))
            {
                throw new IllegalPropertyValueException(package.getResourceString("illegal-property.process.command-line"));
            }
            locCommandLine[index] = component;
        }
        locCommandLine.finalize();
        fldCommandLine = locCommandLine;
    }

    protected void setWorkingDirectory(String newWorkingDirectory) {
        if(newWorkingDirectory == null)
        {
            throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "workingDirectory" }));
        }
        fldWorkingDirectory = newWorkingDirectory;
    }

    protected void setEnvironment(Environment newEnvironment) {
        if(newEnvironment == null)
        {
            throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "environment" }));
        }
        fldEnvironment.assign(newEnvironment);
    }

    protected void setStandardInput(ByteReader newStandardInput) {
        if(newStandardInput != null && !PlatformServices.getInstance().isPlatformInputStream(newStandardInput))
        {
            throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "standardInput" }));
        }
        fldStandardInput = newStandardInput;
    }

    protected void setStandardOutput(ByteWriter newStandardOutput) {
        if(newStandardOutput != null && !PlatformServices.getInstance().isPlatformOutputStream(newStandardOutput))
        {
            throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "standardOutput" }));
        }
        fldStandardOutput = newStandardOutput;
    }

    protected void setStandardError(ByteWriter newStandardError) {
        if(newStandardError != null && !PlatformServices.getInstance().isPlatformOutputStream(newStandardError))
        {
            throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "standardError" }));
        }
        fldStandardError = newStandardError;
    }

    protected int getPriority() { return fldPriority; }

    protected String getWorkingDirectory() { return fldWorkingDirectory; }

    protected Environment createEnvironment() { return null; }

    protected final void clearStarting() { fldStarting = false; }

    protected final native boolean isStarting();

    private String[] getCommandLine() {
        String[] result = fldCommandLine;
        if(result != null && result.isMutable())
        {
            int length = result.length;
            Array.copy(result, 0, fldCommandLine = result = new String[length], 0, length);
            result.finalize();
        }
        return result;
    }
}