2
0
Fork 0
mirror of https://github.com/ethauvin/rife2.git synced 2025-04-29 18:18:12 -07:00

Compare commits

...

38 commits

Author SHA1 Message Date
1184cca9c6 Added config param and list annotation support for elements 2023-04-19 22:56:52 -04:00
edfb2a4eb5 Added convenience method for adding non-string params to UrlBuilder. 2023-04-19 22:47:13 -04:00
fce62fad1c Improvements to bld IDEA project setup related to finding main and test resources. 2023-04-19 21:41:45 -04:00
81f631a918 Added config support to, add support for config filtered value tags. 2023-04-19 20:59:03 -04:00
acb95317f0 Config concurrency improvements 2023-04-19 20:16:29 -04:00
60fd4f74a8 Removed the site config support for now, there might be a better way 2023-04-19 19:54:31 -04:00
257b24f930 Javadocs tweaks 2023-04-19 19:51:23 -04:00
247a681e41 Added config mechanism through the Config class.
Updated version to 1.6.0-SNAPSHOT
2023-04-19 19:25:59 -04:00
5bd8135cea Typo fix 2023-04-18 15:41:09 -04:00
4edb90a675 Make executeAutoDownloadPurge available publicly so that it can be overridden in used as a lifecycle event. 2023-04-18 13:23:10 -04:00
6fb113263c Updated version to 1.5.23-SNAPSHOT 2023-04-17 20:31:36 -04:00
d0d452a8a9 Upgraded to bld 1.5.22 2023-04-17 20:30:05 -04:00
3b8bb14a61 Switching back to temurin JDKs 2023-04-17 19:34:11 -04:00
035960525a Switching back to adoptium JDKs 2023-04-17 19:32:41 -04:00
baf3c17dac Updated version to 1.5.22 2023-04-17 19:08:48 -04:00
9d836f9758 Put local class directories before jar files in bld classpaths. 2023-04-17 17:32:27 -04:00
08b5a613bd Disabling JDK 20 tests again 2023-04-16 22:25:15 -04:00
998360c202 Added support for dependency-tree bld command 2023-04-16 22:00:10 -04:00
6e7376f311 Trying a workaround for JDK 20 date format non breaking space. 2023-04-16 21:27:41 -04:00
88f1e5b3d0 Fix for maven property resolution, it should continue until no resolution can be done anymore. 2023-04-15 19:35:49 -04:00
35689f4442 Updated version to 1.5.21-SNAPSHOT.
Updated Jetty to 11.0.15.
2023-04-14 22:32:47 -04:00
827170170d Updated version to 1.5.20. 2023-04-14 20:45:35 -04:00
ad43626cea More improvements to JUnitOperation, added support for additional commandline options. 2023-04-13 15:21:41 -04:00
783f87ca1b Improvements to JUnitOperation, additional of JUnitOptions 2023-04-13 11:21:04 -04:00
80326f6bd0 Test fix, minor refactoring. 2023-04-12 11:33:29 -04:00
d24940fd8a Minor doc tweaks 2023-04-12 11:19:54 -04:00
4ceeb4ddcf Extracted BaseProject with only the essential commands for a Java project, nothing packaging related. Added new create-base command to create a Java project without any dependencies. 2023-04-12 11:12:50 -04:00
150817adc9 Remove trailing periods from standard dash argument descriptions to fit task summary format 2023-04-12 05:38:13 -04:00
a862d86621 Updated some dependencies 2023-04-12 04:35:04 -04:00
2abcb8f6b0 Improved purge operation to list the directories the files were purged from. 2023-04-12 04:34:34 -04:00
4d8efd7032 Javadocs 2023-04-11 20:24:39 -04:00
01cea132ad Javadocs 2023-04-11 07:08:27 -04:00
9380776081 Javadocs and tests 2023-04-11 06:44:26 -04:00
7741e4c53f Cleanups 2023-04-11 06:34:01 -04:00
21463ef7b5 Added more options to Convert class to allow conversion from String with standard static method names. 2023-04-11 06:32:51 -04:00
b43651c6b6 Updated version to 1.5.20-SNAPSHOT 2023-04-10 23:17:48 -04:00
7e3f37c9b1 Added additional fallback in DbBeanFetcher property conversion logic 2023-04-10 22:40:03 -04:00
13a1f2ce0e Added workaround for legacy MySQL timestamp usage idiom 2023-04-10 22:21:55 -04:00
116 changed files with 8828 additions and 1779 deletions

View file

@ -69,7 +69,7 @@ jobs:
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v3
with:
distribution: 'zulu'
distribution: 'temurin'
java-version: ${{ matrix.java-version }}
- name: Run tests

7
.idea/codeStyles/Project.xml generated Normal file
View file

@ -0,0 +1,7 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<ScalaCodeStyleSettings>
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
</ScalaCodeStyleSettings>
</code_scheme>
</component>

View file

@ -2,11 +2,11 @@
<library name="bld">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/bld" />
<root url="jar://$USER_HOME$/.rife2/dist/rife2-1.5.19.jar!/" />
<root url="jar://$USER_HOME$/.rife2/dist/rife2-1.5.22.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.rife2/dist/rife2-1.5.19-sources.jar!/" />
<root url="jar://$USER_HOME$/.rife2/dist/rife2-1.5.22-sources.jar!/" />
</SOURCES>
<excluded>
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />

View file

@ -2,6 +2,7 @@
<library name="runtime">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/runtime" />
<root url="file://$PROJECT_DIR$/src/main/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>

View file

@ -2,6 +2,7 @@
<library name="test">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/test" />
<root url="file://$PROJECT_DIR$/src/test/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>

View file

@ -1,14 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Tests" type="JUnit" factoryName="JUnit">
<classpathModifications>
<entry path="$PROJECT_DIR$/src/test/resources" />
<entry path="$PROJECT_DIR$/src/main/resources" />
</classpathModifications>
<module name="app" />
<option name="PACKAGE_NAME" value="moog" />
<module name="framework" />
<option name="PACKAGE_NAME" value="rife" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="directory" />
<option name="TEST_OBJECT" value="package" />
<dir value="$PROJECT_DIR$/src/test/java" />
<method v="2">
<option name="Make" enabled="true" />

View file

@ -4,7 +4,7 @@
<entry path="$PROJECT_DIR$/src/main/resources" />
</classpathModifications>
<option name="MAIN_CLASS_NAME" value="rife.bld.Cli" />
<module name="app" />
<module name="framework" />
<method v="2">
<option name="Make" enabled="true" />
</method>

Binary file not shown.

View file

@ -2,7 +2,7 @@ bld.downloadExtensionJavadoc=false
bld.downloadExtensionSources=true
bld.extension-antlr=com.uwyn.rife2:bld-antlr4:1.0.0
bld.extension-archive=com.uwyn.rife2:bld-archive:0.2.0
bld.extension-tests=com.uwyn.rife2:bld-tests-badge:1.1.0
bld.extension-tests=com.uwyn.rife2:bld-tests-badge:1.2.0
bld.repositories=MAVEN_CENTRAL,RIFE2_RELEASES
rife2.downloadLocation=
rife2.version=1.5.19
rife2.version=1.5.22

View file

@ -43,27 +43,27 @@ public class Rife2Build extends Project {
repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES);
scope(provided)
.include(dependency("org.jsoup", "jsoup", version(1,15,4)))
.include(dependency("org.eclipse.jetty", "jetty-server", version(11,0,14)))
.include(dependency("org.eclipse.jetty", "jetty-servlet", version(11,0,14)))
.include(dependency("org.eclipse.jetty", "jetty-server", version(11,0,15)))
.include(dependency("org.eclipse.jetty", "jetty-servlet", version(11,0,15)))
.include(dependency("jakarta.servlet", "jakarta.servlet-api", version(5,0,0)))
.include(dependency("net.imagej", "ij", version("1.54b")));
.include(dependency("net.imagej", "ij", version("1.54d")));
scope(test)
.include(dependency("org.jsoup", "jsoup", version(1,15,4)))
.include(dependency("jakarta.servlet", "jakarta.servlet-api", version(5,0,0)))
.include(dependency("org.eclipse.jetty", "jetty-server", version(11,0,14)))
.include(dependency("org.eclipse.jetty", "jetty-servlet", version(11,0,14)))
.include(dependency("org.slf4j", "slf4j-simple", version(2,0,6)))
.include(dependency("net.imagej", "ij", version("1.54b")))
.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)))
.include(dependency("net.imagej", "ij", version("1.54d")))
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5,9,2)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1,9,2)))
.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,5,4)))
.include(dependency("org.postgresql", "postgresql", version(42,6,0)))
.include(dependency("com.mysql", "mysql-connector-j", version(8,0,32)))
.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("21.9.0.0")))
.include(dependency("com.oracle.database.jdbc", "ojdbc11", version("23.2.0.0")))
.include(dependency("org.json", "json", version(20230227)));
cleanOperation()

File diff suppressed because it is too large Load diff

View file

@ -214,6 +214,11 @@ public class BuildExecutor {
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);
@ -249,9 +254,6 @@ public class BuildExecutor {
}
}
if (show_help) {
help();
}
return exitStatus_;
}

View file

@ -17,6 +17,7 @@ import rife.bld.operations.*;
public class Cli extends BuildExecutor {
private final CreateRife2Operation createRife2Operation_ = new CreateRife2Operation();
private final CreateBlankOperation createBlankOperation_ = new CreateBlankOperation();
private final CreateBaseOperation createBaseOperation_ = new CreateBaseOperation();
private final UpgradeOperation upgradeOperation_ = new UpgradeOperation();
private final VersionOperation versionOperation_ = new VersionOperation();
@ -44,6 +45,18 @@ public class Cli extends BuildExecutor {
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 upgrade} command.
*

File diff suppressed because it is too large Load diff

View 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);
}
}

View file

@ -15,10 +15,12 @@ import java.util.regex.Pattern;
* @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) {
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";
@ -39,12 +41,17 @@ public record Dependency(String groupId, String artifactId, VersionNumber versio
}
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>[^:@]+))?$");

View file

