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

com.github.jlangch.venice.impl.AppRunner Maven / Gradle / Ivy

/*   __    __         _
 *   \ \  / /__ _ __ (_) ___ ___
 *    \ \/ / _ \ '_ \| |/ __/ _ \
 *     \  /  __/ | | | | (_|  __/
 *      \/ \___|_| |_|_|\___\___|
 *
 *
 * Copyright 2017-2024 Venice
 *
 * 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 com.github.jlangch.venice.impl;

import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.github.jlangch.venice.VncException;
import com.github.jlangch.venice.impl.env.Env;
import com.github.jlangch.venice.impl.env.Var;
import com.github.jlangch.venice.impl.functions.JsonFunctions;
import com.github.jlangch.venice.impl.types.VncJavaObject;
import com.github.jlangch.venice.impl.types.VncString;
import com.github.jlangch.venice.impl.types.VncSymbol;
import com.github.jlangch.venice.impl.types.collections.VncList;
import com.github.jlangch.venice.impl.types.collections.VncMap;
import com.github.jlangch.venice.impl.types.util.Coerce;
import com.github.jlangch.venice.impl.util.StringUtil;
import com.github.jlangch.venice.impl.util.io.CharsetUtil;
import com.github.jlangch.venice.impl.util.io.zip.ZipFileSystemUtil;
import com.github.jlangch.venice.javainterop.AcceptAllInterceptor;
import com.github.jlangch.venice.javainterop.IInterceptor;
import com.github.jlangch.venice.javainterop.ILoadPaths;
import com.github.jlangch.venice.javainterop.LoadPathsFactory;
import com.github.jlangch.venice.util.NullInputStream;
import com.github.jlangch.venice.util.NullOutputStream;


public class AppRunner {

    public static String run(
            final File appArchive,
            final VncList cmdLineArgs,
            final ILoadPaths loadPaths,
            final PrintStream stdout,
            final PrintStream stderr,
            final Reader stdin
    ) {
        // Merge the load paths from the command line with the application archive
        final List mergedLoadPaths = new ArrayList<>();
        mergedLoadPaths.add(appArchive.getAbsoluteFile());
        mergedLoadPaths.addAll(loadPaths.getPaths());
        final ILoadPaths appLoadPaths = LoadPathsFactory.of(
                                            mergedLoadPaths,
                                            loadPaths.isUnlimitedAccess());

        final IInterceptor interceptor = new AcceptAllInterceptor(appLoadPaths);

        final VncMap manifest = getManifest(appArchive);

        final String appName = Coerce.toVncString(manifest.get(new VncString("app-name"))).getValue();
        final String mainFile = Coerce.toVncString(manifest.get(new VncString("main-file"))).getValue();

        final IVeniceInterpreter venice = new VeniceInterpreter(interceptor);

        final Env env = createEnv(
                            venice,
                            Arrays.asList(
                                convertCliArgsToVar(cmdLineArgs == null ? VncList.empty() : cmdLineArgs),
                                convertAppNameToVar(appName),
                                convertAppArchiveToVar(appArchive)),
                            stdout,
                            stderr,
                            stdin);

        final String script = String.format("(do (load-file \"%s\") nil)", stripVeniceFileExt(mainFile));

        return venice.PRINT(venice.RE(script, appName, env));
    }


    private static VncMap getManifest(final File app) {
        if (app.exists()) {
            try {
                final String manifest = ZipFileSystemUtil.loadTextFileFromZip(
                                            app,
                                            new File("MANIFEST.MF"),
                                            CharsetUtil.charset("UTF-8"));
                return Coerce.toVncMap(JsonFunctions.read_str.apply(VncList.of(new VncString(manifest))));
            }
            catch (Exception ex) {
                throw new VncException(String.format(
                        "Failed to load manifest from Venice application archive '%s'.",
                        app.getPath()));
            }
        }
        else {
            throw new VncException(String.format(
                    "The Venice application archive '%s' does not exist",
                    app.getPath()));
        }
    }

    private static Env createEnv(
            final IVeniceInterpreter venice,
            final List vars,
            final PrintStream stdout,
            final PrintStream stderr,
            final Reader stdin
    ) {
        final PrintStream stdout_ = stdout == null ? new PrintStream(new NullOutputStream(), true) : stdout;
        final PrintStream stderr_ = stderr == null ? new PrintStream(new NullOutputStream(), true) : stderr;
        final Reader stdin_ = stdin == null ? new InputStreamReader(new NullInputStream()) : stdin;

        return venice.createEnv(true, false, RunMode.APP)
                     .addGlobalVars(vars)
                     .setStdoutPrintStream(stdout_)
                     .setStderrPrintStream(stderr_)
                     .setStdinReader(stdin_);
    }

    private static Var convertAppNameToVar(final String appName) {
        return new Var(new VncSymbol("*app-name*"), new VncString(appName), false, Var.Scope.Global);
    }

    private static Var convertAppArchiveToVar(final File appArchive) {
        return new Var(new VncSymbol("*app-archive*"), new VncJavaObject(appArchive), false, Var.Scope.Global);
    }

    private static Var convertCliArgsToVar(final VncList cmdLineArgs) {
        return new Var(new VncSymbol("*ARGV*"), cmdLineArgs, false, Var.Scope.Global);
    }

    private static String stripVeniceFileExt(final String s) {
        return StringUtil.removeEnd(s, ".venice");
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy