mirror of
https://github.com/ethauvin/bld.git
synced 2025-04-26 00:37:10 -07:00
First commit of standalone repo
This commit is contained in:
commit
696b23b57a
241 changed files with 28028 additions and 0 deletions
254
src/bld/java/rife/BldBuild.java
Normal file
254
src/bld/java/rife/BldBuild.java
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife;
|
||||
|
||||
import rife.bld.BuildCommand;
|
||||
import rife.bld.Project;
|
||||
import rife.bld.dependencies.VersionNumber;
|
||||
import rife.bld.extension.Antlr4Operation;
|
||||
import rife.bld.extension.TestsBadgeOperation;
|
||||
import rife.bld.extension.ZipOperation;
|
||||
import rife.bld.operations.*;
|
||||
import rife.bld.publish.*;
|
||||
import rife.bld.wrapper.Wrapper;
|
||||
import rife.tools.DirBuilder;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static rife.bld.dependencies.Repository.*;
|
||||
import static rife.bld.dependencies.Scope.*;
|
||||
import static rife.bld.operations.JavadocOptions.DocLinkOption.NO_MISSING;
|
||||
import static rife.bld.operations.TemplateType.*;
|
||||
import static rife.tools.FileUtils.path;
|
||||
|
||||
public class BldBuild extends Project {
|
||||
public BldBuild()
|
||||
throws Exception {
|
||||
pkg = "rife";
|
||||
name = "bld";
|
||||
mainClass = "rife.bld.Cli";
|
||||
version = version(FileUtils.readString(new File(srcMainResourcesDirectory(), "BLD_VERSION")));
|
||||
|
||||
javaRelease = 17;
|
||||
downloadSources = true;
|
||||
autoDownloadPurge = true;
|
||||
|
||||
repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES);
|
||||
scope(test)
|
||||
.include(dependency("org.slf4j", "slf4j-simple", version(2,0,7)))
|
||||
.include(dependency("net.imagej", "ij", version("1.54d")))
|
||||
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5,9,3)))
|
||||
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1,9,3)))
|
||||
.include(dependency("com.h2database", "h2", version(2,1,214)))
|
||||
.include(dependency("net.sourceforge.htmlunit", "htmlunit", version(2,70,0)))
|
||||
.include(dependency("org.postgresql", "postgresql", version(42,6,0)))
|
||||
.include(dependency("com.mysql", "mysql-connector-j", version(8,0,33)))
|
||||
.include(dependency("org.mariadb.jdbc", "mariadb-java-client", version(3,1,4)))
|
||||
.include(dependency("org.hsqldb", "hsqldb", version(2,7,1)))
|
||||
.include(dependency("org.apache.derby", "derby", version("10.16.1.1")))
|
||||
.include(dependency("org.apache.derby", "derbytools", version("10.16.1.1")))
|
||||
.include(dependency("com.oracle.database.jdbc", "ojdbc11", version("23.2.0.0")))
|
||||
.include(dependency("org.json", "json", version(20230227)));
|
||||
|
||||
cleanOperation()
|
||||
.directories(
|
||||
new File(workDirectory(), "embedded_dbs"),
|
||||
new File(workDirectory(), "logs"));
|
||||
|
||||
var core_directory = new File(workDirectory(), "core");
|
||||
var core_src_directory = new File(core_directory, "src");
|
||||
var core_src_main_directory = new File(core_src_directory, "main");
|
||||
var core_src_main_java_directory = new File(core_src_main_directory, "java");
|
||||
var core_src_main_resources_directory = new File(core_src_main_directory, "resources");
|
||||
var core_src_test_directory = new File(core_src_directory, "test");
|
||||
var core_src_test_java_directory = new File(core_src_test_directory, "java");
|
||||
var core_src_test_resources_directory = new File(core_src_test_directory, "resources");
|
||||
var core_src_main_resources_templates_directory = new File(core_src_main_resources_directory, "templates");
|
||||
|
||||
antlr4Operation
|
||||
.sourceDirectories(List.of(new File(core_src_main_directory, "antlr")))
|
||||
.outputDirectory(new File(buildDirectory(), "generated/rife/template/antlr"))
|
||||
.visitor()
|
||||
.longMessages();
|
||||
|
||||
precompileOperation()
|
||||
.sourceDirectories(core_src_main_resources_templates_directory)
|
||||
.templateTypes(HTML, XML, SQL, TXT, JSON);
|
||||
|
||||
compileOperation()
|
||||
.mainSourceDirectories(antlr4Operation.outputDirectory(), core_src_main_java_directory)
|
||||
.testSourceDirectories(core_src_test_java_directory)
|
||||
.compileOptions()
|
||||
.debuggingInfo(JavacOptions.DebuggingInfo.ALL);
|
||||
|
||||
jarOperation()
|
||||
.sourceDirectories(core_src_main_resources_directory)
|
||||
.excluded(Pattern.compile("^\\Q" + core_src_main_resources_templates_directory.getAbsolutePath() + "\\E.*"))
|
||||
.manifestAttribute(Attributes.Name.MAIN_CLASS, mainClass());
|
||||
|
||||
zipBldOperation
|
||||
.destinationDirectory(buildDistDirectory())
|
||||
.destinationFileName("rife2-" + version() + "-bld.zip");
|
||||
|
||||
testsBadgeOperation
|
||||
.classpath(core_src_main_resources_directory.getAbsolutePath())
|
||||
.classpath(core_src_test_resources_directory.getAbsolutePath());
|
||||
propagateJavaProperties(testsBadgeOperation.javaOptions(),
|
||||
"test.postgres",
|
||||
"test.mysql",
|
||||
"test.mariadb",
|
||||
"test.oracle",
|
||||
"test.oracle-free",
|
||||
"test.derby",
|
||||
"test.hsqldb",
|
||||
"test.h2");
|
||||
|
||||
javadocOperation()
|
||||
.excluded(
|
||||
"rife/antlr/",
|
||||
"rife/asm/",
|
||||
"rife/.*/databasedrivers/",
|
||||
"rife/.*/imagestoredrivers/",
|
||||
"rife/.*/rawstoredrivers/",
|
||||
"rife/.*/textstoredrivers/",
|
||||
"rife/database/capabilities/"
|
||||
)
|
||||
.javadocOptions()
|
||||
.docTitle("<a href=\"https://rife2.com/bld\">bld</a> " + version())
|
||||
.docLint(NO_MISSING)
|
||||
.keywords()
|
||||
.splitIndex()
|
||||
.tag("apiNote", "a", "API Note:")
|
||||
.link("https://jakarta.ee/specifications/servlet/5.0/apidocs/")
|
||||
.link("https://jsoup.org/apidocs/")
|
||||
.overview(new File(srcMainJavaDirectory(), "overview.html"));
|
||||
|
||||
publishOperation()
|
||||
.repository(version.isSnapshot() ? repository("rife2-snapshots") : repository("rife2-releases"))
|
||||
.repository(version.isSnapshot() ? repository("sonatype-snapshots") : repository("sonatype-releases"))
|
||||
.info(new PublishInfo()
|
||||
.groupId("com.uwyn.rife2")
|
||||
.artifactId("bld")
|
||||
.name("bld")
|
||||
.description("Pure java build tool for developers who don't like dealing with build tools.")
|
||||
.url("https://github.com/rife2/bld")
|
||||
.developer(new PublishDeveloper()
|
||||
.id("gbevin")
|
||||
.name("Geert Bevin")
|
||||
.email("gbevin@uwyn.com")
|
||||
.url("https://github.com/gbevin"))
|
||||
.license(new PublishLicense()
|
||||
.name("The Apache License, Version 2.0")
|
||||
.url("https://www.apache.org/licenses/LICENSE-2.0.txt"))
|
||||
.scm(new PublishScm()
|
||||
.connection("scm:git:https://github.com/rife2/bld.git")
|
||||
.developerConnection("scm:git:git@github.com:rife2/bld.git")
|
||||
.url("https://github.com/rife2/bld"))
|
||||
.signKey(property("sign.key"))
|
||||
.signPassphrase(property("sign.passphrase")))
|
||||
.artifacts(
|
||||
new PublishArtifact(zipBldOperation.destinationFile(), "bld", "zip"));
|
||||
}
|
||||
|
||||
void propagateJavaProperties(JavaOptions options, String... names) {
|
||||
for (var name : names) {
|
||||
if (properties().contains(name)) {
|
||||
options.property(name, properties().getValueString(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Antlr4Operation antlr4Operation = new Antlr4Operation() {
|
||||
@Override
|
||||
public void execute()
|
||||
throws Exception {
|
||||
super.execute();
|
||||
// replace the package name so that it becomes part of RIFE2
|
||||
FileUtils.transformFiles(outputDirectory(), FileUtils.JAVA_FILE_PATTERN, null, s ->
|
||||
StringUtils.replace(s, "org.antlr.v4.runtime", "rife.antlr.v4.runtime"));
|
||||
}
|
||||
};
|
||||
@BuildCommand(summary = "Generates the grammar Java sources")
|
||||
public void generateGrammar()
|
||||
throws Exception {
|
||||
antlr4Operation.executeOnce();
|
||||
}
|
||||
|
||||
public void compile()
|
||||
throws Exception {
|
||||
generateGrammar();
|
||||
super.compile();
|
||||
}
|
||||
|
||||
final ZipOperation zipBldOperation = new ZipOperation();
|
||||
@BuildCommand(value = "zip-bld", summary = "Creates the bld zip archive")
|
||||
public void zipBld()
|
||||
throws Exception {
|
||||
jar();
|
||||
var tmp = Files.createTempDirectory("bld").toFile();
|
||||
try {
|
||||
new Wrapper().createWrapperFiles(path(tmp, "lib").toFile(), VersionNumber.UNKNOWN.toString());
|
||||
new DirBuilder(tmp, t -> {
|
||||
t.dir("bld", b -> {
|
||||
b.dir("bin", i -> {
|
||||
i.file("bld", f -> {
|
||||
f.copy(path(srcMainDirectory(), "bld", "bld"));
|
||||
f.perms(0755);
|
||||
});
|
||||
i.file("bld.bat", f -> {
|
||||
f.copy(path(srcMainDirectory(), "bld", "bld.bat"));
|
||||
f.perms(0755);
|
||||
});
|
||||
});
|
||||
b.dir("lib", l -> {
|
||||
l.file("bld-wrapper.jar", f -> f.move(path(tmp, "lib", "bld-wrapper.jar")));
|
||||
});
|
||||
});
|
||||
t.dir("lib", l -> l.delete());
|
||||
});
|
||||
|
||||
zipBldOperation
|
||||
.sourceDirectories(tmp)
|
||||
.execute();
|
||||
} finally {
|
||||
FileUtils.deleteDirectory(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
private final TestsBadgeOperation testsBadgeOperation = new TestsBadgeOperation();
|
||||
public void test()
|
||||
throws Exception {
|
||||
testsBadgeOperation.executeOnce(() -> testsBadgeOperation
|
||||
.url(property("testsBadgeUrl"))
|
||||
.apiKey(property("testsBadgeApiKey"))
|
||||
.fromProject(this));
|
||||
}
|
||||
|
||||
@BuildCommand(summary = "Creates all the distribution artifacts")
|
||||
public void all()
|
||||
throws Exception {
|
||||
jar();
|
||||
jarSources();
|
||||
jarJavadoc();
|
||||
zipBld();
|
||||
}
|
||||
|
||||
public void publish()
|
||||
throws Exception {
|
||||
all();
|
||||
super.publish();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws Exception {
|
||||
new BldBuild().start(args);
|
||||
}
|
||||
}
|
2
src/main/bld/bld
Executable file
2
src/main/bld/bld
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env sh
|
||||
java -jar "$(dirname "$0")/../lib/bld-wrapper.jar" "$0" "$@"
|
4
src/main/bld/bld.bat
Normal file
4
src/main/bld/bld.bat
Normal file
|
@ -0,0 +1,4 @@
|
|||
@echo off
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
java -jar "%DIRNAME%/../lib/bld-wrapper.jar" "%0" %*
|
1608
src/main/java/rife/bld/BaseProject.java
Normal file
1608
src/main/java/rife/bld/BaseProject.java
Normal file
File diff suppressed because it is too large
Load diff
43
src/main/java/rife/bld/BldVersion.java
Normal file
43
src/main/java/rife/bld/BldVersion.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import rife.resources.ResourceFinderClasspath;
|
||||
import rife.resources.exceptions.ResourceFinderErrorException;
|
||||
|
||||
/**
|
||||
* Singleton class that provides access to the current RIFE2 version as a string.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.0
|
||||
*/
|
||||
public class BldVersion {
|
||||
private String version_;
|
||||
|
||||
BldVersion() {
|
||||
ResourceFinderClasspath resource_finder = ResourceFinderClasspath.instance();
|
||||
try {
|
||||
version_ = resource_finder.getContent("BLD_VERSION");
|
||||
} catch (ResourceFinderErrorException e) {
|
||||
version_ = null;
|
||||
}
|
||||
|
||||
if (version_ != null) {
|
||||
version_ = version_.trim();
|
||||
}
|
||||
if (null == version_) {
|
||||
version_ = "unknown version";
|
||||
}
|
||||
}
|
||||
|
||||
private String getVersionString() {
|
||||
return version_;
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return BldVersionSingleton.INSTANCE.getVersionString();
|
||||
}
|
||||
}
|
||||
|
14
src/main/java/rife/bld/BldVersionSingleton.java
Normal file
14
src/main/java/rife/bld/BldVersionSingleton.java
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
/**
|
||||
* Helper class to avoid Double Check Locking
|
||||
* and still have a thread-safe singleton pattern
|
||||
*/
|
||||
class BldVersionSingleton {
|
||||
static final BldVersion INSTANCE = new BldVersion();
|
||||
}
|
||||
|
52
src/main/java/rife/bld/BuildCommand.java
Normal file
52
src/main/java/rife/bld/BuildCommand.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Declares a {@link BuildExecutor} method to be used as a build command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
@Documented
|
||||
public @interface BuildCommand {
|
||||
/**
|
||||
* When provided, specifies a name for the build command that can be
|
||||
* different from the method name.
|
||||
*
|
||||
* @return a string representing the build command name
|
||||
* @since 1.5
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* When provided, specifies a short description about the command.
|
||||
*
|
||||
* @return the short summary, defaults to {@code ""}
|
||||
* @since 1.5.12
|
||||
*/
|
||||
String summary() default "";
|
||||
|
||||
/**
|
||||
* When provided, specifies the full help description of a command.
|
||||
*
|
||||
* @return the full help description, defaults to {@code ""}
|
||||
* @since 1.5.12
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* When provided, specifies a class that provides help about the
|
||||
* build command.
|
||||
*
|
||||
* @return a class providing help information
|
||||
* @since 1.5
|
||||
*/
|
||||
Class<? extends CommandHelp> help() default CommandHelp.class;
|
||||
}
|
467
src/main/java/rife/bld/BuildExecutor.java
Normal file
467
src/main/java/rife/bld/BuildExecutor.java
Normal file
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import rife.bld.dependencies.DependencyResolver;
|
||||
import rife.bld.dependencies.Repository;
|
||||
import rife.bld.help.HelpHelp;
|
||||
import rife.bld.operations.HelpOperation;
|
||||
import rife.bld.operations.exceptions.ExitStatusException;
|
||||
import rife.ioc.HierarchicalProperties;
|
||||
import rife.tools.ExceptionUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Base class that executes build commands from a list of arguments.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @see BuildCommand
|
||||
* @see CommandDefinition
|
||||
* @since 1.5
|
||||
*/
|
||||
public class BuildExecutor {
|
||||
public static final File RIFE2_USER_DIR = new File(System.getProperty("user.home"), ".rife2");
|
||||
public static final String BLD_PROPERTIES = "bld.properties";
|
||||
public static final String LOCAL_PROPERTIES = "local.properties";
|
||||
|
||||
private static final String ARG_HELP1 = "--help";
|
||||
private static final String ARG_HELP2 = "-h";
|
||||
private static final String ARG_HELP3 = "-?";
|
||||
private static final String ARG_STACKTRACE1 = "--stacktrace";
|
||||
private static final String ARG_STACKTRACE2 = "-s";
|
||||
|
||||
private final HierarchicalProperties properties_;
|
||||
private List<String> arguments_ = Collections.emptyList();
|
||||
private Map<String, CommandDefinition> buildCommands_ = null;
|
||||
private final AtomicReference<String> currentCommandName_ = new AtomicReference<>();
|
||||
private final AtomicReference<CommandDefinition> currentCommandDefinition_ = new AtomicReference<>();
|
||||
private int exitStatus_ = 0;
|
||||
|
||||
/**
|
||||
* Show the full Java stacktrace when exceptions occur, as opposed
|
||||
* to the chain of messages.
|
||||
* <p>
|
||||
* Defaults to {@code false}, can be set to {@code true} by setting
|
||||
* through code or by adding {@code --stacktrace} as a CLI argument.
|
||||
*
|
||||
* @since 1.5.19
|
||||
*/
|
||||
protected boolean showStacktrace = false;
|
||||
|
||||
/**
|
||||
* Creates a new build executor instance.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public BuildExecutor() {
|
||||
properties_ = setupProperties(workDirectory());
|
||||
Repository.resolveMavenLocal(properties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a properties hierarchy for bld execution.
|
||||
*
|
||||
* @param workDirectory the directory where the project build files are location
|
||||
* @return the properties hierarchy
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public static HierarchicalProperties setupProperties(File workDirectory) {
|
||||
var system_properties = HierarchicalProperties.createSystemInstance();
|
||||
|
||||
var java_properties = system_properties;
|
||||
system_properties = java_properties.getParent();
|
||||
|
||||
HierarchicalProperties bld_properties = null;
|
||||
HierarchicalProperties local_properties = null;
|
||||
|
||||
var bld_properties_file = new File(RIFE2_USER_DIR, BLD_PROPERTIES);
|
||||
if (bld_properties_file.exists() && bld_properties_file.isFile() && bld_properties_file.canRead()) {
|
||||
try {
|
||||
var bld = new Properties();
|
||||
bld.load(new FileReader(bld_properties_file));
|
||||
bld_properties = new HierarchicalProperties();
|
||||
bld_properties.putAll(bld);
|
||||
|
||||
bld_properties.parent(system_properties);
|
||||
} catch (IOException e) {
|
||||
Logger.getLogger("rife.bld").warning("Unable to parse " + bld_properties_file + " as a properties file:\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
var local_properties_file = new File(workDirectory, LOCAL_PROPERTIES);
|
||||
if (local_properties_file.exists() && local_properties_file.isFile() && local_properties_file.canRead()) {
|
||||
try {
|
||||
var local = new Properties();
|
||||
local.load(new FileReader(local_properties_file));
|
||||
local_properties = new HierarchicalProperties();
|
||||
local_properties.putAll(local);
|
||||
|
||||
local_properties.parent(Objects.requireNonNullElse(bld_properties, system_properties));
|
||||
} catch (IOException e) {
|
||||
Logger.getLogger("rife.bld").warning("Unable to parse " + local_properties_file + " as a properties file:\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
java_properties.parent(
|
||||
Objects.requireNonNullElse(local_properties,
|
||||
Objects.requireNonNullElse(bld_properties, system_properties)));
|
||||
|
||||
final HierarchicalProperties properties = new HierarchicalProperties();
|
||||
properties.parent(java_properties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the properties uses by this conversation.
|
||||
*
|
||||
* @return the instance of {@code HierarchicalProperties} that is used
|
||||
* by this build executor
|
||||
* @since 1.5
|
||||
*/
|
||||
public HierarchicalProperties properties() {
|
||||
return properties_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a property from the {@link #properties()}.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @return the requested property; or {@code null} if it doesn't exist
|
||||
* @since 1.5.15
|
||||
*/
|
||||
public String property(String name) {
|
||||
return properties().getValueString(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a property from the {@link #properties()} with a default value.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @param defaultValue the value that should be used as a fallback
|
||||
* @return the requested property; or the default value if it doesn't exist
|
||||
* @since 1.5.15
|
||||
*/
|
||||
public String property(String name, String defaultValue) {
|
||||
return properties().getValueString(name, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for the existence of a property in {@link #properties()}.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @return {@code true} if the property exists; or {@code false} otherwise
|
||||
* @since 1.5.15
|
||||
*/
|
||||
public boolean hasProperty(String name) {
|
||||
return properties().contains(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the work directory of the project.
|
||||
* Defaults to this process's user working directory, which when running
|
||||
* through the bld wrapper corresponds to the top-level project directory.
|
||||
*
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public File workDirectory() {
|
||||
return new File(System.getProperty("user.dir"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exist status to use at the end of the execution.
|
||||
*
|
||||
* @param status sets the exit status
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public void exitStatus(int status) {
|
||||
exitStatus_ = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the exit status.
|
||||
*
|
||||
* @return the exit status
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public int exitStatus() {
|
||||
return exitStatus_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the build commands from the provided arguments.
|
||||
* <p>
|
||||
* While the build is executing, the arguments can be retrieved
|
||||
* using {@link #arguments()}.
|
||||
*
|
||||
* @param arguments the arguments to execute the build with
|
||||
* @return the exist status
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public int execute(String[] arguments) {
|
||||
arguments_ = new ArrayList<>(Arrays.asList(arguments));
|
||||
|
||||
var show_help = false;
|
||||
show_help |= arguments_.removeAll(List.of(ARG_HELP1, ARG_HELP2, ARG_HELP3));
|
||||
showStacktrace |= arguments_.removeAll(List.of(ARG_STACKTRACE1, ARG_STACKTRACE2));
|
||||
show_help |= arguments_.isEmpty();
|
||||
|
||||
if (show_help) {
|
||||
new HelpOperation(this, Collections.emptyList()).execute();
|
||||
return exitStatus_;
|
||||
}
|
||||
|
||||
while (!arguments_.isEmpty()) {
|
||||
var command = arguments_.remove(0);
|
||||
|
||||
try {
|
||||
if (!executeCommand(command)) {
|
||||
break;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
exitStatus(1);
|
||||
|
||||
System.err.println();
|
||||
|
||||
if (showStacktrace) {
|
||||
System.err.println(ExceptionUtils.getExceptionStackTrace(e));
|
||||
} else {
|
||||
boolean first = true;
|
||||
var e2 = e;
|
||||
while (e2 != null) {
|
||||
if (e2.getMessage() != null) {
|
||||
if (!first) {
|
||||
System.err.print("> ");
|
||||
}
|
||||
System.err.println(e2.getMessage());
|
||||
first = false;
|
||||
}
|
||||
e2 = e2.getCause();
|
||||
}
|
||||
|
||||
if (first) {
|
||||
System.err.println(ExceptionUtils.getExceptionStackTrace(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return exitStatus_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the execution of the build. This method will call
|
||||
* System.exit() when done with the appropriate exit status.
|
||||
*
|
||||
* @param arguments the arguments to execute the build with
|
||||
* @see #execute
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public void start(String[] arguments) {
|
||||
System.exit(execute(arguments));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of arguments that are being processed.
|
||||
*
|
||||
* @return the list of arguments
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<String> arguments() {
|
||||
return arguments_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the commands that can be executed by this {@code BuildExecutor}.
|
||||
*
|
||||
* @return a map containing the name of the build command and the method that
|
||||
* corresponds to execution
|
||||
* @see BuildCommand
|
||||
* @since 1.5
|
||||
*/
|
||||
public Map<String, CommandDefinition> buildCommands() {
|
||||
if (buildCommands_ == null) {
|
||||
var build_commands = new TreeMap<String, CommandDefinition>();
|
||||
|
||||
Class<?> klass = getClass();
|
||||
|
||||
try {
|
||||
while (klass != null) {
|
||||
for (var method : klass.getDeclaredMethods()) {
|
||||
if (method.getParameters().length == 0 && method.isAnnotationPresent(BuildCommand.class)) {
|
||||
method.setAccessible(true);
|
||||
|
||||
var name = method.getName();
|
||||
var annotation = method.getAnnotation(BuildCommand.class);
|
||||
|
||||
var annotation_name = annotation.value();
|
||||
if (annotation_name != null && !annotation_name.isEmpty()) {
|
||||
name = annotation_name;
|
||||
}
|
||||
|
||||
if (!build_commands.containsKey(name)) {
|
||||
var build_help = annotation.help();
|
||||
CommandHelp command_help = null;
|
||||
if (build_help != null && build_help != CommandHelp.class) {
|
||||
command_help = build_help.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
|
||||
var summary = annotation.summary();
|
||||
var description = annotation.description();
|
||||
if ((summary != null && !summary.isBlank()) ||
|
||||
(description != null && !description.isBlank())) {
|
||||
if (summary == null) summary = "";
|
||||
if (description == null) description = "";
|
||||
if (command_help != null) {
|
||||
if (summary.isBlank()) summary = command_help.getSummary();
|
||||
if (description.isBlank()) description = command_help.getDescription(name);
|
||||
}
|
||||
command_help = new AnnotatedCommandHelp(summary, description);
|
||||
}
|
||||
|
||||
build_commands.put(name, new CommandAnnotated(this, method, command_help));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
klass = klass.getSuperclass();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
buildCommands_ = build_commands;
|
||||
}
|
||||
|
||||
return buildCommands_;
|
||||
}
|
||||
|
||||
private static class AnnotatedCommandHelp implements CommandHelp {
|
||||
private final String summary_;
|
||||
private final String description_;
|
||||
|
||||
AnnotatedCommandHelp(String summary, String description) {
|
||||
summary_ = summary;
|
||||
description_ = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return summary_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String topic) {
|
||||
return description_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the execution of a single command.
|
||||
*
|
||||
* @param command the name of the command to execute
|
||||
* @return {@code true} when the command was found and executed; or
|
||||
* {@code false} if the command couldn't be found
|
||||
* @throws Throwable when an exception occurred during the command execution
|
||||
* @see BuildCommand
|
||||
* @since 1.5
|
||||
*/
|
||||
public boolean executeCommand(String command)
|
||||
throws Throwable {
|
||||
var matched_command = command;
|
||||
var definition = buildCommands().get(command);
|
||||
|
||||
// try to find a match for the provided command amongst
|
||||
// the ones that are known
|
||||
if (definition == null) {
|
||||
// try to find starting matching options
|
||||
var matches = new ArrayList<>(buildCommands().keySet().stream()
|
||||
.filter(c -> c.toLowerCase().startsWith(command.toLowerCase()))
|
||||
.toList());
|
||||
|
||||
if (matches.isEmpty()) {
|
||||
// try to find fuzzy matching options
|
||||
var fuzzy_regexp = new StringBuilder("^.*");
|
||||
for (var ch : command.toCharArray()) {
|
||||
fuzzy_regexp.append("\\Q");
|
||||
fuzzy_regexp.append(ch);
|
||||
fuzzy_regexp.append("\\E.*");
|
||||
}
|
||||
fuzzy_regexp.append("$");
|
||||
var fuzzy_pattern = Pattern.compile(fuzzy_regexp.toString());
|
||||
matches.addAll(buildCommands().keySet().stream()
|
||||
.filter(c -> fuzzy_pattern.matcher(c.toLowerCase()).matches())
|
||||
.toList());
|
||||
}
|
||||
|
||||
// only proceed if exactly one match was found
|
||||
if (matches.size() == 1) {
|
||||
matched_command = matches.get(0);
|
||||
System.out.println("Executing matched command: " + matched_command);
|
||||
definition = buildCommands().get(matched_command);
|
||||
}
|
||||
}
|
||||
|
||||
// execute the command if we found one
|
||||
if (definition != null) {
|
||||
try {
|
||||
currentCommandName_.set(matched_command);
|
||||
currentCommandDefinition_.set(definition);
|
||||
definition.execute();
|
||||
} catch (ExitStatusException e) {
|
||||
exitStatus(e.getExitStatus());
|
||||
return e.getExitStatus() == ExitStatusException.EXIT_SUCCESS;
|
||||
} finally {
|
||||
currentCommandDefinition_.set(null);
|
||||
currentCommandName_.set(null);
|
||||
}
|
||||
} else {
|
||||
new HelpOperation(this, arguments()).executePrintOverviewHelp();
|
||||
System.err.println();
|
||||
System.err.println("ERROR: unknown command '" + command + "'");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the name of the currently executing command.
|
||||
*
|
||||
* @return the name of the current command; or
|
||||
* {@code null} if no command is currently executing
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public String getCurrentCommandName() {
|
||||
return currentCommandName_.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the definition of the currently executing command.
|
||||
*
|
||||
* @return the definition of the current command; or
|
||||
* {@code null} if no command is currently executing
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public CommandDefinition getCurrentCommandDefinition() {
|
||||
return currentCommandDefinition_.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard {@code help} command.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = HelpHelp.class)
|
||||
public void help() {
|
||||
new HelpOperation(this, arguments()).execute();
|
||||
}
|
||||
}
|
100
src/main/java/rife/bld/Cli.java
Normal file
100
src/main/java/rife/bld/Cli.java
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import rife.bld.help.*;
|
||||
import rife.bld.operations.*;
|
||||
|
||||
/**
|
||||
* Implements the RIFE2 CLI build executor that is available when running
|
||||
* the RIFE2 jar as an executable jar.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class Cli extends BuildExecutor {
|
||||
private final CreateBaseOperation createBaseOperation_ = new CreateBaseOperation();
|
||||
private final CreateBlankOperation createBlankOperation_ = new CreateBlankOperation();
|
||||
private final CreateLibOperation createLibOperation_ = new CreateLibOperation();
|
||||
private final CreateRife2Operation createRife2Operation_ = new CreateRife2Operation();
|
||||
private final UpgradeOperation upgradeOperation_ = new UpgradeOperation();
|
||||
private final VersionOperation versionOperation_ = new VersionOperation();
|
||||
|
||||
/**
|
||||
* The standard {@code create} command.
|
||||
*
|
||||
* @throws Exception when an error occurred during the creation process
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = CreateRife2Help.class)
|
||||
public void create()
|
||||
throws Exception {
|
||||
createRife2Operation_.executeOnce(() -> createRife2Operation_.fromArguments(arguments()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard {@code create-blank} command.
|
||||
*
|
||||
* @throws Exception when an error occurred during the creation process
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(value = "create-blank", help = CreateBlankHelp.class)
|
||||
public void createBlank()
|
||||
throws Exception {
|
||||
createBlankOperation_.executeOnce(() -> createBlankOperation_.fromArguments(arguments()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard {@code create-base} command.
|
||||
*
|
||||
* @throws Exception when an error occurred during the creation process
|
||||
* @since 1.5.20
|
||||
*/
|
||||
@BuildCommand(value = "create-base", help = CreateBaseHelp.class)
|
||||
public void createBase()
|
||||
throws Exception {
|
||||
createBaseOperation_.executeOnce(() -> createBaseOperation_.fromArguments(arguments()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard {@code create-lib} command.
|
||||
*
|
||||
* @throws Exception when an error occurred during the creation process
|
||||
* @since 1.6
|
||||
*/
|
||||
@BuildCommand(value = "create-lib", help = CreateLibHelp.class)
|
||||
public void createLib()
|
||||
throws Exception {
|
||||
createLibOperation_.executeOnce(() -> createLibOperation_.fromArguments(arguments()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard {@code upgrade} command.
|
||||
*
|
||||
* @throws Exception when an error occurred during the upgrade process
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = UpgradeHelp.class)
|
||||
public void upgrade()
|
||||
throws Exception {
|
||||
upgradeOperation_.executeOnce();
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard {@code version} command.
|
||||
*
|
||||
* @since 1.5.2
|
||||
*/
|
||||
@BuildCommand(help = VersionHelp.class)
|
||||
public void version()
|
||||
throws Exception {
|
||||
versionOperation_.executeOnce();
|
||||
}
|
||||
|
||||
public static void main(String[] arguments)
|
||||
throws Exception {
|
||||
new Cli().start(arguments);
|
||||
}
|
||||
}
|
36
src/main/java/rife/bld/CommandAnnotated.java
Normal file
36
src/main/java/rife/bld/CommandAnnotated.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
class CommandAnnotated implements CommandDefinition {
|
||||
private final BuildExecutor executor_;
|
||||
private final Method method_;
|
||||
private final CommandHelp help_;
|
||||
|
||||
CommandAnnotated(BuildExecutor executor, Method method, CommandHelp help) {
|
||||
executor_ = executor;
|
||||
method_ = method;
|
||||
if (help == null) {
|
||||
help = new CommandHelp() {};
|
||||
}
|
||||
help_ = help;
|
||||
}
|
||||
|
||||
public void execute()
|
||||
throws Throwable {
|
||||
try {
|
||||
method_.invoke(executor_);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
public CommandHelp getHelp() {
|
||||
return help_;
|
||||
}
|
||||
}
|
33
src/main/java/rife/bld/CommandDefinition.java
Normal file
33
src/main/java/rife/bld/CommandDefinition.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
/**
|
||||
* Defines the logic for a build command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface CommandDefinition {
|
||||
/**
|
||||
* Called when a build command is executed.
|
||||
*
|
||||
* @throws Throwable when an error occurred during the execution of the build command
|
||||
* @since 1.5
|
||||
*/
|
||||
void execute() throws Throwable;
|
||||
|
||||
/**
|
||||
* Retrieves the help information of a build command.
|
||||
* <p>
|
||||
* Defaults to blank help sections.
|
||||
*
|
||||
* @return this build command's help information
|
||||
* @since 1.5
|
||||
*/
|
||||
default CommandHelp getHelp() {
|
||||
return new CommandHelp() {};
|
||||
}
|
||||
}
|
33
src/main/java/rife/bld/CommandHelp.java
Normal file
33
src/main/java/rife/bld/CommandHelp.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
/**
|
||||
* Interface that provides help texts to display about {@link BuildExecutor} commands.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface CommandHelp {
|
||||
/**
|
||||
* Returns a short description about the command.
|
||||
*
|
||||
* @return the short summary, defaults to {@code ""}
|
||||
* @since 1.5
|
||||
*/
|
||||
default String getSummary() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full help description of a command.
|
||||
*
|
||||
* @return the full help description, defaults to {@code ""}
|
||||
* @since 1.5
|
||||
*/
|
||||
default String getDescription(String topic) {
|
||||
return "";
|
||||
}
|
||||
}
|
19
src/main/java/rife/bld/NamedFile.java
Normal file
19
src/main/java/rife/bld/NamedFile.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Combines the information of a filesystem file with the name it's intended
|
||||
* to have.
|
||||
*
|
||||
* @param name the intended name of the file
|
||||
* @param file the location on the filesystem
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public record NamedFile(String name, File file) {
|
||||
}
|
195
src/main/java/rife/bld/Project.java
Normal file
195
src/main/java/rife/bld/Project.java
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import rife.bld.help.*;
|
||||
import rife.bld.operations.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.jar.Attributes;
|
||||
|
||||
/**
|
||||
* Provides the configuration and commands of a Java project for the
|
||||
* build system with all standard commands ready to go.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class Project extends BaseProject {
|
||||
/*
|
||||
* Standard build commands
|
||||
*/
|
||||
|
||||
private final JavadocOperation javadocOperation_ = new JavadocOperation();
|
||||
private final PrecompileOperation precompileOperation_ = new PrecompileOperation();
|
||||
private final JarOperation jarOperation_ = new JarOperation();
|
||||
private final JarOperation jarSourcesOperation_ = new JarOperation();
|
||||
private final JarOperation jarJavadocOperation_ = new JarOperation();
|
||||
private final JUnitOperation junitTestOperation_ = new JUnitOperation();
|
||||
private final UberJarOperation uberJarOperation_ = new UberJarOperation();
|
||||
|
||||
@Override
|
||||
public JUnitOperation testOperation() {
|
||||
return junitTestOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project's default javadoc operation.
|
||||
*
|
||||
* @return the default javadoc operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation javadocOperation() {
|
||||
return javadocOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project's default precompile operation.
|
||||
*
|
||||
* @return the default precompile operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PrecompileOperation precompileOperation() {
|
||||
return precompileOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project's default jar operation.
|
||||
*
|
||||
* @return the default jar operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation jarOperation() {
|
||||
return jarOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project's default jar operation for sources.
|
||||
*
|
||||
* @return the default jar operation instance for sources
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation jarSourcesOperation() {
|
||||
return jarSourcesOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project's default jar operation for javadoc.
|
||||
*
|
||||
* @return the default jar operation instance for javadoc
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation jarJavadocOperation() {
|
||||
return jarJavadocOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project's default uberjar operation.
|
||||
*
|
||||
* @return the default uberjar operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public UberJarOperation uberJarOperation() {
|
||||
return uberJarOperation_;
|
||||
}
|
||||
|
||||
@BuildCommand(help = JUnitHelp.class)
|
||||
@Override
|
||||
public void test()
|
||||
throws Exception {
|
||||
super.test();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, generates javadoc.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
@BuildCommand(help = JavadocHelp.class)
|
||||
public void javadoc()
|
||||
throws Exception {
|
||||
javadocOperation().executeOnce(() -> javadocOperation().fromProject(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, pre-compiles RIFE2 templates to class files.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = PrecompileHelp.class)
|
||||
public void precompile()
|
||||
throws Exception {
|
||||
precompileOperation().executeOnce(() -> precompileOperation().fromProject(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, creates a jar archive for the project.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = JarHelp.class)
|
||||
public void jar()
|
||||
throws Exception {
|
||||
compile();
|
||||
precompile();
|
||||
jarOperation().executeOnce(() -> jarOperation().fromProject(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, creates a sources jar archive for the project.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
@BuildCommand(value = "jar-sources", help = JarSourcesHelp.class)
|
||||
public void jarSources()
|
||||
throws Exception {
|
||||
jarSourcesOperation().executeOnce(() -> jarSourcesOperation()
|
||||
.manifestAttributes(Map.of(Attributes.Name.MANIFEST_VERSION, "1.0"))
|
||||
.sourceDirectories(List.of(srcMainJavaDirectory()))
|
||||
.destinationDirectory(buildDistDirectory())
|
||||
.destinationFileName(sourcesJarFileName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, creates a javadoc jar archive for the project.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
@BuildCommand(value = "jar-javadoc", help = JarJavadocHelp.class)
|
||||
public void jarJavadoc()
|
||||
throws Exception {
|
||||
compile();
|
||||
javadoc();
|
||||
jarJavadocOperation().executeOnce(() -> jarJavadocOperation().manifestAttributes(Map.of(Attributes.Name.MANIFEST_VERSION, "1.0"))
|
||||
.sourceDirectories(List.of(buildJavadocDirectory()))
|
||||
.destinationDirectory(buildDistDirectory())
|
||||
.destinationFileName(javadocJarFileName()));
|
||||
}
|
||||
/**
|
||||
* Standard build command, creates an UberJar archive for the project.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = UberJarHelp.class)
|
||||
public void uberjar()
|
||||
throws Exception {
|
||||
jar();
|
||||
uberJarOperation().executeOnce(() -> uberJarOperation().fromProject(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard publish command, uploads artifacts to the publication repository.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
@BuildCommand(help = PublishHelp.class)
|
||||
public void publish()
|
||||
throws Exception {
|
||||
jar();
|
||||
jarSources();
|
||||
jarJavadoc();
|
||||
publishOperation().executeOnce(() -> publishOperation().fromProject(this));
|
||||
}
|
||||
}
|
134
src/main/java/rife/bld/WebProject.java
Normal file
134
src/main/java/rife/bld/WebProject.java
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld;
|
||||
|
||||
import rife.bld.help.*;
|
||||
import rife.bld.operations.*;
|
||||
import rife.bld.publish.PublishArtifact;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Provides the configuration and commands of a Java web project for the
|
||||
* build system.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class WebProject extends Project {
|
||||
/**
|
||||
* The main war archive creation.
|
||||
*
|
||||
* @see #warFileName()
|
||||
* @since 1.5.0
|
||||
*/
|
||||
protected String warFileName = null;
|
||||
/**
|
||||
* The main webapp directory.
|
||||
*
|
||||
* @see #srcMainWebappDirectory()
|
||||
* @since 1.5
|
||||
*/
|
||||
protected File srcMainWebappDirectory = null;
|
||||
|
||||
/*
|
||||
* Standard build commands
|
||||
*/
|
||||
|
||||
private final WarOperation warOperation_ = new WarOperation();
|
||||
|
||||
/**
|
||||
* Retrieves the project's default war operation.
|
||||
*
|
||||
* @return the default war operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected WarOperation warOperation() {
|
||||
return warOperation_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, creates an UberJar archive for the web project.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@Override
|
||||
public void uberjar()
|
||||
throws Exception {
|
||||
jar();
|
||||
uberJarOperation().executeOnce(() -> {
|
||||
uberJarOperation().fromProject(this);
|
||||
uberJarOperation().sourceDirectories(List.of(new NamedFile("webapp", srcMainWebappDirectory())));
|
||||
uberJarOperation().jarSourceFiles().addAll(standaloneClasspathJars());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard build command, creates a war archive for the web project.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@BuildCommand(help = WarHelp.class)
|
||||
public void war()
|
||||
throws Exception {
|
||||
jar();
|
||||
warOperation().executeOnce(() -> warOperation().fromProject(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard publish-web command, uploads artifacts to the publication repository.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
@BuildCommand(help = PublishWebHelp.class)
|
||||
public void publish()
|
||||
throws Exception {
|
||||
jar();
|
||||
jarSources();
|
||||
jarJavadoc();
|
||||
uberjar();
|
||||
war();
|
||||
publishOperation().executeOnce(() -> {
|
||||
publishOperation().fromProject(this);
|
||||
publishOperation().artifacts().add(new PublishArtifact(new File(buildDistDirectory(), uberJarFileName()), "uber", "jar"));
|
||||
publishOperation().artifacts().add(new PublishArtifact(new File(buildDistDirectory(), warFileName()), "", "war"));
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Project directories
|
||||
*/
|
||||
|
||||
@Override
|
||||
public File libStandaloneDirectory() {
|
||||
return Objects.requireNonNullElseGet(libStandaloneDirectory, () -> new File(libDirectory(), "standalone"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the project main webapp directory.
|
||||
* Defaults to {@code "webapp"} relative to {@link #srcMainDirectory()}.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public File srcMainWebappDirectory() {
|
||||
return Objects.requireNonNullElseGet(srcMainWebappDirectory, () -> new File(srcMainDirectory(), "webapp"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Project options
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns filename to use for the main war archive creation.
|
||||
* By default, appends the version and the {@code war} extension to the {@link #archiveBaseName()}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public String warFileName() {
|
||||
return Objects.requireNonNullElseGet(warFileName, () -> archiveBaseName() + "-" + version() + ".war");
|
||||
}
|
||||
}
|
40
src/main/java/rife/bld/blueprints/BaseProjectBlueprint.java
Normal file
40
src/main/java/rife/bld/blueprints/BaseProjectBlueprint.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.blueprints;
|
||||
|
||||
import rife.bld.Project;
|
||||
import rife.bld.dependencies.VersionNumber;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static rife.bld.dependencies.Repository.MAVEN_CENTRAL;
|
||||
import static rife.bld.dependencies.Repository.SONATYPE_SNAPSHOTS;
|
||||
import static rife.bld.dependencies.Scope.test;
|
||||
|
||||
/**
|
||||
* Provides the dependency information required to create a new base project.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public class BaseProjectBlueprint extends Project {
|
||||
public BaseProjectBlueprint(File work, String packageName, String projectName) {
|
||||
this(work, packageName, projectName, new VersionNumber(0,0,1));
|
||||
}
|
||||
|
||||
public BaseProjectBlueprint(File work, String packageName, String projectName, VersionNumber versionNumber) {
|
||||
workDirectory = work;
|
||||
|
||||
pkg = packageName;
|
||||
name = projectName;
|
||||
mainClass = packageName + "." + StringUtils.capitalize(projectName) + "Main";
|
||||
version = versionNumber;
|
||||
|
||||
downloadSources = true;
|
||||
repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS);
|
||||
}
|
||||
}
|
43
src/main/java/rife/bld/blueprints/BlankProjectBlueprint.java
Normal file
43
src/main/java/rife/bld/blueprints/BlankProjectBlueprint.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.blueprints;
|
||||
|
||||
import rife.bld.Project;
|
||||
import rife.bld.dependencies.VersionNumber;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static rife.bld.dependencies.Repository.MAVEN_CENTRAL;
|
||||
import static rife.bld.dependencies.Repository.SONATYPE_SNAPSHOTS;
|
||||
import static rife.bld.dependencies.Scope.test;
|
||||
|
||||
/**
|
||||
* Provides the dependency information required to create a new blank project.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class BlankProjectBlueprint extends Project {
|
||||
public BlankProjectBlueprint(File work, String packageName, String projectName) {
|
||||
this(work, packageName, projectName, new VersionNumber(0,0,1));
|
||||
}
|
||||
|
||||
public BlankProjectBlueprint(File work, String packageName, String projectName, VersionNumber versionNumber) {
|
||||
workDirectory = work;
|
||||
|
||||
pkg = packageName;
|
||||
name = projectName;
|
||||
mainClass = packageName + "." + StringUtils.capitalize(projectName) + "Main";
|
||||
version = versionNumber;
|
||||
|
||||
downloadSources = true;
|
||||
repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS);
|
||||
scope(test)
|
||||
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5,9,3)))
|
||||
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1,9,3)));
|
||||
}
|
||||
}
|
39
src/main/java/rife/bld/blueprints/LibProjectBlueprint.java
Normal file
39
src/main/java/rife/bld/blueprints/LibProjectBlueprint.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.blueprints;
|
||||
|
||||
import rife.bld.Project;
|
||||
import rife.bld.dependencies.VersionNumber;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static rife.bld.dependencies.Repository.MAVEN_CENTRAL;
|
||||
import static rife.bld.dependencies.Repository.SONATYPE_SNAPSHOTS;
|
||||
|
||||
/**
|
||||
* Provides the dependency information required to create a new lib project.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.6
|
||||
*/
|
||||
public class LibProjectBlueprint extends Project {
|
||||
public LibProjectBlueprint(File work, String packageName, String projectName) {
|
||||
this(work, packageName, projectName, new VersionNumber(0,0,1));
|
||||
}
|
||||
|
||||
public LibProjectBlueprint(File work, String packageName, String projectName, VersionNumber versionNumber) {
|
||||
workDirectory = work;
|
||||
|
||||
pkg = packageName;
|
||||
name = projectName;
|
||||
mainClass = packageName + "." + StringUtils.capitalize(projectName) + "Lib";
|
||||
version = versionNumber;
|
||||
|
||||
downloadSources = true;
|
||||
repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS);
|
||||
}
|
||||
}
|
53
src/main/java/rife/bld/blueprints/Rife2ProjectBlueprint.java
Normal file
53
src/main/java/rife/bld/blueprints/Rife2ProjectBlueprint.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.blueprints;
|
||||
|
||||
import rife.bld.WebProject;
|
||||
import rife.bld.dependencies.VersionNumber;
|
||||
import rife.bld.operations.TemplateType;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static rife.bld.dependencies.Repository.MAVEN_CENTRAL;
|
||||
import static rife.bld.dependencies.Repository.SONATYPE_SNAPSHOTS;
|
||||
import static rife.bld.dependencies.Scope.*;
|
||||
|
||||
/**
|
||||
* Provides the dependency information required to create a new RIFE2 project.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class Rife2ProjectBlueprint extends WebProject {
|
||||
public Rife2ProjectBlueprint(File work, String packageName, String projectName) {
|
||||
this(work, packageName, projectName, new VersionNumber(0,0,1));
|
||||
}
|
||||
|
||||
public Rife2ProjectBlueprint(File work, String packageName, String projectName, VersionNumber versionNumber) {
|
||||
workDirectory = work;
|
||||
|
||||
pkg = packageName;
|
||||
name = projectName;
|
||||
mainClass = packageName + "." + StringUtils.capitalize(projectName) + "Site";
|
||||
version = versionNumber;
|
||||
|
||||
downloadSources = true;
|
||||
repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS);
|
||||
scope(compile)
|
||||
.include(dependency("com.uwyn.rife2", "rife2", version(1,6,3)));
|
||||
scope(test)
|
||||
.include(dependency("org.jsoup", "jsoup", version(1,16,1)))
|
||||
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5,9,3)))
|
||||
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1,9,3)));
|
||||
scope(standalone)
|
||||
.include(dependency("org.eclipse.jetty", "jetty-server", version(11,0,15)))
|
||||
.include(dependency("org.eclipse.jetty", "jetty-servlet", version(11,0,15)))
|
||||
.include(dependency("org.slf4j", "slf4j-simple", version(2,0,7)));
|
||||
|
||||
precompileOperation().templateTypes(TemplateType.HTML);
|
||||
}
|
||||
}
|
10
src/main/java/rife/bld/blueprints/package-info.java
Normal file
10
src/main/java/rife/bld/blueprints/package-info.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides blueprints for project creation.
|
||||
* @since 1.5
|
||||
*/
|
||||
package rife.bld.blueprints;
|
202
src/main/java/rife/bld/dependencies/ArtifactRetriever.java
Normal file
202
src/main/java/rife/bld/dependencies/ArtifactRetriever.java
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
import static rife.tools.HttpUtils.HEADER_AUTHORIZATION;
|
||||
import static rife.tools.HttpUtils.basicAuthorizationHeader;
|
||||
import static rife.tools.StringUtils.encodeHexLower;
|
||||
|
||||
/**
|
||||
* Retrieves artifact data.
|
||||
* <p>
|
||||
* To instantiate, use either {@link #instance()} for direct retrieval of
|
||||
* each request, or {@link #cachingInstance()} where previous retrievals
|
||||
* of remote string content will be cached for faster future retrieval.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public abstract class ArtifactRetriever {
|
||||
private final static ArtifactRetriever UNCACHED = new ArtifactRetriever() {
|
||||
String getCached(RepositoryArtifact artifact) {
|
||||
return null;
|
||||
}
|
||||
|
||||
void cache(RepositoryArtifact artifact, String content) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets an artifact retriever that does direct retrieval of each request.
|
||||
*
|
||||
* @return the direct retrieval instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public static ArtifactRetriever instance() {
|
||||
return UNCACHED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a caching artifact retriever where previous retrievals
|
||||
* of remote string content will be cached for faster future retrieval.
|
||||
*
|
||||
* @return a caching instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public static ArtifactRetriever cachingInstance() {
|
||||
return new ArtifactRetriever() {
|
||||
private final Map<RepositoryArtifact, String> artifactCache = new HashMap<>();
|
||||
|
||||
String getCached(RepositoryArtifact artifact) {
|
||||
return artifactCache.get(artifact);
|
||||
}
|
||||
|
||||
void cache(RepositoryArtifact artifact, String content) {
|
||||
artifactCache.put(artifact, content);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private ArtifactRetriever() {
|
||||
}
|
||||
|
||||
abstract String getCached(RepositoryArtifact artifact);
|
||||
|
||||
abstract void cache(RepositoryArtifact artifact, String content);
|
||||
|
||||
/**
|
||||
* Reads the contents of an artifact as a string.
|
||||
*
|
||||
* @param artifact the artifact who's content to retrieve
|
||||
* @return the string content of the artifact
|
||||
* @throws FileUtilsErrorException when an error occurred when reading the contents
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public String readString(RepositoryArtifact artifact)
|
||||
throws FileUtilsErrorException {
|
||||
if (artifact.repository().isLocal()) {
|
||||
return FileUtils.readString(new File(artifact.location()));
|
||||
} else {
|
||||
var cached = getCached(artifact);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
try {
|
||||
var connection = new URL(artifact.location()).openConnection();
|
||||
connection.setUseCaches(false);
|
||||
if (artifact.repository().username() != null && artifact.repository().password() != null) {
|
||||
connection.setRequestProperty(
|
||||
HEADER_AUTHORIZATION,
|
||||
basicAuthorizationHeader(artifact.repository().username(), artifact.repository().password()));
|
||||
}
|
||||
try (var input_stream = connection.getInputStream()) {
|
||||
var result = FileUtils.readString(input_stream);
|
||||
cache(artifact, result);
|
||||
return result;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FileUtilsErrorException("Error while reading URL '" + artifact.location() + ".", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers artifact into the provided directory.
|
||||
* <p>
|
||||
* The destination directory must exist and be writable.
|
||||
*
|
||||
* @param artifact the artifact to transfer
|
||||
* @param directory the directory to transfer the artifact into
|
||||
* @return {@code true} when the artifact is present in the directory (it could already have been
|
||||
* there and be validated as correct); or {@code false} when the artifact couldn't be transferred
|
||||
* @throws IOException when an error occurred during the transfer
|
||||
* @throws FileUtilsErrorException when an error occurred during the transfer
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public boolean transferIntoDirectory(RepositoryArtifact artifact, File directory)
|
||||
throws IOException, FileUtilsErrorException {
|
||||
if (directory == null) throw new IllegalArgumentException("directory can't be null");
|
||||
if (!directory.exists()) throw new IllegalArgumentException("directory '" + directory + "' doesn't exit");
|
||||
if (!directory.canWrite()) throw new IllegalArgumentException("directory '" + directory + "' can't be written to");
|
||||
if (!directory.isDirectory()) throw new IllegalArgumentException("directory '" + directory + "' is not a directory");
|
||||
|
||||
var download_filename = artifact.location().substring(artifact.location().lastIndexOf("/") + 1);
|
||||
var download_file = new File(directory, download_filename);
|
||||
System.out.print("Downloading: " + artifact.location() + " ... ");
|
||||
System.out.flush();
|
||||
try {
|
||||
if (artifact.repository().isLocal()) {
|
||||
var source = new File(artifact.location());
|
||||
if (source.exists()) {
|
||||
FileUtils.copy(source, download_file);
|
||||
System.out.print("done");
|
||||
return true;
|
||||
} else {
|
||||
System.out.print("not found");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (download_file.exists() && download_file.canRead()) {
|
||||
if (checkHash(artifact, download_file, ".sha256", "SHA-256") ||
|
||||
checkHash(artifact, download_file, ".md5", "MD5")) {
|
||||
System.out.print("exists");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var connection = new URL(artifact.location()).openConnection();
|
||||
connection.setUseCaches(false);
|
||||
if (artifact.repository().username() != null && artifact.repository().password() != null) {
|
||||
connection.setRequestProperty(
|
||||
HEADER_AUTHORIZATION,
|
||||
basicAuthorizationHeader(artifact.repository().username(), artifact.repository().password()));
|
||||
}
|
||||
try (var input_stream = connection.getInputStream()) {
|
||||
var readableByteChannel = Channels.newChannel(input_stream);
|
||||
try (var fileOutputStream = new FileOutputStream(download_file)) {
|
||||
var fileChannel = fileOutputStream.getChannel();
|
||||
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
|
||||
|
||||
System.out.print("done");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.print("not found");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkHash(RepositoryArtifact artifact, File downloadFile, String extension, String algorithm) {
|
||||
try {
|
||||
var hash_sum = readString(artifact.appendPath(extension));
|
||||
var digest = MessageDigest.getInstance(algorithm);
|
||||
digest.update(FileUtils.readBytes(downloadFile));
|
||||
return hash_sum.equals(encodeHexLower(digest.digest()));
|
||||
} catch (Exception e) {
|
||||
// no-op, the hash file couldn't be found or calculated, so it couldn't be checked
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
169
src/main/java/rife/bld/dependencies/Dependency.java
Normal file
169
src/main/java/rife/bld/dependencies/Dependency.java
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Contains the information required to describe an url dependency in the build system.
|
||||
*
|
||||
* @param groupId the dependency group identifier
|
||||
* @param artifactId the dependency url identifier
|
||||
* @param version the dependency version
|
||||
* @param classifier the dependency classier
|
||||
* @param type the dependency type
|
||||
* @param exclusions the dependency exclusions for transitive resolution
|
||||
* @param parent the parent dependency that created this dependency (only for information purposes)
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public record Dependency(String groupId, String artifactId, VersionNumber version, String classifier, String type, ExclusionSet exclusions, Dependency parent) {
|
||||
public static final String CLASSIFIER_SOURCES = "sources";
|
||||
public static final String CLASSIFIER_JAVADOC = "javadoc";
|
||||
|
||||
public Dependency(String groupId, String artifactId) {
|
||||
this(groupId, artifactId, null, null, null);
|
||||
}
|
||||
|
||||
public Dependency(String groupId, String artifactId, VersionNumber version) {
|
||||
this(groupId, artifactId, version, null, null);
|
||||
}
|
||||
|
||||
public Dependency(String groupId, String artifactId, VersionNumber version, String classifier) {
|
||||
this(groupId, artifactId, version, classifier, null);
|
||||
}
|
||||
|
||||
public Dependency(String groupId, String artifactId, VersionNumber version, String classifier, String type) {
|
||||
this(groupId, artifactId, version, classifier, type, null);
|
||||
}
|
||||
|
||||
public Dependency(String groupId, String artifactId, VersionNumber version, String classifier, String type, ExclusionSet exclusions) {
|
||||
this(groupId, artifactId, version, classifier, type, null, null);
|
||||
}
|
||||
|
||||
public Dependency(String groupId, String artifactId, VersionNumber version, String classifier, String type, ExclusionSet exclusions, Dependency parent) {
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
this.version = (version == null ? VersionNumber.UNKNOWN : version);
|
||||
this.classifier = (classifier == null ? "" : classifier);
|
||||
this.type = (type == null ? "jar" : type);
|
||||
this.exclusions = (exclusions == null ? new ExclusionSet() : exclusions);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
private static final Pattern DEPENDENCY_PATTERN = Pattern.compile("^(?<groupId>[^:@]+):(?<artifactId>[^:@]+)(?::(?<version>[^:@]+)(?::(?<classifier>[^:@]+))?)?(?:@(?<type>[^:@]+))?$");
|
||||
|
||||
/**
|
||||
* Parses a dependency from a string representation.
|
||||
* The format is {@code groupId:artifactId:version:classifier@type}.
|
||||
* The {@code version}, {@code classifier} and {@code type} are optional.
|
||||
* <p>
|
||||
* If the string can't be successfully parsed, {@code null} will be returned.
|
||||
*
|
||||
* @param dependency the dependency string to parse
|
||||
* @return a parsed instance of {@code Dependency}; or
|
||||
* {@code null} when the string couldn't be parsed
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public static Dependency parse(String dependency) {
|
||||
if (dependency == null || dependency.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var matcher = DEPENDENCY_PATTERN.matcher(dependency);
|
||||
if (!matcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var groupId = matcher.group("groupId");
|
||||
var artifactId = matcher.group("artifactId");
|
||||
var version = VersionNumber.parse(matcher.group("version"));
|
||||
var classifier = matcher.group("classifier");
|
||||
var type = matcher.group("type");
|
||||
|
||||
return new Dependency(groupId, artifactId, version, classifier, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base dependency of this dependency, replacing the version number
|
||||
* with an unknown version number.
|
||||
*
|
||||
* @return this dependency's base dependency
|
||||
* @since 1.5
|
||||
*/
|
||||
public Dependency baseDependency() {
|
||||
return new Dependency(groupId, artifactId, VersionNumber.UNKNOWN, classifier, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an exclusion to this dependency.
|
||||
*
|
||||
* @param groupId the exclusion group identifier, use {@code "*"} to exclude all groupIds
|
||||
* @param artifactId the exclusion url identifier, use {@code "*"} to exclude all artifactIds
|
||||
* @return this dependency instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public Dependency exclude(String groupId, String artifactId) {
|
||||
exclusions.add(new DependencyExclusion(groupId, artifactId));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new dependency with the same data, except for the provided classifier.
|
||||
*
|
||||
* @param classifier the classifier to use for the new dependency
|
||||
* @return the new dependency with the changed classifier
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public Dependency withClassifier(String classifier) {
|
||||
return new Dependency(groupId, artifactId, version, classifier, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a filename that corresponds to the dependency information.
|
||||
*
|
||||
* @return a filename for the dependency
|
||||
* @since 1.5.4
|
||||
*/
|
||||
public String toFileName() {
|
||||
var result = new StringBuilder(artifactId());
|
||||
result.append("-").append(version());
|
||||
if (!classifier().isEmpty()) {
|
||||
result.append("-").append(classifier());
|
||||
}
|
||||
result.append(".").append(type());
|
||||
return result.toString();
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
var result = new StringBuilder(groupId).append(":").append(artifactId);
|
||||
if (!version.equals(VersionNumber.UNKNOWN)) {
|
||||
result.append(":").append(version);
|
||||
}
|
||||
if (!classifier.isEmpty()) {
|
||||
result.append(":").append(classifier);
|
||||
}
|
||||
if (!type.isEmpty() && !type.equals("jar")) {
|
||||
result.append("@").append(type);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
var that = (Dependency) o;
|
||||
return groupId.equals(that.groupId) &&
|
||||
artifactId.equals(that.artifactId) &&
|
||||
classifier.equals(that.classifier) &&
|
||||
type.equals(that.type);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hash(groupId, artifactId, classifier, type);
|
||||
}
|
||||
}
|
34
src/main/java/rife/bld/dependencies/DependencyExclusion.java
Normal file
34
src/main/java/rife/bld/dependencies/DependencyExclusion.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Contains the information to describe a dependency exclusion.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public record DependencyExclusion(String groupId, String artifactId) {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DependencyExclusion that = (DependencyExclusion) o;
|
||||
return Objects.equals(groupId, that.groupId) && Objects.equals(artifactId, that.artifactId);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hash(groupId, artifactId);
|
||||
}
|
||||
|
||||
boolean matches(PomDependency dependency) {
|
||||
return (groupId().equals("*") && artifactId().equals("*")) ||
|
||||
(groupId().equals("*") && artifactId().equals(dependency.artifactId())) ||
|
||||
(groupId().equals(dependency.groupId()) && artifactId().equals("*")) ||
|
||||
(groupId().equals(dependency.groupId()) && artifactId().equals(dependency.artifactId()));
|
||||
|
||||
}
|
||||
}
|
427
src/main/java/rife/bld/dependencies/DependencyResolver.java
Normal file
427
src/main/java/rife/bld/dependencies/DependencyResolver.java
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import rife.bld.dependencies.exceptions.*;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Resolves a dependency within a list of Maven-compatible repositories.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class DependencyResolver {
|
||||
private final ArtifactRetriever retriever_;
|
||||
private final List<Repository> repositories_;
|
||||
private final Dependency dependency_;
|
||||
|
||||
private MavenMetadata metadata_ = null;
|
||||
private MavenMetadata snapshotMetadata_ = null;
|
||||
|
||||
/**
|
||||
* Creates a new resolver for a particular dependency.
|
||||
* <p>
|
||||
* The repositories will be checked in the order they're listed.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the resolution
|
||||
* @param dependency the dependency to resolve
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public DependencyResolver(ArtifactRetriever retriever, List<Repository> repositories, Dependency dependency) {
|
||||
retriever_ = retriever;
|
||||
if (repositories == null) {
|
||||
repositories = Collections.emptyList();
|
||||
}
|
||||
repositories_ = repositories;
|
||||
dependency_ = dependency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the dependency exists in any of the provided repositories.
|
||||
*
|
||||
* @return {@code true} if the dependency exists; {@code false} otherwise
|
||||
* @since 1.5
|
||||
*/
|
||||
public boolean exists() {
|
||||
try {
|
||||
if (getMavenMetadata() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!dependency_.version().equals(VersionNumber.UNKNOWN)) {
|
||||
return getMavenMetadata().getVersions().contains(dependency_.version());
|
||||
}
|
||||
return true;
|
||||
} catch (ArtifactNotFoundException | ArtifactRetrievalErrorException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the dependency version in the provided repositories.
|
||||
* <p>
|
||||
* When the dependency was defined without a specific version number,
|
||||
* the latest version number will be returned if the dependency exists.
|
||||
* If the dependency couldn't be found and no specific version number
|
||||
* was provided, {@linkplain VersionNumber#UNKNOWN} will be returned.
|
||||
*
|
||||
* @return the resolved version
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber resolveVersion() {
|
||||
var version = dependency_.version();
|
||||
if (version.equals(VersionNumber.UNKNOWN)) {
|
||||
return latestVersion();
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the direct dependencies of the resolved dependency for the
|
||||
* provided scopes.
|
||||
*
|
||||
* @param scopes the scopes to return the direct dependencies for
|
||||
* @return the requested direct dependencies; or an empty {@linkplain DependencySet}
|
||||
* if no direct dependencies could be found or the dependency doesn't exist in
|
||||
* the provided repositories
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencySet getDirectDependencies(Scope... scopes) {
|
||||
var pom_dependencies = getMavenPom(dependency_).getDependencies(scopes);
|
||||
var result = new DependencySet();
|
||||
for (var dependency : pom_dependencies) {
|
||||
result.add(dependency.convertToDependency());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the transitive dependencies of the resolved dependency for the
|
||||
* provided scopes. This includes the dependency of this resolver also.
|
||||
* <p>
|
||||
* This can be a slow and expensive operation since querying continues through
|
||||
* the complete POM hierarchy until all transitive dependencies have been found.
|
||||
*
|
||||
* @param scopes the scopes to return the transitive dependencies for
|
||||
* @return the requested transitive dependencies; or an empty {@linkplain DependencySet}
|
||||
* if no transitive dependencies could be found or the dependency doesn't exist in
|
||||
* the provided repositories
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencySet getAllDependencies(Scope... scopes) {
|
||||
var result = new DependencySet();
|
||||
result.add(dependency_);
|
||||
|
||||
var dependency_queue = new ArrayList<PomDependency>();
|
||||
|
||||
var parent = dependency_;
|
||||
var next_dependencies = getMavenPom(parent).getDependencies(scopes);
|
||||
|
||||
while (parent != null && next_dependencies != null) {
|
||||
// remove any next dependencies that are already queued
|
||||
dependency_queue.forEach(next_dependencies::remove);
|
||||
// remove any next dependencies that match the current exclusion context
|
||||
final var exclusion_context = parent;
|
||||
next_dependencies.removeIf(it -> matchesExclusions(exclusion_context, it));
|
||||
// add all next dependencies to the queue
|
||||
dependency_queue.addAll(next_dependencies);
|
||||
|
||||
// unless we find a next set of dependencies to add, stop resolving
|
||||
parent = null;
|
||||
next_dependencies = null;
|
||||
|
||||
// iterate through the dependency queue until we find one that isn't
|
||||
// part of the results yet
|
||||
while (!dependency_queue.isEmpty()) {
|
||||
var candidate = dependency_queue.remove(0);
|
||||
var dependency = candidate.convertToDependency();
|
||||
if (!result.contains(dependency)) {
|
||||
result.add(dependency);
|
||||
|
||||
// we found a dependency that was added to the result, get its
|
||||
// dependencies so that they can be added to the queue after
|
||||
// filtering
|
||||
parent = dependency;
|
||||
next_dependencies = new DependencyResolver(retriever_, repositories_, dependency).getMavenPom(parent).getDependencies(scopes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean matchesExclusions(Dependency context, PomDependency checked) {
|
||||
while (context != null) {
|
||||
if (context.exclusions() != null) {
|
||||
for (var exclusion : context.exclusions()) {
|
||||
if (exclusion.matches(checked)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
context = context.parent();
|
||||
}
|
||||
|
||||
if (dependency_.exclusions() != null) {
|
||||
for (var exclusion : dependency_.exclusions()) {
|
||||
if (exclusion.matches(checked)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the versions of the resolved dependency.
|
||||
*
|
||||
* @return this dependency's version list; or an empty list if the dependency
|
||||
* couldn't be found in the provided repositories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<VersionNumber> listVersions() {
|
||||
return getMavenMetadata().getVersions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the latest version of the resolved dependency.
|
||||
*
|
||||
* @return this dependency's latest version; or {@link VersionNumber#UNKNOWN}
|
||||
* if the dependency couldn't be found in the provided repositories
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber latestVersion() {
|
||||
return getMavenMetadata().getLatest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the release version of the resolved dependency.
|
||||
*
|
||||
* @return this dependency's release version; or {@link VersionNumber#UNKNOWN}
|
||||
* if the dependency couldn't be found in the provided repositories
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber releaseVersion() {
|
||||
return getMavenMetadata().getRelease();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers the artifacts for the resolved dependency into the provided directory.
|
||||
* <p>
|
||||
* The destination directory must exist and be writable.
|
||||
*
|
||||
* @param directory the directory to transfer the dependency artifact into
|
||||
* @return the artifact that was successfully transferred; or {@code null} if no artifact was transferred
|
||||
* @throws DependencyTransferException when an error occurred during the transfer
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public RepositoryArtifact transferIntoDirectory(File directory)
|
||||
throws DependencyTransferException {
|
||||
for (var artifact : getTransferArtifacts()) {
|
||||
try {
|
||||
if (retriever_.transferIntoDirectory(artifact, directory)) {
|
||||
return artifact;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new DependencyTransferException(dependency_, artifact.location(), directory, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the repositories that are used by this dependency resolver.
|
||||
*
|
||||
* @return the dependency resolver's repositories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Repository> repositories() {
|
||||
return repositories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the dependency that is resolved.
|
||||
*
|
||||
* @return the resolved dependency
|
||||
* @since 1.5
|
||||
*/
|
||||
public Dependency dependency() {
|
||||
return dependency_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the potential locations for the dependency
|
||||
* within the provided repositories.
|
||||
*
|
||||
* @return a list of potential transfer locations
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<String> getTransferLocations() {
|
||||
return getTransferArtifacts().stream().map(RepositoryArtifact::location).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main Maven metadata for this dependency
|
||||
*
|
||||
* @return this dependency's metadata
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public MavenMetadata getMavenMetadata() {
|
||||
if (metadata_ == null) {
|
||||
var locations = getMetadataLocations();
|
||||
metadata_ = parseMavenMetadata(locations);
|
||||
}
|
||||
|
||||
return metadata_;
|
||||
}
|
||||
|
||||
/**
|
||||
* THe Maven metadata with snapshot information when this is a snapshot version.
|
||||
*
|
||||
* @return Maven metadata if this is a snapshot dependency version; or
|
||||
* {@code null} if this version is not a snapshot
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public MavenMetadata getSnapshotMavenMetadata() {
|
||||
if (snapshotMetadata_ == null) {
|
||||
final var version = resolveVersion();
|
||||
if (version.isSnapshot()) {
|
||||
var locations = getSnapshotMetadataLocations();
|
||||
snapshotMetadata_ = parseMavenMetadata(locations);
|
||||
}
|
||||
}
|
||||
|
||||
return snapshotMetadata_;
|
||||
}
|
||||
|
||||
private List<RepositoryArtifact> getTransferArtifacts() {
|
||||
final var version = resolveVersion();
|
||||
final VersionNumber pom_version;
|
||||
if (version.isSnapshot()) {
|
||||
var metadata = getSnapshotMavenMetadata();
|
||||
pom_version = metadata.getSnapshot();
|
||||
} else {
|
||||
pom_version = version;
|
||||
}
|
||||
|
||||
return getArtifactLocations().stream().map(a -> {
|
||||
var result = new StringBuilder();
|
||||
result.append(version).append("/").append(dependency_.artifactId()).append("-").append(pom_version);
|
||||
if (!dependency_.classifier().isEmpty()) {
|
||||
result.append("-").append(dependency_.classifier());
|
||||
}
|
||||
var type = dependency_.type();
|
||||
if (type == null) {
|
||||
type = "jar";
|
||||
}
|
||||
result.append(".").append(type);
|
||||
|
||||
return a.appendPath(result.toString());
|
||||
}).toList();
|
||||
}
|
||||
|
||||
private List<RepositoryArtifact> getArtifactLocations() {
|
||||
return repositories_.stream().map(repository -> new RepositoryArtifact(repository, repository.getArtifactLocation(dependency_))).toList();
|
||||
}
|
||||
|
||||
private List<RepositoryArtifact> getMetadataLocations() {
|
||||
return getArtifactLocations().stream().map(a -> a.appendPath(a.repository().getMetadataName())).toList();
|
||||
}
|
||||
|
||||
private List<RepositoryArtifact> getSnapshotMetadataLocations() {
|
||||
var version = resolveVersion();
|
||||
return getArtifactLocations().stream().map(a -> a.appendPath(version + "/" + a.repository().getMetadataName())).toList();
|
||||
}
|
||||
|
||||
private MavenMetadata parseMavenMetadata(List<RepositoryArtifact> artifacts) {
|
||||
RepositoryArtifact retrieved_artifact = null;
|
||||
String metadata = null;
|
||||
for (var artifact : artifacts) {
|
||||
try {
|
||||
var content = retriever_.readString(artifact);
|
||||
if (content == null) {
|
||||
throw new ArtifactNotFoundException(dependency_, artifact.location());
|
||||
}
|
||||
|
||||
retrieved_artifact = artifact;
|
||||
metadata = content;
|
||||
|
||||
break;
|
||||
} catch (FileUtilsErrorException e) {
|
||||
if (e.getCause() instanceof FileNotFoundException) {
|
||||
continue;
|
||||
}
|
||||
throw new ArtifactRetrievalErrorException(dependency_, artifact.location(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata == null) {
|
||||
throw new ArtifactNotFoundException(dependency_, artifacts.stream().map(RepositoryArtifact::location).collect(Collectors.joining(", ")));
|
||||
}
|
||||
|
||||
var xml = new Xml2MavenMetadata();
|
||||
if (!xml.processXml(metadata)) {
|
||||
throw new DependencyXmlParsingErrorException(dependency_, retrieved_artifact.location(), xml.getErrors());
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
private List<RepositoryArtifact> getPomLocations() {
|
||||
final var version = resolveVersion();
|
||||
final VersionNumber pom_version;
|
||||
if (version.isSnapshot()) {
|
||||
var metadata = getSnapshotMavenMetadata();
|
||||
pom_version = metadata.getSnapshot();
|
||||
} else {
|
||||
pom_version = version;
|
||||
}
|
||||
|
||||
return getArtifactLocations().stream().map(a -> a.appendPath(version + "/" + dependency_.artifactId() + "-" + pom_version + ".pom")).toList();
|
||||
}
|
||||
|
||||
Xml2MavenPom getMavenPom(Dependency parent) {
|
||||
RepositoryArtifact retrieved_artifact = null;
|
||||
String pom = null;
|
||||
var artifacts = getPomLocations();
|
||||
|
||||
for (var artifact : artifacts) {
|
||||
try {
|
||||
var content = retriever_.readString(artifact);
|
||||
if (content == null) {
|
||||
throw new ArtifactNotFoundException(dependency_, artifact.location());
|
||||
}
|
||||
|
||||
retrieved_artifact = artifact;
|
||||
pom = content;
|
||||
|
||||
break;
|
||||
} catch (FileUtilsErrorException e) {
|
||||
if (e.getCause() instanceof FileNotFoundException) {
|
||||
continue;
|
||||
}
|
||||
throw new ArtifactRetrievalErrorException(dependency_, artifact.location(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (pom == null) {
|
||||
throw new ArtifactNotFoundException(dependency_, artifacts.stream().map(RepositoryArtifact::location).collect(Collectors.joining(", ")));
|
||||
}
|
||||
|
||||
var xml = new Xml2MavenPom(parent, retriever_, repositories_);
|
||||
if (!xml.processXml(pom)) {
|
||||
throw new DependencyXmlParsingErrorException(dependency_, retrieved_artifact.location(), xml.getErrors());
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
}
|
141
src/main/java/rife/bld/dependencies/DependencyScopes.java
Normal file
141
src/main/java/rife/bld/dependencies/DependencyScopes.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Convenience class to map a {@link Scope} to its dependencies.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class DependencyScopes extends LinkedHashMap<Scope, DependencySet> {
|
||||
/**
|
||||
* Creates an empty dependency scope map.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencyScopes() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dependency scope map from another one.
|
||||
*
|
||||
* @param other the other map to create this one from
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencyScopes(DependencyScopes other) {
|
||||
for (var entry : other.entrySet()) {
|
||||
put(entry.getKey(), new DependencySet(entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes all the dependencies from another dependency scope map.
|
||||
*
|
||||
* @param other the other map to include dependencies from
|
||||
* @since 1.5
|
||||
*/
|
||||
public void include(DependencyScopes other) {
|
||||
for (var entry : other.entrySet()) {
|
||||
var dependencies = get(entry.getKey());
|
||||
if (dependencies == null) {
|
||||
dependencies = new DependencySet();
|
||||
put(entry.getKey(), dependencies);
|
||||
}
|
||||
dependencies.addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@link DependencySet} for a particular scope.
|
||||
*
|
||||
* @param scope the scope to retrieve the dependencies for
|
||||
* @return the scope's {@code DependencySet};
|
||||
* or an empty {@code DependencySet} if none have been defined for the provided scope.
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencySet scope(Scope scope) {
|
||||
return computeIfAbsent(scope, k -> new DependencySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transitive set of dependencies that would be used for the compile scope in a project.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the resolution
|
||||
* @return the compile scope dependency set
|
||||
* @since 1.6
|
||||
*/
|
||||
public DependencySet resolveCompileDependencies(ArtifactRetriever retriever, List<Repository> repositories) {
|
||||
return resolveScopedDependencies(retriever, repositories,
|
||||
new Scope[]{Scope.provided, Scope.compile},
|
||||
new Scope[]{Scope.compile},
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transitive set of dependencies that would be used for the runtime scope in a project.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the resolution
|
||||
* @return the runtime scope dependency set
|
||||
* @since 1.6
|
||||
*/
|
||||
public DependencySet resolveRuntimeDependencies(ArtifactRetriever retriever, List<Repository> repositories) {
|
||||
return resolveScopedDependencies(retriever, repositories,
|
||||
new Scope[]{Scope.provided, Scope.compile, Scope.runtime},
|
||||
new Scope[]{Scope.compile, Scope.runtime},
|
||||
resolveCompileDependencies(retriever, repositories));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transitive set of dependencies that would be used for the standalone scope in a project.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the resolution
|
||||
* @return the standalone scope dependency set
|
||||
* @since 1.6
|
||||
*/
|
||||
public DependencySet resolveStandaloneDependencies(ArtifactRetriever retriever, List<Repository> repositories) {
|
||||
return resolveScopedDependencies(retriever, repositories,
|
||||
new Scope[]{Scope.standalone},
|
||||
new Scope[]{Scope.compile, Scope.runtime},
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transitive set of dependencies that would be used for the test scope in a project.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the resolution
|
||||
* @return the test scope dependency set
|
||||
* @since 1.6
|
||||
*/
|
||||
public DependencySet resolveTestDependencies(ArtifactRetriever retriever, List<Repository> repositories) {
|
||||
return resolveScopedDependencies(retriever, repositories,
|
||||
new Scope[]{Scope.test},
|
||||
new Scope[]{Scope.compile, Scope.runtime},
|
||||
null);
|
||||
}
|
||||
|
||||
private DependencySet resolveScopedDependencies(ArtifactRetriever retriever, List<Repository> repositories, Scope[] resolvedScopes, Scope[] transitiveScopes, DependencySet excluded) {
|
||||
var dependencies = new DependencySet();
|
||||
for (var scope : resolvedScopes) {
|
||||
var scoped_dependencies = get(scope);
|
||||
if (scoped_dependencies != null) {
|
||||
for (var dependency : scoped_dependencies) {
|
||||
dependencies.addAll(new DependencyResolver(retriever, repositories, dependency).getAllDependencies(transitiveScopes));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excluded != null) {
|
||||
dependencies.removeAll(excluded);
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
}
|
266
src/main/java/rife/bld/dependencies/DependencySet.java
Normal file
266
src/main/java/rife/bld/dependencies/DependencySet.java
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import rife.bld.dependencies.exceptions.DependencyTransferException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Convenience class to handle a set of {@link Dependency} objects.
|
||||
* <p>
|
||||
* Only a single version of each dependency can exist in this set.
|
||||
* When adding a new dependency, it will only be added if it didn't exist
|
||||
* in the set yet, or if the new dependency has a higher version than
|
||||
* the existing one.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class DependencySet extends AbstractSet<Dependency> implements Set<Dependency> {
|
||||
private final Map<Dependency, Dependency> dependencies_ = new LinkedHashMap<>();
|
||||
private final Set<LocalDependency> localDependencies_ = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Creates an empty dependency set.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencySet() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dependency set from another one.
|
||||
*
|
||||
* @param other the other set to create this one from
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencySet(DependencySet other) {
|
||||
addAll(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes a dependency into the dependency set.
|
||||
*
|
||||
* @param dependency the dependency to include
|
||||
* @return this dependency set instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencySet include(Dependency dependency) {
|
||||
add(dependency);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes a local dependency into the dependency set.
|
||||
* <p>
|
||||
* Local dependencies aren't resolved and point to a location on
|
||||
* the file system.
|
||||
*
|
||||
* @param dependency the dependency to include
|
||||
* @return this dependency set instance
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public DependencySet include(LocalDependency dependency) {
|
||||
localDependencies_.add(dependency);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the local dependencies.
|
||||
*
|
||||
* @return the set of local dependencies
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public Set<LocalDependency> localDependencies() {
|
||||
return localDependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers the artifacts for the dependencies into the provided directory.
|
||||
* <p>
|
||||
* The destination directory must exist and be writable.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the transfer
|
||||
* @param directory the directory to transfer the artifacts into
|
||||
* @return the list of artifacts that were transferred successfully
|
||||
* @throws DependencyTransferException when an error occurred during the transfer
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<RepositoryArtifact> transferIntoDirectory(ArtifactRetriever retriever, List<Repository> repositories, File directory) {
|
||||
return transferIntoDirectory(retriever, repositories, directory, (String[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers the artifacts for the dependencies into the provided directory,
|
||||
* including other classifiers.
|
||||
* <p>
|
||||
* The destination directory must exist and be writable.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to use for the download
|
||||
* @param directory the directory to download the artifacts into
|
||||
* @param classifiers the additional classifiers to transfer
|
||||
* @return the list of artifacts that were transferred successfully
|
||||
* @throws DependencyTransferException when an error occurred during the transfer
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<RepositoryArtifact> transferIntoDirectory(ArtifactRetriever retriever, List<Repository> repositories, File directory, String... classifiers) {
|
||||
var result = new ArrayList<RepositoryArtifact>();
|
||||
for (var dependency : this) {
|
||||
var artifact = new DependencyResolver(retriever, repositories, dependency).transferIntoDirectory(directory);
|
||||
if (artifact != null) {
|
||||
result.add(artifact);
|
||||
}
|
||||
|
||||
if (classifiers != null) {
|
||||
for (var classifier : classifiers) {
|
||||
if (classifier != null) {
|
||||
var classifier_artifact = new DependencyResolver(retriever, repositories, dependency.withClassifier(classifier)).transferIntoDirectory(directory);
|
||||
if (classifier_artifact != null) {
|
||||
result.add(classifier_artifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dependency that was stored in the set.
|
||||
* <p>
|
||||
* The version can be different from the dependency passed in and this
|
||||
* method can be used to look up the actual version of the dependency in the set.
|
||||
*
|
||||
* @param dependency the dependency to look for
|
||||
* @return the dependency in the set; or
|
||||
* {@code null} if no such dependency exists
|
||||
* @since 1.5
|
||||
*/
|
||||
public Dependency get(Dependency dependency) {
|
||||
return dependencies_.get(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the string description of the transitive hierarchical tree of
|
||||
* dependencies for a particular scope.
|
||||
*
|
||||
* @param retriever the retriever to use to get artifacts
|
||||
* @param repositories the repositories to look for dependencies in
|
||||
* @param scopes the scopes to return the transitive dependencies for
|
||||
* @return the generated tree description string; or an empty string if
|
||||
* there were no dependencies to describe
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public String generateTransitiveDependencyTree(ArtifactRetriever retriever, List<Repository> repositories, Scope... scopes) {
|
||||
var compile_dependencies = new DependencySet();
|
||||
for (var dependency : this) {
|
||||
compile_dependencies.addAll(new DependencyResolver(retriever, repositories, dependency).getAllDependencies(scopes));
|
||||
}
|
||||
return compile_dependencies.generateDependencyTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the string description of the hierarchical tree of
|
||||
* dependencies in this {@code DependencySet}. This relies on the {@code Dependency}
|
||||
* {@code parent} field to be set correctly to indicate their relationships.
|
||||
*
|
||||
* @return the generated tree description string; or an empty string if
|
||||
* there were no dependencies to describe
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public String generateDependencyTree() {
|
||||
var result = new StringBuilder();
|
||||
|
||||
var dependency_list = new ArrayList<>(this);
|
||||
var dependency_stack = new Stack<DependencyTreeEntry>();
|
||||
|
||||
var roots = dependency_list.stream().filter(dependency -> dependency.parent() == null).toList();
|
||||
dependency_list.removeIf(dependency -> dependency.parent() == null);
|
||||
|
||||
var roots_it = roots.iterator();
|
||||
while (roots_it.hasNext()) {
|
||||
var root = roots_it.next();
|
||||
|
||||
dependency_list.add(0, root);
|
||||
stack:
|
||||
do {
|
||||
var list_it = dependency_list.iterator();
|
||||
while (list_it.hasNext()) {
|
||||
var list_dep = list_it.next();
|
||||
if (list_dep.parent() == null) {
|
||||
list_it.remove();
|
||||
var entry = new DependencyTreeEntry(null, list_dep, !roots_it.hasNext());
|
||||
result.append(entry).append(System.lineSeparator());
|
||||
dependency_stack.add(entry);
|
||||
} else {
|
||||
var stack_entry = dependency_stack.peek();
|
||||
if (list_dep.parent().equals(stack_entry.dependency())) {
|
||||
list_it.remove();
|
||||
|
||||
boolean last = dependency_list.stream().noneMatch(d -> d.parent().equals(stack_entry.dependency()));
|
||||
var entry = new DependencyTreeEntry(stack_entry, list_dep, last);
|
||||
result.append(entry).append(System.lineSeparator());
|
||||
dependency_stack.add(entry);
|
||||
continue stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
dependency_stack.pop();
|
||||
} while (!dependency_stack.isEmpty());
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private record DependencyTreeEntry(DependencyTreeEntry parent, Dependency dependency, boolean last) {
|
||||
public String toString() {
|
||||
var result = new StringBuilder();
|
||||
|
||||
if (last) {
|
||||
result.insert(0, "└─ ");
|
||||
} else {
|
||||
result.insert(0, "├─ ");
|
||||
}
|
||||
|
||||
var p = parent();
|
||||
while (p != null) {
|
||||
if (p.last()) {
|
||||
result.insert(0, " ");
|
||||
} else {
|
||||
result.insert(0, "│ ");
|
||||
}
|
||||
p = p.parent();
|
||||
}
|
||||
|
||||
return result.toString() + dependency;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean add(Dependency dependency) {
|
||||
var existing = dependencies_.get(dependency);
|
||||
if (existing == null) {
|
||||
dependencies_.put(dependency, dependency);
|
||||
return true;
|
||||
}
|
||||
if (dependency.version().compareTo(existing.version()) > 0) {
|
||||
dependencies_.remove(dependency);
|
||||
dependencies_.put(dependency, dependency);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Iterator<Dependency> iterator() {
|
||||
return dependencies_.keySet().iterator();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return dependencies_.size();
|
||||
}
|
||||
}
|
16
src/main/java/rife/bld/dependencies/ExclusionSet.java
Normal file
16
src/main/java/rife/bld/dependencies/ExclusionSet.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* Convenience class to handle a set of {@link DependencyExclusion} objects.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class ExclusionSet extends LinkedHashSet<DependencyExclusion> {
|
||||
}
|
17
src/main/java/rife/bld/dependencies/LocalDependency.java
Normal file
17
src/main/java/rife/bld/dependencies/LocalDependency.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
/**
|
||||
* Contains the information required to describe a local dependency for the build system.
|
||||
* <p>
|
||||
* If the local dependency points to a directory, it will be scanned for jar files.
|
||||
*
|
||||
* @param path the file system path of the local dependency
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public record LocalDependency(String path) {
|
||||
}
|
63
src/main/java/rife/bld/dependencies/MavenMetadata.java
Normal file
63
src/main/java/rife/bld/dependencies/MavenMetadata.java
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides Maven metadata information
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public interface MavenMetadata {
|
||||
/**
|
||||
* Returns latest version number in the metadata.
|
||||
*
|
||||
* @return the latest version number
|
||||
* @since 1.5.8
|
||||
*/
|
||||
VersionNumber getLatest();
|
||||
|
||||
/**
|
||||
* Returns release version number in the metadata.
|
||||
*
|
||||
* @return the release version number
|
||||
* @since 1.5.8
|
||||
*/
|
||||
VersionNumber getRelease();
|
||||
|
||||
/**
|
||||
* Returns snapshot version number in the metadata.
|
||||
*
|
||||
* @return the snapshot version number
|
||||
* @since 1.5.8
|
||||
*/
|
||||
VersionNumber getSnapshot();
|
||||
|
||||
/**
|
||||
* Returns snapshot timestamp in the metadata.
|
||||
*
|
||||
* @return the snapshot timestamp
|
||||
* @since 1.5.8
|
||||
*/
|
||||
String getSnapshotTimestamp();
|
||||
|
||||
/**
|
||||
* Returns snapshot build number in the metadata.
|
||||
*
|
||||
* @return the snapshot build number
|
||||
* @since 1.5.8
|
||||
*/
|
||||
Integer getSnapshotBuildNumber();
|
||||
|
||||
/**
|
||||
* Returns all the release or snapshot versions in the metadata.
|
||||
*
|
||||
* @return the version number list
|
||||
* @since 1.5.8
|
||||
*/
|
||||
List<VersionNumber> getVersions();
|
||||
}
|
47
src/main/java/rife/bld/dependencies/PomDependency.java
Normal file
47
src/main/java/rife/bld/dependencies/PomDependency.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Contains the information required to describe a dependency with all
|
||||
* the details stored in a Maven POM descriptor.
|
||||
* <p>
|
||||
* This is used by the {@linkplain DependencyResolver} while traversing
|
||||
* the dependency graph, eventually resulting into fully resolved
|
||||
* {@linkplain Dependency} instances.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public record PomDependency(String groupId, String artifactId, String version, String classifier, String type,
|
||||
String scope, String optional, ExclusionSet exclusions, Dependency parent) {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PomDependency that = (PomDependency) o;
|
||||
return Objects.equals(groupId, that.groupId) && Objects.equals(artifactId, that.artifactId) && Objects.equals(classifier, that.classifier) && Objects.equals(type, that.type);
|
||||
}
|
||||
|
||||
boolean isPomImport() {
|
||||
return "pom".equals(type()) && "import".equals(scope());
|
||||
}
|
||||
|
||||
Dependency convertToDependency() {
|
||||
return new Dependency(
|
||||
groupId(),
|
||||
artifactId(),
|
||||
VersionNumber.parse(version()),
|
||||
classifier(),
|
||||
type(),
|
||||
exclusions(),
|
||||
parent());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hash(groupId, artifactId, classifier, type);
|
||||
}
|
||||
}
|
197
src/main/java/rife/bld/dependencies/Repository.java
Normal file
197
src/main/java/rife/bld/dependencies/Repository.java
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import rife.ioc.HierarchicalProperties;
|
||||
import rife.tools.StringEncryptor;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* Contains the information required to locate a Maven-compatible repository.
|
||||
*
|
||||
* @param location the base location of the repository
|
||||
* @param username the username to access the repository
|
||||
* @param password the password to access the repository
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public record Repository(String location, String username, String password) {
|
||||
public static Repository MAVEN_LOCAL = null;
|
||||
public static final Repository MAVEN_CENTRAL = new Repository("https://repo1.maven.org/maven2/");
|
||||
public static final Repository SONATYPE_RELEASES = new Repository("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/");
|
||||
public static final Repository SONATYPE_SNAPSHOTS = new Repository("https://s01.oss.sonatype.org/content/repositories/snapshots/");
|
||||
public static final Repository SONATYPE_SNAPSHOTS_LEGACY = new Repository("https://oss.sonatype.org/content/repositories/snapshots/");
|
||||
public static final Repository APACHE = new Repository("https://repo.maven.apache.org/maven2/");
|
||||
public static final Repository RIFE2_RELEASES = new Repository("https://repo.rife2.com/releases/");
|
||||
public static final Repository RIFE2_SNAPSHOTS = new Repository("https://repo.rife2.com/snapshots/");
|
||||
|
||||
private static final String MAVEN_LOCAL_REPO_PROPERTY = "maven.repo.local";
|
||||
|
||||
public static final String PROPERTY_BLD_REPO_PREFIX = "bld.repo.";
|
||||
public static final String PROPERTY_BLD_REPO_USERNAME_SUFFIX = ".username";
|
||||
public static final String PROPERTY_BLD_REPO_PASSWORD_SUFFIX = ".password";
|
||||
|
||||
/**
|
||||
* This method will be called as soon as hierarchical properties
|
||||
* are initialized in the build executor. It is not intended to be called
|
||||
* manually.
|
||||
*
|
||||
* @param properties the hierarchical properties to use for resolving
|
||||
* the maven local repository
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public static void resolveMavenLocal(HierarchicalProperties properties) {
|
||||
var user_home = properties.getValueString("user.home");
|
||||
if (user_home == null) {
|
||||
user_home = System.getProperty("user.home");
|
||||
}
|
||||
var maven_local = properties.getValueString(
|
||||
MAVEN_LOCAL_REPO_PROPERTY,
|
||||
Path.of(user_home, ".m2", "repository").toString());
|
||||
MAVEN_LOCAL = new Repository(maven_local);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the repository in the provided hierarchical properties.
|
||||
* <p>
|
||||
* For instance, using the name {@code myrepo} will look for the following properties:<br>
|
||||
* {@code bld.repo.myrepo}<br>
|
||||
* {@code bld.repo.myrepo.username} (optional)<br>
|
||||
* {@code bld.repo.myrepo.password} (optional)
|
||||
* <p>
|
||||
* If the {@code bld.repo.myrepo} property isn't found, the {@code locationOrName}
|
||||
* parameter will be used as a location instead.
|
||||
*
|
||||
* @param properties the hierarchical properties to look into
|
||||
* @param locationOrName the text to resolve a repository name or to be used as a location
|
||||
* @return the repository instance
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public static Repository resolveRepository(HierarchicalProperties properties, String locationOrName) {
|
||||
if (properties != null && properties.contains(PROPERTY_BLD_REPO_PREFIX + locationOrName)) {
|
||||
var location = properties.getValueString(PROPERTY_BLD_REPO_PREFIX + locationOrName);
|
||||
var username = properties.getValueString(PROPERTY_BLD_REPO_PREFIX + locationOrName + PROPERTY_BLD_REPO_USERNAME_SUFFIX);
|
||||
var password = properties.getValueString(PROPERTY_BLD_REPO_PREFIX + locationOrName + PROPERTY_BLD_REPO_PASSWORD_SUFFIX);
|
||||
return new Repository(location, username, password);
|
||||
}
|
||||
|
||||
return switch (locationOrName) {
|
||||
case "MAVEN_LOCAL" -> Repository.MAVEN_LOCAL;
|
||||
case "MAVEN_CENTRAL" -> Repository.MAVEN_CENTRAL;
|
||||
case "SONATYPE_RELEASES" -> Repository.SONATYPE_RELEASES;
|
||||
case "SONATYPE_SNAPSHOTS" -> Repository.SONATYPE_SNAPSHOTS;
|
||||
case "SONATYPE_SNAPSHOTS_LEGACY" -> Repository.SONATYPE_SNAPSHOTS_LEGACY;
|
||||
case "APACHE" -> Repository.APACHE;
|
||||
case "RIFE2_RELEASES" -> Repository.RIFE2_RELEASES;
|
||||
case "RIFE2_SNAPSHOTS" -> Repository.RIFE2_SNAPSHOTS;
|
||||
default -> new Repository(locationOrName);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new repository with only a location.
|
||||
*
|
||||
* @param location the location to create the repository for
|
||||
* @since 1.5
|
||||
*/
|
||||
public Repository(String location) {
|
||||
this(location, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this repository is local.
|
||||
*
|
||||
* @return {@code true} when this repository is local; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public boolean isLocal() {
|
||||
return location().startsWith("/") || location().startsWith("file:");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new repository instance of the same location, but with
|
||||
* different credentials.
|
||||
*
|
||||
* @param username the username to access the repository
|
||||
* @param password the password to access the repository
|
||||
* @return the new repository
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public Repository withCredentials(String username, String password) {
|
||||
return new Repository(location(), username, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the location for a dependency if it would be located in this repository.
|
||||
*
|
||||
* @param dependency the dependency to create the location for
|
||||
* @return the constructed location
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public String getArtifactLocation(Dependency dependency) {
|
||||
return getArtifactLocation(dependency.groupId(), dependency.artifactId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the location for a dependency if it would be located in this repository.
|
||||
*
|
||||
* @param groupId the groupId dependency to create the location for
|
||||
* @param artifactId the artifactId dependency to create the location for
|
||||
* @return the constructed location
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public String getArtifactLocation(String groupId, String artifactId) {
|
||||
var group_path = groupId.replace(".", "/");
|
||||
var result = new StringBuilder();
|
||||
if (isLocal()) {
|
||||
if (location().startsWith("file://")) {
|
||||
result.append(location().substring("file://".length()));
|
||||
} else {
|
||||
result.append(location());
|
||||
}
|
||||
} else {
|
||||
result.append(location());
|
||||
}
|
||||
if (!location().endsWith("/")) {
|
||||
result.append("/");
|
||||
}
|
||||
return result.append(group_path).append("/").append(artifactId).append("/").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate metadata name.
|
||||
*
|
||||
* @return the metadata name for this repository.
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public String getMetadataName() {
|
||||
if (isLocal()) {
|
||||
return "maven-metadata-local.xml";
|
||||
} else {
|
||||
return "maven-metadata.xml";
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
var result = new StringBuilder(location);
|
||||
if (username() != null) {
|
||||
result.append(":");
|
||||
try {
|
||||
result.append(StringEncryptor.MD5HLO.performEncryption(username(), null));
|
||||
if (password() != null) {
|
||||
result.append(":");
|
||||
result.append(StringEncryptor.MD5HLO.performEncryption(password(), null));
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// should never happen
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
23
src/main/java/rife/bld/dependencies/RepositoryArtifact.java
Normal file
23
src/main/java/rife/bld/dependencies/RepositoryArtifact.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
/**
|
||||
* Represents an artifact location in a repository.
|
||||
*
|
||||
* @param repository the repository of the artifact
|
||||
* @param location the location of the artifact in the repository
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.6
|
||||
*/
|
||||
public record RepositoryArtifact(Repository repository, String location) {
|
||||
public RepositoryArtifact appendPath(String path) {
|
||||
return new RepositoryArtifact(repository, location + path);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return repository + ":" + location;
|
||||
}
|
||||
}
|
44
src/main/java/rife/bld/dependencies/Scope.java
Normal file
44
src/main/java/rife/bld/dependencies/Scope.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
/**
|
||||
* Provides all the dependency scopes that are supported by
|
||||
* the RIFE2 build system.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public enum Scope {
|
||||
/**
|
||||
* Used for compiling the main source code.
|
||||
* @since 1.5
|
||||
*/
|
||||
compile,
|
||||
|
||||
/**
|
||||
* Used when running the main source code.
|
||||
* @since 1.5
|
||||
*/
|
||||
runtime,
|
||||
|
||||
/**
|
||||
* Used when compiling and running the test source code.
|
||||
* @since 1.5
|
||||
*/
|
||||
test,
|
||||
|
||||
/**
|
||||
* Used when running the main source code without container.
|
||||
* @since 1.5
|
||||
*/
|
||||
standalone,
|
||||
|
||||
/**
|
||||
* Provided by a container when running the main source code.
|
||||
* @since 1.5
|
||||
*/
|
||||
provided
|
||||
}
|
249
src/main/java/rife/bld/dependencies/VersionNumber.java
Normal file
249
src/main/java/rife/bld/dependencies/VersionNumber.java
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Contains the information required to describe a dependency version number.
|
||||
* <p>
|
||||
* This operates according to the versioning scheme specified by Maven.
|
||||
* <p>
|
||||
* When the version number is undefined, {@link VersionNumber#UNKNOWN} should be used.
|
||||
*
|
||||
* @param major the major version component
|
||||
* @param minor the minor version component
|
||||
* @param revision the revision of the version
|
||||
* @param qualifier a string qualifier for the version
|
||||
* @param separator the separator used to separate the qualifier from the version number
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public record VersionNumber(Integer major, Integer minor, Integer revision, String qualifier, String separator) implements Comparable<VersionNumber> {
|
||||
public static final String SNAPSHOT_QUALIFIER = "SNAPSHOT";
|
||||
|
||||
/**
|
||||
* Singleton to use when the version is not specified.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static final VersionNumber UNKNOWN = new VersionNumber(0, 0, 0, "");
|
||||
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile("^(?<major>\\d+)(?:\\.(?<minor>\\d+)(?:\\.(?<revision>\\d+))?)?(?:(?<separator>[.\\-])(?<qualifier>.*[^.\\-]))??$");
|
||||
|
||||
/**
|
||||
* Parses a version number from a string representation.
|
||||
* <p>
|
||||
* If the string can't be successfully parsed, {@link VersionNumber#UNKNOWN} will be returned.
|
||||
*
|
||||
* @param version the version string to parse
|
||||
* @return a parsed instance of {@code VersionNumber}; or
|
||||
* {@link VersionNumber#UNKNOWN} when the string couldn't be parsed
|
||||
* @since 1.5
|
||||
*/
|
||||
public static VersionNumber parse(String version) {
|
||||
if (version == null || version.isEmpty()) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
var matcher = VERSION_PATTERN.matcher(version);
|
||||
if (!matcher.matches()) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
var major = matcher.group("major");
|
||||
var minor = matcher.group("minor");
|
||||
var revision = matcher.group("revision");
|
||||
|
||||
var major_integer = (major != null ? Integer.parseInt(major) : null);
|
||||
var minor_integer = (minor != null ? Integer.parseInt(minor) : null);
|
||||
var revision_integer = (revision != null ? Integer.parseInt(revision) : null);
|
||||
|
||||
var qualifier = matcher.group("qualifier");
|
||||
var separator = matcher.group("separator");
|
||||
|
||||
return new VersionNumber(major_integer, minor_integer, revision_integer, qualifier, separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a version number with only a major component.
|
||||
*
|
||||
* @param major the major version component
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber(Integer major) {
|
||||
this(major, null, null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a version number with a major and minor component.
|
||||
*
|
||||
* @param major the major version component
|
||||
* @param minor the minor version component
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber(Integer major, Integer minor) {
|
||||
this(major, minor, null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a version number with major, minor and revision components.
|
||||
*
|
||||
* @param major the major version component
|
||||
* @param minor the minor version component
|
||||
* @param revision the version revision component
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber(Integer major, Integer minor, Integer revision) {
|
||||
this(major, minor, revision, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a complete version number with qualifier, the separator will default to "{@code -}".
|
||||
*
|
||||
* @param major the major version component
|
||||
* @param minor the minor version component
|
||||
* @param revision the version revision component
|
||||
* @param qualifier the version qualifier
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber(Integer major, Integer minor, Integer revision, String qualifier) {
|
||||
this(major, minor, revision, qualifier, "-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a complete version number with qualifier.
|
||||
*
|
||||
* @param major the major version component
|
||||
* @param minor the minor version component
|
||||
* @param revision the version revision component
|
||||
* @param qualifier the version qualifier
|
||||
* @param separator the separator for the version qualifier
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber(Integer major, Integer minor, Integer revision, String qualifier, String separator) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
this.revision = revision;
|
||||
this.qualifier = (qualifier == null ? "" : qualifier);
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the base version number without the qualifier.
|
||||
*
|
||||
* @return the base version number instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public VersionNumber getBaseVersion() {
|
||||
return new VersionNumber(major, minor, revision, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the version number with a different qualifier.
|
||||
*
|
||||
* @return this version number with a different qualifier
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public VersionNumber withQualifier(String qualifier) {
|
||||
return new VersionNumber(major, minor, revision, qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a primitive integer for the major version component.
|
||||
*
|
||||
* @return the major version component as an {@code int}
|
||||
* @since 1.5
|
||||
*/
|
||||
public int majorInt() {
|
||||
return major == null ? 0 : major;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a primitive integer for the minor version component.
|
||||
*
|
||||
* @return the minor version component as an {@code int}
|
||||
* @since 1.5
|
||||
*/
|
||||
public int minorInt() {
|
||||
return minor == null ? 0 : minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a primitive integer for the version revision component.
|
||||
*
|
||||
* @return the version revision component as an {@code int}
|
||||
* @since 1.5
|
||||
*/
|
||||
public int revisionInt() {
|
||||
return revision == null ? 0 : revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this is a snapshot version.
|
||||
*
|
||||
* @return {@code true} if this is a snapshot version; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public boolean isSnapshot() {
|
||||
return qualifier().toUpperCase().contains(SNAPSHOT_QUALIFIER);
|
||||
}
|
||||
|
||||
public int compareTo(VersionNumber other) {
|
||||
if (majorInt() != other.majorInt()) {
|
||||
return majorInt() - other.majorInt();
|
||||
}
|
||||
if (minorInt() != other.minorInt()) {
|
||||
return minorInt() - other.minorInt();
|
||||
}
|
||||
if (revisionInt() != other.revisionInt()) {
|
||||
return revisionInt() - other.revisionInt();
|
||||
}
|
||||
|
||||
if (qualifier.equals(other.qualifier)) {
|
||||
return 0;
|
||||
} else if (qualifier.isEmpty()) {
|
||||
return 1;
|
||||
} else if (other.qualifier.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qualifier.toLowerCase().compareTo(other.qualifier.toLowerCase());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
var version = new StringBuilder();
|
||||
version.append(majorInt());
|
||||
if (minor != null || revision != null) {
|
||||
version.append(".");
|
||||
version.append(minorInt());
|
||||
}
|
||||
if (revision != null) {
|
||||
version.append(".");
|
||||
version.append(revisionInt());
|
||||
}
|
||||
if (qualifier != null && !qualifier.isEmpty()) {
|
||||
version.append(separator);
|
||||
version.append(qualifier);
|
||||
}
|
||||
return version.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other instanceof VersionNumber && compareTo((VersionNumber) other) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = majorInt();
|
||||
result = 31 * result + minorInt();
|
||||
result = 31 * result + revisionInt();
|
||||
result = 31 * result + Objects.hashCode(qualifier.toLowerCase());
|
||||
return result;
|
||||
}
|
||||
}
|
120
src/main/java/rife/bld/dependencies/Xml2MavenMetadata.java
Normal file
120
src/main/java/rife/bld/dependencies/Xml2MavenMetadata.java
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import rife.xml.Xml2Data;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Parses an XML document to generate {@link MavenMetadata}, this is an internal class.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public class Xml2MavenMetadata extends Xml2Data implements MavenMetadata {
|
||||
private VersionNumber latest_ = VersionNumber.UNKNOWN;
|
||||
private VersionNumber release_ = VersionNumber.UNKNOWN;
|
||||
private final List<VersionNumber> versions_;
|
||||
private VersionNumber snapshot_ = VersionNumber.UNKNOWN;
|
||||
|
||||
private StringBuilder characterData_ = null;
|
||||
|
||||
private String snapshotTimestamp_ = null;
|
||||
private Integer snapshotBuildNumber_ = null;
|
||||
|
||||
public Xml2MavenMetadata() {
|
||||
versions_ = new ArrayList<>();
|
||||
}
|
||||
|
||||
public VersionNumber getLatest() {
|
||||
return latest_;
|
||||
}
|
||||
|
||||
public VersionNumber getRelease() {
|
||||
return release_;
|
||||
}
|
||||
|
||||
public VersionNumber getSnapshot() {
|
||||
return snapshot_;
|
||||
}
|
||||
|
||||
public String getSnapshotTimestamp() {
|
||||
return snapshotTimestamp_;
|
||||
}
|
||||
|
||||
public Integer getSnapshotBuildNumber() {
|
||||
return snapshotBuildNumber_;
|
||||
}
|
||||
|
||||
public List<VersionNumber> getVersions() {
|
||||
return versions_;
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) {
|
||||
characterData_ = new StringBuilder();
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
switch (qName) {
|
||||
case "latest" -> latest_ = VersionNumber.parse(characterData_.toString());
|
||||
case "release" -> release_ = VersionNumber.parse(characterData_.toString());
|
||||
case "version" -> versions_.add(VersionNumber.parse(characterData_.toString()));
|
||||
case "timestamp" -> snapshotTimestamp_ = characterData_.toString();
|
||||
case "buildNumber" -> snapshotBuildNumber_ = Integer.parseInt(characterData_.toString());
|
||||
case "snapshot" -> {
|
||||
if (!versions_.isEmpty()) {
|
||||
var version = versions_.get(0);
|
||||
var qualifier = VersionNumber.SNAPSHOT_QUALIFIER;
|
||||
if (snapshotTimestamp_ != null && snapshotBuildNumber_ != null) {
|
||||
qualifier = snapshotTimestamp_ + "-" + snapshotBuildNumber_;
|
||||
}
|
||||
snapshot_ = new VersionNumber(version.major(), version.minor(), version.revision(), qualifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
characterData_ = null;
|
||||
}
|
||||
|
||||
private static final Pattern MILESTONE = Pattern.compile("^m\\d*$");
|
||||
private static final Pattern BETA = Pattern.compile("^b\\d*$");
|
||||
private static final Pattern ALPHA = Pattern.compile("^a\\d*$");
|
||||
|
||||
public void endDocument()
|
||||
throws SAXException {
|
||||
// determine latest stable version by removing pre-release qualifiers
|
||||
var filtered_versions = new TreeSet<VersionNumber>();
|
||||
filtered_versions.addAll(versions_.stream()
|
||||
.filter(v -> {
|
||||
if (v.qualifier() == null) return true;
|
||||
var q = v.qualifier().toLowerCase();
|
||||
return !q.startsWith("rc") &&
|
||||
!q.startsWith("cr") &&
|
||||
!q.contains("milestone") &&
|
||||
!MILESTONE.matcher(q).matches() &&
|
||||
!q.contains("beta") &&
|
||||
!BETA.matcher(q).matches() &&
|
||||
!q.contains("alpha") &&
|
||||
!ALPHA.matcher(q).matches();
|
||||
}).toList());
|
||||
|
||||
// only replace the stable version from the metadata when
|
||||
// something remained from the filtering, then use the
|
||||
// last version in the sorted set
|
||||
if (!filtered_versions.isEmpty()) {
|
||||
latest_ = filtered_versions.last();
|
||||
}
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) {
|
||||
if (characterData_ != null) {
|
||||
characterData_.append(String.copyValueOf(ch, start, length));
|
||||
}
|
||||
}
|
||||
}
|
375
src/main/java/rife/bld/dependencies/Xml2MavenPom.java
Normal file
375
src/main/java/rife/bld/dependencies/Xml2MavenPom.java
Normal file
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import rife.xml.Xml2Data;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Parses an XML document to retrieve POM information, this is an internal class.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.18
|
||||
*/
|
||||
class Xml2MavenPom extends Xml2Data {
|
||||
private final Dependency parent_;
|
||||
private final ArtifactRetriever retriever_;
|
||||
private final List<Repository> repositories_;
|
||||
private Map<Scope, Set<PomDependency>> resolvedDependencies_ = null;
|
||||
|
||||
private final Map<PomDependency, PomDependency> dependencyManagement_ = new LinkedHashMap<>();
|
||||
private final Set<PomDependency> dependencies_ = new LinkedHashSet<>();
|
||||
private final Map<String, String> properties_ = new HashMap<>();
|
||||
private final Stack<String> elementStack_ = new Stack<>();
|
||||
private ExclusionSet exclusions_ = null;
|
||||
|
||||
private boolean collectProperties_ = false;
|
||||
private boolean collectDependencyManagement_ = false;
|
||||
private boolean collectDependencies_ = false;
|
||||
private boolean collectExclusions_ = false;
|
||||
|
||||
private StringBuilder characterData_ = null;
|
||||
|
||||
private String lastGroupId_ = null;
|
||||
private String lastArtifactId_ = null;
|
||||
private String lastVersion_ = null;
|
||||
private String lastType_ = null;
|
||||
private String lastClassifier_ = null;
|
||||
private String lastScope_ = null;
|
||||
private String lastOptional_ = null;
|
||||
private String lastExclusionGroupId_ = null;
|
||||
private String lastExclusionArtifactId_ = null;
|
||||
|
||||
Xml2MavenPom(Dependency parent, ArtifactRetriever retriever, List<Repository> repositories) {
|
||||
parent_ = parent;
|
||||
retriever_ = retriever;
|
||||
repositories_ = repositories;
|
||||
}
|
||||
|
||||
Set<PomDependency> getDependencies(Scope... scopes) {
|
||||
if (scopes == null || scopes.length == 0) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
var scopes_list = Arrays.asList(scopes);
|
||||
|
||||
if (resolvedDependencies_ == null) {
|
||||
var resolved_dependencies = new HashMap<Scope, Set<PomDependency>>();
|
||||
|
||||
if (!dependencies_.isEmpty()) {
|
||||
for (var dependency : dependencies_) {
|
||||
var managed_dependency = dependencyManagement_.get(dependency);
|
||||
var version = dependency.version();
|
||||
var dep_scope = dependency.scope();
|
||||
var optional = dependency.optional();
|
||||
var exclusions = dependency.exclusions();
|
||||
if (managed_dependency != null) {
|
||||
if (version == null) {
|
||||
version = managed_dependency.version();
|
||||
}
|
||||
if (dep_scope == null) {
|
||||
dep_scope = managed_dependency.scope();
|
||||
}
|
||||
if (optional == null) {
|
||||
optional = managed_dependency.optional();
|
||||
}
|
||||
if (exclusions == null) {
|
||||
exclusions = managed_dependency.exclusions();
|
||||
}
|
||||
}
|
||||
if (dep_scope == null) {
|
||||
dep_scope = "compile";
|
||||
}
|
||||
optional = resolveProperties(optional);
|
||||
if ("true".equals(optional)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var resolved_dependency = new PomDependency(
|
||||
resolveProperties(dependency.groupId()),
|
||||
resolveProperties(dependency.artifactId()),
|
||||
resolveProperties(version),
|
||||
resolveProperties(dependency.classifier()),
|
||||
resolveProperties(dependency.type()),
|
||||
dep_scope,
|
||||
"false",
|
||||
exclusions,
|
||||
dependency.parent());
|
||||
if (resolved_dependency.type() == null || resolved_dependency.type().equals("jar")) {
|
||||
var scope = Scope.valueOf(resolved_dependency.scope());
|
||||
if (scopes_list.contains(scope)) {
|
||||
var resolved_dependency_set = resolved_dependencies.computeIfAbsent(scope, k -> new LinkedHashSet<>());
|
||||
resolved_dependency_set.add(resolved_dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolvedDependencies_ = resolved_dependencies;
|
||||
}
|
||||
|
||||
var result = new LinkedHashSet<PomDependency>();
|
||||
for (var scope : scopes) {
|
||||
var deps = resolvedDependencies_.get(scope);
|
||||
if (deps != null) {
|
||||
result.addAll(deps);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PomDependency resolveDependency(PomDependency dependency) {
|
||||
return new PomDependency(
|
||||
resolveProperties(dependency.groupId()),
|
||||
resolveProperties(dependency.artifactId()),
|
||||
resolveProperties(dependency.version()),
|
||||
resolveProperties(dependency.classifier()),
|
||||
resolveProperties(dependency.type()),
|
||||
dependency.scope(),
|
||||
resolveProperties(dependency.optional()),
|
||||
dependency.exclusions(),
|
||||
dependency.parent());
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) {
|
||||
characterData_ = new StringBuilder();
|
||||
|
||||
switch (qName) {
|
||||
case "parent" -> resetState();
|
||||
case "properties" -> {
|
||||
if (isChildOfProject()) {
|
||||
collectProperties_ = true;
|
||||
}
|
||||
}
|
||||
case "dependencyManagement" -> {
|
||||
if (isChildOfProject()) {
|
||||
collectDependencyManagement_ = true;
|
||||
}
|
||||
}
|
||||
case "dependencies" -> {
|
||||
if (isChildOfProject()) {
|
||||
resetState();
|
||||
collectDependencies_ = true;
|
||||
}
|
||||
}
|
||||
case "exclusions" -> {
|
||||
if (collectDependencyManagement_ || collectDependencies_) {
|
||||
collectExclusions_ = true;
|
||||
exclusions_ = new ExclusionSet();
|
||||
}
|
||||
}
|
||||
case "dependency" -> {
|
||||
if (collectDependencies_) resetState();
|
||||
}
|
||||
}
|
||||
|
||||
elementStack_.push(qName);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
elementStack_.pop();
|
||||
|
||||
switch (qName) {
|
||||
case "parent" -> {
|
||||
if (isChildOfProject()) {
|
||||
var parent_dependency = new Dependency(resolveProperties(lastGroupId_), resolveProperties(lastArtifactId_), VersionNumber.parse(resolveProperties(lastVersion_)));
|
||||
var parent = new DependencyResolver(retriever_, repositories_, parent_dependency).getMavenPom(parent_);
|
||||
|
||||
parent.properties_.keySet().removeAll(properties_.keySet());
|
||||
properties_.putAll(parent.properties_);
|
||||
|
||||
parent.dependencyManagement_.keySet().removeAll(dependencyManagement_.keySet());
|
||||
dependencyManagement_.putAll(parent.dependencyManagement_);
|
||||
|
||||
parent.dependencies_.removeAll(dependencies_);
|
||||
dependencies_.addAll(parent.dependencies_);
|
||||
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
case "properties" -> collectProperties_ = false;
|
||||
case "dependencyManagement" -> collectDependencyManagement_ = false;
|
||||
case "dependencies" -> collectDependencies_ = false;
|
||||
case "exclusions" -> collectExclusions_ = false;
|
||||
case "exclusion" -> {
|
||||
if (collectExclusions_) {
|
||||
exclusions_.add(new DependencyExclusion(lastExclusionGroupId_, lastExclusionArtifactId_));
|
||||
}
|
||||
}
|
||||
case "dependency" -> {
|
||||
var dependency = new PomDependency(lastGroupId_, lastArtifactId_, lastVersion_, lastClassifier_, lastType_, lastScope_, lastOptional_, exclusions_, parent_);
|
||||
if (collectDependencyManagement_) {
|
||||
if (dependency.isPomImport()) {
|
||||
var import_dependency = new Dependency(resolveProperties(lastGroupId_), resolveProperties(lastArtifactId_), VersionNumber.parse(resolveProperties(lastVersion_)));
|
||||
var imported_pom = new DependencyResolver(retriever_, repositories_, import_dependency).getMavenPom(parent_);
|
||||
imported_pom.dependencyManagement_.keySet().removeAll(dependencyManagement_.keySet());
|
||||
var resolved_dependencies = new LinkedHashSet<PomDependency>();
|
||||
for (var managed_dependency : imported_pom.dependencyManagement_.keySet()) {
|
||||
resolved_dependencies.add(imported_pom.resolveDependency(managed_dependency));
|
||||
}
|
||||
|
||||
resolved_dependencies.removeAll(dependencyManagement_.keySet());
|
||||
for (var resolved_dependency : resolved_dependencies) {
|
||||
dependencyManagement_.put(resolved_dependency, resolved_dependency);
|
||||
}
|
||||
} else {
|
||||
dependencyManagement_.put(dependency, dependency);
|
||||
}
|
||||
} else if (collectDependencies_) {
|
||||
dependencies_.add(dependency);
|
||||
}
|
||||
resetState();
|
||||
}
|
||||
case "groupId" -> {
|
||||
if (isChildOfProject()) {
|
||||
addProjectProperty(qName);
|
||||
} else if (isChildOfParent() || isChildOfDependency()) {
|
||||
lastGroupId_ = getCharacterData();
|
||||
} else if (collectExclusions_ && isChildOfExclusion()) {
|
||||
lastExclusionGroupId_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "artifactId" -> {
|
||||
if (isChildOfProject()) {
|
||||
addProjectProperty(qName);
|
||||
} else if (isChildOfParent() || isChildOfDependency()) {
|
||||
lastArtifactId_ = getCharacterData();
|
||||
} else if (collectExclusions_ && isChildOfExclusion()) {
|
||||
lastExclusionArtifactId_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "version" -> {
|
||||
if (isChildOfProject()) {
|
||||
addProjectProperty(qName);
|
||||
} else if (isChildOfParent() || isChildOfDependency()) {
|
||||
lastVersion_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "type" -> {
|
||||
if (isChildOfDependency()) {
|
||||
lastType_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "classifier" -> {
|
||||
if (isChildOfDependency()) {
|
||||
lastClassifier_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "scope" -> {
|
||||
if (isChildOfDependency()) {
|
||||
lastScope_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "optional" -> {
|
||||
if (isChildOfDependency()) {
|
||||
lastOptional_ = getCharacterData();
|
||||
}
|
||||
}
|
||||
case "packaging", "name", "description", "url", "inceptionYear" -> {
|
||||
if (isChildOfProject()) {
|
||||
addProjectProperty(qName);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
if (collectProperties_) {
|
||||
properties_.put(qName, getCharacterData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
characterData_ = null;
|
||||
}
|
||||
|
||||
private boolean isChildOfProject() {
|
||||
return elementStack_.peek().equals("project");
|
||||
}
|
||||
|
||||
private boolean isChildOfParent() {
|
||||
return elementStack_.peek().equals("parent");
|
||||
}
|
||||
|
||||
private boolean isChildOfDependency() {
|
||||
return elementStack_.peek().equals("dependency");
|
||||
}
|
||||
|
||||
private boolean isChildOfExclusion() {
|
||||
return elementStack_.peek().equals("exclusion");
|
||||
}
|
||||
|
||||
private void addProjectProperty(String name) {
|
||||
properties_.put("project." + name, getCharacterData());
|
||||
}
|
||||
|
||||
private String getCharacterData() {
|
||||
if (characterData_ == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = characterData_.toString().trim();
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final Pattern MAVEN_PROPERTY = Pattern.compile("\\$\\{([^<>{}]+)}");
|
||||
|
||||
private String resolveProperties(String data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean replaced;
|
||||
do {
|
||||
replaced = false;
|
||||
|
||||
var processed_data = new StringBuilder();
|
||||
var matcher = MAVEN_PROPERTY.matcher(data);
|
||||
var last_end = 0;
|
||||
while (matcher.find()) {
|
||||
if (matcher.groupCount() == 1) {
|
||||
var property = matcher.group(1);
|
||||
if (properties_.containsKey(property)) {
|
||||
processed_data.append(data, last_end, matcher.start());
|
||||
processed_data.append(properties_.get(property));
|
||||
last_end = matcher.end();
|
||||
|
||||
replaced = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_end < data.length()) {
|
||||
processed_data.append(data.substring(last_end));
|
||||
}
|
||||
|
||||
data = processed_data.toString();
|
||||
} while (replaced);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
lastGroupId_ = null;
|
||||
lastArtifactId_ = null;
|
||||
lastVersion_ = null;
|
||||
lastType_ = null;
|
||||
lastClassifier_ = null;
|
||||
lastScope_ = null;
|
||||
lastOptional_ = null;
|
||||
lastExclusionArtifactId_ = null;
|
||||
lastExclusionGroupId_ = null;
|
||||
exclusions_ = null;
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) {
|
||||
if (characterData_ != null) {
|
||||
characterData_.append(String.copyValueOf(ch, start, length));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies.exceptions;
|
||||
|
||||
import rife.bld.dependencies.Dependency;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class ArtifactNotFoundException extends DependencyException {
|
||||
@Serial private static final long serialVersionUID = 3137804373567469249L;
|
||||
|
||||
private final Dependency dependency_;
|
||||
private final String location_;
|
||||
|
||||
public ArtifactNotFoundException(Dependency dependency, String location) {
|
||||
super("Couldn't find artifact for dependency '" + dependency + "' at " + location);
|
||||
|
||||
dependency_ = dependency;
|
||||
location_ = location;
|
||||
}
|
||||
|
||||
public Dependency getDependency() {
|
||||
return dependency_;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies.exceptions;
|
||||
|
||||
import rife.bld.dependencies.Dependency;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class ArtifactRetrievalErrorException extends DependencyException {
|
||||
@Serial private static final long serialVersionUID = 5570184718213503548L;
|
||||
|
||||
private final Dependency dependency_;
|
||||
private final String location_;
|
||||
|
||||
public ArtifactRetrievalErrorException(Dependency dependency, String location, Throwable e) {
|
||||
super("Unexpected error while retrieving artifact for dependency '" + dependency + "' from '" + location + "'", e);
|
||||
|
||||
dependency_ = dependency;
|
||||
location_ = location;
|
||||
}
|
||||
|
||||
public Dependency getDependency() {
|
||||
return dependency_;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class DependencyException extends RuntimeException {
|
||||
@Serial private static final long serialVersionUID = 7683888067001718316L;
|
||||
|
||||
public DependencyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DependencyException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies.exceptions;
|
||||
|
||||
import rife.bld.dependencies.Dependency;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serial;
|
||||
|
||||
public class DependencyTransferException extends DependencyException {
|
||||
@Serial private static final long serialVersionUID = 2128741620203670830L;
|
||||
|
||||
private final Dependency dependency_;
|
||||
private final String location_;
|
||||
private final File destination_;
|
||||
|
||||
public DependencyTransferException(Dependency dependency, String location, File destination, Throwable e) {
|
||||
super("Unable to transfer dependency '" + dependency + "' from '" + location + "' into '" + destination + "'", e);
|
||||
|
||||
dependency_ = dependency;
|
||||
location_ = location;
|
||||
destination_ = destination;
|
||||
}
|
||||
|
||||
public Dependency getDependency() {
|
||||
return dependency_;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location_;
|
||||
}
|
||||
|
||||
public File getDestination() {
|
||||
return destination_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.dependencies.exceptions;
|
||||
|
||||
import rife.bld.dependencies.Dependency;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Set;
|
||||
|
||||
public class DependencyXmlParsingErrorException extends DependencyException {
|
||||
@Serial private static final long serialVersionUID = -1050469071912675264L;
|
||||
|
||||
private final Dependency dependency_;
|
||||
private final String location_;
|
||||
private final Set<String> errors_;
|
||||
|
||||
public DependencyXmlParsingErrorException(Dependency dependency, String location, Set<String> errors) {
|
||||
super("Unable to parse artifact document for dependency '" + dependency + "' from '" + location + "' :\n" + StringUtils.join(errors, "\n"));
|
||||
|
||||
dependency_ = dependency;
|
||||
location_ = location;
|
||||
errors_ = errors;
|
||||
}
|
||||
|
||||
public Dependency getDependency() {
|
||||
return dependency_;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location_;
|
||||
}
|
||||
|
||||
public Set<String> getErrors() {
|
||||
return errors_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides exception classes build system dependency handling.
|
||||
* @since 1.5
|
||||
*/
|
||||
package rife.bld.dependencies.exceptions;
|
10
src/main/java/rife/bld/dependencies/package-info.java
Normal file
10
src/main/java/rife/bld/dependencies/package-info.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides functionalities to resolve and retrieve dependency artifacts.
|
||||
* @since 1.5
|
||||
*/
|
||||
package rife.bld.dependencies;
|
27
src/main/java/rife/bld/help/CleanHelp.java
Normal file
27
src/main/java/rife/bld/help/CleanHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the clean command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CleanHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Cleans the build files";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Cleans the build files.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/CompileHelp.java
Normal file
27
src/main/java/rife/bld/help/CompileHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the compile command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CompileHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Compiles the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Compiles the project.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/CreateBaseHelp.java
Normal file
29
src/main/java/rife/bld/help/CreateBaseHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the create-blank command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public class CreateBaseHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a new baseline Java project with minimal commands";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a new baseline Java project with minimal commands.
|
||||
|
||||
Usage : ${topic} <package> <name>
|
||||
package The package of the project to create
|
||||
name The name of the project to create""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/CreateBlankHelp.java
Normal file
29
src/main/java/rife/bld/help/CreateBlankHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the create-blank command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CreateBlankHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a new blank Java project with standard commands";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a new blank Java project with standard commands.
|
||||
|
||||
Usage : ${topic} <package> <name>
|
||||
package The package of the project to create
|
||||
name The name of the project to create""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/CreateLibHelp.java
Normal file
29
src/main/java/rife/bld/help/CreateLibHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the create-lib command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.6
|
||||
*/
|
||||
public class CreateLibHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a new Java library with minimal commands";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a new library Java project with minimal commands.
|
||||
|
||||
Usage : ${topic} <package> <name>
|
||||
package The package of the project to create
|
||||
name The name of the project to create""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/CreateRife2Help.java
Normal file
29
src/main/java/rife/bld/help/CreateRife2Help.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the create command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CreateRife2Help implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a new RIFE2 project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a new RIFE2 project.
|
||||
|
||||
Usage : ${topic} <package> <name>
|
||||
package The package of the project to create
|
||||
name The name of the project to create""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/DependencyTreeHelp.java
Normal file
27
src/main/java/rife/bld/help/DependencyTreeHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the dependency tree command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public class DependencyTreeHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Outputs the dependency tree of the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Outputs the dependency tree of the project
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/DownloadHelp.java
Normal file
27
src/main/java/rife/bld/help/DownloadHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the download command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class DownloadHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Downloads all dependencies of the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Downloads all dependencies of the project
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
19
src/main/java/rife/bld/help/HelpHelp.java
Normal file
19
src/main/java/rife/bld/help/HelpHelp.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
|
||||
/**
|
||||
* Provides help for the help command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class HelpHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Provides help about any of the other commands";
|
||||
}
|
||||
}
|
35
src/main/java/rife/bld/help/JUnitHelp.java
Normal file
35
src/main/java/rife/bld/help/JUnitHelp.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the JUnit test command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public class JUnitHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Tests the project with JUnit (takes options)";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Tests the project with JUnit.
|
||||
|
||||
Additional JUnit console launcher options can be
|
||||
provided after the command.
|
||||
|
||||
These commandline options are provided by this command:
|
||||
--junit-help see the full list of JUnit launcher options
|
||||
--junit-clear clear the JUnit launcher options the build uses
|
||||
(needs to be provided before other options)
|
||||
|
||||
Usage : ${topic} [OPTIONS]""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/JarHelp.java
Normal file
29
src/main/java/rife/bld/help/JarHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the jar command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class JarHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a jar archive for the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a jar archive for the project.
|
||||
The standard jar command will automatically also execute
|
||||
the compile and precompile commands beforehand.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/JarJavadocHelp.java
Normal file
29
src/main/java/rife/bld/help/JarJavadocHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the jar-javadoc command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public class JarJavadocHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a javadoc jar archive for the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a javadoc jar archive for the project.
|
||||
The standard jar-javadoc command will automatically also execute
|
||||
the compile and javadoc commands beforehand.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/JarSourcesHelp.java
Normal file
27
src/main/java/rife/bld/help/JarSourcesHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the jar-sources command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public class JarSourcesHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a sources jar archive for the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a sources jar archive for the project.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/JavadocHelp.java
Normal file
27
src/main/java/rife/bld/help/JavadocHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the javadoc command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public class JavadocHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Generates javadoc for the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Generates javadoc for the project.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/PrecompileHelp.java
Normal file
27
src/main/java/rife/bld/help/PrecompileHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the precompile command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class PrecompileHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Pre-compiles RIFE2 templates to class files";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Pre-compiles RIFE2 templates to class files
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
30
src/main/java/rife/bld/help/PublishHelp.java
Normal file
30
src/main/java/rife/bld/help/PublishHelp.java
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the publish command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public class PublishHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Publishes the artifacts of your project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Publishes the artifacts of the project to the publication
|
||||
repository.
|
||||
The standard publish command will automatically also execute
|
||||
the jar, jar-sources and jar-javadoc commands beforehand.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
31
src/main/java/rife/bld/help/PublishWebHelp.java
Normal file
31
src/main/java/rife/bld/help/PublishWebHelp.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the publish web command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public class PublishWebHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Publishes the artifacts of your web project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Publishes the artifacts of the web project to the publication
|
||||
repository.
|
||||
The standard web publish command will automatically also execute
|
||||
the jar, jar-sources, jar-javadoc, uberjar and war commands
|
||||
beforehand.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/PurgeHelp.java
Normal file
27
src/main/java/rife/bld/help/PurgeHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the purge command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class PurgeHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Purges all unused artifacts from the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Purges all the unused dependency artifacts from the project
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/RunHelp.java
Normal file
27
src/main/java/rife/bld/help/RunHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the run command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class RunHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Runs the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Runs the project.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/TestHelp.java
Normal file
27
src/main/java/rife/bld/help/TestHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the test command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class TestHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Tests the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Tests the project.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/UberJarHelp.java
Normal file
29
src/main/java/rife/bld/help/UberJarHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the uberjar command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class UberJarHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates an UberJar archive for the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates an UberJar archive for the project.
|
||||
The standard uberjar command will automatically also execute
|
||||
the jar command beforehand.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/UpdatesHelp.java
Normal file
27
src/main/java/rife/bld/help/UpdatesHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the updates command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class UpdatesHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Checks for updates of the project dependencies";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Checks which updates are available for the project dependencies.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/UpgradeHelp.java
Normal file
29
src/main/java/rife/bld/help/UpgradeHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the upgrade command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class UpgradeHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Upgrades the bld wrapper to the latest version";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Upgrades the bld wrapper to the latest version.
|
||||
This command should be executed in the root directory of
|
||||
your project.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
27
src/main/java/rife/bld/help/VersionHelp.java
Normal file
27
src/main/java/rife/bld/help/VersionHelp.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the version command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public class VersionHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Outputs the version of the build system";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Outputs the version of the build system.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
29
src/main/java/rife/bld/help/WarHelp.java
Normal file
29
src/main/java/rife/bld/help/WarHelp.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.help;
|
||||
|
||||
import rife.bld.CommandHelp;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides help for the war command.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class WarHelp implements CommandHelp {
|
||||
public String getSummary() {
|
||||
return "Creates a war archive for the project";
|
||||
}
|
||||
|
||||
public String getDescription(String topic) {
|
||||
return StringUtils.replace("""
|
||||
Creates a war archive for the project.
|
||||
The standard war command will automatically also execute
|
||||
the jar command beforehand.
|
||||
|
||||
Usage : ${topic}""", "${topic}", topic);
|
||||
}
|
||||
}
|
10
src/main/java/rife/bld/help/package-info.java
Normal file
10
src/main/java/rife/bld/help/package-info.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides help texts for build commands.
|
||||
* @since 1.5
|
||||
*/
|
||||
package rife.bld.help;
|
526
src/main/java/rife/bld/operations/AbstractCreateOperation.java
Normal file
526
src/main/java/rife/bld/operations/AbstractCreateOperation.java
Normal file
|
@ -0,0 +1,526 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BldVersion;
|
||||
import rife.bld.Project;
|
||||
import rife.bld.operations.exceptions.OperationOptionException;
|
||||
import rife.bld.wrapper.Wrapper;
|
||||
import rife.template.TemplateFactory;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.StringUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
import rife.validation.ValidityChecks;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides the baseline foundation for creating a project structure.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public abstract class AbstractCreateOperation<T extends AbstractCreateOperation<T, P>, P extends Project> extends AbstractOperation<AbstractCreateOperation<T, P>> {
|
||||
final String templateBase_;
|
||||
|
||||
File workDirectory_ = new File(System.getProperty("user.dir"));
|
||||
String packageName_;
|
||||
String projectName_;
|
||||
boolean downloadDependencies_;
|
||||
|
||||
P project_;
|
||||
|
||||
String projectClassName_;
|
||||
String projectBuildName_;
|
||||
String projectMainName_;
|
||||
String projectMainUberName_;
|
||||
String projectTestName_;
|
||||
|
||||
File bldPackageDirectory_;
|
||||
File mainPackageDirectory_;
|
||||
File testPackageDirectory_;
|
||||
File ideaDirectory_;
|
||||
File ideaLibrariesDirectory_;
|
||||
File ideaRunConfigurationsDirectory_;
|
||||
File vscodeDirectory_;
|
||||
|
||||
protected AbstractCreateOperation(String templateBase) {
|
||||
templateBase_ = templateBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the creation operation.
|
||||
*
|
||||
* @throws FileUtilsErrorException when an error occurred during the creation operation
|
||||
* @throws IOException when an error occurred during the creation operation
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws FileUtilsErrorException, IOException {
|
||||
if (packageName() == null || projectName() == null) {
|
||||
System.err.println("ERROR: Missing package or project name.");
|
||||
return;
|
||||
}
|
||||
|
||||
executeConfigure();
|
||||
executeCreateProjectStructure();
|
||||
executePopulateProjectStructure();
|
||||
executePopulateIdeaProject();
|
||||
executePopulateVscodeProject();
|
||||
if (downloadDependencies()) {
|
||||
executeDownloadDependencies();
|
||||
}
|
||||
if (!silent()) {
|
||||
System.out.println("The project was successfully created at '" + project_.workDirectory() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a blueprint of the project.
|
||||
*
|
||||
* @return a blueprint for project creation
|
||||
* @since 1.5
|
||||
*/
|
||||
protected abstract P createProjectBlueprint();
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, configures the project.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeConfigure() {
|
||||
project_ = createProjectBlueprint();
|
||||
|
||||
// standard names
|
||||
projectClassName_ = StringUtils.capitalize(project_.name());
|
||||
projectBuildName_ = projectBuildClassName(projectClassName_);
|
||||
projectMainName_ = projectMainClassName(projectClassName_);
|
||||
projectMainUberName_ = projectMainUberClassName(projectClassName_);
|
||||
projectTestName_ = projectTestClassName(projectClassName_);
|
||||
|
||||
// create the main project structure
|
||||
ideaDirectory_ = new File(project_.workDirectory(), ".idea");
|
||||
ideaLibrariesDirectory_ = new File(ideaDirectory_, "libraries");
|
||||
ideaRunConfigurationsDirectory_ = new File(ideaDirectory_, "runConfigurations");
|
||||
vscodeDirectory_ = new File(project_.workDirectory(), ".vscode");
|
||||
|
||||
var package_dir = project_.pkg().replace('.', File.separatorChar);
|
||||
bldPackageDirectory_ = new File(project_.srcBldJavaDirectory(), package_dir);
|
||||
mainPackageDirectory_ = new File(project_.srcMainJavaDirectory(), package_dir);
|
||||
testPackageDirectory_ = new File(project_.srcTestJavaDirectory(), package_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the build class name from the project class name
|
||||
* @param projectClassName the project class name
|
||||
* @return the generated build class name
|
||||
* @since 1.6
|
||||
*/
|
||||
protected String projectBuildClassName(String projectClassName) {
|
||||
return projectClassName + "Build";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the main class name from the project class name
|
||||
* @param projectClassName the project class name
|
||||
* @return the generated main class name
|
||||
* @since 1.6
|
||||
*/
|
||||
protected String projectMainClassName(String projectClassName) {
|
||||
return projectClassName + "Main";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the main uber class name from the project class name
|
||||
* @param projectClassName the project class name
|
||||
* @return the generated main uber class name
|
||||
* @since 1.6
|
||||
*/
|
||||
protected String projectMainUberClassName(String projectClassName) {
|
||||
return projectClassName + "Main";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the test class name from the project class name
|
||||
* @param projectClassName the project class name
|
||||
* @return the generated test class name
|
||||
* @since 1.6
|
||||
*/
|
||||
protected String projectTestClassName(String projectClassName) {
|
||||
return projectClassName + "Test";
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, creates the project structure.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCreateProjectStructure() {
|
||||
project_.createProjectStructure();
|
||||
|
||||
bldPackageDirectory_.mkdirs();
|
||||
mainPackageDirectory_.mkdirs();
|
||||
testPackageDirectory_.mkdirs();
|
||||
|
||||
ideaDirectory_.mkdirs();
|
||||
ideaLibrariesDirectory_.mkdirs();
|
||||
ideaRunConfigurationsDirectory_.mkdirs();
|
||||
vscodeDirectory_.mkdirs();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, populates the project structure.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executePopulateProjectStructure()
|
||||
throws FileUtilsErrorException, IOException {
|
||||
// project gitignore
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.TXT.get(templateBase_ + "project_gitignore").getContent(),
|
||||
new File(project_.workDirectory(), ".gitignore"));
|
||||
|
||||
// project main
|
||||
var site_template = TemplateFactory.TXT.get(templateBase_ + "project_main");
|
||||
site_template.setValue("package", project_.pkg());
|
||||
site_template.setValue("projectMain", projectMainName_);
|
||||
var project_main_file = new File(mainPackageDirectory_, projectMainName_ + ".java");
|
||||
FileUtils.writeString(site_template.getContent(), project_main_file);
|
||||
|
||||
// project test
|
||||
var test_template = TemplateFactory.TXT.get(templateBase_ + "project_test");
|
||||
test_template.setValue("package", project_.pkg());
|
||||
test_template.setValue("projectTest", projectTestName_);
|
||||
test_template.setValue("projectMain", projectMainName_);
|
||||
if (test_template.hasValueId("project")) {
|
||||
test_template.setValue("project", projectClassName_);
|
||||
}
|
||||
var project_test_file = new File(testPackageDirectory_, projectTestName_ + ".java");
|
||||
FileUtils.writeString(test_template.getContent(), project_test_file);
|
||||
|
||||
// project build
|
||||
var build_template = TemplateFactory.TXT.get(templateBase_ + "project_build");
|
||||
build_template.setValue("projectBuild", projectBuildName_);
|
||||
build_template.setValue("package", project_.pkg());
|
||||
build_template.setValue("project", projectClassName_);
|
||||
if (build_template.hasValueId("projectMain")) {
|
||||
build_template.setValue("projectMain", projectMainName_);
|
||||
}
|
||||
if (build_template.hasValueId("projectTest")) {
|
||||
build_template.setValue("projectTest", projectTestName_);
|
||||
}
|
||||
if (build_template.hasValueId("projectMainUber")) {
|
||||
build_template.setValue("projectMainUber", projectMainUberName_);
|
||||
}
|
||||
for (var entry : project_.dependencies().entrySet()) {
|
||||
build_template.blankValue("dependencies");
|
||||
|
||||
for (var dependency : entry.getValue()) {
|
||||
build_template.setValue("groupId", dependency.groupId());
|
||||
build_template.setValue("artifactId", dependency.artifactId());
|
||||
var version = dependency.version();
|
||||
var version_string = version.major() + "," + version.minor() + "," + version.revision();
|
||||
if (!version.qualifier().isEmpty()) {
|
||||
version_string += ",\"" + version.qualifier() + "\"";
|
||||
}
|
||||
build_template.setValue("version", version_string);
|
||||
build_template.appendBlock("dependencies", "dependency");
|
||||
}
|
||||
build_template.setValue("name", entry.getKey().name());
|
||||
build_template.appendBlock("scopes", "scope");
|
||||
}
|
||||
var project_build_file = new File(bldPackageDirectory_, projectBuildName_ + ".java");
|
||||
FileUtils.writeString(build_template.getContent(), project_build_file);
|
||||
|
||||
// build shell scripts
|
||||
var build_sh_template = TemplateFactory.TXT.get("bld.bld");
|
||||
build_sh_template.setValue("projectBuild", projectBuildName_);
|
||||
build_sh_template.setValue("package", project_.pkg());
|
||||
var build_sh_file = new File(project_.workDirectory(), "bld");
|
||||
FileUtils.writeString(build_sh_template.getContent(), build_sh_file);
|
||||
build_sh_file.setExecutable(true);
|
||||
|
||||
var build_bat_template = TemplateFactory.TXT.get("bld.bld_bat");
|
||||
build_bat_template.setValue("projectBuild", projectBuildName_);
|
||||
build_bat_template.setValue("package", project_.pkg());
|
||||
var build_bat_file = new File(project_.workDirectory(), "bld.bat");
|
||||
FileUtils.writeString(build_bat_template.getContent(), build_bat_file);
|
||||
|
||||
// create the wrapper files
|
||||
new Wrapper().createWrapperFiles(project_.libBldDirectory(), BldVersion.getVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, populates the IDEA project structure.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executePopulateIdeaProject()
|
||||
throws FileUtilsErrorException {
|
||||
// IDEA project files
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.app_iml").getContent(),
|
||||
new File(ideaDirectory_, "app.iml"));
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.bld_iml").getContent(),
|
||||
new File(ideaDirectory_, "bld.iml"));
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.misc").getContent(),
|
||||
new File(ideaDirectory_, "misc.xml"));
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.modules").getContent(),
|
||||
new File(ideaDirectory_, "modules.xml"));
|
||||
|
||||
var bld_xml_template = TemplateFactory.XML.get(templateBase_ + "idea.libraries.bld");
|
||||
bld_xml_template.setValue("version", BldVersion.getVersion());
|
||||
var bld_xml_file = new File(ideaLibrariesDirectory_, "bld.xml");
|
||||
FileUtils.writeString(bld_xml_template.getContent(), bld_xml_file);
|
||||
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.libraries.compile").getContent(),
|
||||
new File(ideaLibrariesDirectory_, "compile.xml"));
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.libraries.runtime").getContent(),
|
||||
new File(ideaLibrariesDirectory_, "runtime.xml"));
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.libraries.test").getContent(),
|
||||
new File(ideaLibrariesDirectory_, "test.xml"));
|
||||
|
||||
// IDEA run site
|
||||
if (createIdeaRunMain()) {
|
||||
var run_site_template = TemplateFactory.XML.get(templateBase_ + "idea.runConfigurations.Run_Main");
|
||||
run_site_template.setValue("package", project_.pkg());
|
||||
run_site_template.setValue("projectMain", projectMainName_);
|
||||
var run_site_file = new File(ideaRunConfigurationsDirectory_, "Run Main.xml");
|
||||
FileUtils.writeString(run_site_template.getContent(), run_site_file);
|
||||
}
|
||||
|
||||
// IDEA run tests
|
||||
var run_tests_template = TemplateFactory.XML.get(templateBase_ + "idea.runConfigurations.Run_Tests");
|
||||
run_tests_template.setValue("package", project_.pkg());
|
||||
if (run_tests_template.hasValueId("projectTest")) {
|
||||
run_tests_template.setValue("projectTest", projectTestName_);
|
||||
}
|
||||
var run_tests_file = new File(ideaRunConfigurationsDirectory_, "Run Tests.xml");
|
||||
FileUtils.writeString(run_tests_template.getContent(), run_tests_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the IDEA main run target should be generated
|
||||
* @return {@code true} of it should be generated; or {@code false} otherwise
|
||||
* @since 1.6
|
||||
*/
|
||||
protected boolean createIdeaRunMain() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, populates the vscode project structure.
|
||||
*
|
||||
* @since 1.5.6
|
||||
*/
|
||||
protected void executePopulateVscodeProject()
|
||||
throws FileUtilsErrorException {
|
||||
var launch_template = TemplateFactory.JSON.get(templateBase_ + "vscode.launch");
|
||||
launch_template.setValue("package", project_.pkg());
|
||||
if (launch_template.hasValueId("projectMain")) {
|
||||
launch_template.setValue("projectMain", projectMainName_);
|
||||
}
|
||||
if (launch_template.hasValueId("projectTest")) {
|
||||
launch_template.setValue("projectTest", projectTestName_);
|
||||
}
|
||||
var launch_file = new File(vscodeDirectory_, "launch.json");
|
||||
FileUtils.writeString(launch_template.getContent(), launch_file);
|
||||
|
||||
var settings_template = TemplateFactory.JSON.get(templateBase_ + "vscode.settings");
|
||||
if (settings_template.hasValueId("version")) {
|
||||
settings_template.setValue("version", BldVersion.getVersion());
|
||||
}
|
||||
var settings_file = new File(vscodeDirectory_, "settings.json");
|
||||
FileUtils.writeString(settings_template.getContent(), settings_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, downloads the dependencies, when enabled.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeDownloadDependencies() {
|
||||
new DownloadOperation().fromProject(project_).execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a creation operation from command-line arguments.
|
||||
*
|
||||
* @param arguments the arguments that will be considered
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T fromArguments(List<String> arguments) {
|
||||
String package_name = null;
|
||||
String project_name = null;
|
||||
if (arguments.size() > 0) {
|
||||
package_name = arguments.remove(0);
|
||||
}
|
||||
if (arguments.size() > 0) {
|
||||
project_name = arguments.remove(0);
|
||||
}
|
||||
if ((package_name == null || project_name == null) && System.console() == null) {
|
||||
throw new OperationOptionException("ERROR: Expecting the package and project names as the arguments.");
|
||||
}
|
||||
|
||||
if (package_name == null || package_name.isEmpty()) {
|
||||
System.out.println("Please enter a package name (for instance: com.example):");
|
||||
package_name = System.console().readLine();
|
||||
} else {
|
||||
System.out.println("Using package name: " + package_name);
|
||||
}
|
||||
if (project_name == null || project_name.isEmpty()) {
|
||||
System.out.println("Please enter a project name (for instance: myapp):");
|
||||
project_name = System.console().readLine();
|
||||
} else {
|
||||
System.out.println("Using project name: " + project_name);
|
||||
}
|
||||
|
||||
return workDirectory(new File(System.getProperty("user.dir")))
|
||||
.packageName(package_name)
|
||||
.projectName(project_name)
|
||||
.downloadDependencies(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the work directory in which the project will be created.
|
||||
* <p>
|
||||
* If no work directory is provided, the JVM working directory will be used.
|
||||
*
|
||||
* @param directory the directory to use as a work directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T workDirectory(File directory) {
|
||||
if (!directory.exists()) {
|
||||
throw new OperationOptionException("ERROR: The work directory '" + directory + "' doesn't exist.");
|
||||
}
|
||||
if (!directory.isDirectory()) {
|
||||
throw new OperationOptionException("ERROR: '" + directory + "' is not a directory.");
|
||||
}
|
||||
if (!directory.canWrite()) {
|
||||
throw new OperationOptionException("ERROR: The work directory '" + directory + "' is not writable.");
|
||||
}
|
||||
|
||||
workDirectory_ = directory;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the package of the project that will be created.
|
||||
*
|
||||
* @param name the package name
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T packageName(String name) {
|
||||
packageName_ = StringUtils.trim(name);
|
||||
if (packageName_.isEmpty()) {
|
||||
throw new OperationOptionException("ERROR: The package name should not be blank.");
|
||||
}
|
||||
|
||||
if (!ValidityChecks.checkJavaPackage(packageName_)) {
|
||||
throw new OperationOptionException("ERROR: The package name is invalid.");
|
||||
}
|
||||
|
||||
packageName_ = name;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the name of the project that will be created.
|
||||
*
|
||||
* @param name the project name
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T projectName(String name) {
|
||||
projectName_ = StringUtils.trim(name);
|
||||
if (projectName_.isEmpty()) {
|
||||
throw new OperationOptionException("ERROR: The project name should not be blank.");
|
||||
}
|
||||
|
||||
if (!ValidityChecks.checkJavaIdentifier(projectName_)) {
|
||||
throw new OperationOptionException("ERROR: The project name is invalid.");
|
||||
}
|
||||
projectName_ = name;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the dependencies for the project should be downloaded
|
||||
* upon creation, by default this is {@code false}.
|
||||
*
|
||||
* @param flag {@code true} if the dependencies should be downloaded; or
|
||||
* {@code false} otherwise
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T downloadDependencies(boolean flag) {
|
||||
downloadDependencies_ = flag;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the work directory that is used for the project creation.
|
||||
*
|
||||
* @return the work directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File workDirectory() {
|
||||
return workDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the package that is used for the project creation.
|
||||
*
|
||||
* @return the package name
|
||||
* @since 1.5
|
||||
*/
|
||||
public String packageName() {
|
||||
return packageName_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the name that is used for the project creation.
|
||||
*
|
||||
* @return the project name
|
||||
* @since 1.5
|
||||
*/
|
||||
public String projectName() {
|
||||
return projectName_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether dependencies will be downloaded at project creation.
|
||||
*
|
||||
* @return {@code true} if dependencies will be downloaded; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5
|
||||
*/
|
||||
public boolean downloadDependencies() {
|
||||
return downloadDependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the project instance that was used as a blueprint for the
|
||||
* project creation.
|
||||
*
|
||||
* @return the project creation blueprint instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public P project() {
|
||||
return project_;
|
||||
}
|
||||
}
|
86
src/main/java/rife/bld/operations/AbstractOperation.java
Normal file
86
src/main/java/rife/bld/operations/AbstractOperation.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
/**
|
||||
* Provides common features across all operations
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public abstract class AbstractOperation<T extends AbstractOperation<T>> {
|
||||
private boolean silent_ = false;
|
||||
private boolean executed_ = false;
|
||||
|
||||
/**
|
||||
* Changes whether the operation should be silent or not.
|
||||
* <p>
|
||||
* Defaults to not silent.
|
||||
*
|
||||
* @param silent {@code true} if the operation should be silent;
|
||||
* {@code false} otherwise
|
||||
* @return this operation instance
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public T silent(boolean silent) {
|
||||
silent_ = silent;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the operation should be silent or not.
|
||||
*
|
||||
* @return {@code true} if the operation should be silent;
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public boolean silent() {
|
||||
return silent_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that this operation instance is executed once and only once.
|
||||
*
|
||||
* @throws Exception when an exception was thrown by the {@link #execute()} call
|
||||
* @see #executeOnce(Runnable)
|
||||
* @since 1.5.17
|
||||
*/
|
||||
public void executeOnce()
|
||||
throws Exception {
|
||||
executeOnce(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that this operation instance is executed once and only once.
|
||||
* <p>
|
||||
* A setup lambda can be provided that is called when the only execution takes place.
|
||||
*
|
||||
* @param setup the setup lambda that will be called with the only execution
|
||||
* @throws Exception when an exception was thrown by the {@link #execute()} call
|
||||
* @see #executeOnce()
|
||||
* @since 1.5.17
|
||||
*/
|
||||
public void executeOnce(Runnable setup)
|
||||
throws Exception {
|
||||
if (executed_) {
|
||||
return;
|
||||
}
|
||||
executed_ = true;
|
||||
|
||||
if (setup != null) {
|
||||
setup.run();
|
||||
}
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the operation execution that can be wrapped by the {@code #executeOnce} call.
|
||||
*
|
||||
* @throws Exception when an exception occurs during the execution
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public abstract void execute()
|
||||
throws Exception;
|
||||
}
|
337
src/main/java/rife/bld/operations/AbstractProcessOperation.java
Normal file
337
src/main/java/rife/bld/operations/AbstractProcessOperation.java
Normal file
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.operations.exceptions.ExitStatusException;
|
||||
import rife.bld.operations.exceptions.OperationOptionException;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Abstract operation that starts a Java application as a separate process.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public abstract class AbstractProcessOperation<T extends AbstractProcessOperation<T>> extends AbstractOperation<T> {
|
||||
public static final String DEFAULT_JAVA_TOOL = "java";
|
||||
|
||||
protected File workDirectory_ = new File(System.getProperty("user.dir"));
|
||||
protected String javaTool_ = DEFAULT_JAVA_TOOL;
|
||||
protected final JavaOptions javaOptions_ = new JavaOptions();
|
||||
protected final List<String> classpath_ = new ArrayList<>();
|
||||
protected String mainClass_;
|
||||
protected Function<String, Boolean> outputProcessor_;
|
||||
protected Function<String, Boolean> errorProcessor_;
|
||||
protected Process process_;
|
||||
protected boolean successful_;
|
||||
protected Thread outputProcessorThread_;
|
||||
protected Thread errorProcessorThread_;
|
||||
|
||||
/**
|
||||
* Performs the operation.
|
||||
*
|
||||
* @throws InterruptedException when the operation was interrupted
|
||||
* @throws IOException when an exception occurred during the execution of the process
|
||||
* @throws FileUtilsErrorException when an exception occurred during the retrieval of the operation output
|
||||
* @throws ExitStatusException when the exit status was changed during the operation
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException, FileUtilsErrorException, InterruptedException, ExitStatusException {
|
||||
successful_ = true;
|
||||
outputProcessorThread_ = null;
|
||||
errorProcessorThread_ = null;
|
||||
|
||||
process_ = executeStartProcess();
|
||||
|
||||
int status = process_.waitFor();
|
||||
|
||||
if (outputProcessorThread_ != null) {
|
||||
outputProcessorThread_.join();
|
||||
}
|
||||
if (errorProcessorThread_ != null) {
|
||||
errorProcessorThread_.join();
|
||||
}
|
||||
if (!successful_) {
|
||||
status = ExitStatusException.EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ExitStatusException.throwOnFailure(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, constructs the command list
|
||||
* to use for building the process.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
abstract protected List<String> executeConstructProcessCommandList();
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, starts the process.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected Process executeStartProcess()
|
||||
throws IOException {
|
||||
var builder = new ProcessBuilder(executeConstructProcessCommandList());
|
||||
builder.directory(workDirectory());
|
||||
|
||||
final var output_processor = outputProcessor();
|
||||
if (output_processor == null) {
|
||||
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||
} else {
|
||||
builder.redirectOutput(ProcessBuilder.Redirect.PIPE);
|
||||
}
|
||||
|
||||
final var error_processor = errorProcessor();
|
||||
if (error_processor == null) {
|
||||
builder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
} else {
|
||||
builder.redirectError(ProcessBuilder.Redirect.PIPE);
|
||||
}
|
||||
|
||||
final var process = builder.start();
|
||||
|
||||
if (output_processor != null) {
|
||||
outputProcessorThread_ = startProcessStreamProcessor(process.getInputStream(), output_processor);
|
||||
}
|
||||
if (error_processor != null) {
|
||||
errorProcessorThread_ = startProcessStreamProcessor(process.getErrorStream(), error_processor);
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
private Thread startProcessStreamProcessor(InputStream stream, Function<String, Boolean> processor) {
|
||||
var processor_thread = new Thread(() -> {
|
||||
try {
|
||||
String line;
|
||||
var in = new BufferedReader(new InputStreamReader(stream));
|
||||
while ((line = in.readLine()) != null) {
|
||||
successful_ &= processor.apply(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
processor_thread.start();
|
||||
return processor_thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
abstract public T fromProject(BaseProject project);
|
||||
|
||||
/**
|
||||
* Provides the work directory in which the operation will be performed.
|
||||
* <p>
|
||||
* If no work directory is provided, the JVM working directory will be used.
|
||||
*
|
||||
* @param directory the directory to use as a work directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T workDirectory(File directory) {
|
||||
if (!directory.exists()) {
|
||||
throw new OperationOptionException("ERROR: The work directory '" + directory + "' doesn't exist.");
|
||||
}
|
||||
if (!directory.isDirectory()) {
|
||||
throw new OperationOptionException("ERROR: '" + directory + "' is not a directory.");
|
||||
}
|
||||
if (!directory.canWrite()) {
|
||||
throw new OperationOptionException("ERROR: The work directory '" + directory + "' is not writable.");
|
||||
}
|
||||
|
||||
workDirectory_ = directory;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the name of the tool to use for {@code java} execution.
|
||||
* <p>
|
||||
* If no java tool is provided {@code java} will be used.
|
||||
*
|
||||
* @param tool the name of the java tool
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T javaTool(String tool) {
|
||||
javaTool_ = tool;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the options to provide to the java tool.
|
||||
*
|
||||
* @param options the java tool's options
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T javaOptions(List<String> options) {
|
||||
javaOptions_.addAll(options);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classpath entries to use for the operation.
|
||||
*
|
||||
* @param classpath classpath entries for the operation
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public T classpath(String... classpath) {
|
||||
classpath_.addAll(List.of(classpath));
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of classpath entries to use for the operation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param classpath a list of classpath entries for the operation
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T classpath(List<String> classpath) {
|
||||
classpath_.addAll(classpath);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the main class to launch with the java tool.
|
||||
*
|
||||
* @param name the main class to launch
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T mainClass(String name) {
|
||||
mainClass_ = name;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the processor that will be used to handle the process output.
|
||||
* <p>
|
||||
* It will be called for each line in the output.
|
||||
*
|
||||
* @param processor the output processor
|
||||
* @return this operation instance
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public T outputProcessor(Function<String, Boolean> processor) {
|
||||
outputProcessor_ = processor;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the processor that will be used to handle the process errors.
|
||||
* <p>
|
||||
* It will be called for each line in the error output.
|
||||
*
|
||||
* @param processor the error processor
|
||||
* @return this operation instance
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public T errorProcessor(Function<String, Boolean> processor) {
|
||||
errorProcessor_ = processor;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the work directory in which the operation will be performed.
|
||||
*
|
||||
* @return the directory to use as a work directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File workDirectory() {
|
||||
return workDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves the name of the tool to use for {@code java} execution.
|
||||
*
|
||||
* @return the name of the java tool
|
||||
* @since 1.5
|
||||
*/
|
||||
public String javaTool() {
|
||||
return javaTool_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the options to provide to the java tool.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the java tool's options
|
||||
* @since 1.5
|
||||
*/
|
||||
public JavaOptions javaOptions() {
|
||||
return javaOptions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the classpath to use for the operation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the operation's classpath
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<String> classpath() {
|
||||
return classpath_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the main class to launch with the java tool.
|
||||
*
|
||||
* @return the main class to launch
|
||||
* @since 1.5
|
||||
*/
|
||||
public String mainClass() {
|
||||
return mainClass_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the processor that is used to handle the process output.
|
||||
*
|
||||
* @return the output processor
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public Function<String, Boolean> outputProcessor() {
|
||||
return outputProcessor_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the processor that is used to handle the process errors.
|
||||
*
|
||||
* @return the error processor
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public Function<String, Boolean> errorProcessor() {
|
||||
return errorProcessor_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the process that was used for the execution.
|
||||
*
|
||||
* @return the process that was executed
|
||||
* @since 1.5
|
||||
*/
|
||||
public Process process() {
|
||||
return process_;
|
||||
}
|
||||
}
|
101
src/main/java/rife/bld/operations/CleanOperation.java
Normal file
101
src/main/java/rife/bld/operations/CleanOperation.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.Project;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Cleans by deleting a list of directories and all their contents.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CleanOperation extends AbstractOperation<CleanOperation> {
|
||||
private final List<File> directories_ = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Performs the clean operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute() {
|
||||
for (var directory : directories()) {
|
||||
executeCleanDirectory(directory);
|
||||
}
|
||||
if (!silent()) {
|
||||
System.out.println("Cleaning finished successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, cleans an individual directory.
|
||||
*
|
||||
* @param directory the directory to clean.
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCleanDirectory(File directory) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(directory);
|
||||
} catch (FileUtilsErrorException e) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a clean operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the clean operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public CleanOperation fromProject(BaseProject project) {
|
||||
return directories(project.buildDirectory()
|
||||
.listFiles(f -> !f.equals(project.buildBldDirectory())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides directories to clean.
|
||||
*
|
||||
* @param directories directories to clean
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public CleanOperation directories(File... directories) {
|
||||
directories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of directories to clean.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of directories to clean
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CleanOperation directories(List<File> directories) {
|
||||
directories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of directories to clean.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of directories to clean.
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> directories() {
|
||||
return directories_;
|
||||
}
|
||||
}
|
480
src/main/java/rife/bld/operations/CompileOperation.java
Normal file
480
src/main/java/rife/bld/operations/CompileOperation.java
Normal file
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.Project;
|
||||
import rife.bld.operations.exceptions.ExitStatusException;
|
||||
import rife.tools.FileUtils;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Compiles main and test sources in the relevant build directories.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CompileOperation extends AbstractOperation<CompileOperation> {
|
||||
private File buildMainDirectory_;
|
||||
private File buildTestDirectory_;
|
||||
private final List<String> compileMainClasspath_ = new ArrayList<>();
|
||||
private final List<String> compileTestClasspath_ = new ArrayList<>();
|
||||
private final List<File> mainSourceFiles_ = new ArrayList<>();
|
||||
private final List<File> testSourceFiles_ = new ArrayList<>();
|
||||
private final List<File> mainSourceDirectories_ = new ArrayList<>();
|
||||
private final List<File> testSourceDirectories_ = new ArrayList<>();
|
||||
private final JavacOptions compileOptions_ = new JavacOptions();
|
||||
private final List<Diagnostic<? extends JavaFileObject>> diagnostics_ = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Performs the compile operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException, ExitStatusException {
|
||||
executeCreateBuildDirectories();
|
||||
executeBuildMainSources();
|
||||
executeBuildTestSources();
|
||||
if (!diagnostics().isEmpty()) {
|
||||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
}
|
||||
if (!silent()) {
|
||||
System.out.println("Compilation finished successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, creates the build directories.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCreateBuildDirectories() {
|
||||
if (buildMainDirectory() != null) {
|
||||
buildMainDirectory().mkdirs();
|
||||
}
|
||||
if (buildTestDirectory() != null) {
|
||||
buildTestDirectory().mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, builds the main sources.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeBuildMainSources()
|
||||
throws IOException {
|
||||
var sources = new ArrayList<>(mainSourceFiles());
|
||||
for (var directory : mainSourceDirectories()) {
|
||||
sources.addAll(FileUtils.getJavaFileList(directory));
|
||||
}
|
||||
executeBuildSources(
|
||||
compileMainClasspath(),
|
||||
sources,
|
||||
buildMainDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, builds the test sources.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeBuildTestSources()
|
||||
throws IOException {
|
||||
var sources = new ArrayList<>(testSourceFiles());
|
||||
for (var directory : testSourceDirectories()) {
|
||||
sources.addAll(FileUtils.getJavaFileList(directory));
|
||||
}
|
||||
executeBuildSources(
|
||||
compileTestClasspath(),
|
||||
sources,
|
||||
buildTestDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, build sources to a destination.
|
||||
*
|
||||
* @param classpath the classpath list used for the compilation
|
||||
* @param sources the source files to compile
|
||||
* @param destination the destination directory
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeBuildSources(List<String> classpath, List<File> sources, File destination)
|
||||
throws IOException {
|
||||
if (sources.isEmpty() || destination == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var compiler = ToolProvider.getSystemJavaCompiler();
|
||||
try (var file_manager = compiler.getStandardFileManager(null, null, null)) {
|
||||
var compilation_units = file_manager.getJavaFileObjectsFromFiles(sources);
|
||||
var diagnostics = new DiagnosticCollector<JavaFileObject>();
|
||||
var options = new ArrayList<>(List.of("-d", destination.getAbsolutePath(), "-cp", FileUtils.joinPaths(classpath)));
|
||||
options.addAll(compileOptions());
|
||||
var compilation_task = compiler.getTask(null, file_manager, diagnostics, options, null, compilation_units);
|
||||
if (!compilation_task.call()) {
|
||||
diagnostics_.addAll(diagnostics.getDiagnostics());
|
||||
executeProcessDiagnostics(diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, processes the compilation diagnostics.
|
||||
*
|
||||
* @param diagnostics the diagnostics to process
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeProcessDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) {
|
||||
for (var diagnostic : diagnostics.getDiagnostics()) {
|
||||
System.err.print(executeFormatDiagnostic(diagnostic));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, format a single diagnostic.
|
||||
*
|
||||
* @param diagnostic the diagnostic to format
|
||||
* @return a string representation of the diagnostic
|
||||
* @since 1.5
|
||||
*/
|
||||
protected String executeFormatDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||
return diagnostic.toString() + System.lineSeparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a compile operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the compile operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation fromProject(BaseProject project) {
|
||||
var operation = buildMainDirectory(project.buildMainDirectory())
|
||||
.buildTestDirectory(project.buildTestDirectory())
|
||||
.compileMainClasspath(project.compileMainClasspath())
|
||||
.compileTestClasspath(project.compileTestClasspath())
|
||||
.mainSourceFiles(project.mainSourceFiles())
|
||||
.testSourceFiles(project.testSourceFiles());
|
||||
if (project.javaRelease() != null && !compileOptions().containsRelease()) {
|
||||
compileOptions().release(project.javaRelease());
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the main build destination directory.
|
||||
*
|
||||
* @param directory the directory to use for the main build destination
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation buildMainDirectory(File directory) {
|
||||
buildMainDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the test build destination directory.
|
||||
*
|
||||
* @param directory the directory to use for the test build destination
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation buildTestDirectory(File directory) {
|
||||
buildTestDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides entries for the main compilation classpath.
|
||||
*
|
||||
* @param classpath classpath entries
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public CompileOperation compileMainClasspath(String... classpath) {
|
||||
compileMainClasspath_.addAll(Arrays.asList(classpath));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of entries for the main compilation classpath.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param classpath a list of classpath entries
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation compileMainClasspath(List<String> classpath) {
|
||||
compileMainClasspath_.addAll(classpath);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides entries for the test compilation classpath.
|
||||
*
|
||||
* @param classpath classpath entries
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public CompileOperation compileTestClasspath(String... classpath) {
|
||||
compileTestClasspath_.addAll(Arrays.asList(classpath));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of entries for the test compilation classpath.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param classpath a list of classpath entries
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation compileTestClasspath(List<String> classpath) {
|
||||
compileTestClasspath_.addAll(classpath);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides main files that should be compiled.
|
||||
*
|
||||
* @param files main files
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public CompileOperation mainSourceFiles(File... files) {
|
||||
mainSourceFiles_.addAll(Arrays.asList(files));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of main files that should be compiled.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param files a list of main files
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation mainSourceFiles(List<File> files) {
|
||||
mainSourceFiles_.addAll(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test files that should be compiled.
|
||||
*
|
||||
* @param files test files
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public CompileOperation testSourceFiles(File... files) {
|
||||
testSourceFiles_.addAll(Arrays.asList(files));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of test files that should be compiled.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param files a list of test files
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation testSourceFiles(List<File> files) {
|
||||
testSourceFiles_.addAll(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides main source directories that should be compiled.
|
||||
*
|
||||
* @param directories main source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public CompileOperation mainSourceDirectories(File... directories) {
|
||||
mainSourceDirectories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of main source directories that should be compiled.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of main source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public CompileOperation mainSourceDirectories(List<File> directories) {
|
||||
mainSourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test source directories that should be compiled.
|
||||
*
|
||||
* @param directories test source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public CompileOperation testSourceDirectories(File... directories) {
|
||||
testSourceDirectories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of test source directories that should be compiled.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of test source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public CompileOperation testSourceDirectories(List<File> directories) {
|
||||
testSourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of compilation options to provide to the compiler.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param options the list of compilation options
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public CompileOperation compileOptions(List<String> options) {
|
||||
compileOptions_.addAll(options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the main build destination directory.
|
||||
*
|
||||
* @return the main build destination
|
||||
* @since 1.5
|
||||
*/
|
||||
public File buildMainDirectory() {
|
||||
return buildMainDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the test build destination directory.
|
||||
*
|
||||
* @return the test build destination
|
||||
* @since 1.5
|
||||
*/
|
||||
public File buildTestDirectory() {
|
||||
return buildTestDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of entries for the main compilation classpath.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the main compilation classpath list
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<String> compileMainClasspath() {
|
||||
return compileMainClasspath_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of entries for the test compilation classpath.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the test compilation classpath list
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<String> compileTestClasspath() {
|
||||
return compileTestClasspath_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of main files that should be compiled.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of main files to compile
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> mainSourceFiles() {
|
||||
return mainSourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of test files that should be compiled.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of test files to compile
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> testSourceFiles() {
|
||||
return testSourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of main source directories that should be compiled.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of main source directories to compile
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<File> mainSourceDirectories() {
|
||||
return mainSourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of test source directories that should be compiled.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of test source directories to compile
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<File> testSourceDirectories() {
|
||||
return testSourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of compilation options for the compiler.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of compiler options
|
||||
* @since 1.5
|
||||
*/
|
||||
public JavacOptions compileOptions() {
|
||||
return compileOptions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of diagnostics resulting from the compilation.
|
||||
*
|
||||
* @return the list of compilation diagnostics
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Diagnostic<? extends JavaFileObject>> diagnostics() {
|
||||
return diagnostics_;
|
||||
}
|
||||
}
|
26
src/main/java/rife/bld/operations/CreateBaseOperation.java
Normal file
26
src/main/java/rife/bld/operations/CreateBaseOperation.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.Project;
|
||||
import rife.bld.blueprints.BaseProjectBlueprint;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Creates a new base project structure.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public class CreateBaseOperation extends AbstractCreateOperation<CreateBaseOperation, Project> {
|
||||
public CreateBaseOperation() {
|
||||
super("bld.base.");
|
||||
}
|
||||
|
||||
protected Project createProjectBlueprint() {
|
||||
return new BaseProjectBlueprint(new File(workDirectory(), projectName()), packageName(), projectName());
|
||||
}
|
||||
}
|
26
src/main/java/rife/bld/operations/CreateBlankOperation.java
Normal file
26
src/main/java/rife/bld/operations/CreateBlankOperation.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.Project;
|
||||
import rife.bld.blueprints.BlankProjectBlueprint;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Creates a new blank project structure.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CreateBlankOperation extends AbstractCreateOperation<CreateBlankOperation, Project> {
|
||||
public CreateBlankOperation() {
|
||||
super("bld.blank.");
|
||||
}
|
||||
|
||||
protected Project createProjectBlueprint() {
|
||||
return new BlankProjectBlueprint(new File(workDirectory(), projectName()), packageName(), projectName());
|
||||
}
|
||||
}
|
35
src/main/java/rife/bld/operations/CreateLibOperation.java
Normal file
35
src/main/java/rife/bld/operations/CreateLibOperation.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.Project;
|
||||
import rife.bld.blueprints.BaseProjectBlueprint;
|
||||
import rife.bld.blueprints.LibProjectBlueprint;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Creates a new lib project structure.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.6
|
||||
*/
|
||||
public class CreateLibOperation extends AbstractCreateOperation<CreateLibOperation, Project> {
|
||||
public CreateLibOperation() {
|
||||
super("bld.lib.");
|
||||
}
|
||||
|
||||
protected Project createProjectBlueprint() {
|
||||
return new LibProjectBlueprint(new File(workDirectory(), projectName()), packageName(), projectName());
|
||||
}
|
||||
|
||||
protected String projectMainClassName(String projectClassName) {
|
||||
return projectClassName + "Lib";
|
||||
}
|
||||
|
||||
protected boolean createIdeaRunMain() {
|
||||
return false;
|
||||
}
|
||||
}
|
92
src/main/java/rife/bld/operations/CreateRife2Operation.java
Normal file
92
src/main/java/rife/bld/operations/CreateRife2Operation.java
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.blueprints.Rife2ProjectBlueprint;
|
||||
import rife.bld.dependencies.*;
|
||||
import rife.template.TemplateFactory;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Creates a new RIFE2 project structure.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class CreateRife2Operation extends AbstractCreateOperation<CreateRife2Operation, Rife2ProjectBlueprint> {
|
||||
File srcMainWebappCssDirectory_;
|
||||
File srcMainWebappWebInfDirectory_;
|
||||
|
||||
public CreateRife2Operation() {
|
||||
super("bld.rife2_hello.");
|
||||
}
|
||||
|
||||
protected Rife2ProjectBlueprint createProjectBlueprint() {
|
||||
return new Rife2ProjectBlueprint(new File(workDirectory(), projectName()), packageName(), projectName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeConfigure() {
|
||||
super.executeConfigure();
|
||||
|
||||
projectMainName_ = projectClassName_ + "Site";
|
||||
projectMainUberName_ = projectMainName_ + "Uber";
|
||||
srcMainWebappCssDirectory_ = new File(project_.srcMainWebappDirectory(), "css");
|
||||
srcMainWebappWebInfDirectory_ = new File(project_.srcMainWebappDirectory(), "WEB-INF");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeCreateProjectStructure() {
|
||||
super.executeCreateProjectStructure();
|
||||
|
||||
srcMainWebappCssDirectory_.mkdirs();
|
||||
srcMainWebappWebInfDirectory_.mkdirs();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executePopulateProjectStructure()
|
||||
throws FileUtilsErrorException, IOException {
|
||||
super.executePopulateProjectStructure();
|
||||
|
||||
// project site uber
|
||||
var main_uber_template = TemplateFactory.TXT.get(templateBase_ + "project_main_uber");
|
||||
main_uber_template.setValue("package", project_.pkg());
|
||||
main_uber_template.setValue("projectMain", projectMainName_);
|
||||
main_uber_template.setValue("projectMainUber", projectMainUberName_);
|
||||
var project_main_uber_file = new File(mainPackageDirectory_, projectMainUberName_ + ".java");
|
||||
FileUtils.writeString(main_uber_template.getContent(), project_main_uber_file);
|
||||
|
||||
// project template
|
||||
var template_template = TemplateFactory.HTML.get(templateBase_ + "project_template");
|
||||
template_template.setValue("project", projectClassName_);
|
||||
var project_template_file = new File(project_.srcMainResourcesTemplatesDirectory(), "hello.html");
|
||||
FileUtils.writeString(template_template.getContent(), project_template_file);
|
||||
|
||||
// project css
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.TXT.get(templateBase_ + "project_style").getContent(),
|
||||
new File(srcMainWebappCssDirectory_, "style.css"));
|
||||
|
||||
// project web.xml
|
||||
var web_xml_template = TemplateFactory.XML.get(templateBase_ + "project_web");
|
||||
web_xml_template.setValue("package", project_.pkg());
|
||||
web_xml_template.setValue("projectMain", projectMainName_);
|
||||
var project_web_xml_file = new File(srcMainWebappWebInfDirectory_, "web.xml");
|
||||
FileUtils.writeString(web_xml_template.getContent(), project_web_xml_file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executePopulateIdeaProject()
|
||||
throws FileUtilsErrorException {
|
||||
super.executePopulateIdeaProject();
|
||||
FileUtils.writeString(
|
||||
TemplateFactory.XML.get(templateBase_ + "idea.libraries.standalone").getContent(),
|
||||
new File(ideaLibrariesDirectory_, "standalone.xml"));
|
||||
}
|
||||
}
|
181
src/main/java/rife/bld/operations/DependencyTreeOperation.java
Normal file
181
src/main/java/rife/bld/operations/DependencyTreeOperation.java
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.dependencies.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static rife.bld.dependencies.Scope.compile;
|
||||
import static rife.bld.dependencies.Scope.runtime;
|
||||
|
||||
/**
|
||||
* Transitively generates a hierarchical tree of dependencies.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public class DependencyTreeOperation extends AbstractOperation<DependencyTreeOperation> {
|
||||
private ArtifactRetriever retriever_ = null;
|
||||
private final List<Repository> repositories_ = new ArrayList<>();
|
||||
private final DependencyScopes dependencies_ = new DependencyScopes();
|
||||
private final StringBuilder dependencyTree_ = new StringBuilder();
|
||||
|
||||
/**
|
||||
* Performs the dependency tree operation.
|
||||
*
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public void execute() {
|
||||
var compile_tree = executeGenerateCompileDependencies();
|
||||
var runtime_tree = executeGenerateRuntimeDependencies();
|
||||
dependencyTree_.setLength(0);
|
||||
dependencyTree_.append(compile_tree);
|
||||
dependencyTree_.append(System.lineSeparator());
|
||||
dependencyTree_.append(runtime_tree);
|
||||
dependencyTree_.append(System.lineSeparator());
|
||||
|
||||
System.out.println(compile_tree);
|
||||
System.out.println(runtime_tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, generates the tree for the compile scope.
|
||||
*
|
||||
* @since 1.5.21
|
||||
*/
|
||||
protected String executeGenerateCompileDependencies() {
|
||||
var compile_tree = dependencies().scope(compile).generateTransitiveDependencyTree(artifactRetriever(), repositories(), compile);
|
||||
if (compile_tree.isEmpty()) {
|
||||
compile_tree = "no dependencies" + System.lineSeparator();
|
||||
}
|
||||
return "compile:" + System.lineSeparator() + compile_tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, generates the tree for the runtime scope.
|
||||
*
|
||||
* @since 1.5.21
|
||||
*/
|
||||
protected String executeGenerateRuntimeDependencies() {
|
||||
var runtime_tree = dependencies().scope(runtime).generateTransitiveDependencyTree(artifactRetriever(), repositories(), compile, runtime);
|
||||
if (runtime_tree.isEmpty()) {
|
||||
runtime_tree = "no dependencies" + System.lineSeparator();
|
||||
}
|
||||
return "runtime:" + System.lineSeparator() + runtime_tree;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures a dependency tree operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the operation from
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public DependencyTreeOperation fromProject(BaseProject project) {
|
||||
return artifactRetriever(project.artifactRetriever())
|
||||
.repositories(project.repositories())
|
||||
.dependencies(project.dependencies());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides repositories to resolve the dependencies against.
|
||||
*
|
||||
* @param repositories repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public DependencyTreeOperation repositories(Repository... repositories) {
|
||||
repositories_.addAll(List.of(repositories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of repositories to resolve the dependencies against.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param repositories a list of repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public DependencyTreeOperation repositories(List<Repository> repositories) {
|
||||
repositories_.addAll(repositories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides scoped dependencies to generate a tree for.
|
||||
*
|
||||
* @param dependencies the dependencies that will be resolved for tree generation
|
||||
* @return this operation instance
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public DependencyTreeOperation dependencies(DependencyScopes dependencies) {
|
||||
dependencies_.include(dependencies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the artifact retriever to use.
|
||||
*
|
||||
* @param retriever the artifact retriever
|
||||
* @return this operation instance
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public DependencyTreeOperation artifactRetriever(ArtifactRetriever retriever) {
|
||||
retriever_ = retriever;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the repositories in which the dependencies will be resolved.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the repositories used for dependency resolution
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public List<Repository> repositories() {
|
||||
return repositories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the scoped dependencies that will be used for tree generation.
|
||||
* <p>
|
||||
* This is a modifiable structure that can be retrieved and changed.
|
||||
*
|
||||
* @return the scoped dependencies
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public DependencyScopes dependencies() {
|
||||
return dependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact retriever that is used.
|
||||
*
|
||||
* @return the artifact retriever
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public ArtifactRetriever artifactRetriever() {
|
||||
if (retriever_ == null) {
|
||||
return ArtifactRetriever.instance();
|
||||
}
|
||||
return retriever_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last generated dependency tree.
|
||||
*
|
||||
* @return the last generated dependency tree
|
||||
* @since 1.5.21
|
||||
*/
|
||||
public String dependencyTree() {
|
||||
return dependencyTree_.toString();
|
||||
}
|
||||
}
|
355
src/main/java/rife/bld/operations/DownloadOperation.java
Normal file
355
src/main/java/rife/bld/operations/DownloadOperation.java
Normal file
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.dependencies.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static rife.bld.dependencies.Dependency.CLASSIFIER_JAVADOC;
|
||||
import static rife.bld.dependencies.Dependency.CLASSIFIER_SOURCES;
|
||||
|
||||
/**
|
||||
* Transitively downloads all the artifacts for dependencies into
|
||||
* directories that are separated out by scope.
|
||||
* <p>
|
||||
* If a directory is not provided, no download will occur for that
|
||||
* dependency scope.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class DownloadOperation extends AbstractOperation<DownloadOperation> {
|
||||
private ArtifactRetriever retriever_ = null;
|
||||
private final List<Repository> repositories_ = new ArrayList<>();
|
||||
private final DependencyScopes dependencies_ = new DependencyScopes();
|
||||
private File libCompileDirectory_;
|
||||
private File libRuntimeDirectory_;
|
||||
private File libStandaloneDirectory_;
|
||||
private File libTestDirectory_;
|
||||
private boolean downloadSources_ = false;
|
||||
private boolean downloadJavadoc_ = false;
|
||||
|
||||
/**
|
||||
* Performs the download operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute() {
|
||||
executeDownloadCompileDependencies();
|
||||
executeDownloadRuntimeDependencies();
|
||||
executeDownloadStandaloneDependencies();
|
||||
executeDownloadTestDependencies();
|
||||
if (!silent()) {
|
||||
System.out.println("Downloading finished successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, download the {@code compile} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeDownloadCompileDependencies() {
|
||||
executeDownloadDependencies(libCompileDirectory(), dependencies().resolveCompileDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, download the {@code runtime} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeDownloadRuntimeDependencies() {
|
||||
executeDownloadDependencies(libRuntimeDirectory(), dependencies().resolveRuntimeDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, download the {@code standalone} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeDownloadStandaloneDependencies() {
|
||||
executeDownloadDependencies(libStandaloneDirectory(), dependencies().resolveStandaloneDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, download the {@code test} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeDownloadTestDependencies() {
|
||||
executeDownloadDependencies(libTestDirectory(), dependencies().resolveTestDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, download the artifacts for a particular dependency scope.
|
||||
*
|
||||
* @param destinationDirectory the directory in which the artifacts should be downloaded
|
||||
* @param dependencies the dependencies to download
|
||||
* @since 1.6
|
||||
*/
|
||||
protected void executeDownloadDependencies(File destinationDirectory, DependencySet dependencies) {
|
||||
if (destinationDirectory == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
destinationDirectory.mkdirs();
|
||||
|
||||
var additional_classifiers = new String[0];
|
||||
|
||||
if (downloadSources_ || downloadJavadoc_) {
|
||||
var classifiers = new ArrayList<String>();
|
||||
if (downloadSources_) classifiers.add(CLASSIFIER_SOURCES);
|
||||
if (downloadJavadoc_) classifiers.add(CLASSIFIER_JAVADOC);
|
||||
|
||||
additional_classifiers = classifiers.toArray(new String[0]);
|
||||
}
|
||||
|
||||
dependencies.transferIntoDirectory(artifactRetriever(), repositories(), destinationDirectory, additional_classifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a compile operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the compile operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation fromProject(BaseProject project) {
|
||||
return artifactRetriever(project.artifactRetriever())
|
||||
.repositories(project.repositories())
|
||||
.dependencies(project.dependencies())
|
||||
.libCompileDirectory(project.libCompileDirectory())
|
||||
.libRuntimeDirectory(project.libRuntimeDirectory())
|
||||
.libStandaloneDirectory(project.libStandaloneDirectory())
|
||||
.libTestDirectory(project.libTestDirectory())
|
||||
.downloadSources(project.downloadSources())
|
||||
.downloadJavadoc(project.downloadJavadoc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides repositories to resolve the dependencies against.
|
||||
*
|
||||
* @param repositories repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public DownloadOperation repositories(Repository... repositories) {
|
||||
repositories_.addAll(List.of(repositories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of repositories to resolve the dependencies against.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param repositories a list of repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation repositories(List<Repository> repositories) {
|
||||
repositories_.addAll(repositories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides scoped dependencies for artifact download.
|
||||
*
|
||||
* @param dependencies the dependencies that will be resolved for artifact download
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation dependencies(DependencyScopes dependencies) {
|
||||
dependencies_.include(dependencies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code compile} scope download directory.
|
||||
*
|
||||
* @param directory the directory to download the {@code compile} scope artifacts into
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation libCompileDirectory(File directory) {
|
||||
libCompileDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code runtime} scope download directory.
|
||||
*
|
||||
* @param directory the directory to download the {@code runtime} scope artifacts into
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation libRuntimeDirectory(File directory) {
|
||||
libRuntimeDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code standalone} scope download directory.
|
||||
*
|
||||
* @param directory the directory to download the {@code standalone} scope artifacts into
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation libStandaloneDirectory(File directory) {
|
||||
libStandaloneDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code test} scope download directory.
|
||||
*
|
||||
* @param directory the directory to download the {@code test} scope artifacts into
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public DownloadOperation libTestDirectory(File directory) {
|
||||
libTestDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the sources classifier should also be downloaded.
|
||||
*
|
||||
* @param flag {@code true} if the sources classifier should be downloaded; or
|
||||
* {@code false} otherwise
|
||||
* @return this operation instance
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public DownloadOperation downloadSources(boolean flag) {
|
||||
downloadSources_ = flag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the javadoc classifier should also be downloaded.
|
||||
*
|
||||
* @param flag {@code true} if the javadoc classifier should be downloaded; or
|
||||
* {@code false} otherwise
|
||||
* @return this operation instance
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public DownloadOperation downloadJavadoc(boolean flag) {
|
||||
downloadJavadoc_ = flag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the artifact retriever to use.
|
||||
*
|
||||
* @param retriever the artifact retriever
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public DownloadOperation artifactRetriever(ArtifactRetriever retriever) {
|
||||
retriever_ = retriever;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the repositories in which the dependencies will be resolved.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the repositories used for dependency resolution
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Repository> repositories() {
|
||||
return repositories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the scoped dependencies that will be used for artifact download.
|
||||
* <p>
|
||||
* This is a modifiable structure that can be retrieved and changed.
|
||||
*
|
||||
* @return the scoped dependencies
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencyScopes dependencies() {
|
||||
return dependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code compile} scope download directory.
|
||||
*
|
||||
* @return the {@code compile} scope download directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libCompileDirectory() {
|
||||
return libCompileDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code runtime} scope download directory.
|
||||
*
|
||||
* @return the {@code runtime} scope download directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libRuntimeDirectory() {
|
||||
return libRuntimeDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code standalone} scope download directory.
|
||||
*
|
||||
* @return the {@code standalone} scope download directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libStandaloneDirectory() {
|
||||
return libStandaloneDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code test} scope download directory.
|
||||
*
|
||||
* @return the {@code test} scope download directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libTestDirectory() {
|
||||
return libTestDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether the sources classifier should also be downloaded.
|
||||
*
|
||||
* @return {@code true} if the sources classifier should be downloaded; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public boolean downloadSources() {
|
||||
return downloadSources_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether the javadoc classifier should also be downloaded.
|
||||
*
|
||||
* @return {@code true} if the sources classifier should be downloaded; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public boolean downloadJavadoc() {
|
||||
return downloadJavadoc_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact retriever that is used.
|
||||
*
|
||||
* @return the artifact retriever
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public ArtifactRetriever artifactRetriever() {
|
||||
if (retriever_ == null) {
|
||||
return ArtifactRetriever.instance();
|
||||
}
|
||||
return retriever_;
|
||||
}
|
||||
}
|
105
src/main/java/rife/bld/operations/HelpOperation.java
Normal file
105
src/main/java/rife/bld/operations/HelpOperation.java
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BldVersion;
|
||||
import rife.bld.BuildExecutor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Comparator.comparingInt;
|
||||
|
||||
/**
|
||||
* Provides help about the build system commands.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class HelpOperation {
|
||||
private final BuildExecutor executor_;
|
||||
private final List<String> arguments_;
|
||||
|
||||
/**
|
||||
* Creates a new help operation.
|
||||
*
|
||||
* @param executor the build executor that commands are running into
|
||||
* @param arguments the arguments that were provided to the build executor
|
||||
* @since 1.5
|
||||
*/
|
||||
public HelpOperation(BuildExecutor executor, List<String> arguments) {
|
||||
executor_ = executor;
|
||||
arguments_ = arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the help operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute() {
|
||||
var topic = "";
|
||||
if (!arguments_.isEmpty()) {
|
||||
topic = arguments_.remove(0);
|
||||
}
|
||||
|
||||
System.err.println("Welcome to bld " + BldVersion.getVersion() + ".");
|
||||
System.err.println();
|
||||
|
||||
boolean print_full_help = true;
|
||||
try {
|
||||
var commands = executor_.buildCommands();
|
||||
if (commands.containsKey(topic)) {
|
||||
var command = commands.get(topic);
|
||||
var help = command.getHelp().getDescription(topic);
|
||||
if (!help.isEmpty()) {
|
||||
System.err.println(help);
|
||||
print_full_help = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (print_full_help) {
|
||||
executePrintOverviewHelp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, prints the help overview
|
||||
* with summaries of all build commands.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void executePrintOverviewHelp() {
|
||||
var commands = executor_.buildCommands();
|
||||
|
||||
System.err.println("""
|
||||
The RIFE2 CLI provides its features through a series of commands that
|
||||
perform specific tasks. The help command provides more information about
|
||||
the other commands.
|
||||
|
||||
Usage : help [command]
|
||||
|
||||
The following commands are supported.
|
||||
""");
|
||||
|
||||
var command_length = commands.keySet().stream().max(comparingInt(String::length)).get().length() + 2;
|
||||
for (var command : commands.entrySet()) {
|
||||
System.err.print(" ");
|
||||
System.err.printf("%-" + command_length + "s", command.getKey());
|
||||
var build_help = command.getValue().getHelp();
|
||||
System.err.print(build_help.getSummary());
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
System.err.println("""
|
||||
|
||||
-?, -h, --help Shows this help message
|
||||
-D<name>=<value> Set a JVM system property
|
||||
-s, --stacktrace Print out the stacktrace for exceptions
|
||||
""");
|
||||
}
|
||||
}
|
71
src/main/java/rife/bld/operations/JUnitOperation.java
Normal file
71
src/main/java/rife/bld/operations/JUnitOperation.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
|
||||
/**
|
||||
* Tests a Java application with JUnit.
|
||||
* <p>
|
||||
* If no JUnit options are specified, the {@link JUnitOptions#defaultOptions()}
|
||||
* are used. To tweak the default options, manually add them with this method
|
||||
* and use the other desired options.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public class JUnitOperation extends TestOperation<JUnitOperation, JUnitOptions> {
|
||||
public static final String DEFAULT_TEST_TOOL_JUNIT5 = "org.junit.platform.console.ConsoleLauncher";
|
||||
|
||||
@Override
|
||||
protected JUnitOptions createTestToolOptions() {
|
||||
return new JUnitOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JUnitOperation fromProject(BaseProject project) {
|
||||
super.fromProject(project);
|
||||
|
||||
// use the default JUnit 5 console launcher as the test tool
|
||||
if (mainClass() == null) {
|
||||
mainClass(DEFAULT_TEST_TOOL_JUNIT5);
|
||||
}
|
||||
|
||||
// add the default JUnit options if none were specified
|
||||
if (testToolOptions().isEmpty() && mainClass().equals(DEFAULT_TEST_TOOL_JUNIT5)) {
|
||||
testToolOptions().defaultOptions();
|
||||
}
|
||||
|
||||
// evaluate the next arguments and pass them to the JUnit console launcher
|
||||
// if they meet the required conditions
|
||||
var arguments = project.arguments();
|
||||
while (!arguments.isEmpty()) {
|
||||
var argument = arguments.get(0);
|
||||
if (argument.startsWith("-")) {
|
||||
arguments.remove(0);
|
||||
if (argument.equals("--junit-help")) {
|
||||
testToolOptions().add("--help");
|
||||
} else if (argument.equals("--junit-clear")) {
|
||||
testToolOptions().clear();
|
||||
} else {
|
||||
testToolOptions().add(argument);
|
||||
// check whether this option could have the need for an additional argument
|
||||
if (argument.length() == 2 && !arguments.isEmpty()) {
|
||||
switch (argument.charAt(1)) {
|
||||
// these are options in the form of -x where the next argument is separated
|
||||
// by a space and should also be passed on to the JUnit console launcher
|
||||
case 'f', 'd', 'o', 'p', 'c', 'm', 'r', 'i', 'n', 'N', 't', 'T', 'e', 'E' ->
|
||||
testToolOptions().add(arguments.remove(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
508
src/main/java/rife/bld/operations/JUnitOptions.java
Normal file
508
src/main/java/rife/bld/operations/JUnitOptions.java
Normal file
|
@ -0,0 +1,508 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Options for JUnit 5.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public class JUnitOptions extends ArrayList<String> {
|
||||
public enum Details {
|
||||
NONE, SUMMARY, FLAT, TREE, VERBOSE
|
||||
}
|
||||
|
||||
public enum Theme {
|
||||
ASCII, UNICODE
|
||||
}
|
||||
|
||||
private void removeMutuallyExclusiveOptions(String element) {
|
||||
if (element.startsWith("--scan-classpath")) {
|
||||
removeIf(s -> s.startsWith("--select-"));
|
||||
} else if (element.startsWith("--select-")) {
|
||||
removeIf(s -> s.startsWith("--scan-classpath"));
|
||||
}
|
||||
switch (element) {
|
||||
// these are shorthand options for the longer --select-* options
|
||||
case "-u", "-f", "-d", "-o", "-p", "-c", "-m", "-r", "-i" ->
|
||||
removeIf(s -> s.startsWith("--scan-classpath"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends String> c) {
|
||||
var result = super.addAll(c);
|
||||
if (result) {
|
||||
for (var element : c) {
|
||||
removeMutuallyExclusiveOptions(element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends String> c) {
|
||||
var result = super.addAll(index, c);
|
||||
if (result) {
|
||||
for (var element : c) {
|
||||
removeMutuallyExclusiveOptions(element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String set(int index, String element) {
|
||||
var result = super.set(index, element);
|
||||
removeMutuallyExclusiveOptions(element);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(String s) {
|
||||
var result = super.add(s);
|
||||
removeMutuallyExclusiveOptions(s);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, String element) {
|
||||
super.add(index, element);
|
||||
removeMutuallyExclusiveOptions(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the default options that RIFE2 uses when no
|
||||
* options have been explicitly set.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions defaultOptions() {
|
||||
config("junit.jupiter.testclass.order.default", "org.junit.jupiter.api.ClassOrderer$ClassName");
|
||||
details(Details.VERBOSE);
|
||||
scanClassPath();
|
||||
disableBanner();
|
||||
disableAnsiColors();
|
||||
excludeEngine("junit-platform-suite");
|
||||
excludeEngine("junit-vintage");
|
||||
failIfNoTests();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan all directories on the classpath.
|
||||
* <p>
|
||||
* Only directories on the system classpath as well as additional classpath
|
||||
* entries supplied via -cp (directories and JAR files) are scanned.
|
||||
* <p>
|
||||
* Removes all the {@code select} options since they are mutually exclusive.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions scanClassPath() {
|
||||
add("--scan-classpath");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan an explicit classpath root.
|
||||
* <p>
|
||||
* Explicit classpath roots that are not on the classpath will be silently
|
||||
* ignored.
|
||||
* <p>
|
||||
* Removes all the {@code select} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions scanClassPath(String path) {
|
||||
add("--scan-classpath=" + path);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL: Scan all resolved modules for test discovery
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions scanModules() {
|
||||
add("--scan-modules");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a URI for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectUri(String uri) {
|
||||
add("--select-uri=" + uri);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a file for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectFile(File file) {
|
||||
add("--select-file=" + file);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a directory for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectDirectory(File file) {
|
||||
add("--select-directory=" + file);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL: Select single module for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectModule(String name) {
|
||||
add("--select-module=" + name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a package for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectPackage(String name) {
|
||||
add("--select-package=" + name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a class for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectClass(String name) {
|
||||
add("--select-class=" + name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a method for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectMethod(String name) {
|
||||
add("--select-method=" + name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a classpath resource for test discovery.
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectResource(String resource) {
|
||||
add("--select-resource=" + resource);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select iterations for test discovery of format {@code TYPE:VALUE[INDEX(..INDEX)?(,INDEX(..INDEX)?)*]}
|
||||
* (e.g. method:com.acme.Foo#m()[1..2]).
|
||||
* <p>
|
||||
* Removes all the {@code scanClasspath} options since they are mutually exclusive.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions selectIteration(String iteration) {
|
||||
add("--select-iteration=" + iteration);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a regular expression to include only classes whose fully
|
||||
* qualified names match. To avoid loading classes unnecessarily,
|
||||
* the default pattern only includes class names that begin with
|
||||
* "Test" or end with "Test" or "Tests". When this option is
|
||||
* repeated, all patterns will be combined using OR semantics.
|
||||
* Default: ^(Test.*|.+[.$]Test.*|.*Tests?)$
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions includeClassname(String regexPattern) {
|
||||
add("--include-classname=" + regexPattern);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a regular expression to exclude those classes whose fully
|
||||
* qualified names match. When this option is repeated, all
|
||||
* patterns will be combined using OR semantics.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions excludeClassname(String regexPattern) {
|
||||
add("--exclude-classname=" + regexPattern);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a package to be included in the test run. This option can
|
||||
* be repeated.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions includePackage(String name) {
|
||||
add("--include-package=" + name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a package to be excluded from the test run. This option
|
||||
* can be repeated.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions excludePackage(String name) {
|
||||
add("--exclude-package=" + name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a tag or tag expression to include only tests whose tags
|
||||
* match. When this option is repeated, all patterns will be
|
||||
* combined using OR semantics.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions includeTag(String tag) {
|
||||
add("--include-tag=" + tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a tag or tag expression to exclude those tests whose tags
|
||||
* match. When this option is repeated, all patterns will be
|
||||
* combined using OR semantics.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions excludeTag(String tag) {
|
||||
add("--exclude-tag=" + tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the ID of an engine to be included in the test run.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions includeEngine(String id) {
|
||||
add("--include-engine=" + id);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the ID of an engine to be excluded in the test run.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions excludeEngine(String id) {
|
||||
add("--exclude-engine=" + id);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a configuration parameter for test discovery and execution.
|
||||
* <p>
|
||||
* This option can be repeated.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions config(String key, String value) {
|
||||
add("--config=" + key + "=" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail and return exit status code 2 if no tests are found.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions failIfNoTests() {
|
||||
add("--fail-if-no-tests");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable report output into a specified local directory (will be
|
||||
* created if it does not exist).
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions reportsDir(File dir) {
|
||||
add("--reports-dir=" + dir);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable ANSI colors in output (not supported by all terminals).
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions disableAnsiColors() {
|
||||
add("--disable-ansi-colors");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a path to a properties file to customize ANSI style of
|
||||
* output (not supported by all terminals).
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions colorPalette(File file) {
|
||||
add("--color-palette=" + file);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Style test output using only text attributes, no color (not
|
||||
* supported by all terminals).
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions singleColor() {
|
||||
add("--single-color");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable print out of the welcome message.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions disableBanner() {
|
||||
add("--disable-banner");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an output details mode for when tests are executed.
|
||||
* <p>
|
||||
* If 'none' is selected, then only the summary and test failures are shown.
|
||||
* <p>
|
||||
* Default: {@link Details#TREE}.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions details(Details details) {
|
||||
add("--details=" + details.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an output details tree theme for when tests are executed.
|
||||
* <p>
|
||||
* Default is detected based on default character encoding.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public JUnitOptions detailsTheme(Theme theme) {
|
||||
add("--details-theme=" + theme.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
}
|
418
src/main/java/rife/bld/operations/JarOperation.java
Normal file
418
src/main/java/rife/bld/operations/JarOperation.java
Normal file
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.NamedFile;
|
||||
import rife.bld.Project;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Creates a jar archive of the provided sources and directories.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class JarOperation extends AbstractOperation<JarOperation> {
|
||||
private final Map<Attributes.Name, Object> manifestAttributes_ = new HashMap<>();
|
||||
private final List<File> sourceDirectories_ = new ArrayList<>();
|
||||
private final List<NamedFile> sourceFiles_ = new ArrayList<>();
|
||||
private File destinationDirectory_;
|
||||
private String destinationFileName_;
|
||||
private final List<Pattern> included_ = new ArrayList<>();
|
||||
private final List<Pattern> excluded_ = new ArrayList<>();
|
||||
|
||||
private final byte[] buffer_ = new byte[1024];
|
||||
|
||||
/**
|
||||
* Performs the jar operation.
|
||||
*
|
||||
* @throws IOException when an exception occurred during the jar creation process
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException {
|
||||
executeCreateDestinationDirectory();
|
||||
executeCreateJarArchive();
|
||||
|
||||
if (!silent()) {
|
||||
System.out.println("The jar archive was created at '" + destinationFile() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the destination directory.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCreateDestinationDirectory() {
|
||||
destinationDirectory().mkdirs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the jar archive.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCreateJarArchive()
|
||||
throws IOException {
|
||||
var out_file = new File(destinationDirectory(), destinationFileName());
|
||||
try (var jar = new JarOutputStream(new FileOutputStream(out_file), executeCreateManifest())) {
|
||||
for (var source_dir : sourceDirectories()) {
|
||||
for (var file_name : FileUtils.getFileList(source_dir)) {
|
||||
var file = new File(source_dir, file_name);
|
||||
if (StringUtils.filter(file.getAbsolutePath(), included(), excluded(), false)) {
|
||||
executeAddFileToJar(jar, new NamedFile(file_name, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var source_file : sourceFiles()) {
|
||||
if (StringUtils.filter(source_file.file().getAbsolutePath(), included(), excluded(), false)) {
|
||||
executeAddFileToJar(jar, source_file);
|
||||
}
|
||||
}
|
||||
jar.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the manifest for the jar archive.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected Manifest executeCreateManifest() {
|
||||
var manifest = new Manifest();
|
||||
var attributes = manifest.getMainAttributes();
|
||||
for (var entry : manifestAttributes().entrySet()) {
|
||||
// don't use putAll since Attributes does an instanceof check
|
||||
// on the map being passed in, causing it to fail if it's not
|
||||
// and instance of Attributes
|
||||
attributes.put(entry.getKey(), entry.getValue());
|
||||
// ^^^ READ above, don't use putAll
|
||||
}
|
||||
return manifest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, add a single file to the jar archive.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeAddFileToJar(JarOutputStream jar, NamedFile file)
|
||||
throws IOException {
|
||||
var entry = new JarEntry(file.name().replace('\\', '/'));
|
||||
entry.setTime(file.file().lastModified());
|
||||
jar.putNextEntry(entry);
|
||||
|
||||
try (var in = new BufferedInputStream(new FileInputStream(file.file()))) {
|
||||
int count;
|
||||
while ((count = in.read(buffer_)) != -1) {
|
||||
jar.write(buffer_, 0, count);
|
||||
}
|
||||
jar.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a jar operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the jar operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation fromProject(BaseProject project) {
|
||||
return manifestAttributes(Map.of(Attributes.Name.MANIFEST_VERSION, "1.0"))
|
||||
.sourceDirectories(project.buildMainDirectory(), project.srcMainResourcesDirectory())
|
||||
.destinationDirectory(project.buildDistDirectory())
|
||||
.destinationFileName(project.jarFileName())
|
||||
.excluded(Pattern.compile("(?:(?:^.*[/\\\\])|^)\\.DS_Store$"), Pattern.compile("^\\Q" + project.srcMainResourcesTemplatesDirectory().getAbsolutePath() + "\\E.*"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an attribute to put in the jar manifest.
|
||||
*
|
||||
* @param name the attribute name to put in the manifest
|
||||
* @param value the attribute value to put in the manifest
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation manifestAttribute(Attributes.Name name, Object value) {
|
||||
manifestAttributes_.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a map of attributes to put in the jar manifest.
|
||||
* <p>
|
||||
* A copy will be created to allow this map to be independently modifiable.
|
||||
*
|
||||
* @param attributes the attributes to put in the manifest
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation manifestAttributes(Map<Attributes.Name, Object> attributes) {
|
||||
manifestAttributes_.putAll(attributes);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides source directories that will be used for the jar archive creation.
|
||||
*
|
||||
* @param directories source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation sourceDirectories(File... directories) {
|
||||
sourceDirectories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of source directories that will be used for the jar archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation sourceDirectories(List<File> directories) {
|
||||
sourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides source files that will be used for the jar archive creation.
|
||||
*
|
||||
* @param files source files
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation sourceFiles(NamedFile... files) {
|
||||
sourceFiles_.addAll(List.of(files));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of source files that will be used for the jar archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param files a list of source files
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation sourceFiles(List<NamedFile> files) {
|
||||
sourceFiles_.addAll(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination directory in which the jar archive will be created.
|
||||
*
|
||||
* @param directory the jar destination directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation destinationDirectory(File directory) {
|
||||
destinationDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination file name that will be used for the jar archive creation.
|
||||
*
|
||||
* @param name the jar archive destination file name
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation destinationFileName(String name) {
|
||||
destinationFileName_ = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides regex patterns that will be found to determine which files
|
||||
* will be included in the javadoc generation.
|
||||
*
|
||||
* @param included inclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation included(String... included) {
|
||||
included_.addAll(Arrays.stream(included).map(Pattern::compile).toList());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides patterns that will be found to determine which files
|
||||
* will be included in the jar archive.
|
||||
*
|
||||
* @param included inclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation included(Pattern... included) {
|
||||
included_.addAll(List.of(included));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of patterns that will be found to determine which files
|
||||
* will be included in the jar archive.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param included a list of inclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation included(List<Pattern> included) {
|
||||
included_.addAll(included);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides regex patterns that will be found to determine which files
|
||||
* will be excluded from the javadoc generation.
|
||||
*
|
||||
* @param excluded exclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation excluded(String... excluded) {
|
||||
excluded_.addAll(Arrays.stream(excluded).map(Pattern::compile).toList());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides patterns that will be found to determine which files
|
||||
* will be excluded from the jar archive.
|
||||
*
|
||||
* @param excluded exclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JarOperation excluded(Pattern... excluded) {
|
||||
excluded_.addAll(List.of(excluded));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of patterns that will be found to determine which files
|
||||
* will be excluded from the jar archive.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param excluded a list of exclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public JarOperation excluded(List<Pattern> excluded) {
|
||||
excluded_.addAll(excluded);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the map of attributes that will be put in the jar manifest.
|
||||
* <p>
|
||||
* This is a modifiable map that can be retrieved and changed.
|
||||
*
|
||||
* @return the manifest's attributes map
|
||||
* @since 1.5
|
||||
*/
|
||||
public Map<Attributes.Name, Object> manifestAttributes() {
|
||||
return manifestAttributes_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of source directories that will be used for the
|
||||
* jar archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the jar archive's source directories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> sourceDirectories() {
|
||||
return sourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of source files that will be used for the
|
||||
* jar archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the jar archive's source files
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<NamedFile> sourceFiles() {
|
||||
return sourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination directory in which the jar archive will
|
||||
* be created.
|
||||
*
|
||||
* @return the jar archive's destination directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File destinationDirectory() {
|
||||
return destinationDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination file name that will be used for the jar
|
||||
* archive creation.
|
||||
*
|
||||
* @return the jar archive's destination file name
|
||||
* @since 1.5
|
||||
*/
|
||||
public String destinationFileName() {
|
||||
return destinationFileName_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination file where the jar archive will be created.
|
||||
*
|
||||
* @return the jar archive's destination file
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public File destinationFile() {
|
||||
return new File(destinationDirectory(), destinationFileName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of patterns that will be evaluated to determine which files
|
||||
* will be included in the jar archive.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the jar's archive's inclusion patterns
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Pattern> included() {
|
||||
return included_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of patterns that will be evaluated to determine which files
|
||||
* will be excluded the jar archive.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the jar's archive's exclusion patterns
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Pattern> excluded() {
|
||||
return excluded_;
|
||||
}
|
||||
}
|
308
src/main/java/rife/bld/operations/JavaOptions.java
Normal file
308
src/main/java/rife/bld/operations/JavaOptions.java
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Options for the standard java tool.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public class JavaOptions extends ArrayList<String> {
|
||||
public enum Verbose {
|
||||
CLASS, MODULE, GC, JNI
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the "truffle" VM.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions truffle() {
|
||||
add("-truffle");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of directories, each directory is a directory of modules.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions modulePath(File... modules) {
|
||||
return modulePath(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of directories, each directory is a directory of modules.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions modulePath(List<File> modules) {
|
||||
add("--module-path");
|
||||
add(StringUtils.join(modules, ":"));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of directories, each directory is a directory of modules
|
||||
* that replace upgradeable modules in the runtime image
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions upgradeModulePath(File... modulePath) {
|
||||
return upgradeModulePath(Arrays.asList(modulePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* List of directories, each directory is a directory of modules
|
||||
* that replace upgradeable modules in the runtime image
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions upgradeModulePath(List<File> modulePath) {
|
||||
add("--upgrade-module-path");
|
||||
add(StringUtils.join(modulePath, ":"));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Root modules to resolve in addition to the initial module.
|
||||
* The module name can also be ALL-DEFAULT, ALL-SYSTEM,
|
||||
* ALL-MODULE-PATH.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions addModules(String... modules) {
|
||||
return addModules(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Root modules to resolve in addition to the initial module.
|
||||
* The module name can also be ALL-DEFAULT, ALL-SYSTEM,
|
||||
* ALL-MODULE-PATH.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions addModules(List<String> modules) {
|
||||
add("--add-modules");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules that are permitted to perform restricted native operations.
|
||||
* The module name can also be ALL-UNNAMED.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions enableNativeAccess(List... modules) {
|
||||
return enableNativeAccess(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules that are permitted to perform restricted native operations.
|
||||
* The module name can also be ALL-UNNAMED.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions enableNativeAccess(List<String> modules) {
|
||||
add("--enable-native-access");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a system property.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions property(String key, String value) {
|
||||
add("-D" + key + "=" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable verbose output for the given subsystem
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions verbose(Verbose verbose) {
|
||||
add("-verbose:" + verbose.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show module resolution output during startup.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions showModuleResolution() {
|
||||
add("--show-module-resolution");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable assertions with specified granularity, either
|
||||
* package name or class name.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions enableAssertions(String name) {
|
||||
add("-enableassertions:"+name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable assertions with specified granularity, either
|
||||
* package name or class name.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions disableAssertions(String name) {
|
||||
add("-disableassertions:"+name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable system assertions.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions enableSystemAssertions() {
|
||||
add("-enablesystemassertions");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable system assertions.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions disableSystemAssertions() {
|
||||
add("-disablesystemassertions");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load native agent library.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions agentLib(String libName) {
|
||||
return agentLib(libName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load native agent library.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions agentLib(String libName, String options) {
|
||||
add("-agentlib:" + libName + (options == null ? "" : ":" + options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load native agent library by full pathname.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions agentPath(File pathName) {
|
||||
return agentPath(pathName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load native agent library by full pathname.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions agentPath(File pathName, String options) {
|
||||
add("-agentpath:" + pathName + (options == null ? "" : ":" + options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Java programming language agent.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions javaAgent(File jarPath) {
|
||||
return javaAgent(jarPath, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Java programming language agent.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions javaAgent(File jarPath, String options) {
|
||||
add("-javaagent:" + jarPath + (options == null ? "" : ":" + options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow classes to depend on preview features of this release
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions enablePreview() {
|
||||
add("--enable-preview");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the initial Java heap size in megabytes.
|
||||
*
|
||||
* @param megabytes the size
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions initialHeapSize(int megabytes) {
|
||||
add("-Xms" + megabytes + "m");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum Java heap size in megabytes.
|
||||
*
|
||||
* @param megabytes the size
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavaOptions maximumHeapSize(int megabytes) {
|
||||
add("-Xmx" + megabytes + "m");
|
||||
return this;
|
||||
}
|
||||
}
|
427
src/main/java/rife/bld/operations/JavacOptions.java
Normal file
427
src/main/java/rife/bld/operations/JavacOptions.java
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.tools.Convert;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Options for the standard javac tool.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public class JavacOptions extends ArrayList<String> {
|
||||
public enum DebuggingInfo {
|
||||
ALL, NONE, LINES, VAR, SOURCE
|
||||
}
|
||||
|
||||
public enum Implicit {
|
||||
NONE, CLASS
|
||||
}
|
||||
|
||||
public enum Processing {
|
||||
NONE, ONLY
|
||||
}
|
||||
|
||||
/**
|
||||
* Option to pass to annotation processors
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions annotationOption(String key, String value) {
|
||||
add("-A" + key + "=" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Root modules to resolve in addition to the initial modules,
|
||||
* or all modules on the module path if a module is
|
||||
* ALL-MODULE-PATH.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions addModules(String... modules) {
|
||||
return addModules(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Root modules to resolve in addition to the initial modules,
|
||||
* or all modules on the module path if a module is
|
||||
* ALL-MODULE-PATH.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions addModules(List<String> modules) {
|
||||
add("--add-modules");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify character encoding used by source files
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions encoding(String name) {
|
||||
add("-encoding");
|
||||
add("name");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output source locations where deprecated APIs are used
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions deprecation() {
|
||||
add("-deprecation");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable preview language features. To be used in conjunction with {@link #release}.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions enablePreview() {
|
||||
add("--enable-preview");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of endorsed standards path
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions endorsedDirs(File... dirs) {
|
||||
return endorsedDirs(Arrays.asList(dirs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of endorsed standards path
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions endorsedDirs(List<File> dirs) {
|
||||
add("-endorseddirs");
|
||||
add(dirs.stream().map(File::getAbsolutePath).collect(Collectors.joining(",")));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of installed extensions
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions extDirs(File... dirs) {
|
||||
return extDirs(Arrays.asList(dirs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of installed extensions
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions extDirs(List<File> dirs) {
|
||||
add("-extdirs");
|
||||
add(dirs.stream().map(File::getAbsolutePath).collect(Collectors.joining(",")));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the Java SE release was set.
|
||||
*
|
||||
* @return {@code true} if the release was set; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public boolean containsRelease() {
|
||||
return contains("-release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile for the specified Java SE release.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions release(int version) {
|
||||
add("--release");
|
||||
add(Convert.toString(version));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate debugging info
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions debuggingInfo(DebuggingInfo option) {
|
||||
if (option.equals(DebuggingInfo.ALL)) {
|
||||
add("-g");
|
||||
} else {
|
||||
add("-g:" + option.name().toLowerCase());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to place generated native header files
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions nativeHeaders(File path) {
|
||||
add("-h");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether or not to generate class files for implicitly referenced files
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions implicit(Implicit option) {
|
||||
add("-implicit:" + option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the universe of observable modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions limitModules(String... modules) {
|
||||
return limitModules(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the universe of observable modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions limitModules(List<String> modules) {
|
||||
add("--limit-modules");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile only the specified module(s), check timestamps
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions module(String... modules) {
|
||||
return module(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile only the specified module(s), check timestamps
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions module(List<String> modules) {
|
||||
add("--module");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find application modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions modulePath(File... paths) {
|
||||
return modulePath(Arrays.asList(paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find application modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.6.2
|
||||
*/
|
||||
public JavacOptions modulePath(List<File> paths) {
|
||||
add("--module-path");
|
||||
add(FileUtils.joinPaths(paths.stream().map(File::getAbsolutePath).toList()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find input source files for multiple modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions moduleSourcePath(File path) {
|
||||
add("--module-source-path");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify version of modules that are being compiled
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions moduleVersion(String version) {
|
||||
add("--module-version");
|
||||
add(version);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate no warnings
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions noWarn() {
|
||||
add("-nowarn");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate metadata for reflection on method parameters
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions parameters() {
|
||||
add("-parameters");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether annotation processing and/or compilation is done.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions process(Processing option) {
|
||||
add("-proc:" + option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Names of the annotation processors to run; bypasses default discovery process
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions processors(String... classnames) {
|
||||
return processors(Arrays.asList(classnames));
|
||||
}
|
||||
|
||||
/**
|
||||
* Names of the annotation processors to run; bypasses default discovery process
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions processors(List<String> classnames) {
|
||||
add("-processor");
|
||||
add(StringUtils.join(classnames, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a module path where to find annotation processors
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions processorModulePath(File path) {
|
||||
add("--processor-module-path");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find annotation processors
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions processorPath(File path) {
|
||||
add("--processor-path");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that API used is available in the specified profile
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions profile(String profile) {
|
||||
add("-profile");
|
||||
add(profile);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of system modules. Option is <jdk> or none.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions system(String option) {
|
||||
add("--system");
|
||||
add(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of upgradeable modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions upgradeModulePath(File path) {
|
||||
add("--upgrade-module-path");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate compilation if warnings occur
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavacOptions warningError() {
|
||||
add("-Werror");
|
||||
return this;
|
||||
}
|
||||
}
|
436
src/main/java/rife/bld/operations/JavadocOperation.java
Normal file
436
src/main/java/rife/bld/operations/JavadocOperation.java
Normal file
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.Project;
|
||||
import rife.bld.operations.exceptions.ExitStatusException;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Generates javadocs for the main project sources.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public class JavadocOperation extends AbstractOperation<JavadocOperation> {
|
||||
private File buildDirectory_;
|
||||
private final List<String> classpath_ = new ArrayList<>();
|
||||
private final List<File> sourceFiles_ = new ArrayList<>();
|
||||
private final List<File> sourceDirectories_ = new ArrayList<>();
|
||||
private final JavadocOptions javadocOptions_ = new JavadocOptions();
|
||||
private final List<Diagnostic<? extends JavaFileObject>> diagnostics_ = new ArrayList<>();
|
||||
private final List<Pattern> included_ = new ArrayList<>();
|
||||
private final List<Pattern> excluded_ = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Performs the compile operation.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException, ExitStatusException {
|
||||
executeCreateBuildDirectories();
|
||||
executeBuildSources();
|
||||
if (!diagnostics().isEmpty()) {
|
||||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
}
|
||||
if (!silent()) {
|
||||
System.out.println("Javadoc generated successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, creates the build directories.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executeCreateBuildDirectories() {
|
||||
if (buildDirectory() != null) {
|
||||
buildDirectory().mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, builds the main sources.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executeBuildSources()
|
||||
throws IOException {
|
||||
var sources = new ArrayList<>(sourceFiles());
|
||||
for (var directory : sourceDirectories()) {
|
||||
sources.addAll(FileUtils.getJavaFileList(directory));
|
||||
}
|
||||
executeBuildSources(
|
||||
classpath(),
|
||||
sources,
|
||||
buildDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, build sources to a destination.
|
||||
*
|
||||
* @param classpath the classpath list used for the compilation
|
||||
* @param sources the source files to compile
|
||||
* @param destination the destination directory
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executeBuildSources(List<String> classpath, List<File> sources, File destination)
|
||||
throws IOException {
|
||||
if (sources.isEmpty() || destination == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var filtered_sources = new ArrayList<File>();
|
||||
for (var source : sources) {
|
||||
if (StringUtils.filter(source.getAbsolutePath(), included(), excluded(), false)) {
|
||||
filtered_sources.add(source);
|
||||
}
|
||||
}
|
||||
|
||||
var documentation = ToolProvider.getSystemDocumentationTool();
|
||||
try (var file_manager = documentation.getStandardFileManager(null, null, null)) {
|
||||
var compilation_units = file_manager.getJavaFileObjectsFromFiles(filtered_sources);
|
||||
var diagnostics = new DiagnosticCollector<JavaFileObject>();
|
||||
var options = new ArrayList<>(List.of("-d", destination.getAbsolutePath(), "-cp", FileUtils.joinPaths(classpath)));
|
||||
options.addAll(javadocOptions());
|
||||
var documentation_task = documentation.getTask(null, file_manager, diagnostics, null, options, compilation_units);
|
||||
if (!documentation_task.call()) {
|
||||
diagnostics_.addAll(diagnostics.getDiagnostics());
|
||||
executeProcessDiagnostics(diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, processes the compilation diagnostics.
|
||||
*
|
||||
* @param diagnostics the diagnostics to process
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executeProcessDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) {
|
||||
for (var diagnostic : diagnostics.getDiagnostics()) {
|
||||
System.err.print(executeFormatDiagnostic(diagnostic));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, format a single diagnostic.
|
||||
*
|
||||
* @param diagnostic the diagnostic to format
|
||||
* @return a string representation of the diagnostic
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected String executeFormatDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||
return diagnostic.toString() + System.lineSeparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a javadoc operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the javadoc operation from
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation fromProject(BaseProject project) {
|
||||
var operation = buildDirectory(project.buildJavadocDirectory())
|
||||
.classpath(project.compileMainClasspath())
|
||||
.classpath(project.buildMainDirectory().getAbsolutePath())
|
||||
.sourceFiles(project.mainSourceFiles());
|
||||
if (project.javaRelease() != null && !javadocOptions().containsRelease()) {
|
||||
javadocOptions().release(project.javaRelease());
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the javadoc build destination directory.
|
||||
*
|
||||
* @param directory the directory to use for the javadoc build destination
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation buildDirectory(File directory) {
|
||||
buildDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides entries for the javadoc classpath.
|
||||
*
|
||||
* @param classpath classpath entries
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation classpath(String... classpath) {
|
||||
classpath_.addAll(Arrays.asList(classpath));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of entries for the javadoc classpath.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param classpath a list of classpath entries
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation classpath(List<String> classpath) {
|
||||
classpath_.addAll(classpath);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides files for which documentation should be generated.
|
||||
*
|
||||
* @param files source files
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation sourceFiles(File... files) {
|
||||
sourceFiles_.addAll(Arrays.asList(files));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of files for which documentation should be generated.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param files a list of source files
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation sourceFiles(List<File> files) {
|
||||
sourceFiles_.addAll(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides directories for which documentation should be generated.
|
||||
*
|
||||
* @param directories source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation sourceDirectories(File... directories) {
|
||||
sourceDirectories_.addAll(Arrays.asList(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of directories for which documentation should be generated.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation sourceDirectories(List<File> directories) {
|
||||
sourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of options to provide to the javadoc tool.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param options the list of javadoc options
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation javadocOptions(List<String> options) {
|
||||
javadocOptions_.addAll(options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides regex patterns that will be found to determine which files
|
||||
* will be included in the javadoc generation.
|
||||
*
|
||||
* @param included inclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation included(String... included) {
|
||||
included_.addAll(Arrays.stream(included).map(Pattern::compile).toList());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides patterns that will be found to determine which files
|
||||
* will be included in the javadoc generation.
|
||||
*
|
||||
* @param included inclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation included(Pattern... included) {
|
||||
included_.addAll(Arrays.asList(included));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of patterns that will be found to determine which files
|
||||
* will be included in the javadoc generation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param included the list of inclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation included(List<Pattern> included) {
|
||||
included_.addAll(included);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides regex patterns that will be found to determine which files
|
||||
* will be excluded from the javadoc generation.
|
||||
*
|
||||
* @param excluded exclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation excluded(String... excluded) {
|
||||
excluded_.addAll(Arrays.stream(excluded).map(Pattern::compile).toList());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides patterns that will be found to determine which files
|
||||
* will be excluded from the javadoc generation.
|
||||
*
|
||||
* @param excluded exclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOperation excluded(Pattern... excluded) {
|
||||
excluded_.addAll(Arrays.asList(excluded));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of patterns that will be found to determine which files
|
||||
* will be excluded from the javadoc generation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param excluded the list of exclusion patterns
|
||||
* @return this operation instance
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOperation excluded(List<Pattern> excluded) {
|
||||
excluded_.addAll(excluded);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the build destination directory.
|
||||
*
|
||||
* @return the javadoc build destination
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public File buildDirectory() {
|
||||
return buildDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of entries for the javadoc classpath.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the javadoc classpath list
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<String> classpath() {
|
||||
return classpath_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of files for which documentation should be generation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of files documentation is generated for
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<File> sourceFiles() {
|
||||
return sourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of directories for which documentation should be generated.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of source directories documentation is generated for
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public List<File> sourceDirectories() {
|
||||
return sourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of options for the javadoc tool.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of javadoc options
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public JavadocOptions javadocOptions() {
|
||||
return javadocOptions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of diagnostics resulting from the compilation.
|
||||
*
|
||||
* @return the list of compilation diagnostics
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<Diagnostic<? extends JavaFileObject>> diagnostics() {
|
||||
return diagnostics_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of patterns that will be evaluated to determine which files
|
||||
* will be included in the javadoc generation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the javadoc inclusion patterns
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<Pattern> included() {
|
||||
return included_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of patterns that will be evaluated to determine which files
|
||||
* will be excluded the javadoc generation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the javadoc exclusion patterns
|
||||
* @since 1.5.10
|
||||
*/
|
||||
public List<Pattern> excluded() {
|
||||
return excluded_;
|
||||
}
|
||||
}
|
959
src/main/java/rife/bld/operations/JavadocOptions.java
Normal file
959
src/main/java/rife/bld/operations/JavadocOptions.java
Normal file
|
@ -0,0 +1,959 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.tools.Convert;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Options for the standard javadoc tool.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public class JavadocOptions extends ArrayList<String> {
|
||||
public enum Level {
|
||||
PUBLIC, PROTECTED, PACKAGE, PRIVATE
|
||||
}
|
||||
|
||||
public enum ModuleContent {
|
||||
API, ALL
|
||||
}
|
||||
|
||||
public enum ModulePackages {
|
||||
EXPORTED, ALL
|
||||
}
|
||||
|
||||
public enum Override {
|
||||
DETAILS, SUMMARY
|
||||
}
|
||||
|
||||
public enum DocLinkOption {
|
||||
ALL("all"), NONE("none"),
|
||||
ACCESSIBILITY("accessibility"), HTML("html"), MISSING("missing"),
|
||||
REFERENCE("reference"), SYNTAX("syntax"),
|
||||
NO_ACCESSIBILITY("-accessibility"), NO_HTML("-html"), NO_MISSING("-missing"),
|
||||
NO_REFERENCE("-reference"), NO_SYNTAX("-syntax");
|
||||
|
||||
private final String option_;
|
||||
|
||||
DocLinkOption(String option) {
|
||||
option_ = option;
|
||||
}
|
||||
|
||||
private String getOption() {
|
||||
return option_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Root modules to resolve in addition to the initial modules,
|
||||
* or all modules on the module path if a module is
|
||||
* ALL-MODULE-PATH.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions addModules(String... modules) {
|
||||
return addModules(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Root modules to resolve in addition to the initial modules,
|
||||
* or all modules on the module path if a module is
|
||||
* ALL-MODULE-PATH.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions addModules(List<String> modules) {
|
||||
add("--add-modules");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute first sentence with BreakIterator.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions breakIterator() {
|
||||
add("-breakiterator");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate output via alternate doclet
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions doclet(String className) {
|
||||
add("-doclet");
|
||||
add("className");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find doclet class files
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions docletPath(String path) {
|
||||
add("-docletpath");
|
||||
add("path");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable preview language features. To be used in conjunction with {@link #release}.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions enablePreview() {
|
||||
add("--enable-preview");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source file encoding name
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions encoding(String name) {
|
||||
add("-encoding");
|
||||
add("name");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a list of packages to exclude
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions excludePackages(String... name) {
|
||||
return excludePackages(Arrays.asList(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a list of packages to exclude
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions excludePackages(List<String> name) {
|
||||
add("-exclude");
|
||||
add(StringUtils.join(name, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of installed extensions
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions extDirs(File... dirs) {
|
||||
return extDirs(Arrays.asList(dirs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Override location of installed extensions
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions extDirs(List<File> dirs) {
|
||||
add("-extdirs");
|
||||
add(dirs.stream().map(File::getAbsolutePath).collect(Collectors.joining(",")));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the universe of observable modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions limitModules(String... modules) {
|
||||
return limitModules(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the universe of observable modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions limitModules(List<String> modules) {
|
||||
add("--limit-modules");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale to be used, e.g. en_US or en_US_WIN
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions locale(String name) {
|
||||
add("-locale");
|
||||
add("name");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the specified module(s)
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.6.3
|
||||
*/
|
||||
public JavadocOptions module(String... modules) {
|
||||
return module(Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
* Document the specified module(s)
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.6.3
|
||||
*/
|
||||
public JavadocOptions module(List<String> modules) {
|
||||
add("--module");
|
||||
add(StringUtils.join(modules, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find application modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.6.3
|
||||
*/
|
||||
public JavadocOptions modulePath(File... paths) {
|
||||
return modulePath(Arrays.asList(paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find application modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.6.3
|
||||
*/
|
||||
public JavadocOptions modulePath(List<File> paths) {
|
||||
add("--module-path");
|
||||
add(FileUtils.joinPaths(paths.stream().map(File::getAbsolutePath).toList()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify where to find input source files for multiple modules
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.6.3
|
||||
*/
|
||||
public JavadocOptions moduleSourcePath(File path) {
|
||||
add("--module-source-path");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show package/protected/public types and members.
|
||||
* <p>
|
||||
* For named modules, show all packages and all module details.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showPackage() {
|
||||
add("-package");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all types and members.
|
||||
* <p>
|
||||
* For named modules, show all packages and all module details.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showPrivate() {
|
||||
add("-private");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show protected/public types and members (default).
|
||||
* <p>
|
||||
* For named modules, show exported packages and the module's API.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showProtected() {
|
||||
add("-protected");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show only public types and members.
|
||||
* <p>
|
||||
* For named modules, show exported packages and the module's API.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showPublic() {
|
||||
add("-public");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not display status messages
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions quiet() {
|
||||
add("-quiet");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the Java SE release was set.
|
||||
*
|
||||
* @return {@code true} if the release was set; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public boolean containsRelease() {
|
||||
return contains("-release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide source compatibility with specified release
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions release(int version) {
|
||||
add("--release");
|
||||
add(Convert.toString(version));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which members (fields, methods, etc.) will be
|
||||
* documented, where value can be one of "public", "protected",
|
||||
* "package" or "private". The default is "protected", which will
|
||||
* show public and protected members, "public" will show only
|
||||
* public members, "package" will show public, protected and
|
||||
* package members and "private" will show all members.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showMembers(Level option) {
|
||||
add("--show-members");
|
||||
add(option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the documentation granularity of module
|
||||
* declarations. Possible values are "api" or "all".
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showModuleContent(ModuleContent option) {
|
||||
add("--show-module-contents");
|
||||
add(option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which modules packages will be documented. Possible
|
||||
* values are "exported" or "all" packages.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showPackages(ModulePackages option) {
|
||||
add("--show-packages");
|
||||
add(option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which types (classes, interfaces, etc.) will be
|
||||
* documented, where value can be one of "public", "protected",
|
||||
* "package" or "private". The default is "protected", which will
|
||||
* show public and protected types, "public" will show only
|
||||
* public types, "package" will show public, protected and
|
||||
* package types and "private" will show all types.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions showTypes(Level option) {
|
||||
add("--show-types");
|
||||
add(option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a script file to the generated documentation
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions addScript(File file) {
|
||||
add("--add-script");
|
||||
add(file.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a stylesheet file to the generated documentation
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions addStylesheet(File file) {
|
||||
add("--add-stylesheet");
|
||||
add(file.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow JavaScript in options and comments
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions allowScriptInComments() {
|
||||
add("--allow-script-in-comments");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include @author paragraphs
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions author() {
|
||||
add("-author");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include bottom text for each page
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions bottom(String html) {
|
||||
add("-bottom");
|
||||
add(html);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include title for the overview page
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions docTitle(String html) {
|
||||
add("-doctitle");
|
||||
add(html);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include footer text for each page
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions footer(String html) {
|
||||
add("-footer");
|
||||
add(html);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include header text for each page
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions header(String html) {
|
||||
add("-header");
|
||||
add(html);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include HTML meta tags with package, class and member info
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions keywords() {
|
||||
add("-keywords");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create links to javadoc output at {@code url}
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions link(String url) {
|
||||
add("-link");
|
||||
add(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link to docs at {@code url1} using package list at {@code url2}
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions linkOffline(String url1, String url2) {
|
||||
add("-linkoffline");
|
||||
add(url1);
|
||||
add(url2);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link to platform documentation URLs declared in properties file at {@code url}
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions linkPlatformProperties(String url) {
|
||||
add("--link-platform-properties");
|
||||
add(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate source in HTML
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions linkSource() {
|
||||
add("-linksource");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* File to change style of the generated documentation
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions stylesheet(File file) {
|
||||
add("--main-stylesheet");
|
||||
add(file.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppress description and tags, generate only declarations
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noComment() {
|
||||
add("-nocomment");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not include @deprecated information
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noDeprecated() {
|
||||
add("-nodeprecated");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not generate deprecated list
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noDeprecatedList() {
|
||||
add("-nodeprecatedlist");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not generate help link
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noHelp() {
|
||||
add("-nohelp");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not generate index
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noIndex() {
|
||||
add("-noindex");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not generate navigation bar
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noNavbar() {
|
||||
add("-nonavbar");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not generate links to the platform documentation
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noPlatformLinks() {
|
||||
add("--no-platform-links");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude the list of qualifiers from the output
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noQualifier(String... qualifiers) {
|
||||
return noQualifier(Arrays.asList(qualifiers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude the list of qualifiers from the output
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions noQualifier(List<String> qualifiers) {
|
||||
add("-noqualifier");
|
||||
add(StringUtils.join(qualifiers, ":"));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not include @since information
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noSince() {
|
||||
add("-nosince");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not include hidden time stamp
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noTimestamp() {
|
||||
add("-notimestamp");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not generate class hierarchy
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions noTree() {
|
||||
add("-notree");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document overridden methods in the detail or summary sections.
|
||||
* The default is 'detail'.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions overrideMethods(Override option) {
|
||||
add("--override-methods");
|
||||
add(option.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read overview documentation from HTML file
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions overview(File htmlFile) {
|
||||
add("-overview");
|
||||
add(htmlFile.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate warning about @serial tag
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions serialWarn() {
|
||||
add("-serialwarn");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document new and deprecated API in the specified releases
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions since(String... release) {
|
||||
return since(Arrays.asList(release));
|
||||
}
|
||||
|
||||
/**
|
||||
* Document new and deprecated API in the specified releases
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions since(List<String> release) {
|
||||
add("-since");
|
||||
add(StringUtils.join(release, ","));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide text to use in the heading of the "New API" page
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions sinceLabel(String text) {
|
||||
add("--since-label");
|
||||
add(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The path for external snippets
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions snippetPath(File path) {
|
||||
add("--snippet-path");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the number of spaces each tab takes up in the source
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions sourceTab(int number) {
|
||||
add("-sourcetab");
|
||||
add(Convert.toString(number));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split index into one file per letter
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions splitIndex() {
|
||||
add("-splitindex");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify single argument custom tags
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions tag(String name, String locations, String header) {
|
||||
add("-tag");
|
||||
add(name + ":" + locations + ":" + header);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The fully qualified name of Taglet to register
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions taglet(String name) {
|
||||
add("-taglet");
|
||||
add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The path to Taglets
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions tagletPath(File path) {
|
||||
add("-tagletpath");
|
||||
add(path.getAbsolutePath());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include top text for each page
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions top(String html) {
|
||||
add("-top");
|
||||
add(html);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create class and package usage pages
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions use() {
|
||||
add("-use");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include @version paragraphs
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions version() {
|
||||
add("-version");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Browser window title for the documentation
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions windowTitle(String text) {
|
||||
add("-windowtitle");
|
||||
add(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable recommended checks for problems in javadoc comments
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions docLint() {
|
||||
add("-Xdoclint");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable specific checks for problems in javadoc
|
||||
* comments.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions docLint(DocLinkOption option) {
|
||||
add("-Xdoclint:" + option.getOption());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable checks in specific packages.
|
||||
* <p>
|
||||
* A package specifier is either a qualified name of a package or a package
|
||||
* name prefix followed by .*, which expands to all sub-packages
|
||||
* of the given package. Prefix the package specifier with - to
|
||||
* disable checks for the specified packages.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.12
|
||||
*/
|
||||
public JavadocOptions docLintPackage(String... packages) {
|
||||
return docLintPackage(Arrays.asList(packages));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable checks in specific packages.
|
||||
* <p>
|
||||
* A package specifier is either a qualified name of a package or a package
|
||||
* name prefix followed by .*, which expands to all sub-packages
|
||||
* of the given package. Prefix the package specifier with - to
|
||||
* disable checks for the specified packages.
|
||||
*
|
||||
* @return this list of options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public JavadocOptions docLintPackage(List<String> packages) {
|
||||
add("-Xdoclint/package:" + (StringUtils.join(packages, ",")));
|
||||
return this;
|
||||
}
|
||||
}
|
189
src/main/java/rife/bld/operations/PrecompileOperation.java
Normal file
189
src/main/java/rife/bld/operations/PrecompileOperation.java
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.Project;
|
||||
import rife.template.TemplateDeployer;
|
||||
import rife.template.TemplateFactory;
|
||||
import rife.tools.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Pre-compiles RIFE2 templates.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class PrecompileOperation extends AbstractOperation<PrecompileOperation> {
|
||||
private final List<TemplateType> templateTypes_ = new ArrayList<>();
|
||||
private final List<File> sourceDirectories_ = new ArrayList<>();
|
||||
private File destinationDirectory_;
|
||||
|
||||
/**
|
||||
* Performs the precompile operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute() {
|
||||
if (templateTypes_.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (destinationDirectory() != null) {
|
||||
destinationDirectory().mkdirs();
|
||||
}
|
||||
executeCreateTemplateDeployer().execute();
|
||||
if (!silent()) {
|
||||
System.out.println("Template pre-compilation finished successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, gets the template factories for
|
||||
* the registered template types.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected List<TemplateFactory> executeGetTemplateFactories() {
|
||||
var template_factories = new ArrayList<TemplateFactory>();
|
||||
for (var type : templateTypes()) {
|
||||
var factory = TemplateFactory.getFactory(type.identifier());
|
||||
if (factory == null) {
|
||||
System.err.println("ERROR: unknown template type '" + type.identifier() + "'/");
|
||||
} else {
|
||||
template_factories.add(factory);
|
||||
}
|
||||
}
|
||||
|
||||
return template_factories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, creates the {@code TemplateDeployer}
|
||||
* that will precompile the templates.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected TemplateDeployer executeCreateTemplateDeployer() {
|
||||
return new TemplateDeployer()
|
||||
.verbose(true)
|
||||
.directoryPaths(FileUtils.combineToAbsolutePaths(sourceDirectories()))
|
||||
.generationPath(destinationDirectory().getAbsolutePath())
|
||||
.templateFactories(executeGetTemplateFactories());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a precompile operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the precompile operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public PrecompileOperation fromProject(BaseProject project) {
|
||||
return sourceDirectories(project.srcMainResourcesTemplatesDirectory())
|
||||
.destinationDirectory(project.buildTemplatesDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides template types that will be pre-compiled.
|
||||
*
|
||||
* @param types pre-compiled template types
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PrecompileOperation templateTypes(TemplateType... types) {
|
||||
templateTypes_.addAll(List.of(types));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of template types that will be pre-compiled.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param types a list of pre-compiled template types
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PrecompileOperation templateTypes(List<TemplateType> types) {
|
||||
templateTypes_.addAll(types);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides source directories that will be used for the template pre-compilation.
|
||||
*
|
||||
* @param sources source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PrecompileOperation sourceDirectories(File... sources) {
|
||||
sourceDirectories_.addAll(List.of(sources));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of source directories that will be used for the template pre-compilation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param sources a list of source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PrecompileOperation sourceDirectories(List<File> sources) {
|
||||
sourceDirectories_.addAll(sources);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination directory in which the pre-compiled templates will be stored.
|
||||
*
|
||||
* @param directory the pre-compilation destination directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PrecompileOperation destinationDirectory(File directory) {
|
||||
destinationDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the template types that will be pre-compiled.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the pre-compiled template types
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<TemplateType> templateTypes() {
|
||||
return templateTypes_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the source directories that will be used for the template pre-compilation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the source directories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> sourceDirectories() {
|
||||
return sourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination directory in which the pre-compiled templates will be stored.
|
||||
*
|
||||
* @return the pre-compilation destination directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File destinationDirectory() {
|
||||
return destinationDirectory_;
|
||||
}
|
||||
}
|
706
src/main/java/rife/bld/operations/PublishOperation.java
Normal file
706
src/main/java/rife/bld/operations/PublishOperation.java
Normal file
|
@ -0,0 +1,706 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.BldVersion;
|
||||
import rife.bld.dependencies.*;
|
||||
import rife.bld.dependencies.exceptions.DependencyException;
|
||||
import rife.bld.operations.exceptions.OperationOptionException;
|
||||
import rife.bld.operations.exceptions.SignException;
|
||||
import rife.bld.operations.exceptions.UploadException;
|
||||
import rife.bld.publish.*;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.net.http.*;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.*;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static rife.bld.publish.MetadataBuilder.SNAPSHOT_TIMESTAMP_FORMATTER;
|
||||
import static rife.tools.HttpUtils.*;
|
||||
import static rife.tools.StringUtils.encodeHexLower;
|
||||
|
||||
/**
|
||||
* Published artifacts to a Maven repository.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public class PublishOperation extends AbstractOperation<PublishOperation> {
|
||||
private ArtifactRetriever retriever_ = null;
|
||||
private final HttpClient client_ = HttpClient.newHttpClient();
|
||||
|
||||
private ZonedDateTime moment_ = null;
|
||||
private final List<Repository> repositories_ = new ArrayList<>();
|
||||
private final DependencyScopes dependencies_ = new DependencyScopes();
|
||||
private PublishInfo info_ = new PublishInfo();
|
||||
private final List<PublishArtifact> artifacts_ = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Performs the publish operation.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public void execute() {
|
||||
if (repositories().isEmpty()) {
|
||||
throw new OperationOptionException("ERROR: the publication repositories should be specified");
|
||||
}
|
||||
|
||||
var moment = moment_;
|
||||
if (moment == null) {
|
||||
moment = ZonedDateTime.now();
|
||||
}
|
||||
|
||||
executeValidateArtifacts();
|
||||
|
||||
var actual_version = info().version();
|
||||
|
||||
for (var repository : repositories()) {
|
||||
System.out.println("Publishing to '" + repository.location() + "'");
|
||||
|
||||
// treat a snapshot version differently
|
||||
if (info().version().isSnapshot()) {
|
||||
actual_version = executePublishSnapshotMetadata(repository, moment);
|
||||
}
|
||||
|
||||
executePublishArtifacts(repository, actual_version);
|
||||
executePublishPom(repository, actual_version);
|
||||
executePublishMetadata(repository, moment);
|
||||
}
|
||||
if (!silent()) {
|
||||
System.out.println("Publishing finished successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, validates the publishing artifacts.
|
||||
*
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executeValidateArtifacts() {
|
||||
artifacts().removeIf(artifact -> {
|
||||
if (!artifact.file().exists()) {
|
||||
System.out.println("WARNING: Missing artifact file '" + artifact.file() + "', skipping.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, publishes snapshot metadata if this
|
||||
* is a snapshot version.
|
||||
*
|
||||
* @param repository the repository to publish to
|
||||
* @param moment the timestamp at which the operation started executing
|
||||
* @return the adapted version number with the snapshot timestamp and build number
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected VersionNumber executePublishSnapshotMetadata(Repository repository, ZonedDateTime moment) {
|
||||
var metadata = new MetadataBuilder();
|
||||
|
||||
VersionNumber actual_version;
|
||||
if (repository.isLocal()) {
|
||||
actual_version = info().version();
|
||||
metadata.snapshotLocal();
|
||||
} else {
|
||||
var snapshot_timestamp = SNAPSHOT_TIMESTAMP_FORMATTER.format(moment.withZoneSameInstant(ZoneId.of("UTC")));
|
||||
|
||||
// determine which build number to use
|
||||
var snapshot_build_number = 1;
|
||||
try {
|
||||
var resolver = new DependencyResolver(artifactRetriever(), List.of(repository), new Dependency(info().groupId(), info().artifactId(), info().version()));
|
||||
var snapshot_meta = resolver.getSnapshotMavenMetadata();
|
||||
snapshot_build_number = snapshot_meta.getSnapshotBuildNumber() + 1;
|
||||
} catch (DependencyException e) {
|
||||
// start the build number from the beginning
|
||||
System.out.println("Unable to retrieve previous snapshot metadata, using first build number.");
|
||||
System.out.println("This is expected for a first publication or for publication to a staging repository.");
|
||||
}
|
||||
|
||||
// adapt the actual version that's use by the artifacts
|
||||
var snapshot_qualifier = snapshot_timestamp + "-" + snapshot_build_number;
|
||||
actual_version = info().version().withQualifier(snapshot_qualifier);
|
||||
|
||||
// record the snapshot information in the metadata
|
||||
metadata.snapshot(moment, snapshot_build_number);
|
||||
}
|
||||
|
||||
// include version information about each artifact in this snapshot
|
||||
for (var artifact : artifacts()) {
|
||||
metadata.snapshotVersions().add(new SnapshotVersion(artifact.classifier(), artifact.type(), actual_version.toString(), moment));
|
||||
}
|
||||
metadata.snapshotVersions().add(new SnapshotVersion(null, "pom", actual_version.toString(), moment));
|
||||
|
||||
// publish snapshot metadata
|
||||
executePublishStringArtifact(
|
||||
repository,
|
||||
metadata
|
||||
.info(info())
|
||||
.updated(moment)
|
||||
.build(),
|
||||
info().version() + "/" + repository.getMetadataName(), true);
|
||||
return actual_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, publishes all the artifacts
|
||||
* in this operation.
|
||||
*
|
||||
* @param repository the repository to publish to
|
||||
* @param actualVersion the version that was potentially adapted if this is a snapshot
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executePublishArtifacts(Repository repository, VersionNumber actualVersion) {
|
||||
// upload artifacts
|
||||
for (var artifact : artifacts()) {
|
||||
var artifact_name = new StringBuilder(info().artifactId()).append("-").append(actualVersion);
|
||||
if (!artifact.classifier().isEmpty()) {
|
||||
artifact_name.append("-").append(artifact.classifier());
|
||||
}
|
||||
var type = artifact.type();
|
||||
if (type == null) {
|
||||
type = "jar";
|
||||
}
|
||||
artifact_name.append(".").append(type);
|
||||
|
||||
executePublishFileArtifact(repository, artifact.file(), info().version() + "/" + artifact_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, publishes the Maven POM.
|
||||
*
|
||||
* @param repository the repository to publish to
|
||||
* @param actualVersion the version that was potentially adapted if this is a snapshot
|
||||
* @since 1.5.10
|
||||
*/
|
||||
protected void executePublishPom(Repository repository, VersionNumber actualVersion) {
|
||||
// generate and upload pom
|
||||
executePublishStringArtifact(
|
||||
repository,
|
||||
new PomBuilder().info(info()).dependencies(dependencies()).build(),
|
||||
info().version() + "/" + info().artifactId() + "-" + actualVersion + ".pom", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, publishes the artifact metadata.
|
||||
*
|
||||
* @param repository the repository to publish to
|
||||
* @param moment the timestamp at which the operation started executing
|
||||
* @since 1.5.8
|
||||
*/
|
||||
protected void executePublishMetadata(Repository repository, ZonedDateTime moment) {
|
||||
var current_versions = new ArrayList<VersionNumber>();
|
||||
var resolver = new DependencyResolver(artifactRetriever(), List.of(repository), new Dependency(info().groupId(), info().artifactId(), info().version()));
|
||||
try {
|
||||
current_versions.addAll(resolver.getMavenMetadata().getVersions());
|
||||
} catch (DependencyException e) {
|
||||
// no existing versions could be found
|
||||
System.out.println("Unable to retrieve previous artifact metadata, proceeding with empty version list.");
|
||||
System.out.println("This is expected for a first publication or for publication to a staging repository.");
|
||||
}
|
||||
|
||||
// upload metadata
|
||||
executePublishStringArtifact(
|
||||
repository,
|
||||
new MetadataBuilder()
|
||||
.info(info())
|
||||
.updated(moment)
|
||||
.otherVersions(current_versions)
|
||||
.build(),
|
||||
repository.getMetadataName(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, publishes a single artifact with
|
||||
* hashes and a potential signature.
|
||||
*
|
||||
* @param repository the repository to publish to
|
||||
* @param content the content of the file that needs to be published
|
||||
* @param path the path of the artifact within the artifact folder
|
||||
* @param sign indicates whether the artifact should be signed
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected void executePublishStringArtifact(Repository repository, String content, String path, boolean sign)
|
||||
throws UploadException {
|
||||
try {
|
||||
if (sign && info().signKey() != null) {
|
||||
var tmp_file = File.createTempFile(path, "gpg");
|
||||
FileUtils.writeString(content, tmp_file);
|
||||
try {
|
||||
executeTransferArtifact(repository, executeSignFile(tmp_file), path + ".asc");
|
||||
} finally {
|
||||
tmp_file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
if (!repository.isLocal()) {
|
||||
executeTransferArtifact(repository, generateHash(content, "MD5"), path + ".md5");
|
||||
executeTransferArtifact(repository, generateHash(content, "SHA-1"), path + ".sha1");
|
||||
executeTransferArtifact(repository, generateHash(content, "SHA-256"), path + ".sha256");
|
||||
executeTransferArtifact(repository, generateHash(content, "SHA-512"), path + ".sha512");
|
||||
}
|
||||
|
||||
executeTransferArtifact(repository, content, path);
|
||||
} catch (NoSuchAlgorithmException | IOException e) {
|
||||
throw new UploadException(path, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the hash for a particular string and algorithm.
|
||||
*
|
||||
* @param content the string to generate the hash for
|
||||
* @param algorithm the hashing algorithm to use
|
||||
* @return the generates hash, encoded in lowercase hex
|
||||
* @throws NoSuchAlgorithmException when the hashing algorithm couldn't be found
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected String generateHash(String content, String algorithm)
|
||||
throws NoSuchAlgorithmException {
|
||||
var digest = MessageDigest.getInstance(algorithm);
|
||||
digest.update(content.getBytes(StandardCharsets.UTF_8));
|
||||
return encodeHexLower(digest.digest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, publishes a single artifact with
|
||||
* hashes and a potential signature.
|
||||
*
|
||||
* @param repository the repository to publish to
|
||||
* @param file the file that needs to be published
|
||||
* @param path the path of the artifact within the artifact folder
|
||||
* @since 1.5.8
|
||||
*/
|
||||
protected void executePublishFileArtifact(Repository repository, File file, String path)
|
||||
throws UploadException {
|
||||
try {
|
||||
var digest_md5 = MessageDigest.getInstance("MD5");
|
||||
var digest_sha1 = MessageDigest.getInstance("SHA-1");
|
||||
var digest_sha256 = MessageDigest.getInstance("SHA-256");
|
||||
var digest_sha512 = MessageDigest.getInstance("SHA-512");
|
||||
|
||||
try (var is = Files.newInputStream(file.toPath())) {
|
||||
var buffer = new byte[1024];
|
||||
var return_value = -1;
|
||||
while (-1 != (return_value = is.read(buffer))) {
|
||||
digest_md5.update(buffer, 0, return_value);
|
||||
digest_sha1.update(buffer, 0, return_value);
|
||||
digest_sha256.update(buffer, 0, return_value);
|
||||
digest_sha512.update(buffer, 0, return_value);
|
||||
}
|
||||
|
||||
if (info().signKey() != null) {
|
||||
executeTransferArtifact(repository, executeSignFile(file), path + ".asc");
|
||||
}
|
||||
|
||||
if (!repository.isLocal()) {
|
||||
executeTransferArtifact(repository, encodeHexLower(digest_md5.digest()), path + ".md5");
|
||||
executeTransferArtifact(repository, encodeHexLower(digest_sha1.digest()), path + ".sha1");
|
||||
executeTransferArtifact(repository, encodeHexLower(digest_sha256.digest()), path + ".sha256");
|
||||
executeTransferArtifact(repository, encodeHexLower(digest_sha512.digest()), path + ".sha512");
|
||||
}
|
||||
|
||||
executeTransferArtifact(repository, file, path);
|
||||
}
|
||||
} catch (IOException | NoSuchAlgorithmException e) {
|
||||
throw new UploadException(path, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, generates the signature of a file.
|
||||
*
|
||||
* @param file the file whose signature will be generated
|
||||
* @since 1.5.8
|
||||
*/
|
||||
protected String executeSignFile(File file)
|
||||
throws IOException, FileUtilsErrorException {
|
||||
var gpg_path = info().signGpgPath();
|
||||
if (gpg_path == null) {
|
||||
gpg_path = "gpg";
|
||||
}
|
||||
var gpg_arguments = new ArrayList<>(List.of(
|
||||
gpg_path,
|
||||
"--pinentry-mode=loopback",
|
||||
"--no-tty", "--batch", "--detach-sign", "--armor", "-o-",
|
||||
"--local-user", info().signKey()));
|
||||
if (info().signPassphrase() != null) {
|
||||
gpg_arguments.addAll(List.of("--passphrase", info().signPassphrase()));
|
||||
}
|
||||
gpg_arguments.add(file.getAbsolutePath());
|
||||
var builder = new ProcessBuilder(gpg_arguments);
|
||||
builder.redirectOutput(ProcessBuilder.Redirect.PIPE);
|
||||
builder.redirectError(ProcessBuilder.Redirect.PIPE);
|
||||
var process = builder.start();
|
||||
try {
|
||||
process.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
throw new SignException(file, e.getMessage());
|
||||
}
|
||||
|
||||
if (process.exitValue() != 0) {
|
||||
var error = FileUtils.readString(process.getErrorStream());
|
||||
throw new SignException(file, error);
|
||||
}
|
||||
return FileUtils.readString(process.getInputStream());
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, transfers an artifact.
|
||||
*
|
||||
* @param repository the repository to transfer to
|
||||
* @param file the file to transfer
|
||||
* @param path the path of the file within the artifact folder
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected void executeTransferArtifact(Repository repository, File file, String path)
|
||||
throws FileUtilsErrorException, IOException {
|
||||
if (repository.isLocal()) {
|
||||
executeStoreArtifact(repository, file, path);
|
||||
} else {
|
||||
executeUploadArtifact(repository, BodyPublishers.ofFile(file.toPath()), path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, transfers an artifact.
|
||||
*
|
||||
* @param repository the repository to transfer to
|
||||
* @param content the content to transfer
|
||||
* @param path the path of the file within the artifact folder
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected void executeTransferArtifact(Repository repository, String content, String path)
|
||||
throws FileUtilsErrorException, IOException {
|
||||
if (repository.isLocal()) {
|
||||
executeStoreArtifact(repository, content, path);
|
||||
} else {
|
||||
executeUploadArtifact(repository, BodyPublishers.ofString(content), path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, stores an artifact.
|
||||
*
|
||||
* @param repository the repository to store in
|
||||
* @param file the file to store
|
||||
* @param path the path of the file within the artifact folder
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected void executeStoreArtifact(Repository repository, File file, String path)
|
||||
throws FileUtilsErrorException {
|
||||
var location = repository.getArtifactLocation(info().groupId(), info().artifactId()) + path;
|
||||
System.out.print("Storing: " + location + " ... ");
|
||||
try {
|
||||
var target = new File(location);
|
||||
target.getParentFile().mkdirs();
|
||||
FileUtils.copy(file, target);
|
||||
System.out.print("done");
|
||||
} catch (FileUtilsErrorException e) {
|
||||
System.out.print("error");
|
||||
throw e;
|
||||
} finally {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, stores an artifact.
|
||||
*
|
||||
* @param repository the repository to store in
|
||||
* @param content the content to store
|
||||
* @param path the path of the file within the artifact folder
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected void executeStoreArtifact(Repository repository, String content, String path)
|
||||
throws FileUtilsErrorException {
|
||||
var location = repository.getArtifactLocation(info().groupId(), info().artifactId()) + path;
|
||||
System.out.print("Storing: " + location + " ... ");
|
||||
try {
|
||||
var target = new File(location);
|
||||
target.getParentFile().mkdirs();
|
||||
FileUtils.writeString(content, target);
|
||||
System.out.print("done");
|
||||
} catch (FileUtilsErrorException e) {
|
||||
System.out.print("error");
|
||||
throw e;
|
||||
} finally {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, uploads an artifact.
|
||||
*
|
||||
* @param repository the repository to upload to
|
||||
* @param body the body of the file to upload
|
||||
* @param path the path of the file within the artifact folder
|
||||
* @since 1.5.18
|
||||
*/
|
||||
protected void executeUploadArtifact(Repository repository, HttpRequest.BodyPublisher body, String path) {
|
||||
var url = repository.getArtifactLocation(info().groupId(), info().artifactId()) + path;
|
||||
System.out.print("Uploading: " + url + " ... ");
|
||||
System.out.flush();
|
||||
try {
|
||||
var builder = HttpRequest.newBuilder()
|
||||
.PUT(body)
|
||||
.uri(URI.create(url))
|
||||
.header(HEADER_USER_AGENT, "bld/" + BldVersion.getVersion() +
|
||||
" (" + System.getProperty("os.name") + "; " + System.getProperty("os.version") + "; " + System.getProperty("os.arch") + ") " +
|
||||
"(" + System.getProperty("java.vendor") + " " + System.getProperty("java.vm.name") + "; " + System.getProperty("java.version") + "; " + System.getProperty("java.vm.version") + ")");
|
||||
if (repository.username() != null && repository.password() != null) {
|
||||
builder.header(HEADER_AUTHORIZATION, basicAuthorizationHeader(repository.username(), repository.password()));
|
||||
}
|
||||
var request = builder.build();
|
||||
|
||||
HttpResponse<String> response;
|
||||
try {
|
||||
response = client_.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
} catch (IOException e) {
|
||||
System.out.print("I/O error");
|
||||
throw new UploadException(url, e);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.print("interrupted");
|
||||
throw new UploadException(url, e);
|
||||
}
|
||||
|
||||
if (response.statusCode() >= 200 &&
|
||||
response.statusCode() < 300) {
|
||||
System.out.print("done");
|
||||
} else {
|
||||
System.out.print("failed");
|
||||
throw new UploadException(url, response.statusCode());
|
||||
}
|
||||
} finally {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a publish operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the publish operation from
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public PublishOperation fromProject(BaseProject project) {
|
||||
artifactRetriever(project.artifactRetriever());
|
||||
dependencies().include(project.dependencies());
|
||||
artifacts(List.of(
|
||||
new PublishArtifact(new File(project.buildDistDirectory(), project.jarFileName()), "", "jar"),
|
||||
new PublishArtifact(new File(project.buildDistDirectory(), project.sourcesJarFileName()), "sources", "jar"),
|
||||
new PublishArtifact(new File(project.buildDistDirectory(), project.javadocJarFileName()), "javadoc", "jar")));
|
||||
if (info().groupId() == null) {
|
||||
info().groupId(project.pkg());
|
||||
}
|
||||
if (info().artifactId() == null) {
|
||||
info().artifactId(project.name().toLowerCase());
|
||||
}
|
||||
if (info().version() == null) {
|
||||
info().version(project.version());
|
||||
}
|
||||
if (info().name() == null) {
|
||||
info().name(project.name());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the moment of publication.
|
||||
* <p>
|
||||
* If this is not provided, the publication will use the current data and time.
|
||||
*
|
||||
* @param moment the publication moment
|
||||
* @return this operation instance
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public PublishOperation moment(ZonedDateTime moment) {
|
||||
moment_ = moment;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the moment of publication.
|
||||
*
|
||||
* @return the moment of publication; or
|
||||
* {@code null} if it wasn't provided
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public ZonedDateTime moment() {
|
||||
return moment_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a repository to publish to, can be called multiple times to
|
||||
* add more repositories.
|
||||
*
|
||||
* @param repository a repository that the artifacts will be published to
|
||||
* @return this operation instance
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public PublishOperation repository(Repository repository) {
|
||||
repositories_.add(repository);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides repositories to publish to.
|
||||
*
|
||||
* @param repositories repositories where the artifacts will be published
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PublishOperation repositories(Repository... repositories) {
|
||||
repositories_.addAll(List.of(repositories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of repositories to publish to.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param repositories a list of repositories where the artifacts will be published
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PublishOperation repositories(List<Repository> repositories) {
|
||||
repositories_.addAll(repositories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides scoped dependencies to reference in the publication.
|
||||
*
|
||||
* @param dependencies the dependencies that will be references in the publication
|
||||
* @return this operation instance
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public PublishOperation dependencies(DependencyScopes dependencies) {
|
||||
dependencies_.include(dependencies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the publication info structure.
|
||||
*
|
||||
* @param info the publication info
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PublishOperation info(PublishInfo info) {
|
||||
info_ = info;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides artifacts that will be published.
|
||||
*
|
||||
* @param artifacts artifacts to publish
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PublishOperation artifacts(PublishArtifact... artifacts) {
|
||||
artifacts_.addAll(List.of(artifacts));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of artifacts that will be published.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param artifacts a list of artifacts to publish
|
||||
* @return this operation instance
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public PublishOperation artifacts(List<PublishArtifact> artifacts) {
|
||||
artifacts_.addAll(artifacts);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the artifact retriever to use.
|
||||
*
|
||||
* @param retriever the artifact retriever
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PublishOperation artifactRetriever(ArtifactRetriever retriever) {
|
||||
retriever_ = retriever;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the repositories to which will be published.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the repositories where the artifacts will be published
|
||||
* @since 1.51.8
|
||||
*/
|
||||
public List<Repository> repositories() {
|
||||
return repositories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the scoped dependencies to reference in the publication.
|
||||
* <p>
|
||||
* This is a modifiable structure that can be retrieved and changed.
|
||||
*
|
||||
* @return the scoped dependencies
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public DependencyScopes dependencies() {
|
||||
return dependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the publication info structure.
|
||||
* <p>
|
||||
* This is a modifiable structure that can be retrieved and changed.
|
||||
*
|
||||
* @return the publication info
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public PublishInfo info() {
|
||||
return info_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of artifacts that will be published.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the list of artifacts to publish
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public List<PublishArtifact> artifacts() {
|
||||
return artifacts_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact retriever that is used.
|
||||
*
|
||||
* @return the artifact retriever
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public ArtifactRetriever artifactRetriever() {
|
||||
if (retriever_ == null) {
|
||||
return ArtifactRetriever.instance();
|
||||
}
|
||||
return retriever_;
|
||||
}
|
||||
}
|
369
src/main/java/rife/bld/operations/PurgeOperation.java
Normal file
369
src/main/java/rife/bld/operations/PurgeOperation.java
Normal file
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.dependencies.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static rife.bld.dependencies.Dependency.CLASSIFIER_JAVADOC;
|
||||
import static rife.bld.dependencies.Dependency.CLASSIFIER_SOURCES;
|
||||
|
||||
/**
|
||||
* Transitively checks all the artifacts for dependencies in the directories
|
||||
* that are separated out by scope, any files that aren't required will be deleted.
|
||||
* <p>
|
||||
* If a directory is not provided, no purge will occur for that
|
||||
* dependency scope.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class PurgeOperation extends AbstractOperation<PurgeOperation> {
|
||||
private ArtifactRetriever retriever_ = null;
|
||||
private final List<Repository> repositories_ = new ArrayList<>();
|
||||
private final DependencyScopes dependencies_ = new DependencyScopes();
|
||||
private File libCompileDirectory_;
|
||||
private File libRuntimeDirectory_;
|
||||
private File libStandaloneDirectory_;
|
||||
private File libTestDirectory_;
|
||||
private boolean preserveSources_ = false;
|
||||
private boolean preserveJavadoc_ = false;
|
||||
|
||||
/**
|
||||
* Performs the purge operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute() {
|
||||
executePurgeCompileDependencies();
|
||||
executePurgeRuntimeDependencies();
|
||||
executePurgeStandaloneDependencies();
|
||||
executePurgeTestDependencies();
|
||||
if (!silent()) {
|
||||
System.out.println("Purging finished successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, purge the {@code compile} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executePurgeCompileDependencies() {
|
||||
executePurgeDependencies(libCompileDirectory(), dependencies().resolveCompileDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, purge the {@code runtime} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executePurgeRuntimeDependencies() {
|
||||
executePurgeDependencies(libRuntimeDirectory(), dependencies().resolveRuntimeDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, purge the {@code standalone} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executePurgeStandaloneDependencies() {
|
||||
executePurgeDependencies(libStandaloneDirectory(), dependencies().resolveStandaloneDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, purge the {@code test} scope artifacts.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executePurgeTestDependencies() {
|
||||
executePurgeDependencies(libTestDirectory(), dependencies().resolveTestDependencies(artifactRetriever(), repositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, purge the artifacts for a particular dependency scope.
|
||||
*
|
||||
* @param destinationDirectory the directory from which the artifacts should be purged
|
||||
* @param dependencies the dependencies to purge
|
||||
* @since 1.6
|
||||
*/
|
||||
protected void executePurgeDependencies(File destinationDirectory, DependencySet dependencies) {
|
||||
if (destinationDirectory == null) {
|
||||
return;
|
||||
}
|
||||
var filenames = new HashSet<String>();
|
||||
for (var dependency : dependencies) {
|
||||
addTransferLocations(filenames, dependency);
|
||||
if (preserveSources_) {
|
||||
addTransferLocations(filenames, dependency.withClassifier(CLASSIFIER_SOURCES));
|
||||
}
|
||||
if (preserveJavadoc_) {
|
||||
addTransferLocations(filenames, dependency.withClassifier(CLASSIFIER_JAVADOC));
|
||||
}
|
||||
}
|
||||
|
||||
boolean printed_header = false;
|
||||
for (var file : destinationDirectory.listFiles()) {
|
||||
if (!filenames.contains(file.getName())) {
|
||||
if (!printed_header) {
|
||||
printed_header = true;
|
||||
System.out.println("Deleting from " + destinationDirectory.getName() + ":");
|
||||
}
|
||||
System.out.println(" " + file.getName());
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addTransferLocations(HashSet<String> filenames, Dependency dependency) {
|
||||
for (var location : new DependencyResolver(artifactRetriever(), repositories(), dependency).getTransferLocations()) {
|
||||
filenames.add(location.substring(location.lastIndexOf("/") + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a compile operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the compile operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation fromProject(BaseProject project) {
|
||||
return artifactRetriever(project.artifactRetriever())
|
||||
.repositories(project.repositories())
|
||||
.dependencies(project.dependencies())
|
||||
.libCompileDirectory(project.libCompileDirectory())
|
||||
.libRuntimeDirectory(project.libRuntimeDirectory())
|
||||
.libStandaloneDirectory(project.libStandaloneDirectory())
|
||||
.libTestDirectory(project.libTestDirectory())
|
||||
.preserveSources(project.downloadSources())
|
||||
.preserveJavadoc(project.downloadJavadoc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the sources classifier files should be preserved.
|
||||
*
|
||||
* @param flag {@code true} if the sources classifier files should be preserved; or
|
||||
* {@code false} otherwise
|
||||
* @return this operation instance
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public PurgeOperation preserveSources(boolean flag) {
|
||||
preserveSources_ = flag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the javadoc classifier files should be preserved.
|
||||
*
|
||||
* @param flag {@code true} if the javadoc classifier files should be preserved; or
|
||||
* {@code false} otherwise
|
||||
* @return this operation instance
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public PurgeOperation preserveJavadoc(boolean flag) {
|
||||
preserveJavadoc_ = flag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides repositories to resolve the dependencies against.
|
||||
*
|
||||
* @param repositories repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PurgeOperation repositories(Repository... repositories) {
|
||||
repositories_.addAll(List.of(repositories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of repositories to resolve the dependencies against.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param repositories a list of repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation repositories(List<Repository> repositories) {
|
||||
repositories_.addAll(repositories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides scoped dependencies for artifact purge.
|
||||
*
|
||||
* @param dependencies the dependencies that will be resolved for artifact purge
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation dependencies(DependencyScopes dependencies) {
|
||||
dependencies_.include(dependencies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code compile} scope purge directory.
|
||||
*
|
||||
* @param directory the directory to purge the {@code compile} scope artifacts from
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation libCompileDirectory(File directory) {
|
||||
libCompileDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code runtime} scope purge directory.
|
||||
*
|
||||
* @param directory the directory to purge the {@code runtime} scope artifacts from
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation libRuntimeDirectory(File directory) {
|
||||
libRuntimeDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code standalone} scope purge directory.
|
||||
*
|
||||
* @param directory the directory to purge the {@code standalone} scope artifacts from
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation libStandaloneDirectory(File directory) {
|
||||
libStandaloneDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@code test} scope purge directory.
|
||||
*
|
||||
* @param directory the directory to purge the {@code test} scope artifacts from
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public PurgeOperation libTestDirectory(File directory) {
|
||||
libTestDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the artifact retriever to use.
|
||||
*
|
||||
* @param retriever the artifact retriever
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public PurgeOperation artifactRetriever(ArtifactRetriever retriever) {
|
||||
retriever_ = retriever;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the repositories in which the dependencies will be resolved.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the repositories used for dependency resolution
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Repository> repositories() {
|
||||
return repositories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the scoped dependencies that will be used for artifact purge.
|
||||
* <p>
|
||||
* This is a modifiable structure that can be retrieved and changed.
|
||||
*
|
||||
* @return the scoped dependencies
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencyScopes dependencies() {
|
||||
return dependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code compile} scope purge directory.
|
||||
*
|
||||
* @return the {@code compile} scope purge directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libCompileDirectory() {
|
||||
return libCompileDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code runtime} scope purge directory.
|
||||
*
|
||||
* @return the {@code runtime} scope purge directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libRuntimeDirectory() {
|
||||
return libRuntimeDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code standalone} scope purge directory.
|
||||
*
|
||||
* @return the {@code standalone} scope purge directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libStandaloneDirectory() {
|
||||
return libStandaloneDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@code test} scope purge directory.
|
||||
*
|
||||
* @return the {@code test} scope purge directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File libTestDirectory() {
|
||||
return libTestDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether the sources classifier files should be preserved.
|
||||
*
|
||||
* @return {@code true} if the sources classifier should be preserved; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public boolean preserveSources() {
|
||||
return preserveSources_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether the javadoc classifier files should be preserved.
|
||||
*
|
||||
* @return {@code true} if the javadoc classifier should be preserved; or
|
||||
* {@code false} otherwise
|
||||
* @since 1.5.6
|
||||
*/
|
||||
public boolean preserveJavadoc() {
|
||||
return preserveJavadoc_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact retriever that is used.
|
||||
*
|
||||
* @return the artifact retriever
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public ArtifactRetriever artifactRetriever() {
|
||||
if (retriever_ == null) {
|
||||
return ArtifactRetriever.instance();
|
||||
}
|
||||
return retriever_;
|
||||
}
|
||||
}
|
93
src/main/java/rife/bld/operations/RunOperation.java
Normal file
93
src/main/java/rife/bld/operations/RunOperation.java
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.tools.FileUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Runs a Java application.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class RunOperation extends AbstractProcessOperation<RunOperation> {
|
||||
protected final List<String> runOptions_ = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, constructs the command list
|
||||
* to use for building the process.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected List<String> executeConstructProcessCommandList() {
|
||||
var args = new ArrayList<String>();
|
||||
args.add(javaTool());
|
||||
args.addAll(javaOptions());
|
||||
if (!classpath().isEmpty()) {
|
||||
args.add("-cp");
|
||||
args.add(FileUtils.joinPaths(classpath()));
|
||||
}
|
||||
args.add(mainClass());
|
||||
args.addAll(runOptions());
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a run operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the run operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public RunOperation fromProject(BaseProject project) {
|
||||
var operation = workDirectory(project.workDirectory())
|
||||
.javaTool(project.javaTool())
|
||||
.classpath(project.runClasspath())
|
||||
.mainClass(project.mainClass());
|
||||
if (project.usesRife2Agent()) {
|
||||
operation.javaOptions().javaAgent(project.getRife2AgentFile());
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides options for the run operation
|
||||
*
|
||||
* @param options run options
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public RunOperation runOptions(String... options) {
|
||||
runOptions_.addAll(List.of(options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides options for the run operation
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param options run options
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public RunOperation runOptions(List<String> options) {
|
||||
runOptions_.addAll(options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the run options
|
||||
*
|
||||
* @return the run options
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public List<String> runOptions() {
|
||||
return runOptions_;
|
||||
}
|
||||
}
|
59
src/main/java/rife/bld/operations/TemplateType.java
Normal file
59
src/main/java/rife/bld/operations/TemplateType.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Allows template types to be specified for pre-compilation.
|
||||
*/
|
||||
public class TemplateType implements Serializable {
|
||||
@Serial private static final long serialVersionUID = -2736320275307140837L;
|
||||
|
||||
/**
|
||||
* The {@code html} template type.
|
||||
*/
|
||||
public static TemplateType HTML = new TemplateType("html");
|
||||
/**
|
||||
* The {@code json} template type.
|
||||
*/
|
||||
public static TemplateType JSON = new TemplateType("json");
|
||||
/**
|
||||
* The {@code svg} template type.
|
||||
*/
|
||||
public static TemplateType SVG = new TemplateType("svg");
|
||||
/**
|
||||
* The {@code xml} template type.
|
||||
*/
|
||||
public static TemplateType XML = new TemplateType("xml");
|
||||
/**
|
||||
* The {@code txt} template type.
|
||||
*/
|
||||
public static TemplateType TXT = new TemplateType("txt");
|
||||
/**
|
||||
* The {@code sql} template type.
|
||||
*/
|
||||
public static TemplateType SQL = new TemplateType("sql");
|
||||
|
||||
private final String identifier_;
|
||||
|
||||
/**
|
||||
* Creates a new template type instance.
|
||||
*
|
||||
* @param identifier the identifier of this template type
|
||||
*/
|
||||
public TemplateType(String identifier) {
|
||||
identifier_ = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the identifier for this template type
|
||||
* @return the template type identifier as a string
|
||||
*/
|
||||
public String identifier() {
|
||||
return identifier_;
|
||||
}
|
||||
}
|
115
src/main/java/rife/bld/operations/TestOperation.java
Normal file
115
src/main/java/rife/bld/operations/TestOperation.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.Project;
|
||||
import rife.tools.FileUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Tests a Java application.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class TestOperation<T extends TestOperation<T, O>, O extends List<String>> extends AbstractProcessOperation<T> {
|
||||
protected final O testToolOptions_;
|
||||
|
||||
/**
|
||||
* Instantiates a new test operation.
|
||||
* @since 1.5.20
|
||||
*/
|
||||
public TestOperation() {
|
||||
testToolOptions_ = createTestToolOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new collection of test tool options.
|
||||
*
|
||||
* @return the test tool options to use
|
||||
* @since 1.5.20
|
||||
*/
|
||||
protected O createTestToolOptions() {
|
||||
return (O)new ArrayList<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, constructs the command list
|
||||
* to use for building the process.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected List<String> executeConstructProcessCommandList() {
|
||||
if (mainClass() == null) {
|
||||
throw new IllegalArgumentException("ERROR: Missing main class for test execution.");
|
||||
}
|
||||
|
||||
var args = new ArrayList<String>();
|
||||
args.add(javaTool());
|
||||
args.addAll(javaOptions());
|
||||
args.add("-cp");
|
||||
args.add(FileUtils.joinPaths(classpath()));
|
||||
args.add(mainClass());
|
||||
args.addAll(testToolOptions());
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a test operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the test operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public T fromProject(BaseProject project) {
|
||||
var operation = workDirectory(project.workDirectory())
|
||||
.javaTool(project.javaTool())
|
||||
.classpath(project.testClasspath());
|
||||
if (project.usesRife2Agent()) {
|
||||
operation.javaOptions().javaAgent(project.getRife2AgentFile());
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides options to provide to the test tool.
|
||||
*
|
||||
* @param options test tool options
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public T testToolOptions(String... options) {
|
||||
testToolOptions_.addAll(List.of(options));
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides options to provide to the test tool.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param options test tool options
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public T testToolOptions(List<String> options) {
|
||||
testToolOptions_.addAll(options);
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the options for the test tool.
|
||||
*
|
||||
* @return the test tool's options
|
||||
* @since 1.5
|
||||
*/
|
||||
public O testToolOptions() {
|
||||
return (O)testToolOptions_;
|
||||
}
|
||||
}
|
268
src/main/java/rife/bld/operations/UberJarOperation.java
Normal file
268
src/main/java/rife/bld/operations/UberJarOperation.java
Normal file
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.NamedFile;
|
||||
import rife.bld.Project;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Creates an uberjar archive of the provided jars and resources.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class UberJarOperation extends AbstractOperation<UberJarOperation> {
|
||||
private final List<File> jarSourceFiles_ = new ArrayList<>();
|
||||
private final List<NamedFile> sourceDirectories_ = new ArrayList<>();
|
||||
private File destinationDirectory_;
|
||||
private String destinationFileName_;
|
||||
private String mainClass_;
|
||||
|
||||
/**
|
||||
* Performs the uberjar operation.
|
||||
*
|
||||
* @throws IOException when an exception occurred during the uberjar creation process
|
||||
* @throws FileUtilsErrorException when an exception occurred during the uberjar creation process
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException, FileUtilsErrorException {
|
||||
var tmp_dir = Files.createTempDirectory("uberjar").toFile();
|
||||
try {
|
||||
executeCollectSourceJarContents(tmp_dir);
|
||||
executeCollectSourceResources(tmp_dir);
|
||||
executeCreateUberJarArchive(tmp_dir);
|
||||
|
||||
if (!silent()) {
|
||||
System.out.println("The uberjar archive was created at '" + new File(destinationDirectory(), destinationFileName()) + "'");
|
||||
}
|
||||
} finally {
|
||||
FileUtils.deleteDirectory(tmp_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, collect the contents of all the source jars.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCollectSourceJarContents(File stagingDirectory)
|
||||
throws FileUtilsErrorException {
|
||||
for (var jar : jarSourceFiles()) {
|
||||
FileUtils.unzipFile(jar, stagingDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, collect the source resources.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCollectSourceResources(File stagingDirectory)
|
||||
throws FileUtilsErrorException {
|
||||
for (var named_file : sourceDirectories()) {
|
||||
if (named_file.file().exists()) {
|
||||
var destination_file = new File(stagingDirectory, named_file.name());
|
||||
destination_file.mkdirs();
|
||||
FileUtils.copyDirectory(named_file.file(), destination_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the uberjar archive.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCreateUberJarArchive(File stagingDirectory)
|
||||
throws IOException {
|
||||
var existing_manifest = new File(new File(stagingDirectory, "META-INF"), "MANIFEST.MF");
|
||||
existing_manifest.delete();
|
||||
|
||||
new JarOperation()
|
||||
.manifestAttributes(Map.of(
|
||||
Attributes.Name.MANIFEST_VERSION, "1.0",
|
||||
Attributes.Name.MAIN_CLASS, mainClass()))
|
||||
.sourceDirectories(stagingDirectory)
|
||||
.destinationDirectory(destinationDirectory())
|
||||
.destinationFileName(destinationFileName())
|
||||
.excluded(List.of(Pattern.compile("(?:(?:^.*[/\\\\])|^)\\.DS_Store$")))
|
||||
.silent(true)
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an uberjar operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the uberjar operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public UberJarOperation fromProject(BaseProject project) {
|
||||
var jars = new ArrayList<>(project.compileClasspathJars());
|
||||
jars.addAll(project.runtimeClasspathJars());
|
||||
jars.add(new File(project.buildDistDirectory(), project.jarFileName()));
|
||||
|
||||
return jarSourceFiles(jars)
|
||||
.destinationDirectory(project.buildDistDirectory())
|
||||
.destinationFileName(project.uberJarFileName())
|
||||
.mainClass(project.uberJarMainClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides source jar files that will be used for the uberjar archive creation.
|
||||
*
|
||||
* @param files source files
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public UberJarOperation jarSourceFiles(File... files) {
|
||||
jarSourceFiles_.addAll(List.of(files));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of source jar files that will be used for the uberjar archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param files a list of jar source files
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UberJarOperation jarSourceFiles(List<File> files) {
|
||||
jarSourceFiles_.addAll(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides source directories that will be used for the uberjar archive creation.
|
||||
*
|
||||
* @param directories source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public UberJarOperation sourceDirectories(NamedFile... directories) {
|
||||
sourceDirectories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of source directories that will be used for the uberjar archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UberJarOperation sourceDirectories(List<NamedFile> directories) {
|
||||
sourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination directory in which the uberjar archive will be created.
|
||||
*
|
||||
* @param directory the uberjar destination directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UberJarOperation destinationDirectory(File directory) {
|
||||
destinationDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination file name that will be used for the uberjar archive creation.
|
||||
*
|
||||
* @param name the uberjar archive destination file name
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UberJarOperation destinationFileName(String name) {
|
||||
destinationFileName_ = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the main class to run from the uberjar archive.
|
||||
*
|
||||
* @param name the main class to run
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UberJarOperation mainClass(String name) {
|
||||
mainClass_ = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of jar source files that will be used for the
|
||||
* uberjar archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the uberjar archive's jar source files
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> jarSourceFiles() {
|
||||
return jarSourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of source directories that will be used for the
|
||||
* uberjar archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the uberjar archive's source directories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<NamedFile> sourceDirectories() {
|
||||
return sourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination directory in which the uberjar archive will
|
||||
* be created.
|
||||
*
|
||||
* @return the uberjar archive's destination directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File destinationDirectory() {
|
||||
return destinationDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination file name that will be used for the uberjar
|
||||
* archive creation.
|
||||
*
|
||||
* @return the uberjar archive's destination file name
|
||||
* @since 1.5
|
||||
*/
|
||||
public String destinationFileName() {
|
||||
return destinationFileName_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the main class to run from the uberjar archive.
|
||||
*
|
||||
* @return the main class to run
|
||||
* @since 1.5
|
||||
*/
|
||||
public String mainClass() {
|
||||
return mainClass_;
|
||||
}
|
||||
}
|
170
src/main/java/rife/bld/operations/UpdatesOperation.java
Normal file
170
src/main/java/rife/bld/operations/UpdatesOperation.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.Project;
|
||||
import rife.bld.dependencies.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Determines which updates are available for provides dependencies.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class UpdatesOperation extends AbstractOperation<UpdatesOperation> {
|
||||
private ArtifactRetriever retriever_ = null;
|
||||
private final List<Repository> repositories_ = new ArrayList<>();
|
||||
private final DependencyScopes dependencies_ = new DependencyScopes();
|
||||
private DependencyScopes updates_ = new DependencyScopes();
|
||||
|
||||
/**
|
||||
* Performs the updates operation.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute() {
|
||||
var result = new DependencyScopes();
|
||||
for (var entry : dependencies_.entrySet()) {
|
||||
var scope = entry.getKey();
|
||||
for (var dependency : entry.getValue()) {
|
||||
var latest = new DependencyResolver(artifactRetriever(), repositories(), dependency).latestVersion();
|
||||
if (latest.compareTo(dependency.version()) > 0) {
|
||||
var latest_dependency = new Dependency(dependency.groupId(), dependency.artifactId(), latest,
|
||||
dependency.classifier(), dependency.type());
|
||||
result.scope(scope).include(latest_dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
if (!silent()) {
|
||||
System.out.println("No dependency updates found.");
|
||||
}
|
||||
} else {
|
||||
System.out.println("The following dependency updates were found.");
|
||||
for (var entry : result.entrySet()) {
|
||||
var scope = entry.getKey();
|
||||
System.out.println(scope + ":");
|
||||
for (var dependency : entry.getValue()) {
|
||||
System.out.println(" " + dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
updates_ = result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an updates operation from a {@link BaseProject}.
|
||||
*
|
||||
* @param project the project to configure the updates operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public UpdatesOperation fromProject(BaseProject project) {
|
||||
return artifactRetriever(project.artifactRetriever())
|
||||
.repositories(project.repositories())
|
||||
.dependencies(project.dependencies());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides repositories to resolve the dependencies against.
|
||||
*
|
||||
* @param repositories repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public UpdatesOperation repositories(Repository... repositories) {
|
||||
repositories_.addAll(List.of(repositories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of repositories to resolve the dependencies against.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param repositories a list of repositories against which dependencies will be resolved
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UpdatesOperation repositories(List<Repository> repositories) {
|
||||
repositories_.addAll(repositories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides scoped dependencies that will be checked for updates.
|
||||
*
|
||||
* @param dependencies the dependencies that will be checked for updates
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public UpdatesOperation dependencies(DependencyScopes dependencies) {
|
||||
dependencies_.include(dependencies);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the artifact retriever to use.
|
||||
*
|
||||
* @param retriever the artifact retriever
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public UpdatesOperation artifactRetriever(ArtifactRetriever retriever) {
|
||||
retriever_ = retriever;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the repositories in which the dependencies will be resolved.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the repositories used for dependency resolution
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<Repository> repositories() {
|
||||
return repositories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the scoped dependencies that will be checked for updates.
|
||||
* <p>
|
||||
* This is a modifiable structure that can be retrieved and changed.
|
||||
*
|
||||
* @return the scoped dependencies
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencyScopes dependencies() {
|
||||
return dependencies_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the scoped dependencies with updates found after execution.
|
||||
*
|
||||
* @return the scoped dependencies with updates
|
||||
* @since 1.5
|
||||
*/
|
||||
public DependencyScopes updates() {
|
||||
return updates_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact retriever that is used.
|
||||
*
|
||||
* @return the artifact retriever
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public ArtifactRetriever artifactRetriever() {
|
||||
if (retriever_ == null) {
|
||||
return ArtifactRetriever.instance();
|
||||
}
|
||||
return retriever_;
|
||||
}
|
||||
}
|
33
src/main/java/rife/bld/operations/UpgradeOperation.java
Normal file
33
src/main/java/rife/bld/operations/UpgradeOperation.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.BldVersion;
|
||||
import rife.bld.wrapper.Wrapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Upgrades the project's bld wrapper to the version of the running
|
||||
* RIFE2 framework.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class UpgradeOperation extends AbstractOperation<UpgradeOperation> {
|
||||
/**
|
||||
* Performs the upgrade operation.
|
||||
*
|
||||
* @throws IOException when an error occurred during the upgrade operation
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException {
|
||||
new Wrapper().createWrapperFiles(Path.of("lib", "bld").toFile(), BldVersion.getVersion());
|
||||
new Wrapper().upgradeIdeaBldLibrary(new File(".idea"), BldVersion.getVersion());
|
||||
new Wrapper().upgradeVscodeSettings(new File(".vscode"), BldVersion.getVersion());
|
||||
if (!silent()) {
|
||||
System.out.println("The wrapper was successfully upgraded to " + BldVersion.getVersion() + ".");
|
||||
}
|
||||
}
|
||||
}
|
26
src/main/java/rife/bld/operations/VersionOperation.java
Normal file
26
src/main/java/rife/bld/operations/VersionOperation.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
package rife.bld.operations;
|
||||
|
||||
|
||||
import rife.bld.BldVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Outputs the version of the build system.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public class VersionOperation extends AbstractOperation<VersionOperation> {
|
||||
/**
|
||||
* Performs the version operation.
|
||||
*
|
||||
* @throws IOException when an error occurred during the upgrade operation
|
||||
* @since 1.5.2
|
||||
*/
|
||||
public void execute() {
|
||||
if (!silent()) {
|
||||
System.out.println("bld " + BldVersion.getVersion());
|
||||
}
|
||||
}
|
||||
}
|
377
src/main/java/rife/bld/operations/WarOperation.java
Normal file
377
src/main/java/rife/bld/operations/WarOperation.java
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations;
|
||||
|
||||
import rife.bld.*;
|
||||
import rife.tools.FileUtils;
|
||||
import rife.tools.exceptions.FileUtilsErrorException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Creates a war archive.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class WarOperation extends AbstractOperation<WarOperation> {
|
||||
private final List<File> libSourceDirectories_ = new ArrayList<>();
|
||||
private final List<File> classesSourceDirectories_ = new ArrayList<>();
|
||||
private final List<NamedFile> jarSourceFiles_ = new ArrayList<>();
|
||||
private File webappDirectory_;
|
||||
private File webXmlFile_;
|
||||
private File destinationDirectory_;
|
||||
private String destinationFileName_;
|
||||
|
||||
/**
|
||||
* Performs the war operation.
|
||||
*
|
||||
* @throws IOException when an exception occurred during the war creation process
|
||||
* @throws FileUtilsErrorException when an exception occurred war the uberjar creation process
|
||||
* @since 1.5
|
||||
*/
|
||||
public void execute()
|
||||
throws IOException, FileUtilsErrorException {
|
||||
var tmp_dir = Files.createTempDirectory("war").toFile();
|
||||
|
||||
try {
|
||||
var web_inf_dir = executeCreateWebInfDirectory(tmp_dir);
|
||||
executeCopyWebappDirectory(tmp_dir);
|
||||
executeCopyWebInfLibJars(web_inf_dir);
|
||||
executeCopyWebInfClassesFiles(web_inf_dir);
|
||||
executeCopyWebXmlFile(web_inf_dir);
|
||||
|
||||
executeCreateWarArchive(tmp_dir);
|
||||
|
||||
if (!silent()) {
|
||||
System.out.println("The war archive was created at '" + new File(destinationDirectory(), destinationFileName()) + "'");
|
||||
}
|
||||
} finally {
|
||||
FileUtils.deleteDirectory(tmp_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the staging {@code WEB-INF} directory.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected File executeCreateWebInfDirectory(File stagingDirectory) {
|
||||
var web_inf_dir = new File(stagingDirectory, "WEB-INF");
|
||||
web_inf_dir.mkdirs();
|
||||
return web_inf_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the staging webapp directory.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCopyWebappDirectory(File stagingDirectory)
|
||||
throws FileUtilsErrorException {
|
||||
if (webappDirectory() != null) {
|
||||
FileUtils.copyDirectory(webappDirectory(), stagingDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, copy the staging {@code WEB-INF} jars.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCopyWebInfLibJars(File stagingWebInfDirectory)
|
||||
throws FileUtilsErrorException {
|
||||
var web_inf_lib_dir = new File(stagingWebInfDirectory, "lib");
|
||||
if (!libSourceDirectories().isEmpty()) {
|
||||
web_inf_lib_dir.mkdirs();
|
||||
for (var dir : libSourceDirectories()) {
|
||||
FileUtils.copyDirectory(dir, web_inf_lib_dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!jarSourceFiles().isEmpty()) {
|
||||
web_inf_lib_dir.mkdirs();
|
||||
for (var file : jarSourceFiles()) {
|
||||
FileUtils.copy(file.file(), new File(web_inf_lib_dir, file.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, copy the staging {@code WEB-INF} classes.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCopyWebInfClassesFiles(File stagingWebInfDirectory)
|
||||
throws FileUtilsErrorException {
|
||||
var web_inf_classes_dir = new File(stagingWebInfDirectory, "classes");
|
||||
if (!classesSourceDirectories().isEmpty()) {
|
||||
web_inf_classes_dir.mkdirs();
|
||||
for (var dir : classesSourceDirectories()) {
|
||||
FileUtils.copyDirectory(dir, web_inf_classes_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, copy the staging {@code web.xml} file.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCopyWebXmlFile(File stagingWebInfDirectory)
|
||||
throws FileUtilsErrorException {
|
||||
if (webXmlFile() != null) {
|
||||
FileUtils.copy(webXmlFile(), new File(stagingWebInfDirectory, "web.xml"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the {@link #execute} operation, create the war archive from the staging directory.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected void executeCreateWarArchive(File stagingDirectory)
|
||||
throws IOException {
|
||||
new JarOperation()
|
||||
.sourceDirectories(stagingDirectory)
|
||||
.destinationDirectory(destinationDirectory())
|
||||
.destinationFileName(destinationFileName())
|
||||
.excluded(Pattern.compile("(?:(?:^.*[/\\\\])|^)\\.DS_Store$"))
|
||||
.silent(true)
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a war operation from a {@link Project}.
|
||||
*
|
||||
* @param project the project to configure the war operation from
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation fromProject(WebProject project) {
|
||||
var jar_source_files = new ArrayList<NamedFile>();
|
||||
jar_source_files.add(new NamedFile(project.jarFileName(), new File(project.buildDistDirectory(), project.jarFileName())));
|
||||
|
||||
var class_path_jars = new ArrayList<File>();
|
||||
class_path_jars.addAll(project.compileClasspathJars());
|
||||
class_path_jars.addAll(project.runtimeClasspathJars());
|
||||
for (var jar_file : class_path_jars) {
|
||||
jar_source_files.add(new NamedFile(jar_file.getName(), jar_file));
|
||||
}
|
||||
|
||||
return jarSourceFiles(jar_source_files)
|
||||
.webappDirectory(project.srcMainWebappDirectory())
|
||||
.destinationDirectory(project.buildDistDirectory())
|
||||
.destinationFileName(project.warFileName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides lib source directories that will be used for the war archive creation.
|
||||
*
|
||||
* @param directories lib source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public WarOperation libSourceDirectories(File... directories) {
|
||||
libSourceDirectories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of lib source directories that will be used for the war archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of lib source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation libSourceDirectories(List<File> directories) {
|
||||
libSourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes source directories that will be used for the war archive creation.
|
||||
*
|
||||
* @param directories classes source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public WarOperation classesSourceDirectories(File... directories) {
|
||||
classesSourceDirectories_.addAll(List.of(directories));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of classes source directories that will be used for the war archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param directories a list of classes source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation classesSourceDirectories(List<File> directories) {
|
||||
classesSourceDirectories_.addAll(directories);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides jar files that will be included in the war archive creation.
|
||||
*
|
||||
* @param files jar source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5.18
|
||||
*/
|
||||
public WarOperation jarSourceFiles(NamedFile... files) {
|
||||
jarSourceFiles_.addAll(List.of(files));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of jar files that will be included in the war archive creation.
|
||||
* <p>
|
||||
* A copy will be created to allow this list to be independently modifiable.
|
||||
*
|
||||
* @param files a list of jar source directories
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation jarSourceFiles(List<NamedFile> files) {
|
||||
jarSourceFiles_.addAll(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides web application directory that will provide resources for the war archive creation.
|
||||
*
|
||||
* @param directory the webapp directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation webappDirectory(File directory) {
|
||||
webappDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides web.xml file that will be used for the war archive creation.
|
||||
*
|
||||
* @param file the web.xml file
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation webXmlFile(File file) {
|
||||
webXmlFile_ = file;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination directory in which the war archive will be created.
|
||||
*
|
||||
* @param directory the war destination directory
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation destinationDirectory(File directory) {
|
||||
destinationDirectory_ = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the destination file name that will be used for the war archive creation.
|
||||
*
|
||||
* @param name the war archive destination file name
|
||||
* @return this operation instance
|
||||
* @since 1.5
|
||||
*/
|
||||
public WarOperation destinationFileName(String name) {
|
||||
destinationFileName_ = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the lib source directories that will be used for the war archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the lib source directories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> libSourceDirectories() {
|
||||
return libSourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the classes source directories that will be used for the war archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the classes source directories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<File> classesSourceDirectories() {
|
||||
return classesSourceDirectories_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves jar files that will be included in the war archive creation.
|
||||
* <p>
|
||||
* This is a modifiable list that can be retrieved and changed.
|
||||
*
|
||||
* @return the jar source directories
|
||||
* @since 1.5
|
||||
*/
|
||||
public List<NamedFile> jarSourceFiles() {
|
||||
return jarSourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves web application directory that will provide resources for the war archive creation.
|
||||
*
|
||||
* @return the webapp directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File webappDirectory() {
|
||||
return webappDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves web.xml file that will be used for the war archive creation.
|
||||
*
|
||||
* @return the web.xml file
|
||||
* @since 1.5
|
||||
*/
|
||||
public File webXmlFile() {
|
||||
return webXmlFile_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination directory in which the war archive will
|
||||
* be created.
|
||||
*
|
||||
* @return the war archive's destination directory
|
||||
* @since 1.5
|
||||
*/
|
||||
public File destinationDirectory() {
|
||||
return destinationDirectory_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination file name that will be used for the war
|
||||
* archive creation.
|
||||
*
|
||||
* @return the war archive's destination file name
|
||||
* @since 1.5
|
||||
*/
|
||||
public String destinationFileName() {
|
||||
return destinationFileName_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
*/
|
||||
package rife.bld.operations.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* When thrown, indicates that the exit status has changed due
|
||||
* to the operation execution.
|
||||
*
|
||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public class ExitStatusException extends Exception {
|
||||
public static final int EXIT_SUCCESS = 0;
|
||||
public static final int EXIT_FAILURE = 1;
|
||||
|
||||
@Serial private static final long serialVersionUID = 5474282790384325513L;
|
||||
|
||||
private final int exitStatus_;
|
||||
|
||||
public ExitStatusException(int exitStatus) {
|
||||
exitStatus_ = exitStatus;
|
||||
}
|
||||
|
||||
public int getExitStatus() {
|
||||
return exitStatus_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an {@code ExitStatusException} when the status is a failure.
|
||||
*
|
||||
* @param status the status to check
|
||||
* @throws ExitStatusException when the provided status is different from {@code EXIT_SUCCESS}
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public static void throwOnFailure(int status)
|
||||
throws ExitStatusException {
|
||||
if (status != EXIT_SUCCESS) {
|
||||
throw new ExitStatusException(status);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue