Skip to content

Commit

Permalink
Maven plugin: index output directory instead of project artifact, logs (
Browse files Browse the repository at this point in the history
#1538)

Signed-off-by: Michael Edgar <[email protected]>
  • Loading branch information
MikeEdgar authored Aug 16, 2023
1 parent 4eff4f3 commit c00cc60
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
Expand Down Expand Up @@ -323,18 +325,32 @@ private OpenApiDocument generateSchema(IndexView index) throws IOException, Depe
return document;
}

private ClassLoader getClassLoader() throws MalformedURLException, DependencyResolutionRequiredException {
Set<URL> urls = new HashSet<>();
private ClassLoader getClassLoader() throws DependencyResolutionRequiredException {
Set<URI> elements = new HashSet<>();

if (getLog().isDebugEnabled()) {
getLog().debug("Adding directories/artifacts to annotation scanner class loader:");
}

for (String element : mavenProject.getCompileClasspathElements()) {
getLog().debug("Adding " + element + " to annotation scanner class loader");
urls.add(new File(element).toURI().toURL());
if (getLog().isDebugEnabled()) {
getLog().debug(" " + element);
}

elements.add(new File(element).toURI());
}

return URLClassLoader.newInstance(
urls.toArray(new URL[0]),
Thread.currentThread().getContextClassLoader());
URL[] locators = elements.stream()
.map(uri -> {
try {
return uri.toURL();
} catch (MalformedURLException mue) {
throw new UncheckedIOException(mue);
}
})
.toArray(URL[]::new);

return URLClassLoader.newInstance(locators, Thread.currentThread().getContextClassLoader());
}

private OpenAPI generateAnnotationModel(IndexView indexView, OpenApiConfig openApiConfig, ClassLoader classLoader) {
Expand Down Expand Up @@ -399,7 +415,7 @@ private Map<String, String> getProperties() throws IOException {
Properties p = new Properties();
try (InputStream is = Files.newInputStream(configProperties.toPath())) {
p.load(is);
cp.putAll((Map) p);
p.stringPropertyNames().forEach(k -> cp.put(k, p.getProperty(k)));
}
}

Expand Down Expand Up @@ -473,17 +489,7 @@ private void write(OpenApiDocument schema) throws MojoExecutionException {
Files.createDirectories(directory);
}

Charset charset = Charset.defaultCharset();

if (!StringUtils.isBlank(encoding)) {
try {
charset = Charset.forName(encoding.trim());
} catch (IllegalCharsetNameException e) {
throw new MojoExecutionException("encoding parameter does not define a legal charset name", e);
} catch (UnsupportedCharsetException e) {
throw new MojoExecutionException("encoding parameter does not define a supported charset", e);
}
}
Charset charset = getCharset(encoding);

if (Stream.of(OutputFileFilter.ALL, OutputFileFilter.YAML)
.anyMatch(f -> f.equals(OutputFileFilter.valueOf(this.outputFileTypeFilter)))) {
Expand All @@ -502,6 +508,24 @@ private void write(OpenApiDocument schema) throws MojoExecutionException {
}
}

static Charset getCharset(String encoding) throws MojoExecutionException {
if (StringUtils.isBlank(encoding)) {
return Charset.defaultCharset();
}

Charset charset;

try {
charset = Charset.forName(encoding.trim());
} catch (IllegalCharsetNameException e) {
throw new MojoExecutionException("encoding parameter does not define a legal charset name", e);
} catch (UnsupportedCharsetException e) {
throw new MojoExecutionException("encoding parameter does not define a supported charset", e);
}

return charset;
}

private void writeSchemaFile(Path directory, String type, byte[] contents) throws IOException {
Path file = Paths.get(directory.toString(), schemaFilename + "." + type);
if (!Files.exists(file)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package io.smallrye.openapi.mavenplugin;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.maven.artifact.Artifact;
Expand Down Expand Up @@ -71,56 +73,61 @@ public MavenDependencyIndexCreator() {
}

public IndexView createIndex(MavenProject mavenProject, boolean scanDependenciesDisable,
List<String> includeDependenciesScopes, List<String> includeDependenciesTypes) throws Exception {
List<String> includeDependenciesScopes, List<String> includeDependenciesTypes) {

List<Map.Entry<Artifact, Duration>> indexDurations = new ArrayList<>();
List<Map.Entry<File, Duration>> indexDurations = new ArrayList<>();

List<File> artifacts = new ArrayList<>();
String buildOutput = mavenProject.getBuild().getOutputDirectory();
if (buildOutput != null) {
logger.debug("Build output: " + buildOutput);
artifacts.add(new File(buildOutput));
} else {
logger.warn("Build output is null!");
}

List<Artifact> artifacts = new ArrayList<>();
artifacts.add(mavenProject.getArtifact());
if (!scanDependenciesDisable) {
artifacts.addAll(mavenProject.getArtifacts());
mavenProject.getArtifacts()
.stream()
.filter(artifact -> !isIgnored(artifact, includeDependenciesScopes, includeDependenciesTypes))
.map(Artifact::getFile)
.filter(Objects::nonNull)
.forEach(artifacts::add);
}

List<IndexView> indexes = new ArrayList<>();
for (Artifact artifact : artifacts) {
if (isIgnored(artifact, includeDependenciesScopes, includeDependenciesTypes)) {
continue;
}

for (File artifact : artifacts) {
try {
if (artifact.getFile().isDirectory()) {
// Don't' cache local worskpace artifacts. Incremental compilation in IDE's would otherwise use the cached index instead of new one.
if (artifact.isDirectory()) {
// Don't cache local workspace artifacts. Incremental compilation in IDEs would otherwise use the cached index instead of new one.
// Right now, support for incremental compilation inside eclipse is blocked by: https://github.com/eclipse-m2e/m2e-core/issues/364#issuecomment-939987848
// target/classes
LocalDateTime start = LocalDateTime.now();
indexes.add(indexModuleClasses(artifact));
} else if (artifact.getFile().getName().endsWith(".jar")) {
Duration duration = Duration.between(start, LocalDateTime.now());
indexDurations.add(new AbstractMap.SimpleEntry<>(artifact, duration));
} else if (artifact.getName().endsWith(".jar")) {
IndexView artifactIndex = timeAndCache(indexDurations, artifact, () -> {
Result result = JarIndexer.createJarIndex(artifact.getFile(), new Indexer(),
Result result = JarIndexer.createJarIndex(artifact, new Indexer(),
false, false, false);
return result.getIndex();
});
indexes.add(artifactIndex);
}
} catch (IOException | ExecutionException e) {
logger.error("Can't compute index of " + artifact.getFile().getAbsolutePath() + ", skipping", e);
} catch (Exception e) {
logger.error("Can't compute index of " + artifact.getAbsolutePath() + ", skipping", e);
}

}

printIndexDurations(indexDurations);

return CompositeIndex.create(indexes);
}

private void printIndexDurations(List<Map.Entry<Artifact, Duration>> indexDurations) {
private void printIndexDurations(List<Map.Entry<File, Duration>> indexDurations) {
if (logger.isDebugEnabled()) {
indexDurations.sort(Map.Entry.comparingByValue());

indexDurations.forEach(e -> {
if (e.getValue().toMillis() > 25) {
logger.debug(buildGAVCTString(e.getKey()) + " " + e.getValue());
}
});
logger.debug("Indexed directories/artifacts for annotation scanning:");
indexDurations.forEach(e -> logger.debug(" " + e.getKey() + " (index time " + e.getValue() + ")"));
}
}

Expand All @@ -137,10 +144,10 @@ private boolean isIgnored(Artifact artifact, List<String> includeDependenciesSco
|| ignoredArtifacts.contains(artifact.getGroupId() + ":" + artifact.getArtifactId());
}

private IndexView timeAndCache(List<Map.Entry<Artifact, Duration>> indexDurations, Artifact artifact,
Callable<IndexView> callable) throws Exception {
private IndexView timeAndCache(List<Map.Entry<File, Duration>> indexDurations, File artifact,
Callable<IndexView> callable) throws ExecutionException {
LocalDateTime start = LocalDateTime.now();
IndexView result = indexCache.get(buildGAVCTString(artifact), callable);
IndexView result = indexCache.get(artifact.getAbsolutePath(), callable);
LocalDateTime end = LocalDateTime.now();

Duration duration = Duration.between(start, end);
Expand All @@ -150,33 +157,20 @@ private IndexView timeAndCache(List<Map.Entry<Artifact, Duration>> indexDuration
}

// index the classes of this Maven module
private Index indexModuleClasses(Artifact artifact) throws IOException {

Indexer indexer = new Indexer();

private Index indexModuleClasses(File artifact) throws IOException {
// Check first if the classes directory exists, before attempting to create an index for the classes
if (artifact.getFile().exists()) {
try (Stream<Path> stream = Files.walk(artifact.getFile().toPath())) {
List<Path> classFiles = stream
if (artifact.exists()) {
try (Stream<Path> stream = Files.walk(artifact.toPath())) {
File[] classFiles = stream
.filter(path -> path.toString().endsWith(".class"))
.collect(Collectors.toList());
for (Path path : classFiles) {
indexer.index(Files.newInputStream(path));
}
.map(Path::toFile)
.toArray(File[]::new);
return Index.of(classFiles);
}
} else {
logger.warn("Module directory does not exist: " + artifact);
return Index.of(Collections.emptyList());
}
return indexer.complete();
}

private String buildGAVCTString(Artifact artifact) {
return artifact.getGroupId() +
":" +
artifact.getArtifactId() +
":" +
artifact.getVersion() +
":" +
artifact.getClassifier() +
":" +
artifact.getType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.soebes.itf.jupiter.maven.MavenExecutionResult;

@MavenJupiterExtension
@MavenGoal("compile")
@MavenGoal("${project.groupId}:${project.artifactId}:${project.version}:generate-schema")
public class BasicIT extends SchemaTestBase {
@MavenTest
Expand All @@ -50,6 +51,8 @@ void basic_info(MavenExecutionResult result) throws IOException {

assertTrue(servers.contains(properties.get("server1").toString()));
assertTrue(servers.contains(properties.get("server2").toString()));

assertTrue(schema.getPaths().hasPathItem("/hello"));
};

testSchema(result, schemaConsumer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import com.soebes.itf.jupiter.maven.MavenExecutionResult;

import io.smallrye.openapi.runtime.io.OpenApiParser;

public class SchemaTestBase {

/**
Expand All @@ -25,13 +27,13 @@ private OpenAPI readJson(MavenExecutionResult result) throws IOException {
File openapiFile = new File(result.getMavenProjectResult().getTargetProjectDirectory(),
"target/generated/openapi.json");

return TestObjectMapperHolder.json().readValue(openapiFile, OpenAPI.class);
return OpenApiParser.parse(openapiFile.toURI().toURL());
}

private OpenAPI readYaml(MavenExecutionResult result) throws IOException {
File openapiFile = new File(result.getMavenProjectResult().getTargetProjectDirectory(),
"target/generated/openapi.yaml");

return TestObjectMapperHolder.yaml().readValue(openapiFile, OpenAPI.class);
return OpenApiParser.parse(openapiFile.toURI().toURL());
}
}

This file was deleted.

Loading

0 comments on commit c00cc60

Please sign in to comment.