@ -5,22 +5,12 @@
package rife.bld.dependencies;
import rife.bld.dependencies.exceptions.*;
import rife.tools.FileUtils;
import rife.tools.exceptions.FileUtilsErrorException;
import java.io.*;
import java.net.URL;
import java.nio.channels.Channels;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import static rife.tools.HttpUtils.HEADER_AUTHORIZATION;
import static rife.tools.HttpUtils.basicAuthorizationHeader;
import static rife.tools.StringUtils.encodeHexLower;
/**
* Resolves a dependency within a list of Maven-compatible repositories.
*
@ -105,7 +95,7 @@ public class DependencyResolver {
* @since 1.5
*/
public DependencySet getDirectDependencies(Scope... scopes) {
var pom_dependencies = getMavenPom(convertDependency(dependency_)).getDependencies(scopes);
var pom_dependencies = getMavenPom(dependency_).getDependencies(scopes);
var result = new DependencySet();
for (var dependency : pom_dependencies) {
result.add(convertPomDependency(dependency));
@ -132,7 +122,7 @@ public class DependencyResolver {
var dependency_queue = new ArrayList<PomDependency>();
var parent = convertDependency(dependency_);
var parent = dependency_;
var next_dependencies = getMavenPom(parent).getDependencies(scopes);
while (parent != null && next_dependencies != null) {
@ -159,7 +149,7 @@ public class DependencyResolver {
// 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 = candidate;
parent = dependency;
next_dependencies = new DependencyResolver(retriever_, repositories_, dependency).getMavenPom(parent).getDependencies(scopes);
break;
}
@ -168,7 +158,7 @@ public class DependencyResolver {
return result;
}
private boolean matchesExclusions(PomDependency context, PomDependency checked) {
private boolean matchesExclusions(Dependency context, PomDependency checked) {
while (context != null) {
if (context.exclusions() != null) {
for (var exclusion : context.exclusions()) {
@ -338,17 +328,18 @@ public class DependencyResolver {
}
private PomDependency convertDependency(Dependency dependency) {
return new PomDependency(null, dependency.groupId(), dependency.artifactId(), dependency.version().toString(), dependency.type(), dependency.type(), "compile", "false", dependency.exclusions());
return new PomDependency(dependency.groupId(), dependency.artifactId(), dependency.version().toString(), dependency.type(), dependency.type(), "compile", "false", dependency.exclusions(), dependency.parent());
}
private Dependency convertPomDependency(PomDependency pomDependency) {
return new Dependency(
pomDependency.groupId(),
pomDependency.artifactId(),
VersionNumber.parse(pomDependency.version()),
pomDependency.classifier(),
pomDependency.type(),
pomDependency.exclusions());
pomDependency.groupId(),
pomDependency.artifactId(),
VersionNumber.parse(pomDependency.version()),
pomDependency.classifier(),
pomDependency.type(),
pomDependency.exclusions(),
pomDependency.parent());
}
private List<RepositoryArtifact> getArtifactLocations() {
@ -411,7 +402,7 @@ public class DependencyResolver {
return getArtifactLocations().stream().map(a -> a.appendPath(version + "/" + dependency_.artifactId() + "-" + pom_version + ".pom")).toList();
}
Xml2MavenPom getMavenPom(PomDependency parent) {
Xml2MavenPom getMavenPom(Dependency parent) {
RepositoryArtifact retrieved_artifact = null;
String pom = null;
var artifacts = getPomLocations();

View file

@ -135,6 +135,102 @@ public class DependencySet extends AbstractSet<Dependency> implements Set<Depend
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) {

View file

@ -17,7 +17,7 @@ import java.util.*;
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @since 1.5
*/
public record PomDependency(PomDependency parent, String groupId, String artifactId, String version, String classifier, String type, String scope, String optional, ExclusionSet exclusions) {
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;

View file

@ -17,7 +17,7 @@ import java.util.regex.Pattern;
* @since 1.5.18
*/
class Xml2MavenPom extends Xml2Data {
private final PomDependency parent_;
private final Dependency parent_;
private final ArtifactRetriever retriever_;
private final List<Repository> repositories_;
private Map<Scope, Set<PomDependency>> resolvedDependencies_ = null;
@ -45,7 +45,7 @@ class Xml2MavenPom extends Xml2Data {
private String lastExclusionGroupId_ = null;
private String lastExclusionArtifactId_ = null;
Xml2MavenPom(PomDependency parent, ArtifactRetriever retriever, List<Repository> repositories) {
Xml2MavenPom(Dependency parent, ArtifactRetriever retriever, List<Repository> repositories) {
parent_ = parent;
retriever_ = retriever;
repositories_ = repositories;
@ -89,7 +89,6 @@ class Xml2MavenPom extends Xml2Data {
}
var resolved_dependency = new PomDependency(
dependency.parent(),
resolveProperties(dependency.groupId()),
resolveProperties(dependency.artifactId()),
resolveProperties(version),
@ -97,7 +96,8 @@ class Xml2MavenPom extends Xml2Data {
resolveProperties(dependency.type()),
dep_scope,
"false",
exclusions);
exclusions,
dependency.parent());
if (resolved_dependency.type() == null || resolved_dependency.type().equals("jar")) {
var resolved_dependency_set = resolved_dependencies.computeIfAbsent(Scope.valueOf(resolved_dependency.scope()), k -> new LinkedHashSet<>());
resolved_dependency_set.add(resolved_dependency);
@ -163,7 +163,6 @@ class Xml2MavenPom extends Xml2Data {
var parent_dependency = new Dependency(lastGroupId_, lastArtifactId_, VersionNumber.parse(lastVersion_));
var parent = new DependencyResolver(retriever_, repositories_, parent_dependency).getMavenPom(parent_);
parent.properties_.keySet().removeAll(properties_.keySet());
properties_.putAll(parent.properties_);
@ -186,7 +185,7 @@ class Xml2MavenPom extends Xml2Data {
}
}
case "dependency" -> {
var dependency = new PomDependency(parent_, lastGroupId_, lastArtifactId_, lastVersion_, lastClassifier_, lastType_, lastScope_, lastOptional_, exclusions_);
var dependency = new PomDependency(lastGroupId_, lastArtifactId_, lastVersion_, lastClassifier_, lastType_, lastScope_, lastOptional_, exclusions_, parent_);
if (collectDependencyManagement_) {
dependencyManagement_.put(dependency, dependency);
} else if (collectDependencies_) {
@ -293,24 +292,33 @@ class Xml2MavenPom extends Xml2Data {
return null;
}
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();
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));
}
if (last_end < data.length()) {
processed_data.append(data.substring(last_end));
}
return processed_data.toString();
data = processed_data.toString();
} while (replaced);
return data;
}
private void resetState() {

View 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 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);
}
}

View 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);
}
}

View 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);
}
}

View file

@ -157,7 +157,9 @@ public abstract class AbstractCreateOperation<T extends AbstractCreateOperation<
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_);
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);
@ -167,7 +169,12 @@ public abstract class AbstractCreateOperation<T extends AbstractCreateOperation<
build_template.setValue("package", project_.pkg());
build_template.setValue("project", projectClassName_);
build_template.setValue("projectMain", projectMainName_);
if (build_template.hasValueId("projectMainUber")) build_template.setValue("projectMainUber", projectMainUberName_);
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");
@ -252,6 +259,9 @@ public abstract class AbstractCreateOperation<T extends AbstractCreateOperation<
// 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);
}
@ -266,6 +276,9 @@ public abstract class AbstractCreateOperation<T extends AbstractCreateOperation<
var launch_template = TemplateFactory.JSON.get(templateBase_ + "vscode.launch");
launch_template.setValue("package", project_.pkg());
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);

View file

@ -4,7 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.Project;
import rife.bld.BaseProject;
import rife.bld.operations.exceptions.ExitStatusException;
import rife.bld.operations.exceptions.OperationOptionException;
import rife.tools.exceptions.FileUtilsErrorException;
@ -28,7 +28,6 @@ public abstract class AbstractProcessOperation<T extends AbstractProcessOperatio
protected final JavaOptions javaOptions_ = new JavaOptions();
protected final List<String> classpath_ = new ArrayList<>();
protected String mainClass_;
protected final List<String> processOptions_ = new ArrayList<>();
protected Function<String, Boolean> outputProcessor_;
protected Function<String, Boolean> errorProcessor_;
protected Process process_;
@ -129,12 +128,12 @@ public abstract class AbstractProcessOperation<T extends AbstractProcessOperatio
}
/**
* Configures the operation from a {@link Project}.
* Configures the operation from a {@link BaseProject}.
*
* @param project the project to configure the operation from
* @since 1.5
*/
abstract public T fromProject(Project project);
abstract public T fromProject(BaseProject project);
/**
* Provides the work directory in which the operation will be performed.

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.tools.FileUtils;
import rife.tools.exceptions.FileUtilsErrorException;
@ -50,12 +51,12 @@ public class CleanOperation extends AbstractOperation<CleanOperation> {
}
/**
* Configures a clean operation from a {@link Project}.
* Configures a clean operation from a {@link BaseProject}.
*
* @param project the project to configure the clean operation from
* @since 1.5
*/
public CleanOperation fromProject(Project project) {
public CleanOperation fromProject(BaseProject project) {
return directories(List.of(
project.buildDirectory()
.listFiles(f -> !f.equals(project.buildBldDirectory()))));

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.bld.operations.exceptions.ExitStatusException;
import rife.tools.FileUtils;
@ -151,12 +152,12 @@ public class CompileOperation extends AbstractOperation<CompileOperation> {
}
/**
* Configures a compile operation from a {@link Project}.
* Configures a compile operation from a {@link BaseProject}.
*
* @param project the project to configure the compile operation from
* @since 1.5
*/
public CompileOperation fromProject(Project project) {
public CompileOperation fromProject(BaseProject project) {
var operation = buildMainDirectory(project.buildMainDirectory())
.buildTestDirectory(project.buildTestDirectory())
.compileMainClasspath(project.compileMainClasspath())

View 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());
}
}

View 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(), 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();
}
}

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.bld.dependencies.*;
@ -141,13 +142,14 @@ public class DownloadOperation extends AbstractOperation<DownloadOperation> {
}
/**
* Configures a compile operation from a {@link Project}.
* Configures a compile operation from a {@link BaseProject}.
*
* @param project the project to configure the compile operation from
* @since 1.5
*/
public DownloadOperation fromProject(Project project) {
return repositories(project.repositories())
public DownloadOperation fromProject(BaseProject project) {
return artifactRetriever(project.artifactRetriever())
.repositories(project.repositories())
.dependencies(project.dependencies())
.libCompileDirectory(project.libCompileDirectory())
.libRuntimeDirectory(project.libRuntimeDirectory())

View file

@ -97,9 +97,9 @@ public class HelpOperation {
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.
-?, -h, --help Shows this help message
-D<name>=<value> Set a JVM system property
-s, --stacktrace Print out the stacktrace for exceptions
""");
}
}

View 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;
}
}

View 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;
}
}

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.NamedFile;
import rife.bld.Project;
import rife.tools.FileUtils;
@ -121,12 +122,12 @@ public class JarOperation extends AbstractOperation<JarOperation> {
}
/**
* Configures a jar operation from a {@link Project}.
* Configures a jar operation from a {@link BaseProject}.
*
* @param project the project to configure the jar operation from
* @since 1.5
*/
public JarOperation fromProject(Project project) {
public JarOperation fromProject(BaseProject project) {
return manifestAttributes(Map.of(Attributes.Name.MANIFEST_VERSION, "1.0"))
.sourceDirectories(List.of(project.buildMainDirectory(), project.srcMainResourcesDirectory()))
.destinationDirectory(project.buildDistDirectory())

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.bld.operations.exceptions.ExitStatusException;
import rife.tools.FileUtils;
@ -137,12 +138,12 @@ public class JavadocOperation extends AbstractOperation<JavadocOperation> {
}
/**
* Configures a javadoc operation from a {@link Project}.
* 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(Project project) {
public JavadocOperation fromProject(BaseProject project) {
var operation = buildDirectory(project.buildJavadocDirectory())
.classpath(project.compileMainClasspath())
.classpath(project.buildMainDirectory().getAbsolutePath())

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.template.TemplateDeployer;
import rife.template.TemplateFactory;
@ -78,12 +79,12 @@ public class PrecompileOperation extends AbstractOperation<PrecompileOperation>
}
/**
* Configures a precompile operation from a {@link Project}.
* Configures a precompile operation from a {@link BaseProject}.
*
* @param project the project to configure the precompile operation from
* @since 1.5
*/
public PrecompileOperation fromProject(Project project) {
public PrecompileOperation fromProject(BaseProject project) {
return sourceDirectories(List.of(project.srcMainResourcesTemplatesDirectory()))
.destinationDirectory(project.buildTemplatesDirectory());
}

View file

@ -5,6 +5,7 @@
package rife.bld.operations;
import rife.Version;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.bld.dependencies.*;
import rife.bld.dependencies.exceptions.DependencyException;
@ -491,12 +492,13 @@ public class PublishOperation extends AbstractOperation<PublishOperation> {
}
/**
* Configures a publish operation from a {@link Project}.
* 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(Project project) {
public PublishOperation fromProject(BaseProject project) {
artifactRetriever(project.artifactRetriever());
dependencies().include(project.dependencies());
artifacts(List.of(
new PublishArtifact(new File(project.buildDistDirectory(), project.jarFileName()), "", "jar"),

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.bld.dependencies.*;
@ -135,9 +136,14 @@ public class PurgeOperation extends AbstractOperation<PurgeOperation> {
}
}
boolean printed_header = false;
for (var file : destinationDirectory.listFiles()) {
if (!filenames.contains(file.getName())) {
System.out.println("Deleting : " + file.getName());
if (!printed_header) {
printed_header = true;
System.out.println("Deleting from " + destinationDirectory.getName() + ":");
}
System.out.println(" " + file.getName());
file.delete();
}
}
@ -150,13 +156,14 @@ public class PurgeOperation extends AbstractOperation<PurgeOperation> {
}
/**
* Configures a compile operation from a {@link Project}.
* Configures a compile operation from a {@link BaseProject}.
*
* @param project the project to configure the compile operation from
* @since 1.5
*/
public PurgeOperation fromProject(Project project) {
return repositories(project.repositories())
public PurgeOperation fromProject(BaseProject project) {
return artifactRetriever(project.artifactRetriever())
.repositories(project.repositories())
.dependencies(project.dependencies())
.libCompileDirectory(project.libCompileDirectory())
.libRuntimeDirectory(project.libRuntimeDirectory())

View file

@ -4,7 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.Project;
import rife.bld.BaseProject;
import rife.tools.FileUtils;
import java.util.ArrayList;
@ -17,6 +17,8 @@ import java.util.List;
* @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.
@ -37,12 +39,12 @@ public class RunOperation extends AbstractProcessOperation<RunOperation> {
}
/**
* Configures a run operation from a {@link Project}.
* Configures a run operation from a {@link BaseProject}.
*
* @param project the project to configure the run operation from
* @since 1.5
*/
public RunOperation fromProject(Project project) {
public RunOperation fromProject(BaseProject project) {
var operation = workDirectory(project.workDirectory())
.javaTool(project.javaTool())
.classpath(project.runClasspath())
@ -61,7 +63,7 @@ public class RunOperation extends AbstractProcessOperation<RunOperation> {
* @since 1.5.18
*/
public RunOperation runOptions(String... options) {
processOptions_.addAll(List.of(options));
runOptions_.addAll(List.of(options));
return this;
}
@ -75,7 +77,7 @@ public class RunOperation extends AbstractProcessOperation<RunOperation> {
* @since 1.5.18
*/
public RunOperation runOptions(List<String> options) {
processOptions_.addAll(options);
runOptions_.addAll(options);
return this;
}
@ -86,6 +88,6 @@ public class RunOperation extends AbstractProcessOperation<RunOperation> {
* @since 1.5.18
*/
public List<String> runOptions() {
return processOptions_;
return runOptions_;
}
}

View file

@ -4,11 +4,13 @@
*/
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.
@ -16,8 +18,26 @@ import java.util.List;
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @since 1.5
*/
public class TestOperation extends AbstractProcessOperation<TestOperation> {
public static final String DEFAULT_TEST_TOOL_JUNIT5 = "org.junit.platform.console.ConsoleLauncher";
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
@ -26,40 +46,28 @@ public class TestOperation extends AbstractProcessOperation<TestOperation> {
* @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());
var main_class = mainClass();
if (main_class == null) {
main_class = DEFAULT_TEST_TOOL_JUNIT5;
}
args.add(main_class);
var test_tool_options = testToolOptions();
if (test_tool_options.isEmpty() && main_class.equals(DEFAULT_TEST_TOOL_JUNIT5)) {
test_tool_options.add("--config=junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$ClassName");
test_tool_options.add("--details=verbose");
test_tool_options.add("--scan-classpath");
test_tool_options.add("--disable-banner");
test_tool_options.add("--disable-ansi-colors");
test_tool_options.add("--exclude-engine=junit-platform-suite");
test_tool_options.add("--exclude-engine=junit-vintage");
}
args.addAll(test_tool_options);
return args;
}
/**
* Configures a test operation from a {@link Project}.
* Configures a test operation from a {@link BaseProject}.
*
* @param project the project to configure the test operation from
* @since 1.5
*/
public TestOperation fromProject(Project project) {
public T fromProject(BaseProject project) {
var operation = workDirectory(project.workDirectory())
.javaTool(project.javaTool())
.classpath(project.testClasspath());
@ -76,9 +84,9 @@ public class TestOperation extends AbstractProcessOperation<TestOperation> {
* @return this operation instance
* @since 1.5.18
*/
public TestOperation testToolOptions(String... options) {
processOptions_.addAll(List.of(options));
return this;
public T testToolOptions(String... options) {
testToolOptions_.addAll(List.of(options));
return (T)this;
}
/**
@ -90,9 +98,9 @@ public class TestOperation extends AbstractProcessOperation<TestOperation> {
* @return this operation instance
* @since 1.5
*/
public TestOperation testToolOptions(List<String> options) {
processOptions_.addAll(options);
return this;
public T testToolOptions(List<String> options) {
testToolOptions_.addAll(options);
return (T)this;
}
/**
@ -101,7 +109,7 @@ public class TestOperation extends AbstractProcessOperation<TestOperation> {
* @return the test tool's options
* @since 1.5
*/
public List<String> testToolOptions() {
return processOptions_;
public O testToolOptions() {
return (O)testToolOptions_;
}
}

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.NamedFile;
import rife.bld.Project;
import rife.tools.FileUtils;
@ -103,12 +104,12 @@ public class UberJarOperation extends AbstractOperation<UberJarOperation> {
}
/**
* Configures an uberjar operation from a {@link Project}.
* Configures an uberjar operation from a {@link BaseProject}.
*
* @param project the project to configure the uberjar operation from
* @since 1.5
*/
public UberJarOperation fromProject(Project project) {
public UberJarOperation fromProject(BaseProject project) {
var jars = new ArrayList<>(project.compileClasspathJars());
jars.addAll(project.runtimeClasspathJars());
jars.add(new File(project.buildDistDirectory(), project.jarFileName()));

View file

@ -4,6 +4,7 @@
*/
package rife.bld.operations;
import rife.bld.BaseProject;
import rife.bld.Project;
import rife.bld.dependencies.*;
@ -59,13 +60,14 @@ public class UpdatesOperation extends AbstractOperation<UpdatesOperation> {
}
/**
* Configures an updates operation from a {@link Project}.
* Configures an updates operation from a {@link BaseProject}.
*
* @param project the project to configure the updates operation from
* @since 1.5
*/
public UpdatesOperation fromProject(Project project) {
return repositories(project.repositories())
public UpdatesOperation fromProject(BaseProject project) {
return artifactRetriever(project.artifactRetriever())
.repositories(project.repositories())
.dependencies(project.dependencies());
}

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,12 @@ import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;
/**
* Provides configuration over RIFE2 itself.
*
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @since 1.0
*/
public class RifeConfig {
protected RifeConfig() {
}

View file

@ -0,0 +1,200 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.config;
import rife.config.exceptions.ConfigErrorException;
import rife.ioc.HierarchicalProperties;
import rife.ioc.exceptions.PropertyValueException;
import rife.selector.NameSelector;
import rife.tools.Convert;
import rife.xml.Xml2Data;
import rife.xml.exceptions.XmlErrorException;
import java.util.*;
import org.xml.sax.Attributes;
class Xml2Config extends Xml2Data {
private final HierarchicalProperties properties_;
private final Map<String, String> parameters_;
private final List<String> finalParameters_;
private final Map<String, List<String>> lists_;
private final List<String> finalLists_;
private StringBuilder characterDataStack_ = null;
private String currentListName_ = null;
private String currentParameterName_ = null;
Xml2Config(HierarchicalProperties properties, Map<String, String> parameters, List<String> finalParameters, Map<String, List<String>> lists, List<String> finalLists) {
if (properties == null) {
properties = HierarchicalProperties.createSystemInstance();
}
properties_ = properties;
parameters_ = Objects.requireNonNullElseGet(parameters, HashMap::new);
finalParameters_ = Objects.requireNonNullElseGet(finalParameters, ArrayList::new);
lists_ = Objects.requireNonNullElseGet(lists, HashMap::new);
finalLists_ = Objects.requireNonNullElseGet(finalLists, ArrayList::new);
}
public Map<String, String> getParameters() {
return parameters_;
}
public List<String> getFinalParameters() {
return finalParameters_;
}
public Map<String, List<String>> getLists() {
return lists_;
}
public List<String> getFinalLists() {
return finalLists_;
}
public void startDocument() {
characterDataStack_ = null;
currentListName_ = null;
currentParameterName_ = null;
}
public void endDocument() {
characterDataStack_ = null;
currentListName_ = null;
currentParameterName_ = null;
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
if (qName.equals("param") ||
qName.equals("item") ||
qName.equals("include")) {
characterDataStack_ = new StringBuilder();
}
switch (qName) {
case "config", "item", "include" -> {
// do nothing
}
case "list" -> {
var name = atts.getValue("name");
if (!finalLists_.contains(name)) {
currentListName_ = name;
lists_.put(name, new ArrayList<>());
var final_attribute = atts.getValue("final");
if (final_attribute != null &&
(final_attribute.equals("1") ||
final_attribute.equals("t") ||
final_attribute.equals("true"))) {
finalLists_.add(name);
}
}
}
case "param" -> {
var name = atts.getValue("name");
if (!finalParameters_.contains(name)) {
currentParameterName_ = name;
var final_attribute = atts.getValue("final");
if (final_attribute != null &&
Convert.toBoolean(final_attribute, false)) {
finalParameters_.add(name);
}
}
}
case "value" -> {
var parameter_name = atts.getValue("name");
if (parameters_.containsKey(parameter_name)) {
characterDataStack_.append(parameters_.get(parameter_name));
}
}
case "property" -> {
var property_name = atts.getValue("name");
if (properties_ != null && properties_.contains(property_name)) {
try {
characterDataStack_.append(properties_.get(property_name).getValueString());
} catch (PropertyValueException e) {
throw new XmlErrorException("Error while obtain the String value of property '" + property_name + "'.", e);
}
}
}
case "selector" -> {
var selector_name = atts.getValue("class");
Class<?> klass = null;
try {
// try a complete classname
klass = Class.forName(selector_name);
} catch (ClassNotFoundException ignored) {
}
// try this package's prefix if the class couldn't be found
if (null == klass) {
try {
klass = Class.forName(NameSelector.class.getPackage().getName() + "." + selector_name);
} catch (ClassNotFoundException ignored) {
}
}
// if the class was found, create an instance
if (klass != null) {
try {
Object instance = klass.getDeclaredConstructor().newInstance();
if (instance instanceof NameSelector selector) {
characterDataStack_.append(selector.getActiveName());
}
} catch (Exception e) {
throw new XmlErrorException("Error while obtain the name of selector '" + selector_name + "'.", e);
}
}
}
default -> throw new XmlErrorException("Unsupported element name '" + qName + "'.");
}
}
public void endElement(String namespaceURI, String localName, String qName) {
switch (qName) {
case "config", "value" -> {
// do nothing
}
case "param" -> {
if (currentParameterName_ != null) {
var parameter_name = currentParameterName_;
parameters_.put(parameter_name, characterDataStack_.toString());
currentParameterName_ = null;
}
characterDataStack_ = null;
}
case "list" -> {
currentListName_ = null;
}
case "item" -> {
if (currentListName_ != null) {
lists_.get(currentListName_).add(characterDataStack_.toString());
characterDataStack_ = null;
}
}
case "include" -> {
var included_file = characterDataStack_.toString();
try {
Config.fromXmlResource(included_file, getResourceFinder(), properties_, parameters_, finalParameters_, lists_, finalLists_);
} catch (ConfigErrorException e) {
throw new XmlErrorException("Error while processing the included config file '" + included_file + "'.", e);
}
}
}
}
public void characters(char[] ch, int start, int length) {
if (characterDataStack_ != null &&
length > 0) {
characterDataStack_.append(String.copyValueOf(ch, start, length));
}
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.config.exceptions;
import java.io.Serial;
public class CantFindXmlPathException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = 379094904515534057L;
private String xmlPath_ = null;
public CantFindXmlPathException(String xmlPath) {
super("The xml path '" + xmlPath + "' can't be found.");
xmlPath_ = xmlPath;
}
public String getXmlPath() {
return xmlPath_;
}
}

View file

@ -0,0 +1,25 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.config.exceptions;
import java.io.File;
import java.io.Serial;
public class CantWriteToDestinationException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = 2484476576384120796L;
private File destination_ = null;
public CantWriteToDestinationException(File destination) {
super("The destination file for the XML data '" + destination.getAbsolutePath() + "' is not writable.");
destination_ = destination;
}
public File getDestination() {
return destination_;
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.config.exceptions;
import java.io.Serial;
public class ConfigErrorException extends Exception {
@Serial
private static final long serialVersionUID = 4090824718922884219L;
public ConfigErrorException(Throwable cause) {
super(cause);
}
public ConfigErrorException(String message, Throwable cause) {
super(message, cause);
}
public ConfigErrorException(String message) {
super(message);
}
}

View 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.config.exceptions;
import java.io.Serial;
public class ConfigResourceNotFoundException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = 4477782139859668000L;
private String configSource_ = null;
private String xmlPath_ = null;
public ConfigResourceNotFoundException(String configSource) {
super("Couldn't find a valid resource for config source '" + configSource + "'.");
configSource_ = configSource;
}
public ConfigResourceNotFoundException(String configSource, String xmlPath) {
super("Couldn't find a valid resource for config source '" + configSource + "', tried xml path '" + xmlPath + "'.");
configSource_ = configSource;
xmlPath_ = xmlPath;
}
public String getConfigSource() {
return configSource_;
}
public String getXmlPath() {
return xmlPath_;
}
}

View 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.config.exceptions;
import rife.xml.exceptions.XmlErrorException;
import java.io.Serial;
public class InitializationErrorException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = 6946315757564943787L;
private String xmlPath_ = null;
public InitializationErrorException(String xmlPath, Exception cause) {
super("Fatal error during the generation of the config from the XML document '" + xmlPath + "'.", cause);
xmlPath_ = xmlPath;
}
public String getXmlPath() {
return xmlPath_;
}
}

View 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.config.exceptions;
import java.io.Serial;
public class MissingPreferencesUserNodeException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = -22983055927535074L;
public MissingPreferencesUserNodeException() {
super("No preferences user node has been specified, therefore it's impossible to store the configuration through Java's preferences mechanism.");
}
}

View 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.config.exceptions;
import java.io.Serial;
public class MissingXmlFileException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = 3832381866285443663L;
public MissingXmlFileException() {
super("The XML path is missing.");
}
}

View 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.config.exceptions;
import rife.resources.exceptions.ResourceFinderErrorException;
import java.io.Serial;
public class ModificationTimeErrorException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = 7732505426871416111L;
private String xmlPath_ = null;
public ModificationTimeErrorException(String xmlPath, ResourceFinderErrorException cause) {
super("Error while retrieving the modification time of '" + xmlPath + "'", cause);
xmlPath_ = xmlPath;
}
public String getXmlPath() {
return xmlPath_;
}
}

View file

@ -0,0 +1,25 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.config.exceptions;
import java.io.Serial;
import java.util.prefs.Preferences;
public class StorePreferencesErrorException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = -1781853604693398578L;
private Preferences preferences_ = null;
public StorePreferencesErrorException(Preferences preferences, Throwable cause) {
super("An error occurred while storing the data to the preferences user node '" + preferences.absolutePath() + "'.", cause);
preferences_ = preferences;
}
public Preferences getPreferences() {
return preferences_;
}
}

View file

@ -0,0 +1,25 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.config.exceptions;
import java.io.File;
import java.io.Serial;
public class StoreXmlErrorException extends ConfigErrorException {
@Serial
private static final long serialVersionUID = -1414121432509201830L;
private File destination_ = null;
public StoreXmlErrorException(File destination, Throwable cause) {
super("An error occurred while storing the XML data to the destination file '" + destination.getAbsolutePath() + "'.", cause);
destination_ = destination;
}
public File getDestination() {
return destination_;
}
}

View file

@ -4,7 +4,7 @@
*/
/**
* Provides classes for the configuration of RIFE2 itself.
* Provides classes for the configuration framework and for the configuration of RIFE2 itself.
* @since 1.0
*/
package rife.config;

View file

@ -6,11 +6,14 @@ package rife.database;
import rife.database.exceptions.BeanException;
import rife.database.exceptions.DatabaseException;
import rife.tools.Convert;
import rife.tools.exceptions.ConversionException;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
@ -183,26 +186,28 @@ public class DbBeanFetcher<BeanType> extends DbRowProcessor {
else {
var column_string_value = resultSet.getString(columnIndex);
if (column_string_value != null) {
Constructor<?> constructor;
try {
var constructor = property.getPropertyType().getConstructor(String.class);
if (constructor != null) {
constructor = property.getPropertyType().getConstructor(String.class);
} catch (NoSuchMethodException ignored) {
// couldn't find a string argument constructor
constructor = null;
}
if (constructor != null) {
try {
typed_object = constructor.newInstance((Object[]) new String[]{column_string_value});
} catch (SecurityException e) {
throw new SQLException("No permission to obtain the String constructor of the property with name '" + property.getName() + "' and class '" + property.getPropertyType().getName() + "' of the bean with class '" + beanClass_.getName() + "'.", e);
} catch (InstantiationException e) {
throw new SQLException("Can't instantiate a new instance of the property with name '" + property.getName() + "' and class '" + property.getPropertyType().getName() + "' of the bean with class '" + beanClass_.getName() + "'.", e);
}
} else {
try {
typed_object = Convert.toType(column_string_value, property.getPropertyType());
} catch (ConversionException e) {
throw new SQLException("Unable to convert '" + column_string_value + "' nor could find a String constructor for the property with name '" + property.getName() + "' and class '" + property.getPropertyType().getName() + "' of the bean with class '" + beanClass_.getName() + "'.", e);
}
} catch (SecurityException e) {
instance = null;
var e2 = new SQLException("No permission to obtain the String constructor of the property with name '" + property.getName() + "' and class '" + property.getPropertyType().getName() + "' of the bean with class '" + beanClass_.getName() + "'.");
e2.initCause(e);
throw e2;
} catch (NoSuchMethodException e) {
instance = null;
var e2 = new SQLException("Couldn't find a String constructor for the property with name '" + property.getName() + "' and class '" + property.getPropertyType().getName() + "' of the bean with class '" + beanClass_.getName() + "'.");
e2.initCause(e);
throw e2;
} catch (InstantiationException e) {
instance = null;
var e2 = new SQLException("Can't instantiate a new instance of the property with name '" + property.getName() + "' and class '" + property.getPropertyType().getName() + "' of the bean with class '" + beanClass_.getName() + "'.");
e2.initCause(e);
throw e2;
}
}
}
@ -214,25 +219,13 @@ public class DbBeanFetcher<BeanType> extends DbRowProcessor {
write_method.invoke(instance, typed_object);
}
} catch (IllegalAccessException e) {
instance = null;
var e2 = new SQLException("No permission to invoke the '" + write_method.getName() + "' method on the bean with class '" + beanClass_.getName() + "'.");
e2.initCause(e);
throw e2;
throw new SQLException("No permission to invoke the '" + write_method.getName() + "' method on the bean with class '" + beanClass_.getName() + "'.", e);
} catch (IllegalArgumentException e) {
instance = null;
var e2 = new SQLException("Invalid arguments while invoking the '" + write_method.getName() + "' method on the bean with class '" + beanClass_.getName() + "'.");
e2.initCause(e);
throw e2;
throw new SQLException("Invalid arguments while invoking the '" + write_method.getName() + "' method on the bean with class '" + beanClass_.getName() + "'.", e);
} catch (InvocationTargetException e) {
instance = null;
var e2 = new SQLException("The '" + write_method.getName() + "' method of the bean with class '" + beanClass_.getName() + "' has thrown an exception");
e2.initCause(e);
throw e2;
throw new SQLException("The '" + write_method.getName() + "' method of the bean with class '" + beanClass_.getName() + "' has thrown an exception", e);
} catch (SQLException e) {
instance = null;
var e2 = new SQLException("SQLException while invoking the '" + write_method.getName() + "' method of the bean with class '" + beanClass_.getName() + "'");
e2.initCause(e);
throw e2;
throw new SQLException("SQLException while invoking the '" + write_method.getName() + "' method of the bean with class '" + beanClass_.getName() + "'", e);
}
}
}

View file

@ -138,7 +138,7 @@ public interface GenericQueryManager<BeanType> extends ValidationContext {
* #save(Object bean)}.
*
* @param bean the bean to be inserted
* @return the indentier assigned to the new bean
* @return the identifier assigned to the new bean
* @see #save(Object bean)
* @since 1.0
*/
@ -155,7 +155,7 @@ public interface GenericQueryManager<BeanType> extends ValidationContext {
* #save(Object bean)}.
*
* @param bean the bean to be updated
* @return the indentier assigned to the new bean
* @return the identifier assigned to the new bean
* @see #save(Object bean)
* @since 1.0
*/

View file

@ -120,6 +120,13 @@ public class com_mysql_cj_jdbc_Driver extends Common implements SqlConversion {
result = resultSet.getTime(columnNumber);
} else if (type == Types.TIMESTAMP) {
result = resultSet.getTimestamp(columnNumber);
// legacy MySQL sometimes used "0000-00-00 00:00:00" as timestamp format
// this can't be parsed to a timestamp and thus result as a null instance
// but still results in a string value that can't be parsed either
// later in the code, so we return a Timestamp at epoch time instead
if (result == null && !resultSet.wasNull()) {
result = new Timestamp(0);
}
} else if (type == Types.NUMERIC || type == Types.DECIMAL) {
result = resultSet.getBigDecimal(columnNumber);
} else if (type == Types.DOUBLE || type == Types.FLOAT || type == Types.REAL) {

View file

@ -4,7 +4,9 @@
*/
package rife.engine;
import rife.config.Config;
import rife.config.RifeConfig;
import rife.config.exceptions.ConfigErrorException;
import rife.continuations.ContinuationConfigRuntime;
import rife.continuations.ContinuationContext;
import rife.continuations.exceptions.*;
@ -17,6 +19,7 @@ import rife.template.exceptions.TemplateException;
import rife.tools.*;
import rife.tools.exceptions.BeanUtilsException;
import java.io.File;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
@ -840,7 +843,7 @@ public class Context {
* been set, this is never {@code null}, when no values are set an
* empty list is returned
* @see FormBuilder
* @see FormBuilder#selectParameter
* @see FormBuilder#selectParameter
* @since 1.0
*/
public Collection<String> selectParameter(Template template, String name, String[] values) {
@ -1144,7 +1147,7 @@ public class Context {
public boolean isParameterEmpty(String name) {
var parameter = parameter(name);
return null == parameter ||
parameter.trim().equals("");
parameter.trim().equals("");
}
/**
@ -1676,7 +1679,7 @@ public class Context {
parameter_values = parameterValues(parameter_name);
if (null == empty_bean &&
(null == parameter_values ||
0 == parameter_values[0].length())) {
0 == parameter_values[0].length())) {
empty_bean = getNewBeanInstance(bean.getClass());
}
@ -1741,8 +1744,8 @@ public class Context {
public boolean isFileEmpty(String name) {
try (final var file = file(name)) {
return null == file ||
null == file.getFile() ||
0 == file.getFile().length();
null == file.getFile() ||
0 == file.getFile().length();
}
}
@ -2599,7 +2602,7 @@ public class Context {
* Setting parameters acts on a different collection than incoming request
* parameters and is used for RIFE2 state-related features like URL generation.
*
* @param name the name of the parameter to set
* @param name the name of the parameter to set
* @param value the value of the parameter
* @see #urlFor
* @see #setParametersBean(Object)
@ -2625,7 +2628,7 @@ public class Context {
* @see #removeParameter
* @since 1.0
*/
public void setParametersBean(Object bean) {
public void setParametersBean(Object bean) {
setParametersBean(bean, null);
}
@ -2634,7 +2637,7 @@ public class Context {
* Sets named parameters values from bean properties for URL generation
* with {@link #urlFor} or the `route:` filtered template value tags.
*
* @param bean the bean whose properties will be set as parameters
* @param bean the bean whose properties will be set as parameters
* @param prefix the prefix that will be added to the parameter names
* @see #urlFor
* @see #setParameter
@ -2712,7 +2715,7 @@ public class Context {
* Sets a response header with the given name and value.
* <p>If the header had already been set, the new value overwrites the previous one.
*
* @param name the name of the header
* @param name the name of the header
* @param value the additional header value
* @since 1.0
*/
@ -2724,7 +2727,7 @@ public class Context {
* Adds a response header with the given name and value.
* <p>This method allows response headers to have multiple values.
*
* @param name the name of the header
* @param name the name of the header
* @param value the additional header value
* @since 1.0
*/
@ -2760,9 +2763,8 @@ public class Context {
* Adds a response header with the given name and integer value.
* <p>If the header had already been set, the new value overwrites the previous one.
*
* @param name the name of the header
* @param name the name of the header
* @param value the assigned integer value
*
* @since 1.0
*/
public void setHeader(String name, int value) {
@ -2773,9 +2775,8 @@ public class Context {
* Adds a response header with the given name and integer value.
* <p>This method allows response headers to have multiple values.
*
* @param name the name of the header
* @param name the name of the header
* @param value the assigned integer value
*
* @since 1.0
*/
public void addHeader(String name, int value) {
@ -2791,5 +2792,4 @@ public class Context {
public void setStatus(int statusCode) {
response_.setStatus(statusCode);
}
}

View file

@ -39,6 +39,7 @@ class EngineTemplateProcessor {
processApplicationTags(set_values);
processParameters(set_values);
processProperties(set_values);
processConfig(set_values);
processAttributes(set_values);
processCookies(set_values);
processRoutes(set_values);
@ -131,6 +132,24 @@ class EngineTemplateProcessor {
}
}
private void processConfig(final List<String> setValues) {
var config = context_.site().config();
final var config_tags = template_.getFilteredValues(TemplateFactoryFilters.TAG_CONFIG);
if (config_tags != null) {
for (var captured_groups : config_tags) {
var config_value_id = captured_groups[0];
if (!template_.isValueSet(config_value_id)) {
var param_name = captured_groups[1];
var param_value = config.getString(param_name);
if (param_value != null) {
template_.setValue(config_value_id, encoder_.encode(param_value));
setValues.add(config_value_id);
}
}
}
}
}
private void processAttributes(final List<String> setValues) {
var attribute_names = context_.attributeNames();
final var attr_tags = template_.getFilteredValues(TemplateFactoryFilters.TAG_ATTRIBUTE);

View file

@ -12,6 +12,7 @@ import rife.tools.exceptions.ConversionException;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.*;
abstract class RouteAnnotated implements Route {
@ -84,6 +85,7 @@ abstract class RouteAnnotated implements Route {
if (field.isAnnotationPresent(ActiveSite.class) ||
field.isAnnotationPresent(Body.class) ||
field.isAnnotationPresent(Config.class) ||
field.isAnnotationPresent(Cookie.class) ||
field.isAnnotationPresent(FileUpload.class) ||
field.isAnnotationPresent(Header.class) ||
@ -244,6 +246,40 @@ abstract class RouteAnnotated implements Route {
}
field.set(element, value);
}
} else if (field.isAnnotationPresent(Config.class)) {
var config = context.site().config();
var annotation_name = field.getAnnotation(Config.class).value();
if (annotation_name != null && !annotation_name.isEmpty()) {
name = annotation_name;
}
if (List.class.isAssignableFrom(type)) {
var list_items = config.getStringItems(name);
if (list_items != null) {
var generic_type = field.getGenericType();
if (generic_type instanceof ParameterizedType param_type &&
param_type.getActualTypeArguments().length == 1 &&
param_type.getActualTypeArguments()[0] instanceof Class<?> param_class) {
var converted_list = new ArrayList<>();
for (var item : list_items) {
converted_list.add(Convert.fromString(item, param_class));
}
field.set(element, converted_list);
} else {
field.set(element, list_items);
}
}
} else {
var param_value = config.getString(name);
if (param_value != null) {
Object value;
try {
value = Convert.toType(param_value, type);
} catch (ConversionException e) {
value = Convert.getDefaultValue(type);
}
field.set(element, value);
}
}
} else if (field.isAnnotationPresent(Header.class) &&
shouldProcessInFlow(field.getAnnotation(Header.class).flow())) {
var annotation_name = field.getAnnotation(Header.class).value();

View file

@ -80,6 +80,7 @@ class RouteInstance implements Route {
if (field.isAnnotationPresent(ActiveSite.class) ||
field.isAnnotationPresent(Body.class) ||
field.isAnnotationPresent(Config.class) ||
field.isAnnotationPresent(Cookie.class) ||
field.isAnnotationPresent(FileUpload.class) ||
field.isAnnotationPresent(Header.class) ||

View file

@ -4,11 +4,14 @@
*/
package rife.engine;
import rife.config.Config;
import rife.config.exceptions.ConfigErrorException;
import rife.continuations.ContinuationManager;
import rife.engine.exceptions.EngineException;
import rife.tools.StringUtils;
import rife.workflow.Workflow;
import java.io.File;
import java.util.*;
import java.util.concurrent.ExecutorService;
@ -29,6 +32,8 @@ public class Site extends Router {
final ContinuationManager continuationManager_ = new ContinuationManager(new EngineContinuationConfigRuntime(this));
private Config config_ = new Config();
/**
* Looks up the information of the element that is responsible for handling
* a certain URL and path info.
@ -234,4 +239,49 @@ public class Site extends Router {
public Workflow createWorkflow(ExecutorService executor) {
return new Workflow(executor, properties_);
}
/**
* Returns this site's config instance.
*
* @return this site's config instance.
* @since 1.6.0
*/
public Config config() {
return config_;
}
/**
* Looks for a named resource in the classpath, parses it as an
* XML {@link Config} file and sets it as this site's config
* instance.
*
* @param name the name of the resource to parse
* @throws EngineException when an error occurred during the parsing, or
* if the resource couldn't be found
* @since 1.6.0
*/
public void loadConfig(String name) {
try {
config_ = Config.fromXmlResource(name, properties());
} catch (ConfigErrorException e) {
throw new EngineException(e);
}
}
/**
* Parses the provided file as an XML {@link Config} file and
* sets it as this site's config instance.
*
* @param file the file to parse
* @throws EngineException when an error occurred during the parsing, or
* if the resource couldn't be found
* @since 1.6.0
*/
public void loadConfig(File file) {
try {
config_ = Config.fromXmlFile(file, properties());
} catch (ConfigErrorException e) {
throw new EngineException(e);
}
}
}

View file

@ -4,6 +4,7 @@
*/
package rife.engine;
import rife.tools.Convert;
import rife.tools.StringUtils;
import java.util.*;
@ -118,6 +119,20 @@ public class UrlBuilder {
return this;
}
/**
* Sets an outgoing parameter to a particular value.
* <p>This will override any automatic outgoing parameters that are being published by the {@code Context}.
*
* @param name the name of the parameter
* @param value the value of the parameter
* @return this {@code UrlBuilder} instance
* @since 1.6.0
*/
public UrlBuilder param(String name, Object value) {
parameters_.put(name, new String[]{Convert.toString(value)});
return this;
}
/**
* Sets an outgoing parameter to a particular value.
* <p>This will override any automatic outgoing parameters that are being published by the {@code Context}.

View file

@ -0,0 +1,25 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package rife.engine.annotations;
import java.lang.annotation.*;
/**
* Declares a config parameter.
*
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @since 1.6.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface Config {
/**
* The name of the parameter.
*
* @since 1.0
*/
String value() default "";
}

View file

@ -23,7 +23,7 @@ import java.util.ArrayList;
* <p>
* The resources are looked up in the same order as the order in which the
* directories were specified. This means that if a resource is found in the
* first directory but it is also present in the second, only the first one
* first directory, but it is also present in the second, only the first one
* will match.
*
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
@ -40,8 +40,8 @@ public class ResourceFinderDirectories extends AbstractResourceFinder {
* searched in.
* @since 1.0
*/
public ResourceFinderDirectories(File[] directories) {
directories_ = new ArrayList<File>();
public ResourceFinderDirectories(File ... directories) {
directories_ = new ArrayList<>();
if (directories != null) {
for (var directory : directories) {
@ -58,7 +58,7 @@ public class ResourceFinderDirectories extends AbstractResourceFinder {
File resource = null;
for (var directory : directories_) {
var local_name = name.replace('/', File.separatorChar);
resource = new File(directory.getAbsolutePath() + File.separator + local_name);
resource = new File(new File(directory.getAbsolutePath()), local_name);
if (resource.exists() &&
resource.canRead() &&
resource.isFile()) {

View file

@ -43,12 +43,13 @@ public class TemplateFactory extends EnumClass<String> {
{
ValidationBuilder.TAG_MARK,
ValidationBuilder.TAG_ERRORS,
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_AUTH,
TemplateFactoryFilters.TAG_CONFIG,
TemplateFactoryFilters.TAG_COOKIE,
TemplateFactoryFilters.TAG_L10N,
TemplateFactoryFilters.TAG_PARAM,
TemplateFactoryFilters.TAG_PROPERTY,
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_RENDER,
TemplateFactoryFilters.TAG_ROUTE,
TemplateFactoryFilters.TAG_ROUTE_ACTION,
@ -70,12 +71,13 @@ public class TemplateFactory extends EnumClass<String> {
},
new String[]
{
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_AUTH,
TemplateFactoryFilters.TAG_CONFIG,
TemplateFactoryFilters.TAG_COOKIE,
TemplateFactoryFilters.TAG_L10N,
TemplateFactoryFilters.TAG_PARAM,
TemplateFactoryFilters.TAG_PROPERTY,
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_RENDER,
TemplateFactoryFilters.TAG_ROUTE
},
@ -95,12 +97,13 @@ public class TemplateFactory extends EnumClass<String> {
},
new String[]
{
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_AUTH,
TemplateFactoryFilters.TAG_CONFIG,
TemplateFactoryFilters.TAG_COOKIE,
TemplateFactoryFilters.TAG_L10N,
TemplateFactoryFilters.TAG_PARAM,
TemplateFactoryFilters.TAG_PROPERTY,
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_RENDER,
TemplateFactoryFilters.TAG_ROUTE
},
@ -120,12 +123,13 @@ public class TemplateFactory extends EnumClass<String> {
},
new String[]
{
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_AUTH,
TemplateFactoryFilters.TAG_CONFIG,
TemplateFactoryFilters.TAG_COOKIE,
TemplateFactoryFilters.TAG_L10N,
TemplateFactoryFilters.TAG_PARAM,
TemplateFactoryFilters.TAG_PROPERTY,
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_RENDER,
TemplateFactoryFilters.TAG_ROUTE
},
@ -161,12 +165,13 @@ public class TemplateFactory extends EnumClass<String> {
},
new String[]
{
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_AUTH,
TemplateFactoryFilters.TAG_CONFIG,
TemplateFactoryFilters.TAG_COOKIE,
TemplateFactoryFilters.TAG_L10N,
TemplateFactoryFilters.TAG_PARAM,
TemplateFactoryFilters.TAG_PROPERTY,
TemplateFactoryFilters.TAG_ATTRIBUTE,
TemplateFactoryFilters.TAG_RENDER,
TemplateFactoryFilters.TAG_ROUTE
},

View file

@ -5,29 +5,31 @@
package rife.template;
public class TemplateFactoryFilters {
public static final String PREFIX_ATTRIBUTE = "attribute:";
public static final String PREFIX_AUTH = "auth:";
public static final String PREFIX_CONFIG = "config:";
public static final String PREFIX_COOKIE = "cookie:";
public static final String PREFIX_L10N = "l10n:";
public static final String PREFIX_LANG = "lang:";
public static final String PREFIX_COOKIE = "cookie:";
public static final String PREFIX_PARAM = "param:";
public static final String PREFIX_PROPERTY = "property:";
public static final String PREFIX_ATTRIBUTE = "attribute:";
public static final String PREFIX_RENDER = "render:";
public static final String PREFIX_ROUTE = "route:";
public static final String PREFIX_ROUTE_ACTION = PREFIX_ROUTE + "action:";
public static final String PREFIX_ROUTE_INPUTS = PREFIX_ROUTE + "inputs:";
public static final String PREFIX_AUTH = "auth:";
public static final String TAG_ATTRIBUTE = "^" + PREFIX_ATTRIBUTE + "\\s*([^:]*?)\\s*$";
public static final String TAG_AUTH = "^" + PREFIX_AUTH + "\\s*([^:]*?)\\s*$";
public static final String TAG_AUTH_LOGIN = "^" + PREFIX_AUTH + "\\s*([^:]*?)\\s*::\\s*login\\s*:\\s*([^:]*?)\\s*$";
public static final String TAG_AUTH_ROLE = "^" + PREFIX_AUTH + "\\s*([^:]*?)\\s*::\\s*role\\s*:\\s*([^:]*?)\\s*$";
public static final String TAG_CONFIG = "^" + PREFIX_CONFIG + "\\s*([^:]*?)\\s*$";
public static final String TAG_COOKIE = "^" + PREFIX_COOKIE + "\\s*([^:]*?)\\s*$";
public static final String TAG_L10N = "^" + PREFIX_L10N + "\\s*([^:]*)(?::([^:]*))?\\s*$";
public static final String TAG_LANG = "(?s)^(" + PREFIX_LANG + "[^:]*):\\s*(\\w*)\\s*$";
public static final String TAG_COOKIE = "^" + PREFIX_COOKIE + "\\s*([^:]*?)\\s*$";
public static final String TAG_PARAM = "^" + PREFIX_PARAM + "\\s*([^:]*?)\\s*$";
public static final String TAG_PROPERTY = "^" + PREFIX_PROPERTY + "\\s*([^:]*?)\\s*$";
public static final String TAG_ATTRIBUTE = "^" + PREFIX_ATTRIBUTE + "\\s*([^:]*?)\\s*$";
public static final String TAG_RENDER = "^" + PREFIX_RENDER + "\\s*([^:]*?)\\s*(?::([^:]*))?$";
public static final String TAG_ROUTE = "^" + PREFIX_ROUTE + "\\s*([^:]*?)\\s*$";
public static final String TAG_ROUTE_ACTION = "^" + PREFIX_ROUTE_ACTION + "\\s*([^:]*?)\\s*$";
public static final String TAG_ROUTE_INPUTS = "^" + PREFIX_ROUTE_INPUTS + "\\s*([^:]*?)\\s*$";
public static final String TAG_AUTH = "^" + PREFIX_AUTH + "\\s*([^:]*?)\\s*$";
public static final String TAG_AUTH_LOGIN = "^" + PREFIX_AUTH + "\\s*([^:]*?)\\s*::\\s*login\\s*:\\s*([^:]*?)\\s*$";
public static final String TAG_AUTH_ROLE = "^" + PREFIX_AUTH + "\\s*([^:]*?)\\s*::\\s*role\\s*:\\s*([^:]*?)\\s*$";
}

View file

@ -6,11 +6,24 @@ package rife.tools;
import java.util.Date;
/**
* The ClassUtils class provides useful utility methods for working with Java classes.
*
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @since 1.0
*/
public final class ClassUtils {
private ClassUtils() {
// no-op
}
/**
* Returns true if the specified class is numeric.
*
* @param klass the class to check
* @return true if the specified class is numeric, false otherwise
* @since 1.0
*/
public static boolean isNumeric(Class klass) {
return Number.class.isAssignableFrom(klass) ||
byte.class == klass ||
@ -21,12 +34,26 @@ public final class ClassUtils {
double.class == klass;
}
/**
* Returns true if the specified class is text.
*
* @param klass the class to check
* @return true if the specified class is text, false otherwise
* @since 1.0
*/
public static boolean isText(Class klass) {
return CharSequence.class.isAssignableFrom(klass) ||
Character.class == klass ||
char.class == klass;
}
/**
* Returns true if the specified class is a basic type.
*
* @param klass the class to check
* @return true if the specified class is a basic type, false otherwise
* @since 1.0
*/
public static boolean isBasic(Class klass) {
if (null == klass) {
return false;
@ -40,6 +67,13 @@ public final class ClassUtils {
isText(klass);
}
/**
* Returns true if the specified class is from the JDK.
*
* @param klass the class to check
* @return true if the specified class is from the JDK, false otherwise
* @since 1.0
*/
public static boolean isFromJdk(Class klass) {
if (null == klass) {
return false;
@ -48,6 +82,13 @@ public final class ClassUtils {
return isBasic(klass) || klass.getClassLoader() == Object.class.getClassLoader();
}
/**
* Returns the simple name of the specified class without the package name.
*
* @param klass the class whose simple name to return
* @return the simple name of the specified class
* @since 1.0
*/
public static String simpleClassName(Class klass) {
var class_name = klass.getName();
if (klass.getPackage() != null) {
@ -57,10 +98,24 @@ public final class ClassUtils {
return class_name;
}
/**
* Returns a shortened version of the specified class name, with "$" characters replaced by underscores.
*
* @param klass the class whose name to shorten
* @return a shortened version of the specified class name
* @since 1.0
*/
public static String shortenClassName(Class klass) {
return simpleClassName(klass).replace('$', '_');
}
/**
* Returns an array of the values of the enum constants of the specified class, or null if the class is not an enum.
*
* @param klass the class whose enum constant values to return
* @return an array of the values of the enum constants of the specified class, or null if the class is not an enum
* @since 1.0
*/
public static String[] getEnumClassValues(Class klass) {
if (klass.isEnum()) {
var values = klass.getEnumConstants();

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
package rife.xml;
import rife.resources.ResourceFinder;
import rife.resources.ResourceFinderClasspath;
import rife.xml.exceptions.CantFindEntityException;
import java.net.MalformedURLException;
@ -99,6 +100,12 @@ public class XmlEntityResolver implements EntityResolver {
resource = resourceFinder_.getResource(systemId);
if (resource != null) {
return new XmlInputSource(resource);
}
resource = ResourceFinderClasspath.instance().getResource(systemId);
if (null == resource) {
throw new CantFindEntityException(systemId, null);
}

View file

@ -17,23 +17,6 @@ import org.xml.sax.InputSource;
public class XmlInputSource extends InputSource {
private URL resource_ = null;
public XmlInputSource(String xmlPath, ResourceFinder resourceFinder)
throws XmlErrorException {
super();
if (null == xmlPath) throw new IllegalArgumentException("xmlPath can't be null.");
if (xmlPath.length() == 0) throw new IllegalArgumentException("xmlPath can't be empty.");
if (null == resourceFinder) throw new IllegalArgumentException("resourceFinder can't be null.");
var resource = resourceFinder.getResource(xmlPath);
if (null == resource) {
throw new CantFindResourceException(xmlPath, null);
}
setResource(resource);
}
public XmlInputSource(URL resource)
throws XmlErrorException {
super();

View file

@ -1 +1 @@
1.5.19
1.6.0-SNAPSHOT

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
- Licensed under the Apache License, Version 2.0 (the "License")
- PUBLIC ID: -//RIFE2//RIFE2 Config 2.0//EN
- SYSTEM ID: https://rife2.com/dtd/config_2_0.dtd
-->
<!ELEMENT config (param|list|include)*>
<!ELEMENT param (#PCDATA|value|property|selector)*>
<!ATTLIST param name CDATA #REQUIRED
final (0|f|false|1|t|true) "false">
<!ELEMENT value EMPTY>
<!ATTLIST value name CDATA #REQUIRED>
<!ELEMENT list (item*)>
<!ATTLIST list name CDATA #REQUIRED
final (0|f|false|1|t|true) "false">
<!ELEMENT item (#PCDATA|value|property|selector)*>
<!ELEMENT include (#PCDATA|value|property|selector)*>
<!ELEMENT property EMPTY>
<!ATTLIST property name CDATA #REQUIRED>
<!ELEMENT selector EMPTY>
<!ATTLIST selector class CDATA #REQUIRED>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/build/main" />
<output-test url="file://$MODULE_DIR$/build/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/src/main/resources/templates" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" scope="RUNTIME">
<library>
<CLASSES>
<root url="file://$MODULE_DIR$/src/main/resources/templates" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" name="compile" level="project" />
<orderEntry type="library" scope="RUNTIME" name="runtime" level="project" />
<orderEntry type="library" scope="TEST" name="test" level="project" />
</component>
</module>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/build/bld" />
<output-test url="file://$MODULE_DIR$/build/bld" />
<exclude-output />
<content url="file://$MODULE_DIR$/src/bld">
<sourceFolder url="file://$MODULE_DIR$/src/bld/java" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="bld" level="project" />
</component>
</module>

View file

@ -0,0 +1,17 @@
<component name="libraryTable">
<library name="bld">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/bld" />
<root url="jar://$USER_HOME$/.rife2/dist/rife2-{{v version/}}.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.rife2/dist/rife2-{{v version/}}-sources.jar!/" />
</SOURCES>
<excluded>
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />
</excluded>
<jarDirectory url="file://$PROJECT_DIR$/lib/bld" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/bld" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="compile">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/compile" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/compile" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -0,0 +1,14 @@
<component name="libraryTable">
<library name="runtime">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/runtime" />
<root url="file://$PROJECT_DIR$/src/main/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/runtime" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -0,0 +1,14 @@
<component name="libraryTable">
<library name="test">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/test" />
<root url="file://$PROJECT_DIR$/src/test/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/lib/test" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build" />
</component>
</project>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/app.iml" filepath="$PROJECT_DIR$/.idea/app.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/bld.iml" filepath="$PROJECT_DIR$/.idea/bld.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Main" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="{{v package/}}.{{v projectMain/}}" />
<module name="app" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View file

@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Tests" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="{{v package/}}.{{v projectTest/}}" />
<module name="app" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View file

@ -0,0 +1,20 @@
package {{v package/}};
import rife.bld.BaseProject;
import java.util.List;
public class {{v projectBuild/}} extends BaseProject {
public {{v projectBuild/}}() {
pkg = "{{v package/}}";
name = "{{v project/}}";
mainClass = "{{v package/}}.{{v projectMain/}}";
version = version(0,1,0);
testOperation().mainClass("{{v package/}}.{{v projectTest/}}");
}
public static void main(String[] args) {
new {{v projectBuild/}}().start(args);
}
}

View file

@ -0,0 +1,55 @@
.gradle
.DS_Store
build
lib/bld/**
lib/compile/**
lib/runtime/**
lib/standalone/**
lib/test/**
!bld-wrapper.jar
!bld-wrapper.properties
# IDEA ignores
# User-specific
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Editor-based Rest Client
.idea/httpRequests

View file

@ -0,0 +1,11 @@
package {{v package/}};
public class {{v projectMain/}} {
public String getMessage() {
return "Hello World!";
}
public static void main(String[] args) {
System.out.println(new {{v projectMain/}}().getMessage());
}
}

View file

@ -0,0 +1,13 @@
package {{v package/}};
public class {{v projectTest/}} {
void verifyHello() {
if (!"Hello World!".equals(new {{v projectMain/}}().getMessage())) {
throw new AssertionError();
}
}
public static void main(String[] args) {
new {{v projectTest/}}().verifyHello();
}
}

View file

@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Run Main",
"request": "launch",
"mainClass": "{{v package/}}.{{v projectMain/}}"
},
{
"type": "java",
"name": "Run Tests",
"request": "launch",
"mainClass": "{{v package/}}.{{v projectTest/}}"
}
]
}

View file

@ -0,0 +1,15 @@
{
"java.project.sourcePaths": [
"src/main/java",
"src/main/resources",
"src/test/java",
"src/bld/java"
],
"java.configuration.updateBuildConfiguration": "automatic",
"java.project.referencedLibraries": [
"${HOME}/.rife2/dist/rife2-{{v version/}}.jar",
"lib/compile/*.jar",
"lib/runtime/*.jar",
"lib/test/*.jar"
]
}

View file

@ -2,6 +2,7 @@
<library name="runtime">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/runtime" />
<root url="file://$PROJECT_DIR$/src/main/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>

View file

@ -2,6 +2,7 @@
<library name="test">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/test" />
<root url="file://$PROJECT_DIR$/src/test/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>

View file

@ -2,6 +2,7 @@
<library name="runtime">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/runtime" />
<root url="file://$PROJECT_DIR$/src/main/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>

View file

@ -2,6 +2,7 @@
<library name="test">
<CLASSES>
<root url="file://$PROJECT_DIR$/lib/test" />
<root url="file://$PROJECT_DIR$/src/test/resources" />
</CLASSES>
<JAVADOC />
<SOURCES>

View file

@ -183,7 +183,7 @@ public class TestProject {
var project = new CustomProjectInlineHelp(tmp);
project.execute(new String[]{""});
assertTrue(out.toString(StandardCharsets.UTF_8).contains("newcommand mysummary"));
assertTrue(out.toString(StandardCharsets.UTF_8).contains("newcommand mysummary"));
out.reset();
project.execute(new String[]{"help", "newcommand"});
@ -238,7 +238,7 @@ public class TestProject {
try {
var result = new StringBuilder();
var project = new CustomProjectLambda(tmp, result);
project.execute(new String[]{"ne", "nc", "n"});
project.execute(new String[]{"ne2", "nc2", "n2"});
assertEquals("newcommand2" +
"newcommand2" +
"newcommand2", result.toString());

View file

@ -597,7 +597,7 @@ public class TestDependencyResolver {
org.webjars.npm:mobile-drag-drop:2.3.0-rc.2
com.vaadin:vaadin-flow-components-base:23.3.7
org.apache.commons:commons-lang3:3.12.0
com.fasterxml.jackson.core:jackson-annotations
com.fasterxml.jackson.core:jackson-annotations:2.14.1
com.github.oshi:oshi-core:6.1.6
com.auth0:java-jwt:3.19.2
com.helger.commons:ph-commons
@ -998,7 +998,7 @@ public class TestDependencyResolver {
gwt-elemental-2.8.2.vaadin2.jar
httpclient-4.5.13.jar
httpcore-4.4.13.jar
jackson-annotations-2.14.2.jar
jackson-annotations-2.14.1.jar
jackson-core-2.14.1.jar
jackson-databind-2.14.1.jar
jackson-datatype-jsr310-2.14.1.jar
@ -1012,7 +1012,7 @@ public class TestDependencyResolver {
mobile-drag-drop-2.3.0-rc.2.jar
open-8.5.0.jar
oshi-core-6.1.6.jar
ph-commons-11.0.2.jar
ph-commons-11.0.3.jar
ph-css-6.5.0.jar
slf4j-api-1.7.36.jar
throw-if-servlet5-1.0.2.jar

View file

@ -7,7 +7,13 @@ package rife.bld.dependencies;
import org.junit.jupiter.api.Test;
import rife.tools.StringUtils;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static rife.bld.dependencies.Repository.MAVEN_CENTRAL;
import static rife.bld.dependencies.Repository.SONATYPE_SNAPSHOTS;
import static rife.bld.dependencies.Scope.compile;
import static rife.bld.dependencies.Scope.runtime;
public class TestDependencySet {
@Test
@ -72,4 +78,281 @@ public class TestDependencySet {
org.eclipse.jetty:jetty-io:11.0.14
org.eclipse.jetty:jetty-util:11.0.14""", StringUtils.join(set_union2, "\n"));
}
@Test
void testGenerateDependencyTreeJettySlf4j() {
var dependencies = new DependencySet()
.include(new Dependency("org.eclipse.jetty", "jetty-server", new VersionNumber(11, 0, 14)))
.include(new Dependency("org.slf4j", "slf4j-simple", new VersionNumber(2, 0, 6)));
assertEquals("""
org.eclipse.jetty:jetty-server:11.0.14
org.eclipse.jetty.toolchain:jetty-jakarta-servlet-api:5.0.2
org.eclipse.jetty:jetty-http:11.0.14
org.eclipse.jetty:jetty-util:11.0.14
org.eclipse.jetty:jetty-io:11.0.14
org.slf4j:slf4j-simple:2.0.6
org.slf4j:slf4j-api:2.0.6
""", dependencies.generateTransitiveDependencyTree(ArtifactRetriever.instance(), List.of(MAVEN_CENTRAL), compile));
}
@Test
void testGenerateDependencyTreeSpringBoot() {
var dependencies = new DependencySet()
.include(new Dependency("org.springframework.boot", "spring-boot-starter", new VersionNumber(3, 0, 4)));
assertEquals("""
org.springframework.boot:spring-boot-starter:3.0.4
org.springframework.boot:spring-boot:3.0.4
org.springframework:spring-context:6.0.6
org.springframework:spring-aop:6.0.6
org.springframework:spring-beans:6.0.6
org.springframework:spring-expression:6.0.6
org.springframework.boot:spring-boot-autoconfigure:3.0.4
org.springframework.boot:spring-boot-starter-logging:3.0.4
ch.qos.logback:logback-classic:1.4.5
ch.qos.logback:logback-core:1.4.5
org.slf4j:slf4j-api:2.0.4
org.apache.logging.log4j:log4j-to-slf4j:2.19.0
org.apache.logging.log4j:log4j-api:2.19.0
org.slf4j:jul-to-slf4j:2.0.6
jakarta.annotation:jakarta.annotation-api:2.1.1
org.springframework:spring-core:6.0.6
org.springframework:spring-jcl:6.0.6
org.yaml:snakeyaml:1.33
""", dependencies.generateTransitiveDependencyTree(ArtifactRetriever.instance(), List.of(MAVEN_CENTRAL), compile));
}
@Test
void testGenerateDependencyTreeMaven() {
var dependencies = new DependencySet()
.include(new Dependency("org.apache.maven", "maven-core", new VersionNumber(3, 9, 0)));
assertEquals("""
org.apache.maven:maven-core:3.9.0
org.apache.maven:maven-model:3.9.0
org.apache.maven:maven-settings:3.9.0
org.apache.maven:maven-settings-builder:3.9.0
org.codehaus.plexus:plexus-sec-dispatcher:2.0
org.codehaus.plexus:plexus-cipher:2.0
org.apache.maven:maven-builder-support:3.9.0
org.apache.maven:maven-repository-metadata:3.9.0
org.apache.maven:maven-artifact:3.9.0
org.apache.maven:maven-plugin-api:3.9.0
org.apache.maven:maven-model-builder:3.9.0
org.apache.maven:maven-resolver-provider:3.9.0
org.apache.maven.resolver:maven-resolver-impl:1.9.4
org.apache.maven.resolver:maven-resolver-named-locks:1.9.4
org.apache.maven.resolver:maven-resolver-api:1.9.4
org.apache.maven.resolver:maven-resolver-spi:1.9.4
org.apache.maven.resolver:maven-resolver-util:1.9.4
org.apache.maven.shared:maven-shared-utils:3.3.4
org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.5
javax.annotation:javax.annotation-api:1.2
org.eclipse.sisu:org.eclipse.sisu.inject:0.3.5
com.google.inject:guice:5.1.0
aopalliance:aopalliance:1.0
com.google.guava:guava:30.1-jre
com.google.guava:failureaccess:1.0.1
javax.inject:javax.inject:1
org.codehaus.plexus:plexus-utils:3.4.2
org.codehaus.plexus:plexus-classworlds:2.6.0
org.codehaus.plexus:plexus-interpolation:1.26
org.codehaus.plexus:plexus-component-annotations:2.1.0
org.apache.commons:commons-lang3:3.8.1
org.slf4j:slf4j-api:1.7.36
""", dependencies.generateTransitiveDependencyTree(ArtifactRetriever.instance(), List.of(MAVEN_CENTRAL), compile));
}
@Test
void testGenerateDependencyTreePlay() {
var dependencies = new DependencySet()
.include(new Dependency("com.typesafe.play", "play_2.13", new VersionNumber(2, 8, 19)));
assertEquals("""
com.typesafe.play:play_2.13:2.8.19
org.scala-lang:scala-library:2.13.10
com.typesafe.play:build-link:2.8.19
com.typesafe.play:play-exceptions:2.8.19
com.typesafe.play:play-streams_2.13:2.8.19
org.reactivestreams:reactive-streams:1.0.3
com.typesafe.akka:akka-stream_2.13:2.6.20
com.typesafe.akka:akka-protobuf-v3_2.13:2.6.20
com.typesafe.play:twirl-api_2.13:1.5.1
org.scala-lang.modules:scala-xml_2.13:1.2.0
org.slf4j:slf4j-api:1.7.36
org.slf4j:jul-to-slf4j:1.7.36
org.slf4j:jcl-over-slf4j:1.7.36
com.typesafe.akka:akka-actor_2.13:2.6.20
com.typesafe:config:1.4.2
com.typesafe.akka:akka-actor-typed_2.13:2.6.20
com.typesafe.akka:akka-slf4j_2.13:2.6.20
com.typesafe.akka:akka-serialization-jackson_2.13:2.6.20
com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.4
com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.11.4
com.fasterxml.jackson.module:jackson-module-scala_2.13:2.11.4
com.fasterxml.jackson.module:jackson-module-paranamer:2.11.4
com.thoughtworks.paranamer:paranamer:2.8
org.lz4:lz4-java:1.8.0
com.fasterxml.jackson.core:jackson-core:2.11.4
com.fasterxml.jackson.core:jackson-annotations:2.11.4
com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.4
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.4
com.fasterxml.jackson.core:jackson-databind:2.11.4
com.typesafe.play:play-json_2.13:2.8.2
com.typesafe.play:play-functional_2.13:2.8.2
org.scala-lang:scala-reflect:2.13.1
joda-time:joda-time:2.10.5
com.google.guava:guava:30.1.1-jre
com.google.guava:failureaccess:1.0.1
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.code.findbugs:jsr305:3.0.2
org.checkerframework:checker-qual:3.8.0
com.google.errorprone:error_prone_annotations:2.5.1
com.google.j2objc:j2objc-annotations:1.3
io.jsonwebtoken:jjwt:0.9.1
jakarta.xml.bind:jakarta.xml.bind-api:2.3.3
jakarta.activation:jakarta.activation-api:1.2.2
jakarta.transaction:jakarta.transaction-api:1.3.3
javax.inject:javax.inject:1
org.scala-lang.modules:scala-java8-compat_2.13:1.0.2
com.typesafe:ssl-config-core_2.13:0.4.3
org.scala-lang.modules:scala-parser-combinators_2.13:1.1.2
""", dependencies.generateTransitiveDependencyTree(ArtifactRetriever.instance(), List.of(MAVEN_CENTRAL), compile));
}
@Test
void testGenerateDependencyTreeVaadin() {
var dependencies = new DependencySet()
.include(new Dependency("com.vaadin", "vaadin", new VersionNumber(23, 3, 7)));
assertEquals("""
com.vaadin:vaadin:23.3.7
com.vaadin:vaadin-core:23.3.7
com.vaadin:flow-server:23.3.4
com.vaadin.servletdetector:throw-if-servlet5:1.0.2
org.slf4j:slf4j-api:1.7.36
javax.annotation:javax.annotation-api:1.3.2
com.vaadin.external.gwt:gwt-elemental:2.8.2.vaadin2
commons-fileupload:commons-fileupload:1.4
commons-io:commons-io:2.11.0
com.fasterxml.jackson.core:jackson-core:2.14.1
org.jsoup:jsoup:1.15.3
com.helger:ph-css:6.5.0
com.helger.commons:ph-commons
com.google.code.findbugs:jsr305:3.0.2
net.bytebuddy:byte-buddy:1.12.20
com.vaadin.external:gentyref:1.2.0.vaadin1
org.apache.commons:commons-compress:1.22
org.apache.httpcomponents:httpclient:4.5.13
org.apache.httpcomponents:httpcore:4.4.13
commons-logging:commons-logging:1.2
commons-codec:commons-codec:1.15
com.vaadin:vaadin-dev-server:23.3.4
com.vaadin:open:8.5.0
com.vaadin:flow-lit-template:23.3.4
com.vaadin:flow-polymer-template:23.3.4
com.vaadin:flow-push:23.3.4
com.vaadin.external.atmosphere:atmosphere-runtime:2.7.3.slf4jvaadin4
com.vaadin:flow-client:23.3.4
com.vaadin:flow-html-components:23.3.4
com.vaadin:flow-data:23.3.4
javax.validation:validation-api:2.0.1.Final
com.vaadin:flow-dnd:23.3.4
org.webjars.npm:vaadin__vaadin-mobile-drag-drop:1.0.1
org.webjars.npm:mobile-drag-drop:2.3.0-rc.2
com.vaadin:vaadin-lumo-theme:23.3.7
com.vaadin:vaadin-material-theme:23.3.7
com.vaadin:vaadin-accordion-flow:23.3.7
com.vaadin:vaadin-avatar-flow:23.3.7
com.vaadin:vaadin-flow-components-base:23.3.7
com.vaadin:vaadin-button-flow:23.3.7
com.vaadin:vaadin-checkbox-flow:23.3.7
com.vaadin:vaadin-combo-box-flow:23.3.7
com.vaadin:vaadin-confirm-dialog-flow:23.3.7
com.vaadin:vaadin-custom-field-flow:23.3.7
com.vaadin:vaadin-date-picker-flow:23.3.7
com.vaadin:vaadin-date-time-picker-flow:23.3.7
com.vaadin:vaadin-details-flow:23.3.7
com.vaadin:vaadin-time-picker-flow:23.3.7
com.vaadin:vaadin-select-flow:23.3.7
com.vaadin:vaadin-dialog-flow:23.3.7
com.vaadin:vaadin-form-layout-flow:23.3.7
com.vaadin:vaadin-field-highlighter-flow:23.3.7
com.vaadin:vaadin-grid-flow:23.3.7
org.apache.commons:commons-lang3:3.12.0
com.vaadin:vaadin-icons-flow:23.3.7
com.vaadin:vaadin-iron-list-flow:23.3.7
com.vaadin:vaadin-virtual-list-flow:23.3.7
com.vaadin:vaadin-list-box-flow:23.3.7
com.vaadin:vaadin-login-flow:23.3.7
com.vaadin:vaadin-messages-flow:23.3.7
com.vaadin:vaadin-ordered-layout-flow:23.3.7
com.vaadin:vaadin-progress-bar-flow:23.3.7
com.vaadin:vaadin-radio-button-flow:23.3.7
com.vaadin:vaadin-renderer-flow:23.3.7
com.vaadin:vaadin-split-layout-flow:23.3.7
com.vaadin:vaadin-tabs-flow:23.3.7
com.vaadin:vaadin-text-field-flow:23.3.7
com.vaadin:vaadin-upload-flow:23.3.7
com.vaadin:vaadin-notification-flow:23.3.7
com.vaadin:vaadin-app-layout-flow:23.3.7
com.vaadin:vaadin-context-menu-flow:23.3.7
com.vaadin:vaadin-menu-bar-flow:23.3.7
com.vaadin:vaadin-board-flow:23.3.7
com.vaadin:vaadin-charts-flow:23.3.7
com.vaadin:vaadin-cookie-consent-flow:23.3.7
com.vaadin:vaadin-crud-flow:23.3.7
com.vaadin:vaadin-grid-pro-flow:23.3.7
com.vaadin:vaadin-map-flow:23.3.7
com.vaadin:vaadin-rich-text-editor-flow:23.3.7
com.vaadin:collaboration-engine:5.3.0
com.fasterxml.jackson.core:jackson-databind:2.14.1
com.fasterxml.jackson.core:jackson-annotations:2.14.1
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1
com.vaadin:license-checker:1.5.1
com.github.oshi:oshi-core:6.1.6
net.java.dev.jna:jna:5.11.0
net.java.dev.jna:jna-platform:5.11.0
com.auth0:java-jwt:3.19.2
""", dependencies.generateTransitiveDependencyTree(ArtifactRetriever.instance(), List.of(MAVEN_CENTRAL), compile));
}
@Test
void testGenerateDependencyTreeVarious() {
var dependencies = new DependencySet()
.include(new Dependency("com.uwyn.rife2", "rife2", new VersionNumber(1,5,20)))
.include(new Dependency("com.stripe", "stripe-java", new VersionNumber(20,136,0)))
.include(new Dependency("org.json", "json", new VersionNumber(20230227)))
.include(new Dependency("com.itextpdf", "itext7-core", new VersionNumber(7,2,5)))
.include(new Dependency("org.slf4j", "slf4j-simple", new VersionNumber(2,0,7)))
.include(new Dependency("org.apache.thrift", "libthrift", new VersionNumber(0,17,0)))
.include(new Dependency("commons-codec", "commons-codec", new VersionNumber(1,15)))
.include(new Dependency("org.apache.httpcomponents", "httpcore", new VersionNumber(4,4,16)))
.include(new Dependency("com.google.zxing", "javase", new VersionNumber(3,5,1)));
assertEquals("""
com.uwyn.rife2:rife2:1.5.20
com.stripe:stripe-java:20.136.0
org.json:json:20230227
com.itextpdf:itext7-core:7.2.5
com.itextpdf:barcodes:7.2.5
com.itextpdf:font-asian:7.2.5
com.itextpdf:forms:7.2.5
com.itextpdf:hyph:7.2.5
com.itextpdf:io:7.2.5
com.itextpdf:commons:7.2.5
com.itextpdf:kernel:7.2.5
org.bouncycastle:bcpkix-jdk15on:1.70
org.bouncycastle:bcutil-jdk15on:1.70
org.bouncycastle:bcprov-jdk15on:1.70
com.itextpdf:layout:7.2.5
com.itextpdf:pdfa:7.2.5
com.itextpdf:sign:7.2.5
com.itextpdf:styled-xml-parser:7.2.5
com.itextpdf:svg:7.2.5
org.slf4j:slf4j-simple:2.0.7
org.slf4j:slf4j-api:2.0.7
org.apache.thrift:libthrift:0.17.0
commons-codec:commons-codec:1.15
org.apache.httpcomponents:httpcore:4.4.16
com.google.zxing:javase:3.5.1
com.google.zxing:core:3.5.1
com.beust:jcommander:1.82
""", dependencies.generateTransitiveDependencyTree(ArtifactRetriever.instance(), List.of(MAVEN_CENTRAL), compile));
}
}

