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

org.apache.maven.plugins.jlink.AbstractJLinkToolchainExecutor Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.maven.plugins.jlink;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import java.io.File;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.shared.utils.cli.CommandLineException;
import org.apache.maven.shared.utils.cli.CommandLineUtils;
import org.apache.maven.shared.utils.cli.Commandline;
import org.apache.maven.toolchain.Toolchain;

abstract class AbstractJLinkToolchainExecutor extends AbstractJLinkExecutor {
    private final Toolchain toolchain;

    AbstractJLinkToolchainExecutor(Toolchain toolchain, Log log) {
        super(log);
        this.toolchain = toolchain;
    }

    protected Optional getToolchain() {
        return Optional.ofNullable(this.toolchain);
    }

    /**
     * Execute JLink via toolchain.
     *
     * @return the exit code ({@code 0} on success).
     */
    @Override
    public int executeJlink(List jlinkArgs) throws MojoExecutionException {
        File jlinkExecutable = getJlinkExecutable();
        getLog().info("Toolchain in maven-jlink-plugin: jlink [ " + jlinkExecutable + " ]");

        Commandline cmd = createJLinkCommandLine(jlinkArgs);
        cmd.setExecutable(jlinkExecutable.getAbsolutePath());

        return executeCommand(cmd);
    }

    private File getJlinkExecutable() {
        return new File(getJLinkExecutable());
    }

    @Override
    public Optional getJmodsFolder(/* nullable */ File sourceJdkModules) {
        // Really Hacky...do we have a better solution to find the jmods directory of the JDK?
        File jLinkParent = getJlinkExecutable().getParentFile().getParentFile();
        File jmodsFolder;
        if (sourceJdkModules != null && sourceJdkModules.isDirectory()) {
            jmodsFolder = new File(sourceJdkModules, JMODS);
        } else {
            jmodsFolder = new File(jLinkParent, JMODS);
        }

        getLog().debug(" Parent: " + jLinkParent.getAbsolutePath());
        getLog().debug(" jmodsFolder: " + jmodsFolder.getAbsolutePath());

        return Optional.of(jmodsFolder);
    }

    private Commandline createJLinkCommandLine(List jlinkArgs) {
        Commandline cmd = new Commandline();
        jlinkArgs.forEach(arg -> cmd.createArg().setValue("\"" + arg + "\""));

        return cmd;
    }

    private String getJLinkExecutable() {
        Optional toolchain = getToolchain();

        if (!toolchain.isPresent()) {
            getLog().error("Either JDK9+ or a toolchain "
                    + "pointing to a JDK9+ containing a jlink binary is required.");
            getLog().info("See https://maven.apache.org/guides/mini/guide-using-toolchains.html "
                    + "for mor information.");
            throw new IllegalStateException("Running on JDK8 and no toolchain found.");
        }

        String jLinkExecutable =
                toolchain.orElseThrow(NoSuchElementException::new).findTool("jlink");

        if (jLinkExecutable.isEmpty()) {
            throw new IllegalStateException(
                    "The jlink executable '" + jLinkExecutable + "' doesn't exist or is not a file.");
        }

        // TODO: Check if there exist a more elegant way?
        String jLinkCommand = "jlink" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "");

        File jLinkExe = new File(jLinkExecutable);

        if (jLinkExe.isDirectory()) {
            jLinkExe = new File(jLinkExe, jLinkCommand);
        }

        if (SystemUtils.IS_OS_WINDOWS && jLinkExe.getName().indexOf('.') < 0) {
            jLinkExe = new File(jLinkExe.getPath() + ".exe");
        }

        if (!jLinkExe.isFile()) {
            throw new IllegalStateException("The jlink executable '" + jLinkExe + "' doesn't exist or is not a file.");
        }
        return jLinkExe.getAbsolutePath();
    }

    private int executeCommand(Commandline cmd) throws MojoExecutionException {
        if (getLog().isDebugEnabled()) {
            // no quoted arguments ???
            getLog().debug(CommandLineUtils.toString(cmd.getCommandline()).replaceAll("'", ""));
        }

        CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
        CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
        try {
            int exitCode = CommandLineUtils.executeCommandLine(cmd, out, err);

            String output = StringUtils.isEmpty(out.getOutput())
                    ? null
                    : '\n' + out.getOutput().trim();

            if (exitCode != 0) {

                if (output != null && !output.isEmpty()) {
                    // Reconsider to use WARN / ERROR ?
                    //  getLog().error( output );
                    for (String outputLine : output.split("\n")) {
                        getLog().error(outputLine);
                    }
                }

                StringBuilder msg = new StringBuilder("\nExit code: ");
                msg.append(exitCode);
                if (StringUtils.isNotEmpty(err.getOutput())) {
                    msg.append(" - ").append(err.getOutput());
                }
                msg.append('\n');
                msg.append("Command line was: ").append(cmd).append('\n').append('\n');

                throw new MojoExecutionException(msg.toString());
            }

            if (output != null && !output.isEmpty()) {
                // getLog().info( output );
                for (String outputLine : output.split("\n")) {
                    getLog().info(outputLine);
                }
            }

            return exitCode;
        } catch (CommandLineException e) {
            throw new MojoExecutionException("Unable to execute jlink command: " + e.getMessage(), e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy