
com.github.fracpete.bootstrapp.Main Maven / Gradle / Ivy
/*
* Main.java
* Copyright (C) 2020 University of Waikato, Hamilton, NZ
*/
package com.github.fracpete.bootstrapp;
import com.github.fracpete.bootstrapp.core.Maven;
import com.github.fracpete.bootstrapp.core.Resources;
import com.github.fracpete.bootstrapp.core.Template;
import com.github.fracpete.bootstrapp.core.Template.Configuration;
import com.github.fracpete.processoutput4j.core.impl.SimpleStreamingProcessOwner;
import com.github.fracpete.processoutput4j.output.StreamingProcessOutput;
import com.github.fracpete.resourceextractor4j.Content;
import com.github.fracpete.simpleargparse4j.ArgumentParser;
import com.github.fracpete.simpleargparse4j.ArgumentParserException;
import com.github.fracpete.simpleargparse4j.Namespace;
import com.github.fracpete.simpleargparse4j.Option.Type;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.Invoker;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Command-line application for bootstrapping a Maven appplication.
*
* @author FracPete (fracpete at waikato dot ac dot nz)
*/
public class Main {
/** the alternative maven installation. */
protected File m_MavenHome;
/** the actual maven home to use. */
protected transient File m_ActMavenHome;
/** the maven user settings to use. */
protected File m_MavenUserSettings;
/** the alternative java installation. */
protected File m_JavaHome;
/** the actual Java home to use. */
protected transient File m_ActJavaHome;
/** the output directory. */
protected File m_OutputDir;
/** the output directory for maven. */
protected File m_OutputDirMaven;
/** the JVM options. */
protected List m_JVM;
/** the dependencies. */
protected List m_Dependencies;
/** the dependency files. */
protected List m_DependencyFiles;
/** the pom template. */
protected File m_PomTemplate;
/** the actual POM template to use. */
protected transient File m_ActPomTemplate;
/** the name of the projet. */
protected String m_Name;
/** the version of the project. */
protected String m_Version;
/** whether to call the "clean" goal. */
protected boolean m_Clean;
/** the main class to launch. */
protected String m_MainClass;
/** whether to retrieve source jars or not. */
protected boolean m_Sources;
/** whether to generate start scripts (when supplying a main class). */
protected boolean m_Scripts;
/** whether to create spring-boot jar. */
protected boolean m_SpringBoot;
/** whether to build .deb package. */
protected boolean m_Debian;
/** the custom debian maven snippet to use. */
protected File m_DebianSnippet;
/** whether to build .rpm package. */
protected boolean m_Redhat;
/** the custom redhat maven snippet to use. */
protected File m_RedhatSnippet;
/** whether to launch the main class. */
protected boolean m_Launch;
/** for logging. */
protected Logger m_Logger;
/** whether help got requested. */
protected boolean m_HelpRequested;
/**
* Initializes the object.
*/
public Main() {
initialize();
}
/**
* Initializes the members.
*/
protected void initialize() {
m_MavenHome = null;
m_MavenUserSettings = null;
m_JavaHome = null;
m_OutputDir = null;
m_OutputDirMaven = null;
m_JVM = null;
m_Dependencies = null;
m_DependencyFiles = null;
m_PomTemplate = null;
m_Name = Template.DEFAULT_NAME;
m_Version = Template.DEFAULT_VERSION;
m_Clean = false;
m_Sources = false;
m_Scripts = false;
m_Launch = false;
m_SpringBoot = false;
m_Debian = false;
m_DebianSnippet = null;
m_Redhat = false;
m_RedhatSnippet = null;
m_Logger = null;
m_HelpRequested = false;
}
/**
* Returns the logger instance to use.
*
* @return the logger
*/
protected Logger getLogger() {
if (m_Logger == null)
m_Logger = Logger.getLogger(getClass().getName());
return m_Logger;
}
/**
* Sets the alternative maven installation to use.
*
* @param dir the top-level directory (above "bin")
* @return itself
*/
public Main mavenHome(File dir) {
m_MavenHome = dir;
return this;
}
/**
* Returns the alternative maven installation to use.
*
* @return the directory, null to use downloaded one
*/
public File getMavenHome() {
return m_MavenHome;
}
/**
* Sets the alternative maven user settings to use.
*
* @param dir the XML file, null to use default ($HOME/.m2/settings.xml)
* @return itself
*/
public Main mavenUserSettings(File dir) {
m_MavenUserSettings = dir;
return this;
}
/**
* Returns the alternative maven user settings to use.
*
* @return the file, null to use default ($HOME/.m2/settings.xml)
*/
public File getMavenUserSettings() {
return m_MavenUserSettings;
}
/**
* Sets the alternative java installation to use.
*
* @param dir the top-level directory (above "bin")
* @return itself
*/
public Main javaHome(File dir) {
m_JavaHome = dir;
return this;
}
/**
* Returns the alternative java installation to use.
*
* @return the directory, null if using one that class was started with
*/
public File getJavaHome() {
return m_JavaHome;
}
/**
* Sets the output directory for the bootstrapped application.
*
* @param dir the directory
* @return itself
*/
public Main outputDir(File dir) {
m_OutputDir = dir;
return this;
}
/**
* Returns the output directory for the bootstrapped application.
*
* @return the directory, null if none set
*/
public File getOutputDir() {
return m_OutputDir;
}
/**
* Sets the name for the project.
*
* @param name the name
* @return itself
*/
public Main name(String name) {
m_Name = name;
return this;
}
/**
* Returns the name for the project.
*
* @return the name
*/
public String getName() {
return m_Name;
}
/**
* Sets the version of the project.
*
* @param version the version
* @return itself
*/
public Main version(String version) {
m_Version = version;
return this;
}
/**
* Returns the version of the project.
*
* @return the version
*/
public String getVersion() {
return m_Version;
}
/**
* Sets the dependencies to use for bootstrapping.
*
* @param dependencies the dependencies, can be null
* @return itself
*/
public Main dependencies(List dependencies) {
m_Dependencies = dependencies;
return this;
}
/**
* Sets the dependencies to use for bootstrapping.
*
* @param dependencies the dependencies, can be null
* @return itself
*/
public Main dependencies(String... dependencies) {
if (dependencies != null)
m_Dependencies = new ArrayList<>(Arrays.asList(dependencies));
else
m_Dependencies = null;
return this;
}
/**
* Returns the dependencies.
*
* @return the dependencies, can be null
*/
public List getDependencies() {
return m_Dependencies;
}
/**
* Sets the dependency files to use for bootstrapping (one dependency per line).
*
* @param files the dependencies, can be null
* @return itself
*/
public Main dependencyFiles(List files) {
m_DependencyFiles = files;
return this;
}
/**
* Sets the dependency files to use for bootstrapping (one dependency per line).
*
* @param files the dependency files, can be null
* @return itself
*/
public Main dependencyFiles(File... files) {
if (files != null)
m_DependencyFiles = new ArrayList<>(Arrays.asList(files));
else
m_DependencyFiles = null;
return this;
}
/**
* Returns the dependency files.
*
* @return the files, can be null
*/
public List getDependencyFiles() {
return m_DependencyFiles;
}
/**
* Combines manually set dependencies and ones from files into one list.
*
* @return all dependencies
*/
public List getAllDependencies() {
List result;
List lines;
result = new ArrayList<>();
if (m_Dependencies != null)
result.addAll(m_Dependencies);
if (m_DependencyFiles != null) {
for (File depFile: m_DependencyFiles) {
try {
getLogger().info("Reading dependency file: " + depFile);
lines = Files.readAllLines(depFile.toPath());
for (String line: lines) {
line = line.trim();
if (line.isEmpty())
continue;
if (!line.contains(":"))
continue;
result.add(line);
}
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to read dependency file: " + depFile, e);
}
}
}
return result;
}
/**
* Sets whether to execute the "clean" goal.
*
* @param clean true if to clean
* @return itself
*/
public Main clean(boolean clean) {
m_Clean = clean;
return this;
}
/**
* Returns whether to execute the "clean" goal.
*
* @return true if to clean
*/
public boolean getClean() {
return m_Clean;
}
/**
* Sets whether to retrieve the source jars as well.
*
* @param sources true if to get sources
* @return itself
*/
public Main sources(boolean sources) {
m_Sources = sources;
return this;
}
/**
* Returns whether to download source jars as well.
*
* @return true if to get sources
*/
public boolean getSources() {
return m_Sources;
}
/**
* Sets the template for the POM to use.
*
* @param template the template
* @return itself
*/
public Main pomTemplate(File template) {
m_PomTemplate = template;
return this;
}
/**
* Returns the template for the pom.xml to use.
*
* @return the POM template, null if using the default
*/
public File getPomTemplate() {
return m_PomTemplate;
}
/**
* Sets the JVM options to use for launching the main class.
*
* @param options the options, can be null
* @return itself
*/
public Main jvm(List options) {
m_JVM = options;
return this;
}
/**
* Sets the JVM options to use for launching the main class.
*
* @param options the options, can be null
* @return itself
*/
public Main jvm(String... options) {
if (options != null)
m_JVM = new ArrayList<>(Arrays.asList(options));
else
m_JVM = null;
return this;
}
/**
* Returns the JVM options.
*
* @return the options, can be null
*/
public List getJvm() {
return m_JVM;
}
/**
* Sets the main class to launch after bootstrapping.
*
* @param dir the main class
* @return itself
*/
public Main mainClass(String dir) {
m_MainClass = dir;
return this;
}
/**
* Returns the main class to launch after bootstrapping.
*
* @return the main class, null if none set
*/
public String getMainClass() {
return m_MainClass;
}
/**
* Sets whether to create scripts for launching the main class.
*
* @param scripts true if to create scripts
* @return itself
*/
public Main scripts(boolean scripts) {
m_Scripts = scripts;
return this;
}
/**
* Returns whether to create scripts for launching the main class.
*
* @return true if to create scripts
*/
public boolean getScripts() {
return m_Scripts;
}
/**
* Sets whether to create spring-boot jar.
*
* @param springBoot true if to generate jar
* @return itself
*/
public Main springBoot(boolean springBoot) {
m_SpringBoot = springBoot;
return this;
}
/**
* Returns whether to create spring-boot jar.
*
* @return true if to generate jar
*/
public boolean getSpringBoot() {
return m_SpringBoot;
}
/**
* Sets whether to generate .deb package.
*
* @param debian true if to generate .deb
* @return itself
*/
public Main debian(boolean debian) {
m_Debian = debian;
return this;
}
/**
* Returns whether to generate .deb package.
*
* @return true if to generate .deb
*/
public boolean getDebian() {
return m_Debian;
}
/**
* Sets the file containing the custom maven snippet file for generating the debian package.
*
* @param snippet the file
* @return itself
*/
public Main debianSnippet(File snippet) {
m_DebianSnippet = snippet;
return this;
}
/**
* Returns the file containing the custom maven snippet file for generating the debian package.
*
* @return the file
*/
public File getDebianSnippet() {
return m_DebianSnippet;
}
/**
* Sets whether to generate .rpm package.
*
* @param redhat true if to generate .rpm
* @return itself
*/
public Main redhat(boolean redhat) {
m_Redhat = redhat;
return this;
}
/**
* Returns whether to generate .rpm package.
*
* @return true if to generate .rpm
*/
public boolean getRedhat() {
return m_Redhat;
}
/**
* Sets the file containing the custom maven snippet file for generating the redhat package.
*
* @param snippet the file
* @return itself
*/
public Main redhatSnippet(File snippet) {
m_RedhatSnippet = snippet;
return this;
}
/**
* Returns the file containing the custom maven snippet file for generating the redhat package.
*
* @return the file
*/
public File getRedhatSnippet() {
return m_RedhatSnippet;
}
/**
* Sets whether to launch the main class.
*
* @param launch true if to launch
* @return itself
*/
public Main launch(boolean launch) {
m_Launch = launch;
return this;
}
/**
* Returns whether to launch the main class.
*
* @return true if to launch
*/
public boolean getLaunch() {
return m_Launch;
}
/**
* Configures and returns the commandline parser.
*
* @return the parser
*/
protected ArgumentParser getParser() {
ArgumentParser parser;
parser = new ArgumentParser("Bootstrapping Maven applications by supplying only dependencies.");
parser.addOption("-m", "--maven_home")
.required(false)
.type(Type.EXISTING_DIR)
.dest("maven_home")
.help("The directory with a local Maven installation to use instead of the downloaded one.");
parser.addOption("-u", "--maven_user_settings")
.required(false)
.type(Type.EXISTING_FILE)
.dest("maven_user_settings")
.help("The file with the maven user settings to use other than $HOME/.m2/settings.xml.");
parser.addOption("-j", "--java_home")
.required(false)
.type(Type.EXISTING_DIR)
.dest("java_home")
.help("The Java home to use for the Maven execution.");
parser.addOption("-n", "--name")
.required(false)
.setDefault(Template.DEFAULT_NAME)
.dest("name")
.help("The name to use for the project in the pom.xml. Also used as library directory and executable name when generating Debian/Redhat packages.");
parser.addOption("-V", "--version")
.required(false)
.setDefault(Template.DEFAULT_VERSION)
.dest("version")
.help("The version to use for the project in the pom.xml");
parser.addOption("-d", "--dependency")
.required(false)
.multiple(true)
.dest("dependencies")
.help("The maven dependencies to use for bootstrapping the application (group:artifact:version), e.g.: nz.ac.waikato.cms.weka:weka-dev:3.9.4");
parser.addOption("-D", "--dependency-file")
.required(false)
.multiple(true)
.type(Type.EXISTING_FILE)
.dest("dependency_files")
.help("The file(s) with maven dependencies to use for bootstrapping the application (group:artifact:version), one dependency per line.");
parser.addOption("-C", "--clean")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("clean")
.help("If enabled, the 'clean' goals gets executed.");
parser.addOption("-s", "--sources")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("sources")
.help("If enabled, source jars of the Maven artifacts will get downloaded as well and stored in a separated directory.");
parser.addOption("-p", "--pom_template")
.required(false)
.type(Type.EXISTING_FILE)
.dest("pom_template")
.help("The alternative template for the pom.xml to use.");
parser.addOption("-o", "--output_dir")
.required(true)
.type(Type.DIRECTORY)
.dest("output_dir")
.help("The directory to output the bootstrapped application in.");
parser.addOption("-c", "--main_class")
.required(false)
.dest("main_class")
.help("The main class to execute after bootstrapping the application.");
parser.addOption("-v", "--jvm")
.required(false)
.multiple(true)
.dest("jvm")
.help("The parameters to pass to the JVM before launching the application.");
parser.addOption("-e", "--scripts")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("scripts")
.help("If enabled, shell/batch scripts get generated to launch the main class.");
parser.addOption("-b", "--spring-boot")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("spring_boot")
.help("If enabled, a spring-boot jar is generated utilizing the main class (single jar with all dependencies contained).");
parser.addOption("--deb")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("debian")
.help("If enabled, a Debian .deb package is generated. Required tools: fakeroot, dpkg-deb");
parser.addOption("--deb-snippet")
.type(Type.EXISTING_FILE)
.required(false)
.dest("debian_snippet")
.help("The custom Maven pom.xml snippet for generating a Debian package.");
parser.addOption("--rpm")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("redhat")
.help("If enabled, a Redhat .rpm package is generated.");
parser.addOption("--rpm-snippet")
.type(Type.EXISTING_FILE)
.required(false)
.dest("rpm_snippet")
.help("The custom Maven pom.xml snippet for generating a Redhat package.");
parser.addOption("-l", "--launch")
.type(Type.BOOLEAN)
.setDefault(false)
.dest("launch")
.help("If enabled, the supplied main class will get launched.");
return parser;
}
/**
* Sets the parsed options.
*
* @param ns the parsed options
* @return if successfully set
*/
protected boolean setOptions(Namespace ns) {
mavenHome(ns.getFile("maven_home"));
mavenUserSettings(ns.getFile("maven_user_settings"));
javaHome(ns.getFile("java_home"));
outputDir(ns.getFile("output_dir"));
jvm(ns.getList("jvm"));
name(ns.getString("name"));
version(ns.getString("version"));
dependencies(ns.getList("dependencies"));
dependencyFiles(ns.getList("dependency_files"));
clean(ns.getBoolean("clean"));
sources(ns.getBoolean("sources"));
pomTemplate(ns.getFile("pom_template"));
mainClass(ns.getString("main_class"));
scripts(ns.getBoolean("scripts"));
springBoot(ns.getBoolean("spring_boot"));
debian(ns.getBoolean("debian"));
debianSnippet(ns.getFile("debian_snippet"));
redhat(ns.getBoolean("redhat"));
redhatSnippet(ns.getFile("redhat_snippet"));
launch(ns.getBoolean("launch"));
return true;
}
/**
* Returns whether help got requested when setting the options.
*
* @return true if help got requested
*/
public boolean getHelpRequested() {
return m_HelpRequested;
}
/**
* Parses the options and configures the object.
*
* @param options the command-line options
* @return true if successfully set (or help requested)
*/
public boolean setOptions(String[] options) {
ArgumentParser parser;
Namespace ns;
m_HelpRequested = false;
parser = getParser();
try {
ns = parser.parseArgs(options);
}
catch (ArgumentParserException e) {
parser.handleError(e);
m_HelpRequested = parser.getHelpRequested();
return m_HelpRequested;
}
return setOptions(ns);
}
/**
* Initializes Maven support.
*
* @return null if successful, otherwise error message
* @see #m_ActMavenHome
*/
protected String initMavenHome() {
String result;
if (m_MavenHome == null) {
if ((result = Maven.initRemoteMaven()) != null)
return result;
m_ActMavenHome = new File(Maven.homeDir());
}
else {
m_ActMavenHome = m_MavenHome;
}
if (!m_ActMavenHome.exists())
return "Maven home does not exist: " + m_ActMavenHome;
if (!m_ActMavenHome.isDirectory())
return "Maven home is not a directory: " + m_ActMavenHome;
System.setProperty("maven.home", m_ActMavenHome.getAbsolutePath());
return null;
}
/**
* Initializes Java (if a main class has been supplied).
*
* @return null if successful, otherwise error message
* @see #m_JavaHome
*/
protected String initJavaHome() {
if (m_JavaHome == null)
m_ActJavaHome = new File(System.getProperty("java.home"));
else
m_ActJavaHome = m_JavaHome;
if (!m_ActJavaHome.exists())
return "Java home does not exist: " + m_ActJavaHome;
if (!m_ActJavaHome.isDirectory())
return "Java home is not a directory: " + m_ActJavaHome;
return null;
}
/**
* Initializes the output directory.
*
* @return null if successful, otherwise error message
*/
protected String initOutputDir() {
if (!m_OutputDir.exists()) {
if (!m_OutputDir.mkdirs())
return "Failed to create output directory: " + m_OutputDir;
}
if (!m_OutputDir.isDirectory())
return "Output directory is not a directory: " + m_OutputDir;
m_OutputDirMaven = new File(m_OutputDir.getAbsolutePath() + "/target");
return null;
}
/**
* Initializes the POM template.
*
* @return null if successful, otherwise error message
*/
protected String initPomTemplate() {
String result;
Configuration config;
StringBuilder buildPlugins;
String buildPlugin;
List lines;
config = new Configuration();
config.outputDirMaven = m_OutputDirMaven;
config.dependencies = getAllDependencies();
config.noSources = !m_Sources;
config.noSpringBoot = !m_SpringBoot;
config.mainClass = m_MainClass;
config.name = m_Name;
config.version = m_Version;
buildPlugins = new StringBuilder();
if (m_Debian) {
if (m_DebianSnippet != null) {
try {
lines = Files.readAllLines(m_DebianSnippet.toPath());
for (String line: lines)
buildPlugins.append(line).append("\n");
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to load Debian maven snippet: " + m_DebianSnippet, e);
return "Failed to load Debian maven snippet: " + m_DebianSnippet;
}
}
else {
if (m_Sources)
buildPlugin = Content.readString(Resources.LOCATION + "/" + Template.DEBIANBUILDSRC_FILE);
else
buildPlugin = Content.readString(Resources.LOCATION + "/" + Template.DEBIANBUILD_FILE);
buildPlugins.append(buildPlugin);
}
}
if (m_Redhat) {
if (m_RedhatSnippet != null) {
try {
lines = Files.readAllLines(m_RedhatSnippet.toPath());
for (String line: lines)
buildPlugins.append(line).append("\n");
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to load Redhat maven snippet: " + m_RedhatSnippet, e);
return "Failed to load Redhat maven snippet: " + m_RedhatSnippet;
}
}
else {
if (m_Sources)
buildPlugin = Content.readString(Resources.LOCATION + "/" + Template.REDHATBUILDSRC_FILE);
else
buildPlugin = Content.readString(Resources.LOCATION + "/" + Template.REDHATBUILD_FILE);
buildPlugins.append(buildPlugin);
}
}
if (buildPlugins.length() > 0)
config.buildPlugins = buildPlugins.toString();
if (m_PomTemplate == null) {
result = Template.configureBundledTemplate(m_OutputDir, config);
}
else {
if (!m_PomTemplate.exists())
return "pom.xml template does not exist: " + m_PomTemplate;
if (m_PomTemplate.isDirectory())
return "pom.xml template points to a directory: " + m_PomTemplate;
result = Template.configureTemplate(m_PomTemplate, m_OutputDir, config);
}
if (result == null)
m_ActPomTemplate = new File(m_OutputDir.getAbsolutePath() + "/pom.xml");
return result;
}
/**
* Executes maven to pull in the artifacts.
*
* @return null if successful, otherwise error message
*/
protected String executeMaven() {
InvocationRequest request;
Invoker invoker;
List goals;
goals = new ArrayList<>();
if (m_Clean)
goals.add("clean");
goals.add("package");
if (m_Debian)
goals.add("deb:package");
request = new DefaultInvocationRequest();
request.setPomFile(m_ActPomTemplate);
request.setGoals(goals);
request.setJavaHome(m_ActJavaHome);
if (m_MavenUserSettings != null)
request.setUserSettingsFile(m_MavenUserSettings);
invoker = new DefaultInvoker();
invoker.setMavenHome(m_ActMavenHome);
try {
invoker.execute(request);
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to bootstrap the application!", e);
return "Failed to bootstrap the application: " + e;
}
return null;
}
/**
* Builds and returns the launch command for the main class.
*
* @return the command
*/
protected List buildLaunchCommand(String javaBinary, String libDir) {
List result;
result = new ArrayList<>();
result.add(javaBinary);
if (m_JVM != null)
result.addAll(m_JVM);
result.add("-cp");
result.add(libDir);
result.add(m_MainClass);
return result;
}
/**
* Generates startup shell script if a main class was supplied.
*
* @return null if successful, otherwise error message
*/
protected String createShellScript() {
List cmd;
StringBuilder script;
File dir;
File file;
if (m_MainClass != null) {
dir = new File(m_OutputDirMaven.getAbsolutePath() + "/bin");
if (!dir.exists()) {
if (!dir.mkdirs())
return "Failed to create directory for shell script: " + dir;
}
cmd = buildLaunchCommand("java", "\"$CP\"");
file = new File(dir.getAbsolutePath() + "/start.sh");
script = new StringBuilder();
script.append("#!/bin/bash\n");
script.append("#\n");
script.append("# Start script for " + m_Name + "\n");
script.append("#\n");
script.append("BASEDIR=`dirname $0`/..\n");
script.append("BASEDIR=`(cd \"$BASEDIR\"; pwd)`\n");
script.append("LIB=\"$BASEDIR\"/lib\n");
script.append("CP=\"$LIB/*\"\n");
for (String c: cmd)
script.append(c).append(" ");
script.append("\n");
try {
Files.write(file.toPath(), script.toString().getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
file.setExecutable(true);
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to write shell script to: " + file, e);
return "Failed to write shell script to '" + file + "': " + e;
}
}
return null;
}
/**
* Generates startup batch script if a main class was supplied.
*
* @return null if successful, otherwise error message
*/
protected String createBatchScript() {
List cmd;
StringBuilder script;
File dir;
File file;
if (m_MainClass != null) {
dir = new File(m_OutputDirMaven.getAbsolutePath() + "/bin");
if (!dir.exists()) {
if (!dir.mkdirs())
return "Failed to create directory for batch script: " + dir;
}
cmd = buildLaunchCommand("java", "\"%CP%\"");
file = new File(dir.getAbsolutePath() + "/start.bat");
script = new StringBuilder();
script.append("@echo off\n");
script.append("\n");
script.append("REM Start script for " + m_Name + "\n");
script.append("\n");
script.append("set BASEDIR=%~dp0\\..\n");
script.append("set LIB=%BASEDIR%\\lib\n");
script.append("set CP=%LIB%\\*\n");
for (String c: cmd)
script.append(c).append(" ");
script.append("\n");
try {
Files.write(file.toPath(), script.toString().getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to write batch script to: " + file, e);
return "Failed to write batch script to '" + file + "': " + e;
}
}
return null;
}
/**
* Generates startup scripts if a main class was supplied.
*
* @return null if successful, otherwise error message
* @see #createShellScript()
* @see #createBatchScript()
*/
protected String createScripts() {
String result;
if ((result = createShellScript()) != null)
return result;
if ((result = createBatchScript()) != null)
return result;
return null;
}
/**
* Generates startup shell script for debian/redhat packages.
*
* @return null if successful, otherwise error message
*/
protected String createLaunchScript() {
List cmd;
StringBuilder script;
File dir;
File file;
if (m_MainClass == null)
return "Cannot create launch script for Debian/Redhat packages without a main class!";
dir = new File(m_OutputDir.getAbsolutePath());
if (!dir.exists()) {
if (!dir.mkdirs())
return "Failed to create directory for launch script: " + dir;
}
cmd = buildLaunchCommand("java", "\"$CP\"");
file = new File(dir.getAbsolutePath() + "/launch");
script = new StringBuilder();
script.append("#!/bin/bash\n");
script.append("#\n");
script.append("# Start script for " + m_Name + "\n");
script.append("#\n");
script.append("CP=\"/usr/lib/" + m_Name + "/*\"\n");
for (String c: cmd)
script.append(c).append(" ");
script.append("\n");
try {
Files.write(file.toPath(), script.toString().getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
file.setExecutable(true);
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to write launch script to: " + file, e);
return "Failed to write launch script to '" + file + "': " + e;
}
return null;
}
/**
* Launches the main class, if provided.
*
* @return null if successful, otherwise error message
*/
protected String launchMainClass() {
List cmd;
ProcessBuilder builder;
int exitCode;
if (m_MainClass != null) {
cmd = buildLaunchCommand(m_ActJavaHome.getAbsolutePath() + "/bin/java", m_OutputDirMaven.getAbsolutePath() + "/lib/*");
builder = new ProcessBuilder(cmd);
try {
StreamingProcessOutput output = new StreamingProcessOutput(new SimpleStreamingProcessOwner());
output.monitor(builder);
exitCode = output.getExitCode();
if (exitCode != 0)
return "Failed to launch class (" + builder.command() + "): " + exitCode;
}
catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to launch class!", e);
return "Failed to launch class: " + e;
}
}
return null;
}
/**
* Performs the bootstrapping.
*
* @return null if successful, otherwise error message
*/
protected String doExecute() {
String result;
// initialize
m_ActMavenHome = null;
m_ActJavaHome = null;
m_ActPomTemplate = null;
if ((result = initMavenHome()) != null)
return result;
if ((result = initJavaHome()) != null)
return result;
if ((result = initOutputDir()) != null)
return result;
if ((result = initPomTemplate()) != null)
return result;
if (m_Debian || m_Redhat) {
if ((result = createLaunchScript()) != null)
return result;
}
// bootstrap application
if ((result = executeMaven()) != null)
return result;
// main class
if (getScripts() && (result = createScripts()) != null)
return result;
if (getLaunch() && (result = launchMainClass()) != null)
return result;
return null;
}
/**
* Performs the bootstrapping.
*
* @return null if successful, otherwise error message
*/
public String execute() {
String result;
result = doExecute();
if (result != null)
getLogger().severe(result);
return result;
}
/**
* Executes the bootstrapping with the specified command-line arguments.
*
* @param args the options to use
*/
public static void main(String[] args) {
Main main = new Main();
if (!main.setOptions(args)) {
System.err.println("Failed to parse options!");
System.exit(1);
}
else if (main.getHelpRequested()) {
System.exit(0);
}
String result = main.execute();
if (result != null) {
System.err.println("Failed to perform bootstrapping:\n" + result);
System.exit(2);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy