Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.7.1 backports 3 #23479

Merged
merged 14 commits into from
Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
<proton-j.version>0.33.10</proton-j.version>
<okhttp.version>3.14.9</okhttp.version>
<hibernate-quarkus-local-cache.version>0.1.0</hibernate-quarkus-local-cache.version>
<kubernetes-client.version>5.12.0</kubernetes-client.version>
<kubernetes-client.version>5.12.1</kubernetes-client.version>
<flapdoodle.mongo.version>3.2.0</flapdoodle.mongo.version>
<quarkus-spring-api.version>5.2.SP4</quarkus-spring-api.version>
<quarkus-spring-data-api.version>2.1.SP2</quarkus-spring-data-api.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ public class CodeGenContext {
private final Path inputDir;
private final boolean redirectIO;
private final Config config;
private final boolean test;

public CodeGenContext(ApplicationModel model, Path outDir, Path workDir, Path inputDir, boolean redirectIO, Config config) {
public CodeGenContext(ApplicationModel model, Path outDir, Path workDir, Path inputDir, boolean redirectIO,
Config config, boolean test) {
this.model = model;
this.outDir = outDir;
this.workDir = workDir;
this.inputDir = inputDir;
this.redirectIO = redirectIO;
this.config = config;
this.test = test;
}

public ApplicationModel applicationModel() {
Expand All @@ -46,4 +49,8 @@ public boolean shouldRedirectIO() {
public Config config() {
return config;
}

public boolean test() {
return test;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package io.quarkus.deployment;

import java.nio.file.Files;
import java.nio.file.Path;

import org.eclipse.microprofile.config.Config;
import org.wildfly.common.annotation.NotNull;

import io.quarkus.bootstrap.prebuild.CodeGenException;
Expand Down Expand Up @@ -40,4 +44,7 @@ public interface CodeGenProvider {
*/
boolean trigger(CodeGenContext context) throws CodeGenException;

default boolean shouldRun(Path sourceDir, Config config) {
return Files.isDirectory(sourceDir);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ public class CodeGenerator {
public static void initAndRun(ClassLoader classLoader,
PathCollection sourceParentDirs, Path generatedSourcesDir, Path buildDir,
Consumer<Path> sourceRegistrar, ApplicationModel appModel, Properties properties,
String launchMode) throws CodeGenException {
String launchMode, boolean test) throws CodeGenException {
List<CodeGenData> generators = init(classLoader, sourceParentDirs, generatedSourcesDir, buildDir, sourceRegistrar);
for (CodeGenData generator : generators) {
generator.setRedirectIO(true);
trigger(classLoader, generator, appModel, properties, LaunchMode.valueOf(launchMode));
trigger(classLoader, generator, appModel, properties, LaunchMode.valueOf(launchMode), test);
}
}

Expand Down Expand Up @@ -80,14 +80,16 @@ private static <T> T callWithClassloader(ClassLoader deploymentClassLoader, Code
* @param data code gen
* @param appModel app model
* @param properties custom code generation properties
* @param test whether the sources are generated for production code or tests
* @return true if sources have been created
* @throws CodeGenException on failure
*/
public static boolean trigger(ClassLoader deploymentClassLoader,
CodeGenData data,
ApplicationModel appModel,
Properties properties,
LaunchMode launchMode) throws CodeGenException {
LaunchMode launchMode,
boolean test) throws CodeGenException {
return callWithClassloader(deploymentClassLoader, () -> {

final PropertiesConfigSource pcs = new PropertiesConfigSource(properties, "Build system");
Expand All @@ -102,9 +104,10 @@ public static boolean trigger(ClassLoader deploymentClassLoader,
.build();

CodeGenProvider provider = data.provider;
return Files.isDirectory(data.sourceDir)
return provider.shouldRun(data.sourceDir, config)
&& provider.trigger(
new CodeGenContext(appModel, data.outPath, data.buildDir, data.sourceDir, data.redirectIO, config));
new CodeGenContext(appModel, data.outPath, data.buildDir, data.sourceDir, data.redirectIO, config,
test));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ private void startCodeGenWatcher(QuarkusClassLoader classLoader, List<CodeGenDat
try {
CodeGenerator.trigger(classLoader,
codeGen,
curatedApplication.getApplicationModel(), properties, LaunchMode.DEVELOPMENT);
curatedApplication.getApplicationModel(), properties, LaunchMode.DEVELOPMENT, false);
} catch (Exception any) {
log.warn("Code generation failed", any);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,9 @@ private DiscoveryResult discoverTestClasses() {
try {
itClasses.add(Thread.currentThread().getContextClassLoader().loadClass(i));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
log.warnf(
"Failed to load test class %s (possibly as it was added after the test run started), it will not be executed this run.",
i);
}
}
itClasses.sort(Comparator.comparing(new Function<Class<?>, String>() {
Expand Down Expand Up @@ -631,7 +633,9 @@ public String apply(Class<?> aClass) {
try {
utClasses.add(cl.loadClass(i));
} catch (ClassNotFoundException exception) {
throw new RuntimeException(exception);
log.warnf(
"Failed to load test class %s (possibly as it was added after the test run started), it will not be executed this run.",
i);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ public void run() {
Thread.currentThread().setContextClassLoader(testApplication.getAugmentClassLoader());
try {
prepared.run();
} finally {
synchronized (ModuleTestRunner.this) {
runner = null;
}
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,11 @@ public void noTests(TestRunResults results) {
i.runStarted(testCount.get());
}
for (var i : runnables) {
i.run();
try {
i.run();
} catch (Exception e) {
log.error("Failed to run test module", e);
}
}
Map<String, TestClassResult> aggregate = new HashMap<>();
for (var i : allResults) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.inject.Inject;
Expand All @@ -19,6 +23,9 @@
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.plugins.JavaPluginExtension;
Expand All @@ -36,11 +43,14 @@
import org.gradle.util.GradleVersion;

import io.quarkus.bootstrap.BootstrapConstants;
import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.devmode.DependenciesFilter;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.model.PathsCollection;
import io.quarkus.bootstrap.workspace.ArtifactSources;
import io.quarkus.bootstrap.workspace.SourceDir;
import io.quarkus.deployment.dev.DevModeContext;
import io.quarkus.deployment.dev.DevModeMain;
import io.quarkus.deployment.dev.QuarkusDevModeLauncher;
import io.quarkus.gradle.tooling.ToolingUtils;
import io.quarkus.maven.dependency.ArtifactKey;
Expand All @@ -51,7 +61,10 @@
public class QuarkusDev extends QuarkusTask {

public static final String IO_QUARKUS_DEVMODE_ARGS = "io.quarkus.devmode-args";

private static final String EXT_PROPERTIES_PATH = "META-INF/quarkus-extension.properties";
private Set<File> filesIncludedInClasspath = new HashSet<>();

protected Configuration quarkusDevConfiguration;

private File buildDir;
Expand Down Expand Up @@ -268,23 +281,29 @@ private QuarkusDevModeLauncher newLauncher() throws Exception {
.equals(localDep.getWorkspaceModule().getId()));
}

addQuarkusDevModeDeps(builder);

//look for an application.properties
Set<Path> resourceDirs = new HashSet<>();
for (SourceDir resourceDir : appModel.getApplicationModule().getMainSources().getResourceDirs()) {
resourceDirs.add(resourceDir.getOutputDir());
}

Set<ArtifactKey> configuredParentFirst = QuarkusBootstrap.createClassLoadingConfig(PathsCollection.from(resourceDirs),
QuarkusBootstrap.Mode.DEV, Collections.emptyList()).parentFirstArtifacts;

Set<ArtifactKey> parentFirstArtifactKeys = new HashSet<>(configuredParentFirst);
parentFirstArtifactKeys.addAll(appModel.getParentFirst());

for (io.quarkus.maven.dependency.ResolvedDependency artifact : appModel.getDependencies()) {
//we only use the launcher for launching from the IDE, we need to exclude it
if (artifact.getGroupId().equals("io.quarkus")
&& artifact.getArtifactId().equals("quarkus-ide-launcher")) {
continue;
}
if (!projectDependencies.contains(artifact.getKey())) {
artifact.getResolvedPaths().forEach(p -> {
if (Files.exists(p)) {
if (artifact.getGroupId().equals("io.quarkus")
&& artifact.getArtifactId().equals("quarkus-class-change-agent")) {
builder.jvmArgs("-javaagent:" + p.toFile().getAbsolutePath());
} else {
addToClassPaths(builder, p.toFile());
}
File file = p.toFile();
if (file.exists() && parentFirstArtifactKeys.contains(artifact.getKey())
&& filesIncludedInClasspath.add(file)) {
getProject().getLogger().debug("Adding dependency {}", file);
builder.classpathEntry(file);
}

});
}
}
Expand Down Expand Up @@ -327,6 +346,52 @@ protected void modifyDevModeContext(GradleDevModeLauncher.Builder builder) {

}

private void addQuarkusDevModeDeps(GradleDevModeLauncher.Builder builder) {
final String pomPropsPath = "META-INF/maven/io.quarkus/quarkus-core-deployment/pom.properties";
final InputStream devModePomPropsIs = DevModeMain.class.getClassLoader().getResourceAsStream(pomPropsPath);
if (devModePomPropsIs == null) {
throw new GradleException("Failed to locate " + pomPropsPath + " on the classpath");
}
final Properties devModeProps = new Properties();
try (InputStream is = devModePomPropsIs) {
devModeProps.load(is);
} catch (IOException e) {
throw new GradleException("Failed to load " + pomPropsPath + " from the classpath", e);
}
final String devModeGroupId = devModeProps.getProperty("groupId");
if (devModeGroupId == null) {
throw new GradleException("Classpath resource " + pomPropsPath + " is missing groupId");
}
final String devModeArtifactId = devModeProps.getProperty("artifactId");
if (devModeArtifactId == null) {
throw new GradleException("Classpath resource " + pomPropsPath + " is missing artifactId");
}
final String devModeVersion = devModeProps.getProperty("version");
if (devModeVersion == null) {
throw new GradleException("Classpath resource " + pomPropsPath + " is missing version");
}

Dependency devModeDependency = getProject().getDependencies()
.create(String.format("%s:%s:%s", devModeGroupId, devModeArtifactId, devModeVersion));

final Configuration devModeDependencyConfiguration = getProject().getConfigurations()
.detachedConfiguration(devModeDependency);

for (ResolvedArtifact appDep : devModeDependencyConfiguration.getResolvedConfiguration().getResolvedArtifacts()) {
ModuleVersionIdentifier artifactId = appDep.getModuleVersion().getId();
//we only use the launcher for launching from the IDE, we need to exclude it
if (!(artifactId.getGroup().equals("io.quarkus")
&& artifactId.getName().equals("quarkus-ide-launcher"))) {
if (artifactId.getGroup().equals("io.quarkus")
&& artifactId.getName().equals("quarkus-class-change-agent")) {
builder.jvmArgs("-javaagent:" + appDep.getFile().getAbsolutePath());
} else {
builder.classpathEntry(appDep.getFile());
}
}
}
}

private void addLocalProject(ResolvedDependency project, GradleDevModeLauncher.Builder builder, Set<ArtifactKey> addeDeps,
boolean root) {
addeDeps.add(project.getKey());
Expand Down Expand Up @@ -454,13 +519,6 @@ private java.util.Optional<JavaCompile> getJavaCompileTask() {
.ofNullable((JavaCompile) getProject().getTasks().getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME));
}

private void addToClassPaths(GradleDevModeLauncher.Builder classPathManifest, File file) {
if (filesIncludedInClasspath.add(file)) {
getProject().getLogger().debug("Adding dependency {}", file);
classPathManifest.classpathEntry(file);
}
}

public void shouldPropagateJavaCompilerArgs(boolean shouldPropagateJavaCompilerArgs) {
this.shouldPropagateJavaCompilerArgs = shouldPropagateJavaCompilerArgs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ public void prepareQuarkus() {
sourceRegistrar,
appCreationContext.getApplicationModel(),
realProperties,
launchMode.name());
launchMode.name(),
test);

}
} catch (BootstrapException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
Expand Down
23 changes: 1 addition & 22 deletions devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.aesh.readline.terminal.impl.ExecPty;
import org.aesh.readline.terminal.impl.Pty;
Expand Down Expand Up @@ -1009,27 +1007,8 @@ private QuarkusDevModeLauncher newLauncher() throws Exception {
//parent-first cases such as logging
//first we go through and get all the parent first artifacts
Set<ArtifactKey> parentFirstArtifacts = new HashSet<>(configuredParentFirst);
for (Artifact appDep : project.getArtifacts()) {
if (appDep.getArtifactHandler().getExtension().equals("jar") && appDep.getFile().isFile()) {
try (ZipFile file = new ZipFile(appDep.getFile())) {
ZipEntry entry = file.getEntry(EXT_PROPERTIES_PATH);
if (entry != null) {
Properties p = new Properties();
try (InputStream inputStream = file.getInputStream(entry)) {
p.load(inputStream);
String parentFirst = p.getProperty(ApplicationModel.PARENT_FIRST_ARTIFACTS);
if (parentFirst != null) {
String[] artifacts = parentFirst.split(",");
for (String artifact : artifacts) {
parentFirstArtifacts.add(new GACT(artifact.split(":")));
}
}
}
parentFirstArtifacts.addAll(appModel.getParentFirst());

}
}
}
}
for (Artifact appDep : project.getArtifacts()) {
// only add the artifact if it's present in the dev mode context
// we need this to avoid having jars on the classpath multiple times
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,14 @@ void generateCode(Path sourcesDir,

final Class<?> codeGenerator = deploymentClassLoader.loadClass("io.quarkus.deployment.CodeGenerator");
final Method initAndRun = codeGenerator.getMethod("initAndRun", ClassLoader.class, PathCollection.class,
Path.class,
Path.class,
Consumer.class, ApplicationModel.class, Properties.class, String.class);
initAndRun.invoke(null, deploymentClassLoader,
PathList.of(sourcesDir),
generatedSourcesDir(test),
buildDir().toPath(),
sourceRegistrar,
curatedApplication.getApplicationModel(),
mavenProject().getProperties(), launchMode.name());
Path.class, Path.class,
Consumer.class, ApplicationModel.class, Properties.class, String.class,
boolean.class);
initAndRun.invoke(null, deploymentClassLoader, PathList.of(sourcesDir),
generatedSourcesDir(test), buildDir().toPath(),
sourceRegistrar, curatedApplication.getApplicationModel(), mavenProject().getProperties(),
launchMode.name(),
test);
} catch (Exception any) {
throw new MojoExecutionException("Quarkus code generation phase has failed", any);
} finally {
Expand Down
Loading