View 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.operations;
import org.junit.jupiter.api.Test;
import rife.bld.WebProject;
import rife.bld.dependencies.*;
import rife.tools.FileUtils;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
public class TestDependencyTreeOperation {
@Test
void testInstantiation() {
var operation = new DependencyTreeOperation();
assertTrue(operation.dependencies().isEmpty());
assertTrue(operation.repositories().isEmpty());
}
@Test
void testPopulation() {
var repository1 = new Repository("repository1");
var repository2 = new Repository("repository2");
var dependency1 = new Dependency("group1", "artifact1");
var dependency2 = new Dependency("group2", "artifact2");
var operation1 = new DependencyTreeOperation()
.repositories(List.of(repository1, repository2));
var dependency_scopes = new DependencyScopes();
dependency_scopes.scope(Scope.compile).include(dependency1).include(dependency2);
operation1.dependencies(dependency_scopes);
assertTrue(operation1.repositories().contains(repository1));
assertTrue(operation1.repositories().contains(repository2));
assertTrue(operation1.dependencies().scope(Scope.compile).contains(dependency1));
assertTrue(operation1.dependencies().scope(Scope.compile).contains(dependency2));
var operation2 = new DependencyTreeOperation();
operation2.repositories().add(repository1);
operation2.repositories().add(repository2);
operation2.dependencies().scope(Scope.compile).include(dependency1).include(dependency2);
operation2.dependencies(dependency_scopes);
assertTrue(operation2.repositories().contains(repository1));
assertTrue(operation2.repositories().contains(repository2));
assertTrue(operation2.dependencies().scope(Scope.compile).contains(dependency1));
assertTrue(operation2.dependencies().scope(Scope.compile).contains(dependency2));
var operation3 = new DependencyTreeOperation()
.repositories(repository1, repository2);
assertTrue(operation3.repositories().contains(repository1));
assertTrue(operation3.repositories().contains(repository2));
}
@Test
void testExecution()
throws Exception {
var tmp = Files.createTempDirectory("test").toFile();
try {
var operation = new DependencyTreeOperation()
.repositories(List.of(Repository.MAVEN_CENTRAL));
operation.dependencies().scope(Scope.compile)
.include(new Dependency("com.uwyn.rife2", "rife2", new VersionNumber(1,5,20)))
.include(new Dependency("com.stripe", "stripe-java", new VersionNumber(20,136,0)))
.include(new Dependency("org.json", "json", new VersionNumber(20230227)))
.include(new Dependency("com.itextpdf", "itext7-core", new VersionNumber(7,2,5)))
.include(new Dependency("org.slf4j", "slf4j-simple", new VersionNumber(2,0,7)))
.include(new Dependency("org.apache.thrift", "libthrift", new VersionNumber(0,17,0)))
.include(new Dependency("commons-codec", "commons-codec", new VersionNumber(1,15)))
.include(new Dependency("org.apache.httpcomponents", "httpcore", new VersionNumber(4,4,16)))
.include(new Dependency("com.google.zxing", "javase", new VersionNumber(3,5,1)));
operation.dependencies().scope(Scope.runtime)
.include(new Dependency("org.postgresql", "postgresql", new VersionNumber(42,6,0)));
operation.execute();
var tree = operation.dependencyTree();
assertEquals("""
compile:
com.uwyn.rife2:rife2:1.5.20
com.stripe:stripe-java:20.136.0
org.json:json:20230227
com.itextpdf:itext7-core:7.2.5
com.itextpdf:barcodes:7.2.5
com.itextpdf:font-asian:7.2.5
com.itextpdf:forms:7.2.5
com.itextpdf:hyph:7.2.5
com.itextpdf:io:7.2.5
com.itextpdf:commons:7.2.5
com.itextpdf:kernel:7.2.5
org.bouncycastle:bcpkix-jdk15on:1.70
org.bouncycastle:bcutil-jdk15on:1.70
org.bouncycastle:bcprov-jdk15on:1.70
com.itextpdf:layout:7.2.5
com.itextpdf:pdfa:7.2.5
com.itextpdf:sign:7.2.5
com.itextpdf:styled-xml-parser:7.2.5
com.itextpdf:svg:7.2.5
org.slf4j:slf4j-simple:2.0.7
org.slf4j:slf4j-api:2.0.7
org.apache.thrift:libthrift:0.17.0
commons-codec:commons-codec:1.15
org.apache.httpcomponents:httpcore:4.4.16
com.google.zxing:javase:3.5.1
com.google.zxing:core:3.5.1
com.beust:jcommander:1.82
runtime:
org.postgresql:postgresql:42.6.0
org.checkerframework:checker-qual:3.31.0
""", tree);
} finally {
FileUtils.deleteDirectory(tmp);
}
}
static class TestProject extends WebProject {
public TestProject(File tmp) {
workDirectory = tmp;
pkg = "test.pkg";
}
}
@Test
void testFromProject()
throws Exception {
var tmp = Files.createTempDirectory("test").toFile();
try {
var project = new TestProject(tmp);
project.createProjectStructure();
project.repositories().add(Repository.MAVEN_CENTRAL);
project.dependencies().scope(Scope.compile)
.include(new Dependency("com.uwyn.rife2", "rife2", new VersionNumber(1,5,20)))
.include(new Dependency("com.stripe", "stripe-java", new VersionNumber(20,136,0)))
.include(new Dependency("org.json", "json", new VersionNumber(20230227)))
.include(new Dependency("com.itextpdf", "itext7-core", new VersionNumber(7,2,5)))
.include(new Dependency("org.slf4j", "slf4j-simple", new VersionNumber(2,0,7)))
.include(new Dependency("org.apache.thrift", "libthrift", new VersionNumber(0,17,0)))
.include(new Dependency("commons-codec", "commons-codec", new VersionNumber(1,15)))
.include(new Dependency("org.apache.httpcomponents", "httpcore", new VersionNumber(4,4,16)))
.include(new Dependency("com.google.zxing", "javase", new VersionNumber(3,5,1)));
project.dependencies().scope(Scope.runtime)
.include(new Dependency("org.postgresql", "postgresql", new VersionNumber(42,6,0)));
var operation = new DependencyTreeOperation()
.fromProject(project);
operation.execute();
var tree = operation.dependencyTree();
assertEquals("""
compile:
com.uwyn.rife2:rife2:1.5.20
com.stripe:stripe-java:20.136.0
org.json:json:20230227
com.itextpdf:itext7-core:7.2.5
com.itextpdf:barcodes:7.2.5
com.itextpdf:font-asian:7.2.5
com.itextpdf:forms:7.2.5
com.itextpdf:hyph:7.2.5
com.itextpdf:io:7.2.5
com.itextpdf:commons:7.2.5
com.itextpdf:kernel:7.2.5
org.bouncycastle:bcpkix-jdk15on:1.70
org.bouncycastle:bcutil-jdk15on:1.70
org.bouncycastle:bcprov-jdk15on:1.70
com.itextpdf:layout:7.2.5
com.itextpdf:pdfa:7.2.5
com.itextpdf:sign:7.2.5
com.itextpdf:styled-xml-parser:7.2.5
com.itextpdf:svg:7.2.5
org.slf4j:slf4j-simple:2.0.7
org.slf4j:slf4j-api:2.0.7
org.apache.thrift:libthrift:0.17.0
commons-codec:commons-codec:1.15
org.apache.httpcomponents:httpcore:4.4.16
com.google.zxing:javase:3.5.1
com.google.zxing:core:3.5.1
com.beust:jcommander:1.82
runtime:
org.postgresql:postgresql:42.6.0
org.checkerframework:checker-qual:3.31.0
""", tree);
} finally {
FileUtils.deleteDirectory(tmp);
}
}
}

