From b0c94d4b0ee95584ff396cb8c6a9a694acf10579 Mon Sep 17 00:00:00 2001 From: Michael Edgar Date: Wed, 16 Aug 2023 08:57:37 +0800 Subject: [PATCH] Maven plugin: index output directory instead of project artifact, logs (#1538) (backport) Signed-off-by: Michael Edgar backport --- .../mavenplugin/GenerateSchemaMojo.java | 62 ++++++++---- .../MavenDependencyIndexCreator.java | 98 +++++++++---------- .../smallrye/openapi/mavenplugin/BasicIT.java | 3 + .../openapi/mavenplugin/SchemaTestBase.java | 6 +- .../mavenplugin/TestObjectMapperHolder.java | 77 --------------- .../mavenplugin/BasicIT/basic_info/pom.xml | 16 +++ .../io/smallrye/example/ExampleResource.java | 16 +++ 7 files changed, 128 insertions(+), 150 deletions(-) delete mode 100644 tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/TestObjectMapperHolder.java create mode 100644 tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/src/main/java/io/smallrye/example/ExampleResource.java diff --git a/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/GenerateSchemaMojo.java b/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/GenerateSchemaMojo.java index 7d61e6afb..feee84abb 100644 --- a/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/GenerateSchemaMojo.java +++ b/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/GenerateSchemaMojo.java @@ -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; @@ -295,18 +297,32 @@ private OpenApiDocument generateSchema(IndexView index) throws IOException, Depe return document; } - private ClassLoader getClassLoader() throws MalformedURLException, DependencyResolutionRequiredException { - Set urls = new HashSet<>(); + private ClassLoader getClassLoader() throws DependencyResolutionRequiredException { + Set 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) { @@ -371,7 +387,7 @@ private Map 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))); } } @@ -438,17 +454,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); writeSchemaFile(directory, "yaml", yaml.getBytes(charset)); @@ -461,6 +467,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)) { diff --git a/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/MavenDependencyIndexCreator.java b/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/MavenDependencyIndexCreator.java index fd97d6442..e2b2be402 100644 --- a/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/MavenDependencyIndexCreator.java +++ b/tools/maven-plugin/src/main/java/io/smallrye/openapi/mavenplugin/MavenDependencyIndexCreator.java @@ -1,5 +1,6 @@ package io.smallrye.openapi.mavenplugin; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -7,13 +8,14 @@ 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; @@ -71,40 +73,50 @@ public MavenDependencyIndexCreator() { } public IndexView createIndex(MavenProject mavenProject, boolean scanDependenciesDisable, - List includeDependenciesScopes, List includeDependenciesTypes) throws Exception { + List includeDependenciesScopes, List includeDependenciesTypes) { - List> indexDurations = new ArrayList<>(); + List> indexDurations = new ArrayList<>(); + + List 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 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 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); @@ -112,15 +124,10 @@ public IndexView createIndex(MavenProject mavenProject, boolean scanDependencies return CompositeIndex.create(indexes); } - private void printIndexDurations(List> indexDurations) { + private void printIndexDurations(List> 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() + ")")); } } @@ -137,10 +144,10 @@ private boolean isIgnored(Artifact artifact, List includeDependenciesSco || ignoredArtifacts.contains(artifact.getGroupId() + ":" + artifact.getArtifactId()); } - private IndexView timeAndCache(List> indexDurations, Artifact artifact, - Callable callable) throws Exception { + private IndexView timeAndCache(List> indexDurations, File artifact, + Callable 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); @@ -150,33 +157,20 @@ private IndexView timeAndCache(List> 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 stream = Files.walk(artifact.getFile().toPath())) { - List classFiles = stream + if (artifact.exists()) { + try (Stream 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(); - } } diff --git a/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/BasicIT.java b/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/BasicIT.java index 755bff863..783af3b0b 100644 --- a/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/BasicIT.java +++ b/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/BasicIT.java @@ -18,6 +18,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 @@ -44,6 +45,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); diff --git a/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/SchemaTestBase.java b/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/SchemaTestBase.java index 16e8fe05c..0c7d6dce9 100644 --- a/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/SchemaTestBase.java +++ b/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/SchemaTestBase.java @@ -8,6 +8,8 @@ import com.soebes.itf.jupiter.maven.MavenExecutionResult; +import io.smallrye.openapi.runtime.io.OpenApiParser; + public class SchemaTestBase { /** @@ -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()); } } diff --git a/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/TestObjectMapperHolder.java b/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/TestObjectMapperHolder.java deleted file mode 100644 index a998c0244..000000000 --- a/tools/maven-plugin/src/test/java/io/smallrye/openapi/mavenplugin/TestObjectMapperHolder.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.smallrye.openapi.mavenplugin; - -import org.eclipse.microprofile.openapi.models.OpenAPI; -import org.eclipse.microprofile.openapi.models.Paths; -import org.eclipse.microprofile.openapi.models.info.Contact; -import org.eclipse.microprofile.openapi.models.info.Info; -import org.eclipse.microprofile.openapi.models.info.License; -import org.eclipse.microprofile.openapi.models.servers.Server; - -import com.fasterxml.jackson.core.Version; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; - -import io.smallrye.openapi.api.models.OpenAPIImpl; -import io.smallrye.openapi.api.models.PathsImpl; -import io.smallrye.openapi.api.models.info.ContactImpl; -import io.smallrye.openapi.api.models.info.InfoImpl; -import io.smallrye.openapi.api.models.info.LicenseImpl; -import io.smallrye.openapi.api.models.servers.ServerImpl; - -public class TestObjectMapperHolder { - private static ObjectMapper json; - - private static ObjectMapper yaml; - - public static ObjectMapper json() { - if (json != null) { - return json; - } - - ObjectMapper mapper = new ObjectMapper(); - - configure(mapper); - - json = mapper; - - return mapper; - } - - public static ObjectMapper yaml() { - if (yaml != null) { - return yaml; - } - - YAMLFactory factory = new YAMLFactory(); - factory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES); - factory.enable(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS); - ObjectMapper mapper = new ObjectMapper(factory); - - configure(mapper); - - yaml = mapper; - - return mapper; - } - - private static void configure(ObjectMapper mapper) { - { - SimpleModule module = new SimpleModule("AbstractTypeMapping", Version.unknownVersion()); - - SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver(); - resolver.addMapping(OpenAPI.class, OpenAPIImpl.class); - resolver.addMapping(Info.class, InfoImpl.class); - resolver.addMapping(Contact.class, ContactImpl.class); - resolver.addMapping(License.class, LicenseImpl.class); - resolver.addMapping(Server.class, ServerImpl.class); - resolver.addMapping(Paths.class, PathsImpl.class); - - module.setAbstractTypes(resolver); - - mapper.registerModule(module); - } - } -} diff --git a/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/pom.xml b/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/pom.xml index 3f3f94095..2b092bfe5 100644 --- a/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/pom.xml +++ b/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/pom.xml @@ -23,8 +23,24 @@ https://staging.example.com + + + javax.ws.rs + javax.ws.rs-api + 2.1.1 + + + + + maven-compiler-plugin + 3.11.0 + + 1.8 + 1.8 + + @project.groupId@ @project.artifactId@ diff --git a/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/src/main/java/io/smallrye/example/ExampleResource.java b/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/src/main/java/io/smallrye/example/ExampleResource.java new file mode 100644 index 000000000..0dc195acb --- /dev/null +++ b/tools/maven-plugin/src/test/resources-its/io/smallrye/openapi/mavenplugin/BasicIT/basic_info/src/main/java/io/smallrye/example/ExampleResource.java @@ -0,0 +1,16 @@ +package io.smallrye.example; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; + +@Path("/") +public class ExampleResource { + + @GET + @Path("/hello") + public String sayHello(@QueryParam("greeting") String greeting) { + return greeting + " world!"; + } + +}