Skip to content

Commit

Permalink
More appropriate test application module initialization in QuarkusDev…
Browse files Browse the repository at this point in the history
…ModeTest
  • Loading branch information
Alexey Loubyansky committed Nov 28, 2024
1 parent d4cbdb2 commit 074f1b2
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.ObjectInputStream;
import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
Expand All @@ -24,6 +25,7 @@

import io.quarkus.bootstrap.app.CuratedApplication;
import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.deployment.util.ProcessUtil;
import io.quarkus.dev.appstate.ApplicationStateNotification;
import io.quarkus.dev.spi.DevModeType;
Expand All @@ -39,12 +41,18 @@ public class DevModeMain implements Closeable {
private static final Logger log = Logger.getLogger(DevModeMain.class);

private final DevModeContext context;
private final ApplicationModel appModel;

private volatile CuratedApplication curatedApplication;
private Closeable realCloseable;

public DevModeMain(DevModeContext context) {
this(context, null);
}

public DevModeMain(DevModeContext context, ApplicationModel appModel) {
this.context = context;
this.appModel = appModel;
}

public static void main(String... args) throws Exception {
Expand All @@ -65,47 +73,15 @@ public static void main(String... args) throws Exception {

public void start() throws Exception {
//propagate system props
for (Map.Entry<String, String> i : context.getSystemProperties().entrySet()) {
if (!System.getProperties().containsKey(i.getKey())) {
System.setProperty(i.getKey(), i.getValue());
}
}
propagateSystemProperties();

try {
URL thisArchive = getClass().getResource(DevModeMain.class.getSimpleName() + ".class");
int endIndex = thisArchive.getPath().indexOf("!");
Path path;
if (endIndex != -1) {
path = Paths.get(new URI(thisArchive.getPath().substring(0, endIndex)));
} else {
path = Paths.get(thisArchive.toURI());
path = path.getParent();
for (char i : DevModeMain.class.getName().toCharArray()) {
if (i == '.') {
path = path.getParent();
}
}
}
final PathList.Builder appRootsBuilder = PathList.builder();
final Path classesPath = Path.of(context.getApplicationRoot().getMain().getClassesPath());
if (Files.exists(classesPath)) {
appRootsBuilder.add(classesPath);
}
if (context.getApplicationRoot().getMain().getResourcesOutputPath() != null
&& !context.getApplicationRoot().getMain().getResourcesOutputPath()
.equals(context.getApplicationRoot().getMain().getClassesPath())) {
final Path resourcesOutputPath = Paths.get(context.getApplicationRoot().getMain().getResourcesOutputPath());
if (Files.exists(resourcesOutputPath)) {
appRootsBuilder.add(resourcesOutputPath);
}
}

final PathList appRoots = appRootsBuilder.build();
QuarkusBootstrap.Builder bootstrapBuilder = QuarkusBootstrap.builder()
.setApplicationRoot(appRoots)
.setApplicationRoot(getApplicationBuildDirs())
.setExistingModel(appModel)
.setIsolateDeployment(true)
.setLocalProjectDiscovery(context.isLocalProjectDiscovery())
.addAdditionalDeploymentArchive(path)
.addAdditionalDeploymentArchive(getThisClassOrigin())
.setBaseName(context.getBaseName())
.setMode(context.getMode());
if (context.getDevModeRunnerJarFile() != null) {
Expand Down Expand Up @@ -139,6 +115,64 @@ public void start() throws Exception {
}
}

private PathList getApplicationBuildDirs() {
final String classesDir = context.getApplicationRoot().getMain().getClassesPath();
final String resourcesOutputDir = context.getApplicationRoot().getMain().getResourcesOutputPath();
if (resourcesOutputDir == null || resourcesOutputDir.equals(classesDir)) {
return toListOfExistingOrEmpty(Path.of(classesDir));
}
return toListOfExistingOrEmpty(Path.of(classesDir), Path.of(resourcesOutputDir));
}

private static PathList toListOfExistingOrEmpty(Path p1, Path p2) {
if (!Files.exists(p1)) {
return toListOfExistingOrEmpty(p2);
}
if (!Files.exists(p2)) {
return toListOfExistingOrEmpty(p1);
}
return PathList.of(p1, p2);
}

/**
* Returns a {@link PathList} containing the path if it exists, otherwise returns an empty {@link PathList}.
*
* @param path path
* @return {@link PathList} containing the path if it exists, otherwise returns an empty {@link PathList}
*/
private static PathList toListOfExistingOrEmpty(Path path) {
return Files.exists(path) ? PathList.of(path) : PathList.empty();
}

/**
* Returns the classpath element containing this class
*
* @return classpath element containing this class
* @throws URISyntaxException in case of a failure
*/
private Path getThisClassOrigin() throws URISyntaxException {
URL thisArchive = getClass().getResource(DevModeMain.class.getSimpleName() + ".class");
int endIndex = thisArchive.getPath().indexOf("!");
if (endIndex != -1) {
return Path.of(new URI(thisArchive.getPath().substring(0, endIndex)));
}
Path path = Path.of(thisArchive.toURI());
path = path.getParent();
for (char i : DevModeMain.class.getName().toCharArray()) {
if (i == '.') {
path = path.getParent();
}
}

return path;
}

private void propagateSystemProperties() {
for (Map.Entry<String, String> i : context.getSystemProperties().entrySet()) {
System.getProperties().putIfAbsent(i.getKey(), i.getValue());
}
}

private Path resolveProjectRoot() {
final Path projectRoot;
if (context.getProjectDir() != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package io.quarkus.test;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.model.ExtensionCapabilities;
import io.quarkus.bootstrap.model.ExtensionDevModeConfig;
import io.quarkus.bootstrap.model.PlatformImports;
import io.quarkus.maven.dependency.ArtifactKey;
import io.quarkus.maven.dependency.ResolvedDependency;

/**
* {@link ApplicationModel} implementation that allows overriding the application artifact
* of another {@link ApplicationModel} instance.
*/
class DevModeTestApplicationModel implements ApplicationModel {

private final ResolvedDependency appArtifact;
private final ApplicationModel delegate;

DevModeTestApplicationModel(ResolvedDependency testAppArtifact, ApplicationModel delegate) {
this.appArtifact = testAppArtifact;
this.delegate = delegate;
}

@Override
public ResolvedDependency getAppArtifact() {
return appArtifact;
}

@Override
public Collection<ResolvedDependency> getDependencies() {
return delegate.getDependencies();
}

@Override
public Iterable<ResolvedDependency> getDependencies(int flags) {
return delegate.getDependencies(flags);
}

@Override
public Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int... flags) {
return delegate.getDependenciesWithAnyFlag(flags);
}

@Override
public Collection<ResolvedDependency> getRuntimeDependencies() {
return delegate.getRuntimeDependencies();
}

@Override
public PlatformImports getPlatforms() {
return delegate.getPlatforms();
}

@Override
public Collection<ExtensionCapabilities> getExtensionCapabilities() {
return delegate.getExtensionCapabilities();
}

@Override
public Set<ArtifactKey> getParentFirst() {
return delegate.getParentFirst();
}

@Override
public Set<ArtifactKey> getRunnerParentFirst() {
return delegate.getRunnerParentFirst();
}

@Override
public Set<ArtifactKey> getLowerPriorityArtifacts() {
return delegate.getLowerPriorityArtifacts();
}

@Override
public Set<ArtifactKey> getReloadableWorkspaceDependencies() {
return delegate.getReloadableWorkspaceDependencies();
}

@Override
public Map<ArtifactKey, Set<String>> getRemovedResources() {
return delegate.getRemovedResources();
}

@Override
public Collection<ExtensionDevModeConfig> getExtensionDevModeConfig() {
return delegate.getExtensionDevModeConfig();
}
}
Loading

0 comments on commit 074f1b2

Please sign in to comment.