View file

@ -15,10 +15,10 @@ import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertNull;
public class TestTestOperation {
public class TestJUnitOperation {
@Test
void testInstantiation() {
var operation = new TestOperation();
var operation = new JUnitOperation();
assertNotNull(operation.workDirectory());
assertTrue(operation.workDirectory().exists());
assertTrue(operation.workDirectory().isDirectory());
@ -48,7 +48,7 @@ public class TestTestOperation {
Function<String, Boolean> test_output_consumer = (String) -> true;
Function<String, Boolean> test_error_consumer = (String) -> true;
var operation1 = new TestOperation();
var operation1 = new JUnitOperation();
operation1
.workDirectory(work_directory)
.javaTool(java_tool)
@ -71,7 +71,7 @@ public class TestTestOperation {
assertSame(test_output_consumer, operation1.outputProcessor());
assertSame(test_error_consumer, operation1.errorProcessor());
var operation2 = new TestOperation();
var operation2 = new JUnitOperation();
operation2.workDirectory(work_directory);
operation2.javaTool(java_tool);
operation2.javaOptions().add(test_java_option1);
@ -96,7 +96,7 @@ public class TestTestOperation {
assertSame(test_output_consumer, operation2.outputProcessor());
assertSame(test_error_consumer, operation2.errorProcessor());
var operation3 = new TestOperation();
var operation3 = new JUnitOperation();
operation3
.classpath(test_classpath1, test_classpath2)
.testToolOptions(test_tool_option1, test_tool_option2);
@ -153,7 +153,7 @@ public class TestTestOperation {
assertTrue(compile_operation.diagnostics().isEmpty());
var output = new StringBuilder();
var test_operation = new TestOperation()
var test_operation = new JUnitOperation()
.mainClass("Source2")
.classpath(List.of(build_main.getAbsolutePath(), build_test.getAbsolutePath()))
.outputProcessor(s -> {
@ -184,7 +184,7 @@ public class TestTestOperation {
.fromProject(create_operation.project()).execute();
var check_result = new StringBuilder();
new TestOperation()
new JUnitOperation()
.fromProject(create_operation.project())
.outputProcessor(s -> {
check_result.append(s).append(System.lineSeparator());

Some files were not shown because too many files have changed in this diff Show more