From 5742468ff4bd0b56cc807d11bf0c35f613f4458d Mon Sep 17 00:00:00 2001 From: Henry Lee Date: Thu, 30 Nov 2023 20:15:30 +0900 Subject: [PATCH] refactor(java): maven-plugin-tools --- Java-base/maven-plugin-tools/Dockerfile | 28 + Java-base/maven-plugin-tools/src/Jenkinsfile | 20 + Java-base/maven-plugin-tools/src/README.md | 99 +++ .../maven-plugin-tools/src/deploySite.sh | 23 + .../src/maven-plugin-annotations/pom.xml | 41 + .../maven/plugins/annotations/Component.java | 54 ++ .../maven/plugins/annotations/Execute.java | 58 ++ .../annotations/InstantiationStrategy.java | 46 + .../plugins/annotations/LifecyclePhase.java | 77 ++ .../maven/plugins/annotations/Mojo.java | 120 +++ .../maven/plugins/annotations/Parameter.java | 92 ++ .../plugins/annotations/ResolutionScope.java | 75 ++ .../src/site/apt/index.apt.vm | 38 + .../src/site/site.xml | 31 + .../src/maven-plugin-plugin/pom.xml | 368 ++++++++ .../invoker.properties | 20 + .../pom.xml | 131 +++ .../apache/maven/plugin/coreit/FirstMojo.java | 75 ++ .../resources/META-INF/maven/lifecycle.xml | 37 + .../verify.groovy | 99 +++ .../invoker.properties | 20 + .../module-abstract-mojo/pom.xml | 32 + .../maven/plugins/AbstractFirstMojo.java | 64 ++ .../module-mojo/pom.xml | 62 ++ .../maven/plugin/coreit/CoreIt0014Mojo.java | 66 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 80 ++ .../maven/plugin/coreit/SecondMojo.java | 39 + .../resources/META-INF/maven/lifecycle.xml | 37 + .../pom.xml | 101 +++ .../verify.groovy | 99 +++ .../invoker.properties | 22 + .../it/annotation-with-inheritance/pom.xml | 129 +++ .../plugin/coreit/AbstractFirstMojo.java | 63 ++ .../maven/plugin/coreit/AbstractFooMojo.java | 43 + .../maven/plugin/coreit/CoreIt0014Mojo.java | 66 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 87 ++ .../maven/plugin/coreit/SecondMojo.java | 39 + .../apache/maven/plugin/coreit/ThirdMojo.java | 87 ++ .../resources/META-INF/maven/lifecycle.xml | 37 + .../annotation-with-inheritance/verify.groovy | 103 +++ .../src/it/ant-basic/invoker.properties | 20 + .../src/it/ant-basic/pom.xml | 69 ++ .../src/main/scripts/touch.build.xml | 27 + .../src/main/scripts/touch.mojos.xml | 44 + .../src/it/ant-basic/verify.groovy | 30 + .../invoker.properties | 20 + .../src/it/ant-reference-parameter/pom.xml | 65 ++ .../plugins/antWithRefs/ArtifactsTask.java | 35 + .../maven/plugins/antWithRefs/antlib.xml | 25 + .../src/main/scripts/test.build.xml | 29 + .../src/main/scripts/test.mojos.xml | 41 + .../it/ant-simple-usage/invoker.properties | 20 + .../src/it/ant-simple-usage/plugin/pom.xml | 69 ++ .../plugin/src/main/scripts/test.build.xml | 26 + .../plugin/src/main/scripts/test.mojos.xml | 40 + .../src/it/ant-simple-usage/pom.xml | 48 + .../src/it/ant-simple-usage/usage/pom.xml | 63 ++ .../src/it/ant-since-maven-plugin/pom.xml | 49 ++ .../src/main/scripts/sample.build.xml | 35 + .../src/main/scripts/sample.mojos.xml | 46 + .../src/it/asm-failure/invoker.properties | 18 + .../src/it/asm-failure/pom.xml | 67 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 51 ++ .../src/it/asm-failure/verify.groovy | 24 + .../it/beanshell-simple/invoker.properties | 20 + .../src/it/beanshell-simple/pom.xml | 68 ++ .../src/main/scripts/touch.bsh | 65 ++ .../src/it/beanshell-simple/verify.groovy | 27 + .../antsample-maven-plugin/pom.xml | 77 ++ .../src/main/scripts/sample.build.xml | 35 + .../src/main/scripts/sample.mojos.xml | 46 + .../antsample-maven-plugin/src/site/site.xml | 36 + .../it/fix-maven-since-3.x/invoker.properties | 21 + .../javasample-maven-plugin/pom.xml | 49 ++ .../src/main/java/test/MyMojo.java | 65 ++ .../javasample-maven-plugin/src/site/site.xml | 37 + .../src/it/fix-maven-since-3.x/pom.xml | 94 ++ .../src/it/fix-maven-since-3.x/verify.groovy | 27 + .../src/it/help-basic-jdk11/expected-help.txt | 25 + .../it/help-basic-jdk11/invoker.properties | 23 + .../src/it/help-basic-jdk11/pom.xml | 92 ++ .../src/main/java/test/MyMojo.java | 68 ++ .../src/it/help-basic-jdk11/test.properties | 19 + .../src/it/help-basic-jdk11/verify.groovy | 28 + .../src/it/help-basic/expected-help.txt | 25 + .../src/it/help-basic/invoker.properties | 23 + .../src/it/help-basic/pom.xml | 87 ++ .../help-basic/src/main/java/test/MyMojo.java | 68 ++ .../src/it/help-basic/test.properties | 19 + .../src/it/help-basic/verify.groovy | 28 + .../src/it/help-package/invoker.properties | 18 + .../src/it/help-package/pom.xml | 80 ++ .../src/main/java/test/MyMojo.java | 37 + .../src/it/help-package/verify.bsh | 26 + .../ignore-plugin-class-realm/dep-a/pom.xml | 40 + .../dep-a/src/main/java/test/ClassA.java | 24 + .../ignore-plugin-class-realm/dep-b/pom.xml | 48 + .../dep-b/src/main/java/test/ClassB.java | 33 + .../invoker.properties | 22 + .../src/it/ignore-plugin-class-realm/pom.xml | 64 ++ .../it/ignore-plugin-class-realm/test/pom.xml | 73 ++ .../test/src/main/java/test/SomeMojo.java | 34 + .../invoker.properties | 21 + .../it/java-basic-annotations-jdk8/pom.xml | 108 +++ .../maven/plugin/coreit/CoreIt0014Mojo.java | 66 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 91 ++ .../maven/plugin/coreit/MPlugin220Mojo.java | 47 + .../apache/maven/plugin/coreit/Maximal.java | 76 ++ .../apache/maven/plugin/coreit/Minimal.java | 43 + .../maven/plugin/coreit/TestInterface.java | 30 + .../java-basic-annotations-jdk8/verify.groovy | 231 +++++ .../invoker.properties | 21 + .../java-basic-annotations-jdkcurrent/pom.xml | 103 +++ .../maven/plugin/coreit/CoreIt0014Mojo.java | 66 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 91 ++ .../maven/plugin/coreit/MPlugin220Mojo.java | 47 + .../apache/maven/plugin/coreit/Maximal.java | 76 ++ .../apache/maven/plugin/coreit/Minimal.java | 43 + .../maven/plugin/coreit/TestInterface.java | 30 + .../verify.groovy | 231 +++++ .../java-basic-annotations/invoker.properties | 20 + .../src/it/java-basic-annotations/pom.xml | 100 +++ .../maven/plugin/coreit/CoreIt0014Mojo.java | 66 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 91 ++ .../maven/plugin/coreit/MPlugin220Mojo.java | 47 + .../apache/maven/plugin/coreit/Maximal.java | 76 ++ .../apache/maven/plugin/coreit/Minimal.java | 43 + .../it/java-basic-annotations/verify.groovy | 231 +++++ .../src/it/java-basic/invoker.properties | 20 + .../src/it/java-basic/pom.xml | 63 ++ .../maven/plugin/coreit/CoreIt0013Mojo.java | 67 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 102 +++ .../apache/maven/plugin/coreit/Maximal.java | 71 ++ .../apache/maven/plugin/coreit/Minimal.java | 46 + .../src/it/java-basic/verify.groovy | 182 ++++ .../src/it/mplugin-187/invoker.properties | 18 + .../src/it/mplugin-187/pom.xml | 45 + .../src/it/mplugin-191/invoker.properties | 18 + .../src/it/mplugin-191/pom.xml | 67 ++ .../maven/plugins/plugin/it/MyMojo.java | 64 ++ .../src/it/mplugin-191/verify.groovy | 24 + .../src/it/mplugin-223/invoker.properties | 15 + .../src/it/mplugin-223/pom.xml | 84 ++ .../maven/plugins/plugin/it/MyMojo.java | 64 ++ .../src/it/mplugin-223/verify.groovy | 28 + .../it/mplugin-272_java8/invoker.properties | 19 + .../src/it/mplugin-272_java8/pom.xml | 83 ++ .../src/main/java/fr/ca/MyMojo.java | 37 + .../src/main/java/fr/ca/TestInterface.java | 30 + .../invoker.properties | 20 + .../it/mplugin-299_no-configuration/pom.xml | 87 ++ .../src/main/java/test/MyMojo.java | 37 + .../test.properties | 19 + .../invoker.properties | 18 + .../pom.xml | 82 ++ .../plugins/plugin/it/CustomSurefireMojo.java | 289 ++++++ .../verify.groovy | 26 + .../invoker.properties | 18 + .../mplugin-305_emptyMojoDependencies/pom.xml | 85 ++ .../plugins/plugin/it/CustomSurefireMojo.java | 289 ++++++ .../verify.groovy | 26 + .../invoker.properties | 18 + .../pom.xml | 85 ++ .../plugins/plugin/it/CustomSurefireMojo.java | 289 ++++++ .../verify.groovy | 26 + .../invoker.properties | 19 + .../src/it/mplugin-319_report-since/pom.xml | 86 ++ .../src/main/java/org/MyMojo.java | 67 ++ .../it/mplugin-319_report-since/verify.groovy | 27 + .../it/mplugin-324_javadoc/invoker.properties | 18 + .../src/it/mplugin-324_javadoc/pom.xml | 95 ++ .../src/main/java/test/MyMojo.java | 68 ++ .../src/it/packaging-jar/invoker.properties | 18 + .../src/it/packaging-jar/pom.xml | 102 +++ .../apache/maven/plugin/coreit/FirstMojo.java | 35 + .../src/it/packaging-jar/verify.groovy | 31 + .../invoker.properties | 18 + .../plugin-info-jdk-default-version/pom.xml | 92 ++ .../maven/plugins/issues/plugin/MyMojo.java | 64 ++ .../src/site/site.xml | 30 + .../verify.groovy | 27 + .../src/it/plugin-info-jdk/invoker.properties | 18 + .../src/it/plugin-info-jdk/plugin/pom.xml | 62 ++ .../main/resources/META-INF/maven/plugin.xml | 69 ++ .../plugin-info-jdk/pluginManagement/pom.xml | 53 ++ .../main/resources/META-INF/maven/plugin.xml | 69 ++ .../src/it/plugin-info-jdk/pom.xml | 96 ++ .../src/it/plugin-info-jdk/property/pom.xml | 39 + .../main/resources/META-INF/maven/plugin.xml | 69 ++ .../it/plugin-info-jdk/requirement/pom.xml | 78 ++ .../main/resources/META-INF/maven/plugin.xml | 69 ++ .../src/it/plugin-info-jdk/test.properties | 18 + .../src/it/plugin-info-jdk/verify.groovy | 25 + .../invoker.properties | 18 + .../src/it/plugin-report-annotations/pom.xml | 119 +++ .../src/main/java/org/DummyReport.java | 227 +++++ .../src/main/java/org/MyMojo.java | 65 ++ .../it/plugin-report-annotations/verify.bsh | 55 ++ .../src/it/plugin-report/invoker.properties | 18 + .../src/it/plugin-report/pom.xml | 109 +++ .../src/main/java/org/DummyReport.java | 210 +++++ .../src/main/java/org/MyMojo.java | 67 ++ .../src/it/plugin-report/verify.bsh | 56 ++ .../maven-plugin-plugin/src/it/settings.xml | 62 ++ .../src/it/skip/invoker.properties | 19 + .../maven-plugin-plugin/src/it/skip/pom.xml | 56 ++ .../maven/plugin/coreit/CoreIt0013Mojo.java | 67 ++ .../apache/maven/plugin/coreit/FirstMojo.java | 72 ++ .../maven/plugin/coreit/SecondMojo.java | 39 + .../src/it/skip/verify.groovy | 23 + .../src/it/source-encoding/latin-1/pom.xml | 66 ++ .../latin-1/src/main/java/test/MyMojo.java | 39 + .../src/it/source-encoding/pom.xml | 39 + .../src/it/source-encoding/utf-8/pom.xml | 66 ++ .../utf-8/src/main/java/test/MyMojo.java | 39 + .../src/it/source-encoding/verify.groovy | 32 + .../META-INF/plexus/components.xml | 93 ++ .../plugin/plugin/AbstractGeneratorMojo.java | 322 +++++++ .../plugin/DescriptorGeneratorMojo.java | 94 ++ .../plugin/plugin/HelpGeneratorMojo.java | 101 +++ .../maven/plugin/plugin/PluginReport.java | 828 ++++++++++++++++++ .../AddPluginArtifactMetadataMojo.java | 109 +++ .../MNG6109PluginDescriptorBuilder.java | 62 ++ .../src/main/mdo/pluginRequirements.mdo | 78 ++ .../main/resources/plugin-report.properties | 48 + .../resources/plugin-report_de.properties | 48 + .../resources/plugin-report_en.properties | 23 + .../resources/plugin-report_fr.properties | 48 + .../resources/plugin-report_sv.properties | 48 + .../src/site/apt/examples/ant-mojo.apt.vm | 80 ++ .../site/apt/examples/beanshell-mojo.apt.vm | 73 ++ .../apt/examples/generate-descriptor.apt.vm | 118 +++ .../site/apt/examples/generate-help.apt.vm | 58 ++ .../site/apt/examples/generate-report.apt.vm | 50 ++ .../apt/examples/using-annotations.apt.vm | 126 +++ .../src/site/apt/index.apt | 83 ++ .../site/apt/multiple-language-support.apt | 53 ++ .../src/site/apt/usage.apt | 87 ++ .../src/maven-plugin-plugin/src/site/site.xml | 52 ++ .../maven-plugin-tools-annotations/pom.xml | 159 ++++ ...avaAnnotationsMojoDescriptorExtractor.java | 740 ++++++++++++++++ .../datamodel/AnnotatedContent.java | 65 ++ .../annotations/datamodel/AnnotatedField.java | 61 ++ .../datamodel/ComponentAnnotationContent.java | 92 ++ .../datamodel/ExecuteAnnotationContent.java | 88 ++ .../datamodel/MojoAnnotationContent.java | 232 +++++ .../datamodel/ParameterAnnotationContent.java | 212 +++++ .../DefaultMojoAnnotationsScanner.java | 340 +++++++ .../scanner/MojoAnnotatedClass.java | 168 ++++ .../scanner/MojoAnnotationsScanner.java | 53 ++ .../MojoAnnotationsScannerRequest.java | 102 +++ .../visitors/MojoAnnotationVisitor.java | 83 ++ .../scanner/visitors/MojoClassVisitor.java | 174 ++++ .../scanner/visitors/MojoFieldVisitor.java | 93 ++ .../src/site/apt/index.apt | 134 +++ .../src/site/site.xml | 31 + .../annotations/AbstractFooMojo.java | 30 + .../plugin/extractor/annotations/FooMojo.java | 72 ++ .../annotations/TestAnnotationsReader.java | 89 ++ .../DefaultMojoAnnotationsScannerTest.java | 46 + .../src/test/resources/java8-annotations.jar | Bin 0 -> 539 bytes .../src/test/resources/java9-module.jar | Bin 0 -> 266 bytes .../src/maven-plugin-tools-api/pom.xml | 96 ++ .../plugin/DefaultPluginToolsRequest.java | 179 ++++ .../tools/plugin/ExtendedMojoDescriptor.java | 54 ++ .../tools/plugin/PluginToolsRequest.java | 143 +++ ...stractScriptedMojoDescriptorExtractor.java | 233 +++++ .../plugin/extractor/ExtractionException.java | 49 ++ .../extractor/MojoDescriptorExtractor.java | 47 + .../plugin/scanner/DefaultMojoScanner.java | 157 ++++ .../tools/plugin/scanner/MojoScanner.java | 59 ++ .../maven/tools/plugin/util/PluginUtils.java | 146 +++ .../resources/META-INF/plexus/components.xml | 42 + .../src/site/apt/index.apt | 36 + .../maven-plugin-tools-api/src/site/site.xml | 31 + .../scanner/DefaultMojoScannerTest.java | 207 +++++ .../plugin/scanner/ScannerTestExtractor.java | 63 ++ .../tools/plugin/scanner/TestExtractor.java | 53 ++ .../tools/plugin/util/PluginUtilsTest.java | 66 ++ .../maven/tools/plugin/util/TestUtils.java | 72 ++ .../tools/plugin/util/stubs/MojoStub.java | 99 +++ .../META-INF/plexus/scannerTestComponents.xml | 41 + .../src/test/resources/test.txt | 18 + .../src/test/resources/testExcludes.txt | 18 + .../src/maven-plugin-tools-generators/pom.xml | 129 +++ .../tools/plugin/generator/Generator.java | 45 + .../plugin/generator/GeneratorException.java | 33 + .../plugin/generator/GeneratorUtils.java | 711 +++++++++++++++ .../generator/PluginDescriptorGenerator.java | 616 +++++++++++++ .../plugin/generator/PluginHelpGenerator.java | 437 +++++++++ .../plugin/generator/PluginXdocGenerator.java | 823 +++++++++++++++++ .../src/main/resources/help-class-source.vm | 490 +++++++++++ .../src/main/resources/pluginxdoc.properties | 62 ++ .../main/resources/pluginxdoc_de.properties | 56 ++ .../main/resources/pluginxdoc_en.properties | 23 + .../main/resources/pluginxdoc_fr.properties | 60 ++ .../src/site/site.xml | 34 + .../generator/AbstractGeneratorTestCase.java | 170 ++++ .../plugin/generator/GeneratorUtilsTest.java | 205 +++++ .../PluginDescriptorGeneratorTest.java | 127 +++ .../generator/PluginHelpGeneratorTest.java | 39 + .../generator/PluginXdocGeneratorTest.java | 46 + .../generator/stubs/MavenReportStub.java | 79 ++ .../src/maven-plugin-tools-java/pom.xml | 92 ++ .../JavaJavadocMojoDescriptorExtractor.java | 656 ++++++++++++++ .../javadoc/JavadocMojoAnnotation.java | 506 +++++++++++ .../src/site/apt/index.apt | 145 +++ .../maven-plugin-tools-java/src/site/site.xml | 31 + .../JavaMojoDescriptorExtractorTest.java | 268 ++++++ .../src/test/resources/MPLUGIN-290/Test.java | 32 + .../resources/MPLUGIN-290/plugin-expected.xml | 33 + .../test/resources/MPLUGIN-314/MyMojo.java | 41 + .../resources/MPLUGIN-314/plugin-expected.xml | 56 ++ .../resources/MPLUGIN-320/Exceptions.java | 32 + .../resources/MPLUGIN-320/plugin-expected.xml | 33 + .../src/test/resources/dir-flag.txt | 27 + .../src/test/resources/java-1.5/MyEnum.java | 33 + .../src/test/resources/java-1.5/MyMojo.java | 40 + .../resources/java-1.5/plugin-expected.xml | 50 ++ .../src/test/resources/source/Default.java | 59 ++ .../src/test/resources/source/Full.java | 86 ++ .../test/resources/source/package-info.java | 23 + .../test/resources/source/plugin-expected.xml | 124 +++ .../src/test/resources/source2/Bla.java | 24 + .../source2/JavaExtractorTestThree.java | 53 ++ .../resources/source2/plugin-expected.xml | 61 ++ .../src/test/resources/source2/sub/MyBla.java | 27 + .../resources/source3/TestAnnotation.java | 27 + .../resources/source3/plugin-expected.xml | 33 + .../maven-plugin-tools-ant/pom.xml | 78 ++ .../ant/AntMojoDescriptorExtractor.java | 244 ++++++ .../src/site/apt/index.apt | 37 + .../maven-plugin-tools-ant/src/site/site.xml | 31 + .../ant/AntMojoDescriptorExtractorTest.java | 141 +++ .../src/test/resources/basic/test.build.xml | 29 + .../src/test/resources/basic/test.mojos.xml | 74 ++ .../maven-plugin-tools-beanshell/pom.xml | 74 ++ .../BeanshellMojoDescriptorExtractor.java | 131 +++ .../src/main/resources/extractor.bsh | 242 +++++ .../src/site/apt/index.apt | 33 + .../src/site/site.xml | 31 + .../maven-plugin-tools-model/pom.xml | 102 +++ .../model/PluginMetadataParseException.java | 78 ++ .../extractor/model/PluginMetadataParser.java | 190 ++++ .../src/main/mdo/plugin-metadata.mdo | 357 ++++++++ .../src/site/apt/index.apt | 41 + .../src/site/site.xml | 31 + .../model/PluginMetadataParserTest.java | 80 ++ .../src/test/resources/test.mojos.xml | 37 + .../src/test/resources/test2.mojos.xml | 38 + .../src/maven-script/maven-script-ant/pom.xml | 73 ++ .../script/ant/AntMojoComponentFactory.java | 42 + .../maven/script/ant/AntMojoWrapper.java | 383 ++++++++ .../maven/script/ant/AntPropertyHelper.java | 205 +++++ .../resources/META-INF/plexus/components.xml | 28 + .../maven-script-ant/src/site/site.xml | 36 + .../maven/script/ant/AntMojoWrapperTest.java | 293 +++++++ .../resources/META-INF/maven/plugin-2.0.xml | 63 ++ .../resources/META-INF/maven/plugin-2.1.xml | 89 ++ .../src/test/resources/test.build.xml | 35 + .../maven-script-beanshell/pom.xml | 50 ++ .../beanshell/BeanshellMojoAdapter.java | 70 ++ .../maven-script-beanshell/src/site/site.xml | 36 + .../src/maven-script/pom.xml | 44 + .../src/maven-script/src/site/site.xml | 30 + Java-base/maven-plugin-tools/src/pom.xml | 417 +++++++++ .../src/src/site/resources/download.cgi | 22 + .../resources/images/plugin-tools-deps.png | Bin 0 -> 47339 bytes .../maven-plugin-tools/src/src/site/site.xml | 42 + .../src/src/site/xdoc/download.xml.vm | 126 +++ .../src/src/site/xdoc/index.xml | 132 +++ .../src/src/site/xdoc/plugin-tools-deps.odg | Bin 0 -> 26872 bytes .../Dockerfile | 18 + .../buggy.java | 345 ++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 345 ++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 312 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 312 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 149 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 140 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 604 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 664 ++++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 660 ++++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 608 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 608 +++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 560 ++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 652 ++++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 660 ++++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 199 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 212 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 580 ++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 476 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 476 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 446 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 479 ++++++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 169 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 167 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 153 ++++ .../metadata.json | 21 + .../npe.json | 7 + 528 files changed, 51948 insertions(+) create mode 100644 Java-base/maven-plugin-tools/Dockerfile create mode 100644 Java-base/maven-plugin-tools/src/Jenkinsfile create mode 100644 Java-base/maven-plugin-tools/src/README.md create mode 100644 Java-base/maven-plugin-tools/src/deploySite.sh create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/InstantiationStrategy.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/ResolutionScope.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/apt/index.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFooMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/ThirdMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/java/org/apache/maven/plugins/antWithRefs/ArtifactsTask.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/resources/org/apache/maven/plugins/antWithRefs/antlib.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/usage/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/src/main/scripts/touch.bsh create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/expected-help.txt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/test.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/expected-help.txt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/test.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/verify.bsh create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/src/main/java/test/ClassA.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/src/main/java/test/ClassB.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/src/main/java/test/SomeMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Maximal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Minimal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Maximal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Minimal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Maximal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Minimal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Maximal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Minimal.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/TestInterface.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/test.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/src/main/java/org/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/main/java/org/apache/maven/plugins/issues/plugin/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/src/main/resources/META-INF/maven/plugin.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/src/main/resources/META-INF/maven/plugin.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/src/main/resources/META-INF/maven/plugin.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/src/main/resources/META-INF/maven/plugin.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/test.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/DummyReport.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/verify.bsh create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/DummyReport.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/verify.bsh create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/settings.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/invoker.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/src/main/java/test/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/verify.groovy create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/filtered-resources/META-INF/plexus/components.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/metadata/AddPluginArtifactMetadataMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/MNG6109PluginDescriptorBuilder.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/mdo/pluginRequirements.mdo create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_de.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_en.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_fr.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_sv.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/ant-mojo.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/beanshell-mojo.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-descriptor.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-help.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-report.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/multiple-language-support.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/usage.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedContent.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedField.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ComponentAnnotationContent.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/AbstractFooMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/resources/java8-annotations.jar create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/resources/java9-module.jar create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/ExtractionException.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/MojoScanner.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/resources/META-INF/plexus/components.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScannerTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/TestUtils.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MojoStub.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/META-INF/plexus/scannerTestComponents.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/test.txt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/testExcludes.txt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/help-class-source.vm create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGeneratorTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavadocMojoAnnotation.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/Test.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/Exceptions.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/dir-flag.txt create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyEnum.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyMojo.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Default.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Full.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/package-info.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/Bla.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/JavaExtractorTestThree.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/sub/MyBla.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/TestAnnotation.java create mode 100644 Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/plugin-expected.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractorTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/resources/extractor.bsh create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParseException.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/mdo/plugin-metadata.mdo create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/apt/index.apt create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParserTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test2.mojos.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoComponentFactory.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntPropertyHelper.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/resources/META-INF/plexus/components.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/java/org/apache/maven/script/ant/AntMojoWrapperTest.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.0.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.1.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/test.build.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/main/java/org/apache/maven/script/beanshell/BeanshellMojoAdapter.java create mode 100644 Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/maven-script/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/pom.xml create mode 100644 Java-base/maven-plugin-tools/src/src/site/resources/download.cgi create mode 100644 Java-base/maven-plugin-tools/src/src/site/resources/images/plugin-tools-deps.png create mode 100644 Java-base/maven-plugin-tools/src/src/site/site.xml create mode 100644 Java-base/maven-plugin-tools/src/src/site/xdoc/download.xml.vm create mode 100644 Java-base/maven-plugin-tools/src/src/site/xdoc/index.xml create mode 100644 Java-base/maven-plugin-tools/src/src/site/xdoc/plugin-tools-deps.odg create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_239/Dockerfile create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_239/buggy.java create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_239/metadata.json create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_239/npe.json create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_279/Dockerfile create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_279/buggy.java create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_279/metadata.json create mode 100644 Java/maven-plugin-tools-AntMojoWrapper_279/npe.json create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/Dockerfile create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/buggy.java create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/metadata.json create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/npe.json create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/Dockerfile create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/buggy.java create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/metadata.json create mode 100644 Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/npe.json create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_139/Dockerfile create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_139/buggy.java create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_139/metadata.json create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_139/npe.json create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_89/Dockerfile create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_89/buggy.java create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_89/metadata.json create mode 100644 Java/maven-plugin-tools-DefaultMojoScanner_89/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/npe.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/Dockerfile create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/buggy.java create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/metadata.json create mode 100644 Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/npe.json create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_185/Dockerfile create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_185/buggy.java create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_185/metadata.json create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_185/npe.json create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_204/Dockerfile create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_204/buggy.java create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_204/metadata.json create mode 100644 Java/maven-plugin-tools-ParameterAnnotationContent_204/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_155/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_155/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_155/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_155/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_360/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_360/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_360/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_360/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_380/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_380/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_380/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_380/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_403/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_403/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_403/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_403/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_424/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_424/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_424/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_424/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_455/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_455/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_455/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_455/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_467/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_467/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_467/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_467/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_474/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_474/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_474/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_474/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_490/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_490/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_490/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_490/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_502/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_502/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_502/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_502/npe.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_551/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_551/buggy.java create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_551/metadata.json create mode 100644 Java/maven-plugin-tools-PluginDescriptorGenerator_551/npe.json create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_120/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_120/buggy.java create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_120/metadata.json create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_120/npe.json create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_97/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_97/buggy.java create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_97/metadata.json create mode 100644 Java/maven-plugin-tools-PluginMetadataParser_97/npe.json create mode 100644 Java/maven-plugin-tools-PluginUtils_134/Dockerfile create mode 100644 Java/maven-plugin-tools-PluginUtils_134/buggy.java create mode 100644 Java/maven-plugin-tools-PluginUtils_134/metadata.json create mode 100644 Java/maven-plugin-tools-PluginUtils_134/npe.json diff --git a/Java-base/maven-plugin-tools/Dockerfile b/Java-base/maven-plugin-tools/Dockerfile new file mode 100644 index 000000000..e208c4890 --- /dev/null +++ b/Java-base/maven-plugin-tools/Dockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:22.04 + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y software-properties-common \ + && add-apt-repository ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y \ + build-essential \ + git \ + vim \ + jq \ + && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/list/* + +RUN apt-get -y install sudo \ + openjdk-8-jdk \ + maven + +RUN bash -c "echo 2 | update-alternatives --config java" + +COPY src /workspace +WORKDIR /workspace + +RUN mvn install -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false + +RUN mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 + +ENV TZ=Asia/Seoul diff --git a/Java-base/maven-plugin-tools/src/Jenkinsfile b/Java-base/maven-plugin-tools/src/Jenkinsfile new file mode 100644 index 000000000..e9f05f7d9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/Jenkinsfile @@ -0,0 +1,20 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +asfMavenTlpPlgnBuild() diff --git a/Java-base/maven-plugin-tools/src/README.md b/Java-base/maven-plugin-tools/src/README.md new file mode 100644 index 000000000..d784709e3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/README.md @@ -0,0 +1,99 @@ + +Contributing to [Apache Maven Plugin Tools](https://maven.apache.org/plugin-tools/) +====================== + +[![ASF Jira](https://img.shields.io/endpoint?url=https%3A%2F%2Fmaven.apache.org%2Fbadges%2Fasf_jira-MPLUGIN.json)][jira] +[![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/apache/maven.svg?label=License)][license] +[![Maven Central](https://img.shields.io/maven-central/v/org.apache.maven.plugins/maven-plugin-plugin.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.maven.plugins/maven-plugin-plugin) +[![Jenkins Status](https://img.shields.io/jenkins/s/https/builds.apache.org/job/maven-box/job/maven-plugin-tools/job/master.svg?)][build] +[![Jenkins tests](https://img.shields.io/jenkins/t/https/builds.apache.org/job/maven-box/job/maven-plugin-tools/job/master.svg?)][test-results] + + +You have found a bug or you have an idea for a cool new feature? Contributing +code is a great way to give something back to the open source community. Before +you dig right into the code, there are a few guidelines that we need +contributors to follow so that we can have a chance of keeping on top of +things. + +Getting Started +--------------- + ++ Make sure you have a [JIRA account](https://issues.apache.org/jira/). ++ Make sure you have a [GitHub account](https://github.com/signup/free). ++ If you're planning to implement a new feature, it makes sense to discuss your changes + on the [dev list][ml-list] first. + This way you can make sure you're not wasting your time on something that isn't + considered to be in Apache Maven's scope. ++ Submit a ticket for your issue, assuming one does not already exist. + + Clearly describe the issue, including steps to reproduce when it is a bug. + + Make sure you fill in the earliest version that you know has the issue. ++ Fork the repository on GitHub. + +Making and Submitting Changes +-------------- + +We accept Pull Requests via GitHub. The [developer mailing list][ml-list] is the +main channel of communication for contributors. +There are some guidelines which will make applying PRs easier for us: ++ Create a topic branch from where you want to base your work (this is usually the master branch). + Push your changes to a topic branch in your fork of the repository. ++ Make commits of logical units. ++ Respect the original code style: by using the same [codestyle][code-style], + patches should only highlight the actual difference, not being disturbed by any formatting issues: + + Only use spaces for indentation. + + Create minimal diffs - disable on save actions like reformat source code or organize imports. + If you feel the source code should be reformatted, create a separate PR for this change. + + Check for unnecessary whitespace with `git diff --check` before committing. ++ Make sure your commit messages are in the proper format. Your commit message should contain the key of the JIRA issue. +``` +[MPLUGIN-XXX] - Subject of the JIRA Ticket + Optional supplemental description. +``` ++ Make sure you have added the necessary tests (JUnit/IT) for your changes. ++ Run all the tests with `mvn -Prun-its verify` to assure nothing else was accidentally broken. ++ Submit a pull request to the repository in the Apache organization. ++ Update your JIRA ticket and include a link to the pull request in the ticket. + +If you plan to contribute on a regular basis, please consider filing a [contributor license agreement][cla]. + +Making Trivial Changes +---------------------- + +For changes of a trivial nature to comments and documentation, it is not always +necessary to create a new ticket in JIRA. In this case, it is appropriate to +start the first line of a commit with '(doc)' instead of a ticket number. + +Additional Resources +-------------------- + ++ [Contributing patches](https://maven.apache.org/guides/development/guide-maven-development.html#Creating_and_submitting_a_patch) ++ [Apache Maven Plugin Tools JIRA project page][jira] ++ [Contributor License Agreement][cla] ++ [General GitHub documentation](https://help.github.com/) ++ [GitHub pull request documentation](https://help.github.com/send-pull-requests/) ++ [Apache Maven Twitter Account](https://twitter.com/ASFMavenProject) ++ #Maven IRC channel on freenode.org + +[jira]: https://issues.apache.org/jira/projects/MPLUGIN/ +[license]: https://www.apache.org/licenses/LICENSE-2.0 +[ml-list]: https://maven.apache.org/mailing-lists.html +[code-style]: https://maven.apache.org/developers/conventions/code.html +[cla]: https://www.apache.org/licenses/#clas +[maven-wiki]: https://cwiki.apache.org/confluence/display/MAVEN/Index +[test-results]: https://builds.apache.org/job/maven-box/job/maven-plugin-tools-plugin/job/master/lastCompletedBuild/testReport/ +[build]: https://builds.apache.org/job/maven-box/job/maven-plugin-tools-plugin/job/master/ diff --git a/Java-base/maven-plugin-tools/src/deploySite.sh b/Java-base/maven-plugin-tools/src/deploySite.sh new file mode 100644 index 000000000..f6c265d75 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/deploySite.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +mvn -Preporting site site:stage $@ +mvn scm-publish:publish-scm $@ diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/pom.xml new file mode 100644 index 000000000..444286ffc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/pom.xml @@ -0,0 +1,41 @@ + + + + 4.0.0 + + + maven-plugin-tools + org.apache.maven.plugin-tools + 3.6.1-SNAPSHOT + + + maven-plugin-annotations + + Maven Plugin Tools Java Annotations + Java annotations to use in Mojos + + + + org.apache.maven + maven-artifact + 3.0 + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java new file mode 100644 index 000000000..9afbd65b6 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Component.java @@ -0,0 +1,54 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to configure injection of Plexus components by + * + * MavenPluginManager.getConfiguredMojo(...). + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD } ) +@Inherited +public @interface Component +{ + /** + * role of the component to inject. + * @return the role + */ + Class role() default Object.class; + + /** + * hint of the component to inject. + * @return the hint + */ + String hint() default ""; +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java new file mode 100644 index 000000000..1cf479bf8 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java @@ -0,0 +1,58 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used if your Mojo needs to fork a lifecycle. + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Execute +{ + /** + * lifecycle phase to fork. Note that specifying a phase overrides specifying a goal. + * @return the phase + */ + LifecyclePhase phase() default LifecyclePhase.NONE; + + /** + * goal to fork. Note that specifying a phase overrides specifying a goal. + * @return the goal + */ + String goal() default ""; + + /** + * lifecycle id to fork. + * @return the lifecycle id + */ + String lifecycle() default ""; +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/InstantiationStrategy.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/InstantiationStrategy.java new file mode 100644 index 000000000..2e6b1782c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/InstantiationStrategy.java @@ -0,0 +1,46 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Component instantiation strategy. + * + * @author Hervé Boutemy + * @since 3.0 + */ +public enum InstantiationStrategy +{ + PER_LOOKUP( "per-lookup" ), + SINGLETON( "singleton" ), + KEEP_ALIVE( "keep-alive" ), + POOLABLE( "poolable" ); + + private final String id; + + InstantiationStrategy( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java new file mode 100644 index 000000000..4930ebcbc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/LifecyclePhase.java @@ -0,0 +1,77 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Lifecycle phases. + * @author Olivier Lamy + * @since 3.0 + */ +public enum LifecyclePhase +{ + + VALIDATE( "validate" ), + INITIALIZE( "initialize" ), + GENERATE_SOURCES( "generate-sources" ), + PROCESS_SOURCES( "process-sources" ), + GENERATE_RESOURCES( "generate-resources" ), + PROCESS_RESOURCES( "process-resources" ), + COMPILE( "compile" ), + PROCESS_CLASSES( "process-classes" ), + GENERATE_TEST_SOURCES( "generate-test-sources" ), + PROCESS_TEST_SOURCES( "process-test-sources" ), + GENERATE_TEST_RESOURCES( "generate-test-resources" ), + PROCESS_TEST_RESOURCES( "process-test-resources" ), + TEST_COMPILE( "test-compile" ), + PROCESS_TEST_CLASSES( "process-test-classes" ), + TEST( "test" ), + PREPARE_PACKAGE( "prepare-package" ), + PACKAGE( "package" ), + PRE_INTEGRATION_TEST( "pre-integration-test" ), + INTEGRATION_TEST( "integration-test" ), + POST_INTEGRATION_TEST( "post-integration-test" ), + VERIFY( "verify" ), + INSTALL( "install" ), + DEPLOY( "deploy" ), + + PRE_CLEAN( "pre-clean" ), + CLEAN( "clean" ), + POST_CLEAN( "post-clean" ), + + PRE_SITE( "pre-site" ), + SITE( "site" ), + POST_SITE( "post-site" ), + SITE_DEPLOY( "site-deploy" ), + + NONE( "" ); + + private final String id; + + LifecyclePhase( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java new file mode 100644 index 000000000..e442310f1 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Mojo.java @@ -0,0 +1,120 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin). + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Mojo +{ + /** + * goal name (required). + * @return the goal name + */ + String name(); + + /** + * default phase to bind your mojo. + * @return the default phase + */ + LifecyclePhase defaultPhase() default LifecyclePhase.NONE; + + /** + * the required dependency resolution scope. + * @return the required dependency resolution scope + */ + ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE; + + /** + * the required dependency collection scope. + * @return the required dependency collection scope + */ + ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE; + + /** + * your Mojo instantiation strategy. (Only per-lookup and singleton are supported) + * @return the instantiation strategy + */ + InstantiationStrategy instantiationStrategy() default InstantiationStrategy.PER_LOOKUP; + + /** + * execution strategy: once-per-session or always. + * @return once-per-session or always + */ + String executionStrategy() default "once-per-session"; + + /** + * does your mojo requires a project to be executed? + * @return requires a project + */ + boolean requiresProject() default true; + + /** + * does your mojo requires a reporting context to be executed? + * @return requires a reporting context + */ + boolean requiresReports() default false; + + /** + * if the Mojo uses the Maven project and its child modules. + * @return uses the Maven project and its child modules + */ + boolean aggregator() default false; + + /** + * can this Mojo be invoked directly only? + * @return invoked directly only + */ + boolean requiresDirectInvocation() default false; + + /** + * does this Mojo need to be online to be executed? + * @return need to be online + */ + boolean requiresOnline() default false; + + boolean inheritByDefault() default true; + + /** + * own configurator class. + * @return own configurator class + */ + String configurator() default ""; + + /** + * is your mojo thread safe (since Maven 3.x)? + * @return is thread safe + */ + boolean threadSafe() default false; +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java new file mode 100644 index 000000000..e6d98e77d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java @@ -0,0 +1,92 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to configure your Mojo parameters to be injected by + * + * MavenPluginManager.getConfiguredMojo(...). + *

+ * Beans injected into Mojo parameters are prepared by Sisu JSR330-based + * container: this annotation is only effective on fields of the Mojo class itself, nested bean injection + * requires Sisu or JSR330 annotations. + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD } ) +@Inherited +public @interface Parameter +{ + /** + * name of the bean property used to get/set the field: by default, field name is used. + * @return the name of the bean property + */ + String name() default ""; + + /** + * alias supported to get parameter value. + * @return the alias + */ + String alias() default ""; + + /** + * Property to use to retrieve a value. Can come from -D execution, setting properties or pom + * properties. + * @return property name + */ + String property() default ""; + + /** + * parameter default value, eventually containing ${...} expressions which will be interpreted at + * inject time: see + * + * PluginParameterExpressionEvaluator. + * @return the default value + */ + String defaultValue() default ""; + + /** + * is the parameter required? + * @return true if the Mojo should fail when the parameter cannot be injected + */ + boolean required() default false; + + /** + * Specifies that this parameter cannot be configured directly by the user (as in the case of POM-specified + * configuration). This is useful when you want to force the user to use common POM elements rather than plugin + * configurations, as in the case where you want to use the artifact's final name as a parameter. In this case, you + * want the user to modify <build><finalName/></build> rather than specifying a value + * for finalName directly in the plugin configuration section. It is also useful to ensure that - for example - a + * List-typed parameter which expects items of type Artifact doesn't get a List full of Strings. + * + * @return true if the user should not be allowed to configure the parameter directly + */ + boolean readonly() default false; +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/ResolutionScope.java b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/ResolutionScope.java new file mode 100644 index 000000000..f8eaf6128 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/ResolutionScope.java @@ -0,0 +1,75 @@ +package org.apache.maven.plugins.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; + +/** + * Dependencies resolution scopes available before + * mojo execution. + * + * @author Hervé Boutemy + * @since 3.0 + */ +public enum ResolutionScope +{ + /** + * empty resolution scope + */ + NONE( null ), + /** + * compile resolution scope + * = compile + system + provided dependencies + */ + COMPILE( Artifact.SCOPE_COMPILE ), + /** + * compile+runtime resolution scope (Maven 3 only) + * = compile + system + provided + runtime dependencies + */ + COMPILE_PLUS_RUNTIME( Artifact.SCOPE_COMPILE_PLUS_RUNTIME ), + /** + * runtime resolution scope + * = compile + runtime dependencies + */ + RUNTIME( Artifact.SCOPE_RUNTIME ), + /** + * runtime+system resolution scope (Maven 3 only) + * = compile + system + runtime dependencies + */ + RUNTIME_PLUS_SYSTEM( Artifact.SCOPE_RUNTIME_PLUS_SYSTEM ), + /** + * test resolution scope + * = compile + system + provided + runtime + test + * dependencies + */ + TEST( Artifact.SCOPE_TEST ); + + private final String id; + + ResolutionScope( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/apt/index.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/apt/index.apt.vm new file mode 100644 index 000000000..dbc2ce963 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/apt/index.apt.vm @@ -0,0 +1,38 @@ + ------ + About ${project.name} + ------ + Hervé Boutemy + ------ + 2012-06-03 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +About ${project.name} + + ${project.description} + +* Usage + + To be able to {{{../maven-plugin-tools-annotations/index.html}use Maven Plugin Tools Java Annotations}}, + some configuration has to be done in <<>>: see + {{{../maven-plugin-plugin/examples/using-annotations.html#POM_configuration} Using Plugin Tools Java5 Annotations}} + example in {{{../maven-plugin-plugin} <<>>}} documentation. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-annotations/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + +

+ + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/pom.xml new file mode 100644 index 000000000..8578d40dc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/pom.xml @@ -0,0 +1,368 @@ + + + + 4.0.0 + + + maven-plugin-tools + org.apache.maven.plugin-tools + 3.6.1-SNAPSHOT + + + org.apache.maven.plugins + maven-plugin-plugin + maven-plugin + + Maven Plugin Plugin + + The Plugin Plugin is used to create a Maven plugin descriptor for any Mojo's found in the source tree, + to include in the JAR. It is also used to generate Xdoc files for the Mojos as well as the artifact metadata + and a generic help goal. + + + + 1.9.1 + 1.9.2 + true + + + + + org.apache.maven + maven-core + + + org.apache.maven + maven-compat + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + org.apache.maven.plugin-tools + maven-plugin-tools-generators + + + + + org.apache.maven.plugin-tools + maven-plugin-tools-java + runtime + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + runtime + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + + + + + + + + org.apache.maven.doxia + doxia-sink-api + ${doxiaVersion} + + + org.apache.maven.doxia + doxia-site-renderer + ${doxia-sitetoolsVersion} + + + org.codehaus.plexus + plexus-container-default + + + org.codehaus.plexus + plexus-component-api + + + + + + + org.apache.maven + maven-plugin-api + + + org.apache.maven + maven-model + + + org.apache.maven + maven-repository-metadata + ${mavenVersion} + + + org.apache.maven + maven-artifact + + + + + org.apache.maven.reporting + maven-reporting-impl + 3.0.0 + + + + + org.codehaus.plexus + plexus-utils + + + org.sonatype.sisu + sisu-inject-plexus + 1.4.2 + + + org.codehaus.plexus + plexus-velocity + + + velocity + velocity + + + + + + + org.apache.maven.plugin-tools + maven-script-beanshell + ${project.version} + test + + + org.apache.maven.plugin-tools + maven-script-ant + ${project.version} + test + + + + + + + + src/main/resources + + + src/main/filtered-resources + true + + + + + + org.apache.rat + apache-rat-plugin + + + + src/it/help-basic**/expected-help**.txt + + + + + + + + org.codehaus.modello + modello-maven-plugin + + + + java + + + + + 1.0.0 + + src/main/mdo/pluginRequirements.mdo + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + + enforce + + ensure-no-container-api + + + + + org.codehaus.plexus:plexus-component-api + + The new containers are not supported. You probably added a dependency that is missing the exclusions. + + + true + + + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.5 + + + + default-descriptor + process-classes + + + generated-helpmojo + + helpmojo + + + true + + + + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.3 + + + + report + + + + + + org.apache.maven.plugins + maven-invoker-plugin + ${mavenInvokerPluginVersion} + + + + + + + reporting + + + + org.apache.maven.plugins + maven-invoker-plugin + ${mavenInvokerPluginVersion} + + + org.codehaus.mojo + l10n-maven-plugin + 1.0-alpha-2 + + + de + fr + sv + + + + + org.apache.maven.plugins + maven-changes-plugin + 2.5 + + + Type,Key,Summary,Assignee,Status,Resolution,Fix Version + 200 + true + Closed + Type,Key + + + + + jira-report + + + + + + + + + run-its + + + + org.apache.maven.plugins + maven-invoker-plugin + ${mavenInvokerPluginVersion} + + ${it.debug} + src/it + ${project.build.directory}/it + setup + verify + ${project.build.directory}/local-repo + src/it/settings.xml + + 3.3 + ${antVersion} + + + ${maven.compiler.source} + ${maven.compiler.target} + ${https.protocols} + + + + + integration-test + + install + run + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties new file mode 100644 index 000000000..41266d1c6 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = install +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance-from-deps:annotation-with-inheritance-from-deps:1.0-SNAPSHOT:first +invoker.goals.3 = org.apache.maven.its.annotation-with-inheritance-from-deps:annotation-with-inheritance-from-deps:1.0-SNAPSHOT:help diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml new file mode 100644 index 000000000..792836cb4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml @@ -0,0 +1,131 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-from-deps + annotation-with-inheritance-from-deps + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: annotation-with-inheritance-from-deps + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + @mavenVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + @project.version@ + tests + + + + junit + junit + 4.12 + + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..3acb9b138 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,75 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.extractor.annotations.FooMojo; +import org.apache.maven.project.MavenProjectHelper; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +public class FirstMojo + extends FooMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class )// , roleHint = "default" + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + if ( bar == null ) + { + throw new MojoExecutionException( "bar == null" ); + } + if ( beer == null ) + { + throw new MojoExecutionException( "beer == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 000000000..908dcfea9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,37 @@ + + + + + + my-lifecycle + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy new file mode 100644 index 000000000..b46c82854 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" ); +assert !oldHelpClass.exists() + +File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ); +assert newHelpClass.exists() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'package' +assert mojo.executeLifecycle.text() == 'my-lifecycle' + +assert mojo.configuration.bar[0].text() == '${thebar}' +assert mojo.configuration.bar[0].'@implementation' == 'java.lang.String' +assert mojo.configuration.bar[0].'@default-value' == 'coolbar' + +assert mojo.configuration.beer[0].text() == '${thebeer}' +assert mojo.configuration.beer[0].'@implementation' == 'java.lang.String' +assert mojo.configuration.beer[0].'@default-value' == 'coolbeer' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[1].role.text() == 'org.codehaus.plexus.compiler.manager.CompilerManager' +assert mojo.requirements.requirement[1].'role-hint'.text() == '' +assert mojo.requirements.requirement[1].'field-name'.text() == 'compilerManager' + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +//assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "beer"}[0] + +assert parameter.name.text() == 'beer' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == "wine is better" +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == 'beer for non french folks' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "bar"}[0] + +assert parameter.name.text() == 'bar' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == 'the cool bar to go' + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties new file mode 100644 index 000000000..260443cdf --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance-reactor:module-mojo:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.annotation-with-inheritance-reactor:module-mojo:1.0-SNAPSHOT:first diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml new file mode 100644 index 000000000..0207b3788 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/pom.xml @@ -0,0 +1,32 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.annotation-with-inheritance-reactor + annotation-with-inheritance-reactor + 1.0-SNAPSHOT + + + module-abstract-mojo + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java new file mode 100644 index 000000000..985805805 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-abstract-mojo/src/main/java/org/apache/maven/plugins/AbstractFirstMojo.java @@ -0,0 +1,64 @@ +package org.apache.maven.plugins; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; + +import java.io.File; + +/** + * Touches a test file. + * + */ +public abstract class AbstractFirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + protected File basedir; + + @Parameter( property = "first.touchFile", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + protected File touchFile; + + /** + * Plexus compiler manager. + */ + @Component + protected CompilerManager compilerManager; + + /** + * + */ + @Component( role = ArtifactMetadataSource.class, hint = "maven" ) + protected ArtifactMetadataSource artifactMetadataSource; + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml new file mode 100644 index 000000000..b6502d817 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/pom.xml @@ -0,0 +1,62 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.annotation-with-inheritance-reactor + annotation-with-inheritance-reactor + 1.0-SNAPSHOT + + + module-mojo + maven-plugin + + + + org.apache.maven.its.annotation-with-inheritance-reactor + module-abstract-mojo + ${project.version} + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 000000000..26b9ce6a5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014" ) +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter( property = "project.build.directory", required = true ) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..b0b40fea6 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,80 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.AbstractFirstMojo; +import org.apache.maven.project.MavenProjectHelper; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractFirstMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class ) + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + if ( basedir == null ) + { + throw new MojoExecutionException( "basedir == null" ); + } + if ( touchFile == null ) + { + throw new MojoExecutionException( "touchFile == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + if (! ( projectHelper instanceof MavenProjectHelper )) + { + throw new MojoExecutionException( "! projectHelper instanceof MavenProjectHelper" ); + } + + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java new file mode 100644 index 000000000..8dc9dff17 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java @@ -0,0 +1,39 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * Does nothing special. + * + */ +@Mojo( name = "second", requiresDependencyCollection = ResolutionScope.COMPILE, threadSafe = true ) +public class SecondMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 000000000..5510b5e4f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/module-mojo/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,37 @@ + + + + + + cobertura + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml new file mode 100644 index 000000000..ad37af04f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/pom.xml @@ -0,0 +1,101 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-reactor + annotation-with-inheritance-reactor + 1.0-SNAPSHOT + + Maven Integration Test :: annotation-with-inheritance + pom + + module-abstract-mojo + module-mojo + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + @project.version@ + tests + + + + junit + junit + 4.12 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy new file mode 100644 index 000000000..d5aa091da --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance-reactor/verify.groovy @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "module-mojo/target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "module-mojo/target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +assert pluginDescriptor.mojos.mojo.size() == 3 + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +//assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile"}[0] + +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir"}[0] + +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "second"}[0] + +assert mojo.requiresDependencyCollection.text() == 'compile' +assert mojo.threadSafe.text() == 'true' + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties new file mode 100644 index 000000000..17e8ee4c7 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/invoker.properties @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:first +invoker.goals.4 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:help +invoker.goals.5 = org.apache.maven.its.annotation-with-inheritance:annotation-with-inheritance:1.0-SNAPSHOT:third \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml new file mode 100644 index 000000000..4921b29bc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/pom.xml @@ -0,0 +1,129 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance + annotation-with-inheritance + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: annotation-with-inheritance + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven + maven-compat + @mavenVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.commons + commons-exec + 1.1 + runtime + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java new file mode 100644 index 000000000..c0eee7cf1 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFirstMojo.java @@ -0,0 +1,63 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; + +import java.io.File; + +/** + * + */ +public abstract class AbstractFirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + protected File basedir; + + @Parameter( property = "first.touchFile", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + protected File touchFile; + + /** + * Plexus compiler manager. + */ + @Component + protected CompilerManager compilerManager; + + /** + * + */ + @Component( role = ArtifactMetadataSource.class, hint = "maven" ) + protected ArtifactMetadataSource artifactMetadataSource; + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFooMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFooMojo.java new file mode 100644 index 000000000..8f7c8e3cc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/AbstractFooMojo.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; + +import java.io.File; + +/** + * + */ +public abstract class AbstractFooMojo + extends AbstractFirstMojo +{ + + // MPLUGIN-206 + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 000000000..26b9ce6a5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014" ) +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter( property = "project.build.directory", required = true ) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..e88906eb5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,87 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +import java.util.Set; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = ResolutionScope.COMPILE, + defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractFirstMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class )//, roleHint = "default" + private Object projectHelper; + + @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true ) + private Set dependencies; + + public void execute() + throws MojoExecutionException + { + if ( basedir == null ) + { + throw new MojoExecutionException( "basedir == null" ); + } + if ( touchFile == null ) + { + throw new MojoExecutionException( "touchFile == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + if ( dependencies.isEmpty() ) + { + throw new MojoExecutionException( "dependencies.isEmpty()" ); + } + + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java new file mode 100644 index 000000000..8dc9dff17 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java @@ -0,0 +1,39 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * Does nothing special. + * + */ +@Mojo( name = "second", requiresDependencyCollection = ResolutionScope.COMPILE, threadSafe = true ) +public class SecondMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/ThirdMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/ThirdMojo.java new file mode 100644 index 000000000..4334f73b0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/java/org/apache/maven/plugin/coreit/ThirdMojo.java @@ -0,0 +1,87 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +import java.util.Set; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "third", requiresDependencyResolution = ResolutionScope.COMPILE, + defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class ThirdMojo + extends AbstractFooMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class )//, roleHint = "default" + private Object projectHelper; + + @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true ) + private Set dependencies; + + public void execute() + throws MojoExecutionException + { + if ( basedir == null ) + { + throw new MojoExecutionException( "basedir == null" ); + } + if ( touchFile == null ) + { + throw new MojoExecutionException( "touchFile == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + if ( dependencies.isEmpty() ) + { + throw new MojoExecutionException( "dependencies.isEmpty()" ); + } + + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 000000000..5510b5e4f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,37 @@ + + + + + + cobertura + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy new file mode 100644 index 000000000..f4e1ba5a3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" ); +assert !oldHelpClass.exists() + +File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ); +assert newHelpClass.exists() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'compile' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +//assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 4 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile"}[0] + +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir"}[0] + +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "second"}[0] + +assert mojo.requiresDependencyCollection.text() == 'compile' +assert mojo.threadSafe.text() == 'true' + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/invoker.properties new file mode 100644 index 000000000..0d94ede8a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.ant.it:maven-ant-it-basic:1.0-SNAPSHOT:touch -Dname=touch.txt + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/pom.xml new file mode 100644 index 000000000..1e6763419 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/pom.xml @@ -0,0 +1,69 @@ + + + + + + 4.0.0 + + org.apache.maven.ant.it + maven-ant-it-basic + 1.0-SNAPSHOT + maven-plugin + + Basic Ant-Mojo Integration Test + Tests the simplest case of using an Ant script to drive a mojo. + + + @project.version@ + + + + + org.apache.ant + ant + @antVersion@ + + + org.apache.maven.plugin-tools + maven-script-ant + @project.version@ + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + ${pluginPluginVersion} + + antBasic + + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + ${pluginPluginVersion} + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.build.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.build.xml new file mode 100644 index 000000000..dc163ecfb --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.build.xml @@ -0,0 +1,27 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.mojos.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.mojos.xml new file mode 100644 index 000000000..d904ca783 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.mojos.xml @@ -0,0 +1,44 @@ + + + + + + + + + touch-file + + touch + + + name + ${name} + true + false + java.lang.String + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/verify.groovy new file mode 100644 index 000000000..71ea7e143 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-basic/verify.groovy @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" ); +assert !oldHelpClass.exists() + + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/invoker.properties new file mode 100644 index 000000000..adcfaf53e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.ant.it:maven-ant-it-referenceParameter:1.0-SNAPSHOT:test + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/pom.xml new file mode 100644 index 000000000..0de107d67 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/pom.xml @@ -0,0 +1,65 @@ + + + + + + 4.0.0 + + org.apache.maven.ant.it + maven-ant-it-referenceParameter + 1.0-SNAPSHOT + maven-plugin + + Ant-Mojo Integration Test with non-String parameter + Tests using an Ant script to drive a mojo where a parameter is not a String type. + + + + org.apache.ant + ant + @antVersion@ + + + org.apache.maven.plugin-tools + maven-script-ant + @project.version@ + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + antWithRefs + + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + @project.version@ + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/java/org/apache/maven/plugins/antWithRefs/ArtifactsTask.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/java/org/apache/maven/plugins/antWithRefs/ArtifactsTask.java new file mode 100644 index 000000000..8c8e20eb0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/java/org/apache/maven/plugins/antWithRefs/ArtifactsTask.java @@ -0,0 +1,35 @@ +package org.apache.maven.plugins.antWithRefs; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +public class ArtifactsTask + extends Task +{ + + public void execute() + throws BuildException + { + log( String.valueOf( getProject().getReference( "artifacts" ) ) ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/resources/org/apache/maven/plugins/antWithRefs/antlib.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/resources/org/apache/maven/plugins/antWithRefs/antlib.xml new file mode 100644 index 000000000..2fb4b4f28 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/resources/org/apache/maven/plugins/antWithRefs/antlib.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.build.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.build.xml new file mode 100644 index 000000000..72a61c96e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.build.xml @@ -0,0 +1,29 @@ + + + + + + + + + Project artifacts: + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.mojos.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.mojos.xml new file mode 100644 index 000000000..ef296d041 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-reference-parameter/src/main/scripts/test.mojos.xml @@ -0,0 +1,41 @@ + + + + + + + test + test + compile + + + artifacts + ${project.artifacts} + true + true + java.util.List + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/invoker.properties new file mode 100644 index 000000000..853271b38 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +#invoker.goals.2 = org.apache.maven.ant.it:maven-ant-it-referenceParameter:1.0-SNAPSHOT:test + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/pom.xml new file mode 100644 index 000000000..1cd1a9b60 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/pom.xml @@ -0,0 +1,69 @@ + + + + + + 4.0.0 + + org.apache.maven.ant.it + simpleUsage-root + 1.0-SNAPSHOT + + simpleUsage-plugin + Simple Ant-Mojo + maven-plugin + Tests the simplest case of using an Ant script to drive a mojo. + + + @project.version@ + + + + + org.apache.ant + ant + + + org.apache.maven.plugin-tools + maven-script-ant + @project.version@ + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + ${pluginPluginVersion} + + antSimpleUsage + + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + @project.version@ + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.build.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.build.xml new file mode 100644 index 000000000..8ba12c136 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.build.xml @@ -0,0 +1,26 @@ + + + + + + + Hello, ${name}! + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.mojos.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.mojos.xml new file mode 100644 index 000000000..464d8aa6d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/plugin/src/main/scripts/test.mojos.xml @@ -0,0 +1,40 @@ + + + + + + + test + test + + + name + ${name} + true + false + java.lang.String + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/pom.xml new file mode 100644 index 000000000..46eb6738b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/pom.xml @@ -0,0 +1,48 @@ + + + + + + 4.0.0 + + org.apache.maven.ant.it + simpleUsage-root + 1.0-SNAPSHOT + pom + + Simple-Usage Ant-Mojo Integration Test - Root + Tests the simplest case of using an Ant script to drive a mojo. + + + + + org.apache.ant + ant + @antVersion@ + + + + + + plugin + usage + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/usage/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/usage/pom.xml new file mode 100644 index 000000000..7339c8049 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-simple-usage/usage/pom.xml @@ -0,0 +1,63 @@ + + + + + + 4.0.0 + + org.apache.maven.ant.it + simpleUsage-root + 1.0-SNAPSHOT + + simpleUsage-usage + Simple Ant-Mojo Usage Case + Tests the simplest case of using an Ant script to drive a mojo. + + + + org.apache.ant + ant + + + + + + + org.apache.maven.ant.it + simpleUsage-plugin + 1.0-SNAPSHOT + + + Hani + + + + + test + package + + test + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/pom.xml new file mode 100644 index 000000000..3b882f696 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/pom.xml @@ -0,0 +1,49 @@ + + + + 4.0.0 + test + trivial-maven-plugin + maven-plugin + 1.0 + trivial-maven-plugin + Just a test project + http://nowere.test + 2012 + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + @project.version@ + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.build.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.build.xml new file mode 100644 index 000000000..a2793dc40 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.build.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.mojos.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.mojos.xml new file mode 100644 index 000000000..988c04af5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ant-since-maven-plugin/src/main/scripts/sample.mojos.xml @@ -0,0 +1,46 @@ + + + + + + sample + sample-task + Just a test + false + false + 1.0 + + + + message + java.lang.String + true + true + 1.0 + Test param + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/invoker.properties new file mode 100644 index 000000000..203dc210c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.debug = false diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/pom.xml new file mode 100644 index 000000000..a45177ae3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/pom.xml @@ -0,0 +1,67 @@ + + + + + + 4.0.0 + + org.apache.maven.its.asm-failure + asm-failure + 1.0-SNAPSHOT + maven-plugin + + MPLUGIN-328 ignore ASM failures when reading .class + + ASM failure caused by com.ibm.icu:icu4j:2.6.1 dependency, precisely + com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class + Same failure happens with dependencies compiled with AspectJ + + + + UTF-8 + + + + + + maven-plugin-plugin + @project.version@ + + + + + + org.apache.maven + maven-plugin-api + 3.0 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + com.ibm.icu + icu4j + 2.6.1 + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..8b4d041d3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,51 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** + * Touches a test file. + * + * @since 1.2 + */ +@Mojo( name = "first" ) +public class FirstMojo + extends AbstractMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + public void execute() + throws MojoExecutionException + { + getLog().info( "touch" ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/verify.groovy new file mode 100644 index 000000000..c5ef43ba1 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/asm-failure/verify.groovy @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +build = new File( basedir, "build.log" ).text +assert build.contains( "[WARNING] Error analyzing class com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class in " ) +assert build =~ /com[\\\/]ibm[\\\/]icu[\\\/]icu4j[\\\/]2.6.1[\\\/]icu4j-2.6.1.jar: ignoring class/ + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/invoker.properties new file mode 100644 index 000000000..8ec6452ae --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.beanshell.it:maven-beanshell-it-basic:1.0-SNAPSHOT:touch -Dname=touch.txt + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/pom.xml new file mode 100644 index 000000000..57e8c6f68 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/pom.xml @@ -0,0 +1,68 @@ + + + + + + 4.0.0 + + org.apache.maven.beanshell.it + maven-beanshell-it-basic + 1.0-SNAPSHOT + maven-plugin + + Basic Beanshell-Mojo Integration Test + + + @project.version@ + + + + + bsh + bsh + 1.3.0 + + + org.apache.maven.plugin-tools + maven-script-beanshell + @project.version@ + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + ${pluginPluginVersion} + + beanshellBasic + + + + org.apache.maven.plugin-tools + maven-plugin-tools-beanshell + ${pluginPluginVersion} + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/src/main/scripts/touch.bsh b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/src/main/scripts/touch.bsh new file mode 100644 index 000000000..99de7e4c5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/src/main/scripts/touch.bsh @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// START SNIPPET: beanshell-mojo +/** + * Touches a test file. + * + * @goal touch + * @requiresDependencyResolution=test + * @deprecated Don't use! + * @since 1.2 + */ + +import org.apache.maven.plugin.Mojo; +import org.apache.maven.script.beanshell.BeanshellMojoAdapter; +import org.codehaus.plexus.util.FileUtils; + + + +execute() +{ + logger.info( "Executing beanshell mojo..." ); + FileUtils.fileWrite( outDir + "/" + name, "This is a Beanshell test" ); +} + +/** + * Output directory for files. + * + * @parameter expression="${project.build.directory}" + * @required + */ +setOutDir( file ) +{ + outDir = file; +} + +/** + * + * + * @parameter expression="${name}" + * @required + */ +setName( name ) +{ + name = name; +} + +return new BeanshellMojoAdapter( (Mojo) this, this.interpreter ); +// END SNIPPET: beanshell-mojo diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/verify.groovy new file mode 100644 index 000000000..c58c823e5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/beanshell-simple/verify.groovy @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.exists() +assert touchFile.isFile() +content = touchFile.text +assert content.contains('This is a Beanshell test'); + + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/pom.xml new file mode 100644 index 000000000..7b846ea3d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/pom.xml @@ -0,0 +1,77 @@ + + + + 4.0.0 + + + test + maven-since-3.x + 1.0-SNAPSHOT + + + test + antsample-maven-plugin + maven-plugin + ANT Sample + Just a test project + http://nowere.test + 2012 + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + @project.version@ + + + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.build.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.build.xml new file mode 100644 index 000000000..4e8e415ca --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.build.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.mojos.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.mojos.xml new file mode 100644 index 000000000..1116b9075 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/main/scripts/sample.mojos.xml @@ -0,0 +1,46 @@ + + + + + + sample + sample-task + Just a test + false + false + 1.0 + + + + message + java.lang.String + true + false + 0.9 + Test param + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/site/site.xml new file mode 100644 index 000000000..fc47fd705 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/antsample-maven-plugin/src/site/site.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + ${reports} + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/invoker.properties new file mode 100644 index 000000000..d5748af0e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/invoker.properties @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install site +invoker.maven.version = 3.0+ + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/pom.xml new file mode 100644 index 000000000..027f542e9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/pom.xml @@ -0,0 +1,49 @@ + + + + 4.0.0 + + + test + maven-since-3.x + 1.0-SNAPSHOT + + + test + javasample-maven-plugin + maven-plugin + + Java Sample + Java Maven Mojo. + http://maven.apache.org + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..978e62425 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/main/java/test/MyMojo.java @@ -0,0 +1,65 @@ +package test; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Goal which touches a timestamp file. + * + * @goal touch + * @since 1.0 + * + * @phase process-sources + */ +public class MyMojo + extends AbstractMojo +{ + /** + * Location of the file. + * @parameter property="project.build.directory" + * @required + */ + private File outputDirectory; + + public void execute() + throws MojoExecutionException + { + File f = outputDirectory; + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try ( FileWriter w = new FileWriter( touch ) ) + { + w.write( "touch.txt" ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error creating file " + touch, e ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/site/site.xml new file mode 100644 index 000000000..45203145f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/javasample-maven-plugin/src/site/site.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + ${reports} + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/pom.xml new file mode 100644 index 000000000..eec11c397 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/pom.xml @@ -0,0 +1,94 @@ + + + + 4.0.0 + test + maven-since-3.x + 1.0-SNAPSHOT + Samples + pom + Just a test project + http://nowere.test + 2012 + + + antsample-maven-plugin + javasample-maven-plugin + + + + + org.codehaus.plexus + plexus-utils + 3.0.2 + + + + + + + maven-plugin-plugin + 3.1 + + + generated-helpmojo + + helpmojo + + + + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + 3.1 + + + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + org.apache.maven.plugins + maven-help-plugin + 2.1.1 + + + + + + true + + + org.apache.maven.plugins + maven-plugin-plugin + 3.1 + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/verify.groovy new file mode 100644 index 000000000..19e281a8d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/fix-maven-since-3.x/verify.groovy @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "antsample-maven-plugin/target/site/sample-mojo.html" ) +assert touchFile.exists() +assert touchFile.isFile() +content = touchFile.text +assert content.contains('Since'); + + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/expected-help.txt b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/expected-help.txt new file mode 100644 index 000000000..6b5fe3184 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/expected-help.txt @@ -0,0 +1,25 @@ +[INFO] help-jdk11 1.0-SNAPSHOT + Tests generation and compilation of the help mojo. + +help-jdk11:test + Deprecated. As of 1.0, use the "quoted" goal instead. + + MOJO-DESCRIPTION. Some 'quotation' marks and backslashes '\\', some important + javadoc + and an inline link to AnotherMojo. + + Available parameters: + + defaultParam (Default: escape\backslash) + This parameter uses 'quotation' marks and backslashes '\\' in its + description. Those characters must be escaped in Java string literals. + + deprecatedParam + Deprecated. As of version 1.0, use the {@link #defaultParam} instead. + + This parameter is deprecated. + + undocumentedParam + + Required: Yes + User property: test.undocumented diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/invoker.properties new file mode 100644 index 000000000..e1086cb54 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/invoker.properties @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.java.version = 11+ +invoker.maven.version = 3.0+ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.plugin:help-jdk11:1.0-SNAPSHOT:help +invoker.goals.3 = --log-file help.log org.apache.maven.its.plugin:help-jdk11:1.0-SNAPSHOT:help +# --log-file option is only supported by Maven 3 diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/pom.xml new file mode 100644 index 000000000..ea2e7b428 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/pom.xml @@ -0,0 +1,92 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + help-jdk11 + 1.0-SNAPSHOT + maven-plugin + + + Tests generation and compilation of the help mojo. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + provided + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + 11 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + default-descriptor + process-classes + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..0be9fd35f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/src/main/java/test/MyMojo.java @@ -0,0 +1,68 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** + * MOJO-DESCRIPTION. Some "quotation" marks and backslashes '\\', some important javadoc
and an + * inline link to {@link test.AnotherMojo}. + * + * @deprecated As of 1.0, use the "quoted" goal instead. + * @since 2.1 + */ +@Mojo( name= "test" ) +public class MyMojo + extends AbstractMojo +{ + + /** + * This parameter uses "quotation" marks and backslashes '\\' in its description. Those characters must be + * escaped in Java string literals. + * + * @since 2.0 + */ + @Parameter( defaultValue = "escape\\backslash" ) + private String defaultParam; + + /** + * This parameter is deprecated. + * + * @deprecated As of version 1.0, use the {@link #defaultParam} instead. + */ + @Parameter + private String deprecatedParam; + + @Parameter( property = "test.undocumented", required = true ) + private String undocumentedParam; + + /** + * Readonly parameter: should not be proposed for configuration. + */ + @Parameter( defaultValue = "not for configuration", readonly = true ) + private String readonly; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/test.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/test.properties new file mode 100644 index 000000000..16e4de3cc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/test.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +detail = true +goal = test diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/verify.groovy new file mode 100644 index 000000000..22f0af90c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic-jdk11/verify.groovy @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +expected = new File( basedir, "expected-help.txt" ).text.trim().replace( "\r", "" ); + +log = new File( basedir, "help.log" ).text.replace( "\r", "" ); +log = log.substring( log.indexOf( "[INFO] help-jdk11 1.0-SNAPSHOT" ) ); +log = log.substring( 0, log.indexOf( "[INFO]", 5 ) ).trim(); + +assert log == expected; + +return true; \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/expected-help.txt b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/expected-help.txt new file mode 100644 index 000000000..5dc8bb88d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/expected-help.txt @@ -0,0 +1,25 @@ +[INFO] help 1.0-SNAPSHOT + Tests generation and compilation of the help mojo. + +help:test + Deprecated. As of 1.0, use the "quoted" goal instead. + + MOJO-DESCRIPTION. Some 'quotation' marks and backslashes '\\', some important + javadoc + and an inline link to AnotherMojo. + + Available parameters: + + defaultParam (Default: escape\backslash) + This parameter uses 'quotation' marks and backslashes '\\' in its + description. Those characters must be escaped in Java string literals. + + deprecatedParam + Deprecated. As of version 1.0, use the {@link #defaultParam} instead. + + This parameter is deprecated. + + undocumentedParam + + Required: Yes + User property: test.undocumented diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/invoker.properties new file mode 100644 index 000000000..544361b7d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/invoker.properties @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.maven.version = 3.0+ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.plugin:help:1.0-SNAPSHOT:help +invoker.goals.3 = --log-file help.log org.apache.maven.its.plugin:help:1.0-SNAPSHOT:help +# --log-file option is only supported by Maven 3 +invoker.maven.version = 3.0+ diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/pom.xml new file mode 100644 index 000000000..4a164bc71 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/pom.xml @@ -0,0 +1,87 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + help + 1.0-SNAPSHOT + maven-plugin + + + Tests generation and compilation of the help mojo. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + provided + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + default-descriptor + process-classes + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..0be9fd35f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/src/main/java/test/MyMojo.java @@ -0,0 +1,68 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** + * MOJO-DESCRIPTION. Some "quotation" marks and backslashes '\\', some important javadoc
and an + * inline link to {@link test.AnotherMojo}. + * + * @deprecated As of 1.0, use the "quoted" goal instead. + * @since 2.1 + */ +@Mojo( name= "test" ) +public class MyMojo + extends AbstractMojo +{ + + /** + * This parameter uses "quotation" marks and backslashes '\\' in its description. Those characters must be + * escaped in Java string literals. + * + * @since 2.0 + */ + @Parameter( defaultValue = "escape\\backslash" ) + private String defaultParam; + + /** + * This parameter is deprecated. + * + * @deprecated As of version 1.0, use the {@link #defaultParam} instead. + */ + @Parameter + private String deprecatedParam; + + @Parameter( property = "test.undocumented", required = true ) + private String undocumentedParam; + + /** + * Readonly parameter: should not be proposed for configuration. + */ + @Parameter( defaultValue = "not for configuration", readonly = true ) + private String readonly; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/test.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/test.properties new file mode 100644 index 000000000..16e4de3cc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/test.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +detail = true +goal = test diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/verify.groovy new file mode 100644 index 000000000..eb4ad85c5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-basic/verify.groovy @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +expected = new File( basedir, "expected-help.txt" ).text.trim().replace( "\r", "" ); + +log = new File( basedir, "help.log" ).text.replace( "\r", "" ); +log = log.substring( log.indexOf( "[INFO] help 1.0-SNAPSHOT" ) ); +log = log.substring( 0, log.indexOf( "[INFO]", 5 ) ).trim(); + +assert log == expected; + +return true; \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/invoker.properties new file mode 100644 index 000000000..4024c9bc8 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean compile diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/pom.xml new file mode 100644 index 000000000..7735aee0c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/pom.xml @@ -0,0 +1,80 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + help-package + 1.0-SNAPSHOT + maven-plugin + + + Tests generation of the help mojo in a user-specified package (MPLUGIN-168). + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + test.help + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..5d2317fec --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/src/main/java/test/MyMojo.java @@ -0,0 +1,37 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; + +/** + * MOJO-DESCRIPTION. + * + * @goal test + */ +public class MyMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/verify.bsh b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/verify.bsh new file mode 100644 index 000000000..951241d1a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/help-package/verify.bsh @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.*; + +File helpMojo = new File( basedir, "target/classes/test/help/HelpMojo.class" ); +if ( !helpMojo.isFile() ) +{ + throw new FileNotFoundException( "Missing/misplaced: " + helpMojo ); +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml new file mode 100644 index 000000000..453104572 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/pom.xml @@ -0,0 +1,40 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin + ipcr + 1.0-SNAPSHOT + + + ipcr-dep-a + jar + + Dependency A + + Test that the component used to scan sources for annotations does not analyze classes from the plugin's own class + realm while traversing the class hierarchy (see QDOX-148). This module provides a simple dependency to build up + the class realm of interest. + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/src/main/java/test/ClassA.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/src/main/java/test/ClassA.java new file mode 100644 index 000000000..610276788 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-a/src/main/java/test/ClassA.java @@ -0,0 +1,24 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public class ClassA +{ +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml new file mode 100644 index 000000000..8999cc246 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/pom.xml @@ -0,0 +1,48 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin + ipcr + 1.0-SNAPSHOT + + + ipcr-dep-b + jar + + Dependency B + + Test that the component used to scan sources for annotations does not analyze classes from the plugin's own class + realm while traversing the class hierarchy (see QDOX-148). This module provides a simple dependency to build up + the class realm of interest. + + + + + org.apache.maven.its.plugin + ipcr-dep-a + ${project.version} + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/src/main/java/test/ClassB.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/src/main/java/test/ClassB.java new file mode 100644 index 000000000..452bd7205 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/dep-b/src/main/java/test/ClassB.java @@ -0,0 +1,33 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public class ClassB +{ + + /** + * For the test we want to trigger a linkage error when resolving ClassA. However, we want this error to occur when + * analyzing ClassB and not when loading ClassB itself. + */ + public void triggerLazyLinkageError(ClassA param) + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties new file mode 100644 index 000000000..5493444d1 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/invoker.properties @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.profiles.1 = setup + +invoker.goals.2 = clean process-classes +invoker.profiles.2 = test diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml new file mode 100644 index 000000000..7b98666a8 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/pom.xml @@ -0,0 +1,64 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + ipcr + 1.0-SNAPSHOT + pom + + Aggregator + + Test that the component used to scan sources for annotations does not analyze classes from the plugin's own class + realm while traversing the class hierarchy (see QDOX-148). + + + + + + setup + + dep-a + dep-b + + + + + test + + test + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml new file mode 100644 index 000000000..c616620d8 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/pom.xml @@ -0,0 +1,73 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin + ipcr + 1.0-SNAPSHOT + + + ipcr-plugin + maven-plugin + + Test Plugin + + Test that the component used to scan sources for annotations does not analyze classes from the plugin's own class + realm while traversing the class hierarchy (see QDOX-148). This module provides the plugin sources to scan. + + + + + + org.apache.maven.its.plugin + ipcr-dep-b + ${project.version} + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + + + org.apache.maven.its.plugin + ipcr-dep-b + 1.0-SNAPSHOT + + + org.apache.maven.its.plugin + ipcr-dep-a + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/src/main/java/test/SomeMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/src/main/java/test/SomeMojo.java new file mode 100644 index 000000000..f46c3bf27 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/ignore-plugin-class-realm/test/src/main/java/test/SomeMojo.java @@ -0,0 +1,34 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * This is the source class to be scanned for annotations. While scanning, QDox must not try to resolve references to + * other types like the super class from the plugin class realm. The plugin class realm has no relation at all to + * the project class path. In particular, the plugin class realm could (by incident) contain different versions of those + * types or could be incomplete (due to exclusions). The later case leads to NoClassDefFoundErrors, crashing the scan. + * + * @goal test + */ +public class SomeMojo + extends ClassB +{ + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties new file mode 100644 index 000000000..a67d07c8f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.java.version = 1.8+ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:help \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml new file mode 100644 index 000000000..0531c7d25 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml @@ -0,0 +1,108 @@ + + + + + + 4.0.0 + + org.apache.maven.its.basic-java-annotations + maven-it-basic-java-annotations + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: basic-java-annotations-jdk8 + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + + + 1.8 + 1.8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven + maven-core + 2.2.1 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 000000000..26b9ce6a5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014" ) +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter( property = "project.build.directory", required = true ) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..62247a0f0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,91 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; +import org.apache.maven.settings.Settings; + +import java.io.File; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + private File basedir; + + @Parameter( property = "first.touchFile", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + private File touchFile; + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( name = "namedParam", alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class, hint = "test" ) + private Object projectHelper; + + @Component + private MavenSession session; + + @Component + private MavenProject project; + + @Component + private MojoExecution mojo; + + @Component + private PluginDescriptor plugin; + + @Component + private Settings settings; + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java new file mode 100644 index 000000000..06b606816 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java @@ -0,0 +1,47 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Could not use regex in @Parameter(defaultValue) + */ +@Mojo( name = "mplugin-220" ) +public class MPlugin220Mojo + extends AbstractMojo +{ + + @Parameter( defaultValue = "[a-zA-Z]{2,}-\\\\d+" ) + private String regex; + + public void execute() + throws MojoExecutionException + { + getLog().info( "regex = " + regex ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Maximal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Maximal.java new file mode 100644 index 000000000..1ca4ca149 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Maximal.java @@ -0,0 +1,76 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.InstantiationStrategy; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +/** + * Checks maximum annotations with non-default values. + * + * @since since-text + * @deprecated deprecated-text + */ +@Mojo( name = "maximal", + aggregator = true, + configurator = "configurator-hint", + requiresDependencyResolution = ResolutionScope.COMPILE, + requiresDependencyCollection = ResolutionScope.TEST, + defaultPhase = LifecyclePhase.PACKAGE, + executionStrategy = "always", + instantiationStrategy = InstantiationStrategy.SINGLETON, + inheritByDefault = false, + requiresDirectInvocation = true, + requiresOnline = true, + requiresProject = false, + requiresReports = true, + threadSafe = true ) +@Execute( phase = LifecyclePhase.COMPILE ) +public class Maximal + extends AbstractMojo +{ + /** + * Parameter description. + * + * @since since-text + * @deprecated deprecated-text + */ + @Parameter( alias = "myAlias", + property = "aProperty", + defaultValue = "${anExpression}", + readonly = true, + required = true ) + private String param; + + @Component( role = MavenProjectHelper.class, hint = "test" ) + private Object projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Minimal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Minimal.java new file mode 100644 index 000000000..18f3cfb4c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/Minimal.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +// minimum annotations => default values +@Mojo( name = "minimal" ) +public class Minimal + extends AbstractMojo +{ + @Parameter + private String param; + + @Component + private MavenProjectHelper projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java new file mode 100644 index 000000000..16ee6d524 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java @@ -0,0 +1,30 @@ +package fr.ca; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public interface TestInterface { + + /** + * Java 8 required to support such default method implementation + */ + public default void foo(){ + + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy new file mode 100644 index 000000000..294f53866 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.configuration.session[0].text() == '' +assert mojo.configuration.session[0].'@implementation' == 'org.apache.maven.execution.MavenSession' +assert mojo.configuration.session[0].'@default-value' == '${session}' + +assert mojo.configuration.project[0].text() == '' +assert mojo.configuration.project[0].'@implementation' == 'org.apache.maven.project.MavenProject' +assert mojo.configuration.project[0].'@default-value' == '${project}' + +assert mojo.configuration.mojo[0].text() == '' +assert mojo.configuration.mojo[0].'@implementation' == 'org.apache.maven.plugin.MojoExecution' +assert mojo.configuration.mojo[0].'@default-value' == '${mojoExecution}' + +assert mojo.configuration.plugin[0].text() == '' +assert mojo.configuration.plugin[0].'@implementation' == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert mojo.configuration.plugin[0].'@default-value' == '${plugin}' + +assert mojo.configuration.settings[0].text() == '' +assert mojo.configuration.settings[0].'@implementation' == 'org.apache.maven.settings.Settings' +assert mojo.configuration.settings[0].'@default-value' == '${settings}' + +assert mojo.requirements.requirement.size() == 1 + +assert mojo.requirements.requirement[0].role.text() == 'org.apache.maven.project.MavenProjectHelper' +assert mojo.requirements.requirement[0].'role-hint'.text() == 'test' +assert mojo.requirements.requirement[0].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 8 + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "namedParam" }[0] +assert parameter.name.text() == 'namedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir" }[0] +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "mojo" }[0] +assert parameter.name.text() == 'mojo' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.plugin.MojoExecution' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "plugin" }[0] +assert parameter.name.text() == 'plugin' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "project" }[0] +assert parameter.name.text() == 'project' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.project.MavenProject' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "session" }[0] +assert parameter.name.text() == 'session' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.execution.MavenSession' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "settings" }[0] +assert parameter.name.text() == 'settings' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.settings.Settings' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile" }[0] +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +// check default values +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "minimal"}[0] + +assert mojo.goal.text() == 'minimal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Minimal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == '' +assert mojo.deprecated.text() == '' +assert mojo.requiresDependencyResolution.text() == '' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.requiresReports.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == '' +assert mojo.executePhase.text() == '' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'once-per-session' +assert mojo.inheritedByDefault.text() == 'true' +assert mojo.instantiationStrategy.text() == 'per-lookup' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == '' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == '' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +def requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check values set by every annotation +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "maximal"}[0] + +assert mojo.goal.text() == 'maximal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Maximal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Checks maximum annotations with non-default values.' +assert mojo.deprecated.text() == 'deprecated-text' +assert mojo.requiresDependencyResolution.text() == 'compile' +assert mojo.requiresDependencyCollection.text() == 'test' +assert mojo.requiresProject.text() == 'false' +assert mojo.requiresOnline.text() == 'true' +assert mojo.requiresDirectInvocation.text() == 'true' +assert mojo.requiresReports.text() == 'true' +assert mojo.aggregator.text() == 'true' +assert mojo.configurator.text() == 'configurator-hint' +assert mojo.threadSafe.text() == 'true' +assert mojo.phase.text() == 'package' +assert mojo.executePhase.text() == 'compile' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'always' +assert mojo.inheritedByDefault.text() == 'false' +assert mojo.instantiationStrategy.text() == 'singleton' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == 'myAlias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.since.text() == 'since-text' +assert parameter.deprecated.text() == 'deprecated-text' +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Parameter description.' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check help mojo source and class +assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile() +assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile() +assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile() + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/invoker.properties new file mode 100644 index 000000000..64ad8107e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/invoker.properties @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.java.version = 9+ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:help \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/pom.xml new file mode 100644 index 000000000..53d92fb1a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/pom.xml @@ -0,0 +1,103 @@ + + + + + + 4.0.0 + + org.apache.maven.its.basic-java-annotations + maven-it-basic-java-annotations + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: basic-java-annotations-jdk8 + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven + maven-core + 2.2.1 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${java.specification.version} + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 000000000..26b9ce6a5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014" ) +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter( property = "project.build.directory", required = true ) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..62247a0f0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,91 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; +import org.apache.maven.settings.Settings; + +import java.io.File; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + private File basedir; + + @Parameter( property = "first.touchFile", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + private File touchFile; + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( name = "namedParam", alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class, hint = "test" ) + private Object projectHelper; + + @Component + private MavenSession session; + + @Component + private MavenProject project; + + @Component + private MojoExecution mojo; + + @Component + private PluginDescriptor plugin; + + @Component + private Settings settings; + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java new file mode 100644 index 000000000..06b606816 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java @@ -0,0 +1,47 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Could not use regex in @Parameter(defaultValue) + */ +@Mojo( name = "mplugin-220" ) +public class MPlugin220Mojo + extends AbstractMojo +{ + + @Parameter( defaultValue = "[a-zA-Z]{2,}-\\\\d+" ) + private String regex; + + public void execute() + throws MojoExecutionException + { + getLog().info( "regex = " + regex ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Maximal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Maximal.java new file mode 100644 index 000000000..1ca4ca149 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Maximal.java @@ -0,0 +1,76 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.InstantiationStrategy; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +/** + * Checks maximum annotations with non-default values. + * + * @since since-text + * @deprecated deprecated-text + */ +@Mojo( name = "maximal", + aggregator = true, + configurator = "configurator-hint", + requiresDependencyResolution = ResolutionScope.COMPILE, + requiresDependencyCollection = ResolutionScope.TEST, + defaultPhase = LifecyclePhase.PACKAGE, + executionStrategy = "always", + instantiationStrategy = InstantiationStrategy.SINGLETON, + inheritByDefault = false, + requiresDirectInvocation = true, + requiresOnline = true, + requiresProject = false, + requiresReports = true, + threadSafe = true ) +@Execute( phase = LifecyclePhase.COMPILE ) +public class Maximal + extends AbstractMojo +{ + /** + * Parameter description. + * + * @since since-text + * @deprecated deprecated-text + */ + @Parameter( alias = "myAlias", + property = "aProperty", + defaultValue = "${anExpression}", + readonly = true, + required = true ) + private String param; + + @Component( role = MavenProjectHelper.class, hint = "test" ) + private Object projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Minimal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Minimal.java new file mode 100644 index 000000000..18f3cfb4c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/Minimal.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +// minimum annotations => default values +@Mojo( name = "minimal" ) +public class Minimal + extends AbstractMojo +{ + @Parameter + private String param; + + @Component + private MavenProjectHelper projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java new file mode 100644 index 000000000..16ee6d524 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/src/main/java/org/apache/maven/plugin/coreit/TestInterface.java @@ -0,0 +1,30 @@ +package fr.ca; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public interface TestInterface { + + /** + * Java 8 required to support such default method implementation + */ + public default void foo(){ + + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy new file mode 100644 index 000000000..294f53866 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.configuration.session[0].text() == '' +assert mojo.configuration.session[0].'@implementation' == 'org.apache.maven.execution.MavenSession' +assert mojo.configuration.session[0].'@default-value' == '${session}' + +assert mojo.configuration.project[0].text() == '' +assert mojo.configuration.project[0].'@implementation' == 'org.apache.maven.project.MavenProject' +assert mojo.configuration.project[0].'@default-value' == '${project}' + +assert mojo.configuration.mojo[0].text() == '' +assert mojo.configuration.mojo[0].'@implementation' == 'org.apache.maven.plugin.MojoExecution' +assert mojo.configuration.mojo[0].'@default-value' == '${mojoExecution}' + +assert mojo.configuration.plugin[0].text() == '' +assert mojo.configuration.plugin[0].'@implementation' == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert mojo.configuration.plugin[0].'@default-value' == '${plugin}' + +assert mojo.configuration.settings[0].text() == '' +assert mojo.configuration.settings[0].'@implementation' == 'org.apache.maven.settings.Settings' +assert mojo.configuration.settings[0].'@default-value' == '${settings}' + +assert mojo.requirements.requirement.size() == 1 + +assert mojo.requirements.requirement[0].role.text() == 'org.apache.maven.project.MavenProjectHelper' +assert mojo.requirements.requirement[0].'role-hint'.text() == 'test' +assert mojo.requirements.requirement[0].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 8 + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "namedParam" }[0] +assert parameter.name.text() == 'namedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir" }[0] +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "mojo" }[0] +assert parameter.name.text() == 'mojo' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.plugin.MojoExecution' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "plugin" }[0] +assert parameter.name.text() == 'plugin' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "project" }[0] +assert parameter.name.text() == 'project' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.project.MavenProject' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "session" }[0] +assert parameter.name.text() == 'session' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.execution.MavenSession' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "settings" }[0] +assert parameter.name.text() == 'settings' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.settings.Settings' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile" }[0] +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +// check default values +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "minimal"}[0] + +assert mojo.goal.text() == 'minimal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Minimal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == '' +assert mojo.deprecated.text() == '' +assert mojo.requiresDependencyResolution.text() == '' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.requiresReports.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == '' +assert mojo.executePhase.text() == '' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'once-per-session' +assert mojo.inheritedByDefault.text() == 'true' +assert mojo.instantiationStrategy.text() == 'per-lookup' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == '' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == '' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +def requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check values set by every annotation +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "maximal"}[0] + +assert mojo.goal.text() == 'maximal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Maximal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Checks maximum annotations with non-default values.' +assert mojo.deprecated.text() == 'deprecated-text' +assert mojo.requiresDependencyResolution.text() == 'compile' +assert mojo.requiresDependencyCollection.text() == 'test' +assert mojo.requiresProject.text() == 'false' +assert mojo.requiresOnline.text() == 'true' +assert mojo.requiresDirectInvocation.text() == 'true' +assert mojo.requiresReports.text() == 'true' +assert mojo.aggregator.text() == 'true' +assert mojo.configurator.text() == 'configurator-hint' +assert mojo.threadSafe.text() == 'true' +assert mojo.phase.text() == 'package' +assert mojo.executePhase.text() == 'compile' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'always' +assert mojo.inheritedByDefault.text() == 'false' +assert mojo.instantiationStrategy.text() == 'singleton' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == 'myAlias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.since.text() == 'since-text' +assert parameter.deprecated.text() == 'deprecated-text' +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Parameter description.' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check help mojo source and class +assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile() +assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile() +assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile() + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties new file mode 100644 index 000000000..f3a9963d6 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014 +invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:help \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml new file mode 100644 index 000000000..097785d2b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/pom.xml @@ -0,0 +1,100 @@ + + + + + + 4.0.0 + + org.apache.maven.its.basic-java-annotations + maven-it-basic-java-annotations + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: basic-java-annotations + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven + maven-core + 2.2.1 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java new file mode 100644 index 000000000..26b9ce6a5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/CoreIt0014Mojo.java @@ -0,0 +1,66 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + */ +@Mojo( name = "it0014" ) +public class CoreIt0014Mojo + extends AbstractMojo +{ + + @Parameter( property = "project.build.directory", required = true ) + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..62247a0f0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,91 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; +import org.apache.maven.settings.Settings; + +import java.io.File; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +@Execute( phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura" ) +public class FirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + */ + @Parameter( defaultValue = "${basedir}", readonly = true ) + private File basedir; + + @Parameter( property = "first.touchFile", defaultValue = "${project.build.directory}/touch.txt", + required = true ) + private File touchFile; + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( name = "namedParam", alias = "alias" ) + private String aliasedParam; + + @Component( role = MavenProjectHelper.class, hint = "test" ) + private Object projectHelper; + + @Component + private MavenSession session; + + @Component + private MavenProject project; + + @Component + private MojoExecution mojo; + + @Component + private PluginDescriptor plugin; + + @Component + private Settings settings; + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java new file mode 100644 index 000000000..06b606816 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/MPlugin220Mojo.java @@ -0,0 +1,47 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.IOException; + +/** + * Could not use regex in @Parameter(defaultValue) + */ +@Mojo( name = "mplugin-220" ) +public class MPlugin220Mojo + extends AbstractMojo +{ + + @Parameter( defaultValue = "[a-zA-Z]{2,}-\\\\d+" ) + private String regex; + + public void execute() + throws MojoExecutionException + { + getLog().info( "regex = " + regex ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Maximal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Maximal.java new file mode 100644 index 000000000..1ca4ca149 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Maximal.java @@ -0,0 +1,76 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.InstantiationStrategy; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +/** + * Checks maximum annotations with non-default values. + * + * @since since-text + * @deprecated deprecated-text + */ +@Mojo( name = "maximal", + aggregator = true, + configurator = "configurator-hint", + requiresDependencyResolution = ResolutionScope.COMPILE, + requiresDependencyCollection = ResolutionScope.TEST, + defaultPhase = LifecyclePhase.PACKAGE, + executionStrategy = "always", + instantiationStrategy = InstantiationStrategy.SINGLETON, + inheritByDefault = false, + requiresDirectInvocation = true, + requiresOnline = true, + requiresProject = false, + requiresReports = true, + threadSafe = true ) +@Execute( phase = LifecyclePhase.COMPILE ) +public class Maximal + extends AbstractMojo +{ + /** + * Parameter description. + * + * @since since-text + * @deprecated deprecated-text + */ + @Parameter( alias = "myAlias", + property = "aProperty", + defaultValue = "${anExpression}", + readonly = true, + required = true ) + private String param; + + @Component( role = MavenProjectHelper.class, hint = "test" ) + private Object projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Minimal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Minimal.java new file mode 100644 index 000000000..18f3cfb4c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/src/main/java/org/apache/maven/plugin/coreit/Minimal.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; + +// minimum annotations => default values +@Mojo( name = "minimal" ) +public class Minimal + extends AbstractMojo +{ + @Parameter + private String param; + + @Component + private MavenProjectHelper projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy new file mode 100644 index 000000000..294f53866 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.configuration.session[0].text() == '' +assert mojo.configuration.session[0].'@implementation' == 'org.apache.maven.execution.MavenSession' +assert mojo.configuration.session[0].'@default-value' == '${session}' + +assert mojo.configuration.project[0].text() == '' +assert mojo.configuration.project[0].'@implementation' == 'org.apache.maven.project.MavenProject' +assert mojo.configuration.project[0].'@default-value' == '${project}' + +assert mojo.configuration.mojo[0].text() == '' +assert mojo.configuration.mojo[0].'@implementation' == 'org.apache.maven.plugin.MojoExecution' +assert mojo.configuration.mojo[0].'@default-value' == '${mojoExecution}' + +assert mojo.configuration.plugin[0].text() == '' +assert mojo.configuration.plugin[0].'@implementation' == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert mojo.configuration.plugin[0].'@default-value' == '${plugin}' + +assert mojo.configuration.settings[0].text() == '' +assert mojo.configuration.settings[0].'@implementation' == 'org.apache.maven.settings.Settings' +assert mojo.configuration.settings[0].'@default-value' == '${settings}' + +assert mojo.requirements.requirement.size() == 1 + +assert mojo.requirements.requirement[0].role.text() == 'org.apache.maven.project.MavenProjectHelper' +assert mojo.requirements.requirement[0].'role-hint'.text() == 'test' +assert mojo.requirements.requirement[0].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 8 + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "namedParam" }[0] +assert parameter.name.text() == 'namedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir" }[0] +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "mojo" }[0] +assert parameter.name.text() == 'mojo' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.plugin.MojoExecution' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "plugin" }[0] +assert parameter.name.text() == 'plugin' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "project" }[0] +assert parameter.name.text() == 'project' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.project.MavenProject' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "session" }[0] +assert parameter.name.text() == 'session' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.execution.MavenSession' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "settings" }[0] +assert parameter.name.text() == 'settings' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'org.apache.maven.settings.Settings' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile" }[0] +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +// check default values +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "minimal"}[0] + +assert mojo.goal.text() == 'minimal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Minimal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == '' +assert mojo.deprecated.text() == '' +assert mojo.requiresDependencyResolution.text() == '' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.requiresReports.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == '' +assert mojo.executePhase.text() == '' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'once-per-session' +assert mojo.inheritedByDefault.text() == 'true' +assert mojo.instantiationStrategy.text() == 'per-lookup' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == '' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == '' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +def requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check values set by every annotation +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "maximal"}[0] + +assert mojo.goal.text() == 'maximal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Maximal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Checks maximum annotations with non-default values.' +assert mojo.deprecated.text() == 'deprecated-text' +assert mojo.requiresDependencyResolution.text() == 'compile' +assert mojo.requiresDependencyCollection.text() == 'test' +assert mojo.requiresProject.text() == 'false' +assert mojo.requiresOnline.text() == 'true' +assert mojo.requiresDirectInvocation.text() == 'true' +assert mojo.requiresReports.text() == 'true' +assert mojo.aggregator.text() == 'true' +assert mojo.configurator.text() == 'configurator-hint' +assert mojo.threadSafe.text() == 'true' +assert mojo.phase.text() == 'package' +assert mojo.executePhase.text() == 'compile' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'always' +assert mojo.inheritedByDefault.text() == 'false' +assert mojo.instantiationStrategy.text() == 'singleton' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == 'myAlias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.since.text() == 'since-text' +assert parameter.deprecated.text() == 'deprecated-text' +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Parameter description.' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check help mojo source and class +assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile() +assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile() +assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile() + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/invoker.properties new file mode 100644 index 000000000..6672f025a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = org.apache.maven.its.it0013:maven-it-it0013:1.0-SNAPSHOT:it0013 + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/pom.xml new file mode 100644 index 000000000..37a44a146 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/pom.xml @@ -0,0 +1,63 @@ + + + + + + 4.0.0 + + org.apache.maven.its.it0013 + maven-it-it0013 + 1.0-SNAPSHOT + maven-plugin + + Maven Integration Test :: it0013 + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven + maven-core + 2.2.1 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java new file mode 100644 index 000000000..824f0436c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java @@ -0,0 +1,67 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + * @goal it0013 + */ +public class CoreIt0013Mojo + extends AbstractMojo +{ + + /** + * @parameter property="project.build.directory" + * @required + */ + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..8772049a0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,102 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + * @goal first + * @requiresDependencyResolution test + * @phase integration-test + * @execute phase="generate-sources" lifecycle="cobertura" + * @deprecated Don't use! + * @since 1.2 + */ +public class FirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + * @parameter default-value="${basedir}" + * @readonly + */ + private File basedir; + + /** + * @parameter expression="first.touchFile" default-value="${project.build.directory}/touch.txt" + * @required + */ + private File touchFile; + + /** + * @parameter name="namedParam" alias="alias" + * @deprecated As of 0.2 + * @since 0.1 + */ + private String aliasedParam; + + /** + * @component role="org.apache.maven.project.MavenProjectHelper" roleHint="test" + */ + private Object projectHelper; + + /** + * @component + */ + private MavenSession session; + + /** + * @component + */ + private MavenProject project; + + /** + * @component + */ + private MojoExecution mojo; + + /** + * @component + */ + private PluginDescriptor plugin; + + /** + * @component + */ + private Settings settings; + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Maximal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Maximal.java new file mode 100644 index 000000000..1ff8f2849 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Maximal.java @@ -0,0 +1,71 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.project.MavenProjectHelper; + +/** + * Checks maximum annotations with non-default values. + * + * @goal maximal + * @aggregator + * @configurator configurator-hint + * @execute phase="compile" + * @executionStrategy always + * @inheritByDefault false + * @instantiationStrategy singleton + * @phase package + * @requiresDependencyResolution compile + * @requiresDependencyCollection test + * @requiresDirectInvocation true + * @requiresOnline true + * @requiresProject false + * @requiresReports true + * @threadSafe + * @since since-text + * @deprecated deprecated-text + */ +public class Maximal + extends AbstractMojo +{ + /** + * Parameter description. + * + * @parameter alias="myAlias" implementation="my.implementation" property="aProperty" default-value="${anExpression}" + * @readonly + * @required + * @since since-text + * @deprecated deprecated-text + */ + private String param; + + /** + * @component role="org.apache.maven.project.MavenProjectHelper" roleHint="test" + * @since since-text + * @deprecated deprecated-text + */ + private Object projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Minimal.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Minimal.java new file mode 100644 index 000000000..27b91d681 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/src/main/java/org/apache/maven/plugin/coreit/Minimal.java @@ -0,0 +1,46 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.project.MavenProjectHelper; + +// minimum annotations => default values +/** + * @goal minimal + */ +public class Minimal + extends AbstractMojo +{ + /** + * @parameter + */ + private String param; + + /** + * @component + */ + private MavenProjectHelper projectHelper; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/verify.groovy new file mode 100644 index 000000000..33f9fb716 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/java-basic/verify.groovy @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File touchFile = new File( basedir, "target/touch.txt" ) +assert touchFile.isFile() + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'generate-sources' +assert mojo.executeLifecycle.text() == 'cobertura' + +assert mojo.configuration.basedir[0].text() == '' +assert mojo.configuration.basedir[0].'@implementation' == 'java.io.File' +assert mojo.configuration.basedir[0].'@default-value' == '${basedir}' + +assert mojo.configuration.touchFile[0].text() == '${first.touchFile}' +assert mojo.configuration.touchFile[0].'@implementation' == 'java.io.File' +assert mojo.configuration.touchFile[0].'@default-value' == '${project.build.directory}/touch.txt' + +assert mojo.requirements.requirement.size() == 6 + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "session" }[0] +assert requirement.role.text() == 'org.apache.maven.execution.MavenSession' +assert requirement.'field-name'.text() == 'session' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "project" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProject' +assert requirement.'field-name'.text() == 'project' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "mojo" }[0] +assert requirement.role.text() == 'org.apache.maven.plugin.MojoExecution' +assert requirement.'field-name'.text() == 'mojo' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "plugin" }[0] +assert requirement.role.text() == 'org.apache.maven.plugin.descriptor.PluginDescriptor' +assert requirement.'field-name'.text() == 'plugin' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "settings" }[0] +assert requirement.role.text() == 'org.apache.maven.settings.Settings' +assert requirement.'field-name'.text() == 'settings' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' +assert requirement.'role-hint'.text() == 'test' +assert requirement.'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "namedParam" }[0] +assert parameter.name.text() == 'namedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "basedir" }[0] +assert parameter.name.text() == 'basedir' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Project directory.' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile" }[0] +assert parameter.name.text() == 'touchFile' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.io.File' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +// check default values +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "minimal"}[0] + +assert mojo.goal.text() == 'minimal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Minimal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == '' +assert mojo.deprecated.text() == '' +assert mojo.requiresDependencyResolution.text() == '' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.requiresReports.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == '' +assert mojo.executePhase.text() == '' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'once-per-session' +assert mojo.inheritedByDefault.text() == 'true' +assert mojo.instantiationStrategy.text() == 'per-lookup' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == '' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == '' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +def requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +// check values set by every annotation +mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "maximal"}[0] + +assert mojo.goal.text() == 'maximal' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.Maximal' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Checks maximum annotations with non-default values.' +assert mojo.deprecated.text() == 'deprecated-text' +assert mojo.requiresDependencyResolution.text() == 'compile' +assert mojo.requiresDependencyCollection.text() == 'test' +assert mojo.requiresProject.text() == 'false' +assert mojo.requiresOnline.text() == 'true' +assert mojo.requiresDirectInvocation.text() == 'true' +assert mojo.requiresReports.text() == 'true' +assert mojo.aggregator.text() == 'true' +assert mojo.configurator.text() == 'configurator-hint' +assert mojo.threadSafe.text() == 'true' +assert mojo.phase.text() == 'package' +assert mojo.executePhase.text() == 'compile' +assert mojo.executeLifecycle.text() == '' +assert mojo.executionStrategy.text() == 'always' +assert mojo.inheritedByDefault.text() == 'false' +assert mojo.instantiationStrategy.text() == 'singleton' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "param" }[0] +assert parameter.name.text() == 'param' +assert parameter.alias.text() == 'myAlias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.since.text() == 'since-text' +assert parameter.deprecated.text() == 'deprecated-text' +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'false' +assert parameter.description.text() == 'Parameter description.' + +requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "projectHelper" }[0] +assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper' + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/invoker.properties new file mode 100644 index 000000000..5659577bc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean plugin:report -DskipTests diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/pom.xml new file mode 100644 index 000000000..541ee69ab --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-187/pom.xml @@ -0,0 +1,45 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + mplugin-187 + 1.0-SNAPSHOT + + Verify that plugin:report succeeds + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/invoker.properties new file mode 100644 index 000000000..8123c49df --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean compile plugin:report diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/pom.xml new file mode 100644 index 000000000..b6b63569b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/pom.xml @@ -0,0 +1,67 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + mplugin-191 + 1.0-SNAPSHOT + maven-plugin + + Verify that plugin-info.html and mojo pages are generated in the correct folder + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java new file mode 100644 index 000000000..0f75f16a9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java @@ -0,0 +1,64 @@ +package org.apache.maven.plugins.plugin.it; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Goal which touches a timestamp file. + */ +@Mojo(name = "touch", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) +public class MyMojo + extends AbstractMojo +{ + /** + * Location of the file. + */ + @Parameter(defaultValue = "${project.build.directory}", required = true) + private File outputDirectory; + + public void execute() + throws MojoExecutionException + { + File f = outputDirectory; + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try ( FileWriter w = new FileWriter( touch ) ) + { + w.write( "touch.txt" ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error creating file " + touch, e ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/verify.groovy new file mode 100644 index 000000000..5a33abdd5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-191/verify.groovy @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +File pluginInfo = new File( basedir, "target/site/plugin-info.html" ); +assert pluginInfo.isFile() + +File touchMojo = new File( basedir, "target/generated-site/xdoc/touch-mojo.xml" ); +assert touchMojo.isFile() + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/invoker.properties new file mode 100644 index 000000000..adce2cd6b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/invoker.properties @@ -0,0 +1,15 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +invoker.goals.1 = clean verify -DskipTests diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/pom.xml new file mode 100644 index 000000000..927202586 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/pom.xml @@ -0,0 +1,84 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + massembly-223 + 1.0-SNAPSHOT + maven-plugin + + massembly-223 Maven Plugin + http://maven.apache.org + + + @project.version@ + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginPluginVersion} + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins + maven-plugin-plugin + ${mavenPluginPluginVersion} + + + java-annotations + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java new file mode 100644 index 000000000..0f75f16a9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/src/main/java/org/apache/maven/plugins/plugin/it/MyMojo.java @@ -0,0 +1,64 @@ +package org.apache.maven.plugins.plugin.it; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Goal which touches a timestamp file. + */ +@Mojo(name = "touch", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) +public class MyMojo + extends AbstractMojo +{ + /** + * Location of the file. + */ + @Parameter(defaultValue = "${project.build.directory}", required = true) + private File outputDirectory; + + public void execute() + throws MojoExecutionException + { + File f = outputDirectory; + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try ( FileWriter w = new FileWriter( touch ) ) + { + w.write( "touch.txt" ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error creating file " + touch, e ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/verify.groovy new file mode 100644 index 000000000..909149790 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-223/verify.groovy @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "help" }[0] + +// check help mojo plugin descriptor +assert mojo != null + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/invoker.properties new file mode 100644 index 000000000..ea9f1350d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/invoker.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.java.version = 1.8+ +invoker.goals.1 = clean verify \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/pom.xml new file mode 100644 index 000000000..85b4259a9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/pom.xml @@ -0,0 +1,83 @@ + + + + + + 4.0.0 + + test-plugin + test-plugin + 1.0-SNAPSHOT + maven-plugin + + + + org.apache.maven + maven-plugin-api + 3.2.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + FOO + + + + default-descriptor + + descriptor + + + + process-classes + + + help-descriptor + + helpmojo + + process-classes + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/MyMojo.java new file mode 100644 index 000000000..077502034 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/MyMojo.java @@ -0,0 +1,37 @@ +package fr.ca; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * Created by clement.agarini on 04/08/14. + */ +@Mojo(name="test-plugin",defaultPhase = LifecyclePhase.GENERATE_SOURCES) +public class MyMojo extends AbstractMojo { + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/TestInterface.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/TestInterface.java new file mode 100644 index 000000000..16ee6d524 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-272_java8/src/main/java/fr/ca/TestInterface.java @@ -0,0 +1,30 @@ +package fr.ca; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public interface TestInterface { + + /** + * Java 8 required to support such default method implementation + */ + public default void foo(){ + + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/invoker.properties new file mode 100644 index 000000000..a9041f9bf --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/invoker.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.maven.version = 3.0+ +invoker.goals.1 = clean install -DskipTests +invoker.goals.2 = --log-file help.log org.apache.maven.its.plugin:help:1.0-SNAPSHOT:help diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/pom.xml new file mode 100644 index 000000000..cafacd434 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/pom.xml @@ -0,0 +1,87 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + help + 1.0-SNAPSHOT + maven-plugin + + + Tests generation and compilation of the help mojo. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + provided + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + default-descriptor + process-classes + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..2a5e51835 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/src/main/java/test/MyMojo.java @@ -0,0 +1,37 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +@Mojo( name= "test" ) +public class MyMojo + extends AbstractMojo +{ + @Parameter + private String empyAnnotatedParameter; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/test.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/test.properties new file mode 100644 index 000000000..8b28eaabd --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-299_no-configuration/test.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +detail = true +goal = test diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/invoker.properties new file mode 100644 index 000000000..2ae68688f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean process-classes \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/pom.xml new file mode 100644 index 000000000..b77ad77a2 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/pom.xml @@ -0,0 +1,82 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + mplugin305 + 1.0-SNAPSHOT + maven-plugin + + https://issues.apache.org/jira/browse/MPLUGIN-305 + + + @project.version@ + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginPluginVersion} + provided + + + org.apache.maven.surefire + maven-surefire-common + 2.19.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins + maven-plugin-plugin + ${mavenPluginPluginVersion} + + + java-annotations + + true + + + + mojo-descriptor + + descriptor + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java new file mode 100644 index 000000000..89a197b0d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java @@ -0,0 +1,289 @@ +package org.apache.maven.plugins.plugin.it; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.List; + +import org.apache.maven.plugin.surefire.AbstractSurefireMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.surefire.suite.RunResult; + +@Mojo(name="custom-surefire") +public class CustomSurefireMojo extends AbstractSurefireMojo { + + public File getBasedir() + { + return null; + } + + public File getClassesDirectory() + { + return null; + } + + public String getDebugForkedProcess() + { + return null; + } + + public Boolean getFailIfNoSpecifiedTests() + { + return null; + } + + public int getForkedProcessTimeoutInSeconds() + { + return 0; + } + + public double getParallelTestsTimeoutForcedInSeconds() + { + return 0; + } + + public double getParallelTestsTimeoutInSeconds() + { + return 0; + } + + public String getReportFormat() + { + return null; + } + + public File getReportsDirectory() + { + return null; + } + + public String getShutdown() + { + return null; + } + + public int getSkipAfterFailureCount() + { + return 0; + } + + public String getTest() + { + return null; + } + + public File getTestClassesDirectory() + { + return null; + } + + public boolean isPrintSummary() + { + return false; + } + + public boolean isSkip() + { + return false; + } + + public boolean isSkipExec() + { + return false; + } + + public boolean isSkipTests() + { + return false; + } + + public boolean isUseFile() + { + return false; + } + + public boolean isUseManifestOnlyJar() + { + return false; + } + + public boolean isUseSystemClassLoader() + { + return false; + } + + public void setBasedir( File arg0 ) + { + } + + public void setClassesDirectory( File arg0 ) + { + } + + public void setDebugForkedProcess( String arg0 ) + { + } + + public void setFailIfNoSpecifiedTests( boolean arg0 ) + { + } + + public void setForkedProcessTimeoutInSeconds( int arg0 ) + { + } + + public void setParallelTestsTimeoutForcedInSeconds( double arg0 ) + { + } + + public void setParallelTestsTimeoutInSeconds( double arg0 ) + { + } + + public void setPrintSummary( boolean arg0 ) + { + } + + public void setReportFormat( String arg0 ) + { + } + + public void setReportsDirectory( File arg0 ) + { + } + + public void setSkip( boolean arg0 ) + { + } + + public void setSkipExec( boolean arg0 ) + { + } + + public void setSkipTests( boolean arg0 ) + { + } + + public void setTest( String arg0 ) + { + } + + public void setTestClassesDirectory( File arg0 ) + { + } + + public void setUseFile( boolean arg0 ) + { + } + + public void setUseManifestOnlyJar( boolean arg0 ) + { + } + + public void setUseSystemClassLoader( boolean arg0 ) + { + } + + @Override + protected String[] getDefaultIncludes() + { + return null; + } + + @Override + public File getExcludesFile() + { + return null; + } + + @Override + public List getIncludes() + { + return null; + } + + @Override + public File getIncludesFile() + { + return null; + } + + @Override + protected String getPluginName() + { + return null; + } + + @Override + protected int getRerunFailingTestsCount() + { + return 0; + } + + @Override + public String getRunOrder() + { + return null; + } + + @Override + public File[] getSuiteXmlFiles() + { + return null; + } + + @Override + protected void handleSummary( RunResult arg0, Exception arg1 ) + { + } + + @Override + protected boolean hasSuiteXmlFiles() + { + return false; + } + + @Override + protected boolean isSkipExecution() + { + return false; + } + + @Override + public void setIncludes( List arg0 ) + { + } + + @Override + public void setRunOrder( String arg0 ) + { + } + + @Override + public void setSuiteXmlFiles( File[] arg0 ) + { + } + + @Override + protected List suiteXmlFiles() + { + return null; + } +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/verify.groovy new file mode 100644 index 000000000..5105ea1be --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_defaultMojoDependencies/verify.groovy @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +assert pluginDescriptor.mojos.mojo.size() == 1 +assert pluginDescriptor.mojos.mojo.parameters.parameter.size() == 50 + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/invoker.properties new file mode 100644 index 000000000..2ae68688f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean process-classes \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/pom.xml new file mode 100644 index 000000000..f5c309c2a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/pom.xml @@ -0,0 +1,85 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + mplugin305 + 1.0-SNAPSHOT + maven-plugin + + https://issues.apache.org/jira/browse/MPLUGIN-305 + + + @project.version@ + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginPluginVersion} + provided + + + org.apache.maven.surefire + maven-surefire-common + 2.19.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins + maven-plugin-plugin + ${mavenPluginPluginVersion} + + + java-annotations + + true + + + + mojo-descriptor + + descriptor + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java new file mode 100644 index 000000000..89a197b0d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java @@ -0,0 +1,289 @@ +package org.apache.maven.plugins.plugin.it; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.List; + +import org.apache.maven.plugin.surefire.AbstractSurefireMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.surefire.suite.RunResult; + +@Mojo(name="custom-surefire") +public class CustomSurefireMojo extends AbstractSurefireMojo { + + public File getBasedir() + { + return null; + } + + public File getClassesDirectory() + { + return null; + } + + public String getDebugForkedProcess() + { + return null; + } + + public Boolean getFailIfNoSpecifiedTests() + { + return null; + } + + public int getForkedProcessTimeoutInSeconds() + { + return 0; + } + + public double getParallelTestsTimeoutForcedInSeconds() + { + return 0; + } + + public double getParallelTestsTimeoutInSeconds() + { + return 0; + } + + public String getReportFormat() + { + return null; + } + + public File getReportsDirectory() + { + return null; + } + + public String getShutdown() + { + return null; + } + + public int getSkipAfterFailureCount() + { + return 0; + } + + public String getTest() + { + return null; + } + + public File getTestClassesDirectory() + { + return null; + } + + public boolean isPrintSummary() + { + return false; + } + + public boolean isSkip() + { + return false; + } + + public boolean isSkipExec() + { + return false; + } + + public boolean isSkipTests() + { + return false; + } + + public boolean isUseFile() + { + return false; + } + + public boolean isUseManifestOnlyJar() + { + return false; + } + + public boolean isUseSystemClassLoader() + { + return false; + } + + public void setBasedir( File arg0 ) + { + } + + public void setClassesDirectory( File arg0 ) + { + } + + public void setDebugForkedProcess( String arg0 ) + { + } + + public void setFailIfNoSpecifiedTests( boolean arg0 ) + { + } + + public void setForkedProcessTimeoutInSeconds( int arg0 ) + { + } + + public void setParallelTestsTimeoutForcedInSeconds( double arg0 ) + { + } + + public void setParallelTestsTimeoutInSeconds( double arg0 ) + { + } + + public void setPrintSummary( boolean arg0 ) + { + } + + public void setReportFormat( String arg0 ) + { + } + + public void setReportsDirectory( File arg0 ) + { + } + + public void setSkip( boolean arg0 ) + { + } + + public void setSkipExec( boolean arg0 ) + { + } + + public void setSkipTests( boolean arg0 ) + { + } + + public void setTest( String arg0 ) + { + } + + public void setTestClassesDirectory( File arg0 ) + { + } + + public void setUseFile( boolean arg0 ) + { + } + + public void setUseManifestOnlyJar( boolean arg0 ) + { + } + + public void setUseSystemClassLoader( boolean arg0 ) + { + } + + @Override + protected String[] getDefaultIncludes() + { + return null; + } + + @Override + public File getExcludesFile() + { + return null; + } + + @Override + public List getIncludes() + { + return null; + } + + @Override + public File getIncludesFile() + { + return null; + } + + @Override + protected String getPluginName() + { + return null; + } + + @Override + protected int getRerunFailingTestsCount() + { + return 0; + } + + @Override + public String getRunOrder() + { + return null; + } + + @Override + public File[] getSuiteXmlFiles() + { + return null; + } + + @Override + protected void handleSummary( RunResult arg0, Exception arg1 ) + { + } + + @Override + protected boolean hasSuiteXmlFiles() + { + return false; + } + + @Override + protected boolean isSkipExecution() + { + return false; + } + + @Override + public void setIncludes( List arg0 ) + { + } + + @Override + public void setRunOrder( String arg0 ) + { + } + + @Override + public void setSuiteXmlFiles( File[] arg0 ) + { + } + + @Override + protected List suiteXmlFiles() + { + return null; + } +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/verify.groovy new file mode 100644 index 000000000..1e8629203 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_emptyMojoDependencies/verify.groovy @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +assert pluginDescriptor.mojos.mojo.size() == 1 +assert pluginDescriptor.mojos.mojo.parameters.parameter.size() == 0 + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/invoker.properties new file mode 100644 index 000000000..2ae68688f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean process-classes \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/pom.xml new file mode 100644 index 000000000..db8fd5a54 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/pom.xml @@ -0,0 +1,85 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + mplugin305 + 1.0-SNAPSHOT + maven-plugin + + https://issues.apache.org/jira/browse/MPLUGIN-305 + + + @project.version@ + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginPluginVersion} + provided + + + org.apache.maven.surefire + maven-surefire-common + 2.19.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins + maven-plugin-plugin + ${mavenPluginPluginVersion} + + + java-annotations + + true + + org.apache.maven.surefire:maven-surefire-common + + + + + mojo-descriptor + + descriptor + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java new file mode 100644 index 000000000..89a197b0d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/src/main/java/org/apache/maven/plugins/plugin/it/CustomSurefireMojo.java @@ -0,0 +1,289 @@ +package org.apache.maven.plugins.plugin.it; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.List; + +import org.apache.maven.plugin.surefire.AbstractSurefireMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.surefire.suite.RunResult; + +@Mojo(name="custom-surefire") +public class CustomSurefireMojo extends AbstractSurefireMojo { + + public File getBasedir() + { + return null; + } + + public File getClassesDirectory() + { + return null; + } + + public String getDebugForkedProcess() + { + return null; + } + + public Boolean getFailIfNoSpecifiedTests() + { + return null; + } + + public int getForkedProcessTimeoutInSeconds() + { + return 0; + } + + public double getParallelTestsTimeoutForcedInSeconds() + { + return 0; + } + + public double getParallelTestsTimeoutInSeconds() + { + return 0; + } + + public String getReportFormat() + { + return null; + } + + public File getReportsDirectory() + { + return null; + } + + public String getShutdown() + { + return null; + } + + public int getSkipAfterFailureCount() + { + return 0; + } + + public String getTest() + { + return null; + } + + public File getTestClassesDirectory() + { + return null; + } + + public boolean isPrintSummary() + { + return false; + } + + public boolean isSkip() + { + return false; + } + + public boolean isSkipExec() + { + return false; + } + + public boolean isSkipTests() + { + return false; + } + + public boolean isUseFile() + { + return false; + } + + public boolean isUseManifestOnlyJar() + { + return false; + } + + public boolean isUseSystemClassLoader() + { + return false; + } + + public void setBasedir( File arg0 ) + { + } + + public void setClassesDirectory( File arg0 ) + { + } + + public void setDebugForkedProcess( String arg0 ) + { + } + + public void setFailIfNoSpecifiedTests( boolean arg0 ) + { + } + + public void setForkedProcessTimeoutInSeconds( int arg0 ) + { + } + + public void setParallelTestsTimeoutForcedInSeconds( double arg0 ) + { + } + + public void setParallelTestsTimeoutInSeconds( double arg0 ) + { + } + + public void setPrintSummary( boolean arg0 ) + { + } + + public void setReportFormat( String arg0 ) + { + } + + public void setReportsDirectory( File arg0 ) + { + } + + public void setSkip( boolean arg0 ) + { + } + + public void setSkipExec( boolean arg0 ) + { + } + + public void setSkipTests( boolean arg0 ) + { + } + + public void setTest( String arg0 ) + { + } + + public void setTestClassesDirectory( File arg0 ) + { + } + + public void setUseFile( boolean arg0 ) + { + } + + public void setUseManifestOnlyJar( boolean arg0 ) + { + } + + public void setUseSystemClassLoader( boolean arg0 ) + { + } + + @Override + protected String[] getDefaultIncludes() + { + return null; + } + + @Override + public File getExcludesFile() + { + return null; + } + + @Override + public List getIncludes() + { + return null; + } + + @Override + public File getIncludesFile() + { + return null; + } + + @Override + protected String getPluginName() + { + return null; + } + + @Override + protected int getRerunFailingTestsCount() + { + return 0; + } + + @Override + public String getRunOrder() + { + return null; + } + + @Override + public File[] getSuiteXmlFiles() + { + return null; + } + + @Override + protected void handleSummary( RunResult arg0, Exception arg1 ) + { + } + + @Override + protected boolean hasSuiteXmlFiles() + { + return false; + } + + @Override + protected boolean isSkipExecution() + { + return false; + } + + @Override + public void setIncludes( List arg0 ) + { + } + + @Override + public void setRunOrder( String arg0 ) + { + } + + @Override + public void setSuiteXmlFiles( File[] arg0 ) + { + } + + @Override + protected List suiteXmlFiles() + { + return null; + } +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/verify.groovy new file mode 100644 index 000000000..5105ea1be --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-305_singleMojoDependencies/verify.groovy @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +assert pluginDescriptor.mojos.mojo.size() == 1 +assert pluginDescriptor.mojos.mojo.parameters.parameter.size() == 50 + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/invoker.properties new file mode 100644 index 000000000..40c7ac61f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/invoker.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean plugin:report +invoker.mavenOpts = -Duser.language=en -Duser.country=US -Duser.variant=US diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/pom.xml new file mode 100644 index 000000000..628999dfb --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/pom.xml @@ -0,0 +1,86 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.its.plugin + report-since + 1.0-SNAPSHOT + maven-plugin + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + + index + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/src/main/java/org/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/src/main/java/org/MyMojo.java new file mode 100644 index 000000000..915a2db15 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/src/main/java/org/MyMojo.java @@ -0,0 +1,67 @@ +package org; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; + +/** + * Does nothing. + * + * @goal noop + * @phase process-sources + * @requiresDependencyResolution test + * @requiresDirectInvocation true + * @requiresOnline + * @inheritByDefault false + * @execute phase="compile" + * @aggregator + * @since 1.0 + * + * @deprecated You don't use test goals, do you? + */ +public class MyMojo + extends AbstractMojo +{ + + /** + * This is a test. + * + * @parameter + * @required + */ + @SuppressWarnings( "unused" ) + private String required; + + /** + * This is a test. + * + * @parameter expression="${string}" default-value="${project.version}/" + * @deprecated Just testing. + * @since 1.1 + */ + @SuppressWarnings( "unused" ) + private String string; + + public void execute() + { + // intentional do nothing + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/verify.groovy new file mode 100644 index 000000000..294a0c008 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-319_report-since/verify.groovy @@ -0,0 +1,27 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +assert new File( basedir, 'target/generated-site' ).exists() + +content = new File( basedir, 'target/generated-site/xdoc/noop-mojo.xml' ).text + +assert content.contains( '
  • Since: 1.0
  • ' ) +assert content.contains( '
  • Since: 1.1
  • ' ) + +return true \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/invoker.properties new file mode 100644 index 000000000..e1c03fcc4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = process-classes javadoc:javadoc diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/pom.xml new file mode 100644 index 000000000..8eae5c42f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/pom.xml @@ -0,0 +1,95 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.plugin.its + mplugin3224 + 1.0-SNAPSHOT + maven-plugin + + + Generation javadoc for private methods should be valid + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + provided + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + private + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + default-descriptor + process-classes + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..8e7dec5de --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/mplugin-324_javadoc/src/main/java/test/MyMojo.java @@ -0,0 +1,68 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** + * MOJO-DESCRIPTION. Some "quotation" marks and backslashes '\\', some important javadoc
    and an + * inline link to {@link org.apache.maven.plugin.AbstractMojo}. + * + * @deprecated As of 1.0, use the "quoted" goal instead. + * @since 2.1 + */ +@Mojo( name= "test" ) +public class MyMojo + extends AbstractMojo +{ + + /** + * This parameter uses "quotation" marks and backslashes '\\' in its description. Those characters must be + * escaped in Java string literals. + * + * @since 2.0 + */ + @Parameter( defaultValue = "escape\\backslash" ) + private String defaultParam; + + /** + * This parameter is deprecated. + * + * @deprecated As of version 1.0, use the {@link #defaultParam} instead. + */ + @Parameter + private String deprecatedParam; + + @Parameter( property = "test.undocumented", required = true ) + private String undocumentedParam; + + /** + * Readonly parameter: should not be proposed for configuration. + */ + @Parameter( defaultValue = "not for configuration", readonly = true ) + private String readonly; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/invoker.properties new file mode 100644 index 000000000..43be5b1d2 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals.1 = clean install diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/pom.xml new file mode 100644 index 000000000..ebaeba714 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/pom.xml @@ -0,0 +1,102 @@ + + + + + + 4.0.0 + + org.apache.maven.its.packaging-jar + packaging-jar + 1.0-SNAPSHOT + jar + + Maven Integration Test :: packaging-jar + + Test plugin-plugin can be enabled for projects with alternative packaging types, + "jar" in this particular case. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.2.1 + + + org.apache.maven + maven-core + 2.2.1 + + + org.codehaus.plexus + plexus-utils + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + jar + + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..bb31a860d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,35 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; + +/** + * @deprecated Don't use! + */ +@Mojo( name = "first" ) +public class FirstMojo + extends AbstractMojo +{ + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/verify.groovy new file mode 100644 index 000000000..3883bb425 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/packaging-jar/verify.groovy @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties new file mode 100644 index 000000000..a16bae843 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean plugin:report diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml new file mode 100644 index 000000000..2ac965012 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/pom.xml @@ -0,0 +1,92 @@ + + + + + + 4.0.0 + + org.apache.maven.its + jdk-default-version + 1.0-SNAPSHOT + maven-plugin + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + + index + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/main/java/org/apache/maven/plugins/issues/plugin/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/main/java/org/apache/maven/plugins/issues/plugin/MyMojo.java new file mode 100644 index 000000000..2cabe0c79 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/main/java/org/apache/maven/plugins/issues/plugin/MyMojo.java @@ -0,0 +1,64 @@ +package org.apache.maven.plugins.issues.plugin; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Goal which touches a timestamp file. + * + * @goal touch + * + * @phase process-sources + */ +public class MyMojo + extends AbstractMojo +{ + /** + * Location of the file. + * @parameter expression="${project.build.directory}" + * @required + */ + private File outputDirectory; + + public void execute() + throws MojoExecutionException + { + File f = outputDirectory; + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try ( FileWriter w = new FileWriter( touch ) ) + { + w.write( "touch.txt" ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error creating file " + touch, e ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/site/site.xml new file mode 100644 index 000000000..3c125b591 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/src/site/site.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/verify.groovy new file mode 100644 index 000000000..45dae7590 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk-default-version/verify.groovy @@ -0,0 +1,27 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +assert new File( basedir, 'target/site' ).exists(); + +content = new File( basedir, 'target/site/plugin-info.html' ).text; + +assert !content.contains( '1.1' ); +assert content.contains( 'Default target for maven-compiler-plugin version' ); + +return true; \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/invoker.properties new file mode 100644 index 000000000..5cc536a2e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean site diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/pom.xml new file mode 100644 index 000000000..9b2aba185 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/pom.xml @@ -0,0 +1,62 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin-info-jdk + parent + 1.0-SNAPSHOT + + plugin + target bytecode defined by plugin configuration + maven-plugin + + + 1.3 + ${maven.compiler.source} + + + + + + + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + + maven-compiler-plugin + + 1.5 + 1.5 + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/src/main/resources/META-INF/maven/plugin.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/src/main/resources/META-INF/maven/plugin.xml new file mode 100644 index 000000000..d8fd44068 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/plugin/src/main/resources/META-INF/maven/plugin.xml @@ -0,0 +1,69 @@ + + + + + + target bytecode defined by plugin configuration + + org.apache.maven.its.plugin-info-jdk + plugin + 1.0-SNAPSHOT + + false + true + + + touch + Goal which touches a timestamp file. + false + true + false + false + false + true + process-sources + org.apache.maven.plugins.issues.plugin.MyMojo + java + per-lookup + once-per-session + false + + + outputDirectory + java.io.File + true + true + Location of the file. + + + + ${project.build.directory} + + + + + + org.apache.maven + maven-plugin-api + jar + 2.0 + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/pom.xml new file mode 100644 index 000000000..75dd6ec51 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/pom.xml @@ -0,0 +1,53 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin-info-jdk + parent + 1.0-SNAPSHOT + + pluginManagement + target bytecode defined by pluginManagement configuration + maven-plugin + + + 1.3 + ${maven.compiler.source} + + + + + + + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/src/main/resources/META-INF/maven/plugin.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/src/main/resources/META-INF/maven/plugin.xml new file mode 100644 index 000000000..6a49de713 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pluginManagement/src/main/resources/META-INF/maven/plugin.xml @@ -0,0 +1,69 @@ + + + + + + target bytecode defined by pluginManagement configuration + + org.apache.maven.its.plugin-info-jdk + pluginManagement + 1.0-SNAPSHOT + Management + false + true + + + touch + Goal which touches a timestamp file. + false + true + false + false + false + true + process-sources + org.apache.maven.plugins.issues.plugin.MyMojo + java + per-lookup + once-per-session + false + + + outputDirectory + java.io.File + true + true + Location of the file. + + + + ${project.build.directory} + + + + + + org.apache.maven + maven-plugin-api + jar + 2.0 + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pom.xml new file mode 100644 index 000000000..a184f458d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/pom.xml @@ -0,0 +1,96 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin-info-jdk + parent + 1.0-SNAPSHOT + pom + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + property + pluginManagement + plugin + requirement + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + + index + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/pom.xml new file mode 100644 index 000000000..aa21b8207 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/pom.xml @@ -0,0 +1,39 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin-info-jdk + parent + 1.0-SNAPSHOT + + property + target bytecode defined by maven.compiler.target property + maven-plugin + + + 1.3 + ${maven.compiler.source} + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/src/main/resources/META-INF/maven/plugin.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/src/main/resources/META-INF/maven/plugin.xml new file mode 100644 index 000000000..29305e592 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/property/src/main/resources/META-INF/maven/plugin.xml @@ -0,0 +1,69 @@ + + + + + + target bytecode defined by maven.compiler.target property + + org.apache.maven.its.plugin-info-jdk + property + 1.0-SNAPSHOT + property + false + true + + + touch + Goal which touches a timestamp file. + false + true + false + false + false + true + process-sources + org.apache.maven.plugins.issues.plugin.MyMojo + java + per-lookup + once-per-session + false + + + outputDirectory + java.io.File + true + true + Location of the file. + + + + ${project.build.directory} + + + + + + org.apache.maven + maven-plugin-api + jar + 2.0 + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/pom.xml new file mode 100644 index 000000000..5ab103f4f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/pom.xml @@ -0,0 +1,78 @@ + + + + + + 4.0.0 + + + org.apache.maven.its.plugin-info-jdk + parent + 1.0-SNAPSHOT + + requirement + target bytecode defined by report jdk requirement configuration + maven-plugin + + + 1.3 + ${maven.compiler.source} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + + + 1.8 + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/src/main/resources/META-INF/maven/plugin.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/src/main/resources/META-INF/maven/plugin.xml new file mode 100644 index 000000000..0c19b0250 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/requirement/src/main/resources/META-INF/maven/plugin.xml @@ -0,0 +1,69 @@ + + + + + + target bytecode defined by report jdk requirement configuration + + org.apache.maven.its.plugin-info-jdk + requirement + 1.0-SNAPSHOT + requirement + false + true + + + touch + Goal which touches a timestamp file. + false + true + false + false + false + true + process-sources + org.apache.maven.plugins.issues.plugin.MyMojo + java + per-lookup + once-per-session + false + + + outputDirectory + java.io.File + true + true + Location of the file. + + + + ${project.build.directory} + + + + + + org.apache.maven + maven-plugin-api + jar + 2.0 + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/test.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/test.properties new file mode 100644 index 000000000..3db902bb5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/test.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +maven.compiler.source=1.3 +maven.compiler.target=1.3 \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/verify.groovy new file mode 100644 index 000000000..2b437142e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-info-jdk/verify.groovy @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +assert new File( basedir, 'property/target/site/plugin-info.html' ).text.contains( '1.3' ) +assert new File( basedir, 'pluginManagement/target/site/plugin-info.html' ).text.contains( '1.4' ) +assert new File( basedir, 'plugin/target/site/plugin-info.html' ).text.contains( '1.5' ) +assert new File( basedir, 'requirement/target/site/plugin-info.html' ).text.contains( '1.8' ) + +return true; \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/invoker.properties new file mode 100644 index 000000000..abdde0d42 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean site -DskipTests diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/pom.xml new file mode 100644 index 000000000..4893fe283 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/pom.xml @@ -0,0 +1,119 @@ + + + + + + 4.0.0 + + org.apache.maven.its + plugin-report + 1.0-SNAPSHOT + maven-plugin + + MPLUGIN-105 + + Test basic site generation to guard against regression. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + compile + + + org.apache.maven.reporting + maven-reporting-impl + 2.0.5 + + + org.apache.maven.reporting + maven-reporting-api + 3.0 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + + descriptor + + + + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + + index + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/DummyReport.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/DummyReport.java new file mode 100644 index 000000000..9eabcd550 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/DummyReport.java @@ -0,0 +1,227 @@ +package org; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.doxia.siterenderer.Renderer; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.AbstractMavenReport; +import org.apache.maven.reporting.AbstractMavenReportRenderer; +import org.apache.maven.reporting.MavenReportException; + +import java.io.File; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * Dummy Reporting Plugin. + */ +@Mojo( name = "report", requiresReports = true ) +@Execute( phase = LifecyclePhase.COMPILE ) +public class DummyReport + extends AbstractMavenReport +{ + /** + * Report output directory. + */ + @Parameter( defaultValue = "${project.build.directory}/generated-site/xdoc" ) + private File outputDirectory; + + /** + * Doxia Site Renderer. + */ + @Component + private Renderer siteRenderer; + + /** + * The Maven Project. + */ + @Parameter( property = "project", readonly = true, required = true ) + private MavenProject project; + + + /** + * The goal prefix that will appear before the ":". + * + * @since 2.4 + */ + @Parameter( property = "goalPrefix" ) + protected String goalPrefix; + + /** + * Set this to "true" to skip invoking any goals or reports of the plugin. + * + * @since 2.8 + */ + @Parameter( defaultValue = "false", property = "maven.plugin.skip" ) + private boolean skip; + + /** + * Set this to "true" to skip generating the report. + * + * @since 2.8 + */ + @Parameter( defaultValue = "false", property = "maven.plugin.report.skip" ) + private boolean skipReport; + + /** + * {@inheritDoc} + */ + protected Renderer getSiteRenderer() + { + return siteRenderer; + } + + /** + * {@inheritDoc} + */ + protected String getOutputDirectory() + { + return outputDirectory.getPath(); + } + + /** + * {@inheritDoc} + */ + protected MavenProject getProject() + { + return project; + } + + /** + * {@inheritDoc} + */ + public boolean canGenerateReport() + { + return true; + } + + /** + * {@inheritDoc} + */ + protected void executeReport( Locale locale ) + throws MavenReportException + { + if ( !canGenerateReport() ) + { + return; + } + if ( skip || skipReport ) + { + getLog().info( "Maven Plugin Plugin Report generation skipped." ); + return; + } + + // Generate the plugin's documentation + generatePluginDocumentation( locale ); + } + + /** + * {@inheritDoc} + */ + public String getDescription( Locale locale ) + { + return getBundle( locale ).getString( "report.plugin.description" ); + } + + /** + * {@inheritDoc} + */ + public String getName( Locale locale ) + { + return getBundle( locale ).getString( "report.plugin.name" ); + } + + /** + * {@inheritDoc} + */ + public String getOutputName() + { + return "plugin-info"; + } + + /** + * @param pluginDescriptor not null + * @param locale not null + * @throws MavenReportException if any + */ + private void generatePluginDocumentation( Locale locale ) + throws MavenReportException + { + File outputDir = new File( getOutputDirectory() ); + outputDir.mkdirs(); + PluginOverviewRenderer r = new PluginOverviewRenderer( getSink(), locale ); + r.render(); + } + + /** + * @param locale not null + * @return the bundle for this report + */ + protected static ResourceBundle getBundle( Locale locale ) + { + return ResourceBundle.getBundle( "plugin-report", locale, DummyReport.class.getClassLoader() ); + } + + /** + * Generates an overview page with the list of goals + * and a link to the goal's page. + */ + static class PluginOverviewRenderer + extends AbstractMavenReportRenderer + { + private final Locale locale; + + /** + * @param project not null + * @param sink not null + * @param locale not null + */ + public PluginOverviewRenderer( Sink sink, Locale locale ) + { + super( sink ); + + this.locale = locale; + } + + /** + * {@inheritDoc} + */ + public String getTitle() + { + return getBundle( locale ).getString( "report.plugin.title" ); + } + + /** + * {@inheritDoc} + */ + public void renderBody() + { + startSection( getTitle() ); + paragraph( "This is a report." ); + endSection(); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/MyMojo.java new file mode 100644 index 000000000..82a95ab37 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/src/main/java/org/MyMojo.java @@ -0,0 +1,65 @@ +package org; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +/** + * Does nothing. + * + * @since 1.0 + * @deprecated You don't use test goals, do you? + */ +@Mojo( name = "noop", defaultPhase = LifecyclePhase.PROCESS_SOURCES, + requiresDependencyResolution = ResolutionScope.TEST, + requiresDirectInvocation = true, requiresOnline = true, inheritByDefault = false, aggregator = true ) +@Execute( phase = LifecyclePhase.COMPILE ) +public class MyMojo + extends AbstractMojo +{ + + /** + * This is a test. + */ + @SuppressWarnings( "unused" ) + @Parameter( required = true ) + private String required; + + /** + * This is a test. + * + * @since 1.1 + * @deprecated Just testing. + */ + @SuppressWarnings( "unused" ) + @Parameter( property = "string", defaultValue = "${project.version}/" ) + private String string; + + public void execute() + { + // intentional do nothing + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/verify.bsh b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/verify.bsh new file mode 100644 index 000000000..e884269ea --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report-annotations/verify.bsh @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.*; +import java.util.*; +import java.util.regex.*; + +try +{ + File siteDir = new File( basedir, "target/site" ); + System.out.println( "Checking for existence of site directory: " + siteDir ); + if ( !siteDir.isDirectory() ) + { + System.out.println( "FAILED!" ); + return false; + } + + String[] expectedFiles = { + "noop-mojo.html", + "report-mojo.html", + }; + for ( String path : expectedFiles ) + { + File file = new File( siteDir, path ); + System.out.println( "Checking for existence of doc file: " + file ); + if ( !file.isFile() || file.length() <= 0 ) + { + System.out.println( "FAILED!" ); + return false; + } + } +} +catch( Throwable t ) +{ + t.printStackTrace(); + return false; +} + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/invoker.properties new file mode 100644 index 000000000..abdde0d42 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = clean site -DskipTests diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/pom.xml new file mode 100644 index 000000000..cf7ac803b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/pom.xml @@ -0,0 +1,109 @@ + + + + + + 4.0.0 + + + org.apache.maven + maven-parent + 21 + + + org.apache.maven.its + plugin-report + 1.0-SNAPSHOT + maven-plugin + + MPLUGIN-105 + + Test basic site generation to guard against regression of MPLUGIN-105. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven.reporting + maven-reporting-impl + 2.0.5 + + + org.apache.maven.reporting + maven-reporting-api + 3.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + org.apache.maven.plugins + maven-site-plugin + @sitePluginVersion@ + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + + index + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/DummyReport.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/DummyReport.java new file mode 100644 index 000000000..302314dd9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/DummyReport.java @@ -0,0 +1,210 @@ +package org; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.Locale; +import java.util.ResourceBundle; + +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.doxia.siterenderer.Renderer; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.AbstractMavenReport; +import org.apache.maven.reporting.AbstractMavenReportRenderer; +import org.apache.maven.reporting.MavenReportException; + +/** + * Dummy Reporting Plugin. + * + * @goal report + * @requiresReports true + * @execute phase="compile" + */ +public class DummyReport + extends AbstractMavenReport +{ + /** + * Report output directory. + * + * @parameter default-value="${project.build.directory}/generated-site/xdoc" + */ + private File outputDirectory; + + /** + * Doxia Site Renderer. + * + * @component + */ + private Renderer siteRenderer; + + /** + * The Maven Project. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + + /** + * The goal prefix that will appear before the ":". + * + * @parameter expression="${goalPrefix}" + * @since 2.4 + */ + protected String goalPrefix; + + /** + * Set this to "true" to skip invoking any goals or reports of the plugin. + * + * @parameter default-value="false" expression="${maven.plugin.skip}" + * @since 2.8 + */ + private boolean skip; + + /** + * Set this to "true" to skip generating the report. + * + * @parameter default-value="false" expression="${maven.plugin.report.skip}" + * @since 2.8 + */ + private boolean skipReport; + + /** {@inheritDoc} */ + protected Renderer getSiteRenderer() + { + return siteRenderer; + } + + /** {@inheritDoc} */ + protected String getOutputDirectory() + { + return outputDirectory.getPath(); + } + + /** {@inheritDoc} */ + protected MavenProject getProject() + { + return project; + } + + /** {@inheritDoc} */ + public boolean canGenerateReport() + { + return true; + } + + /** {@inheritDoc} */ + protected void executeReport( Locale locale ) + throws MavenReportException + { + if ( !canGenerateReport() ) + { + return; + } + if (skip || skipReport) + { + getLog().info( "Maven Plugin Plugin Report generation skipped." ); + return; + } + + // Generate the plugin's documentation + generatePluginDocumentation( locale ); + } + + /** {@inheritDoc} */ + public String getDescription( Locale locale ) + { + return getBundle( locale ).getString( "report.plugin.description" ); + } + + /** {@inheritDoc} */ + public String getName( Locale locale ) + { + return getBundle( locale ).getString( "report.plugin.name" ); + } + + /** {@inheritDoc} */ + public String getOutputName() + { + return "plugin-info"; + } + + /** + * @param pluginDescriptor not null + * @param locale not null + * @throws MavenReportException if any + */ + private void generatePluginDocumentation( Locale locale ) + throws MavenReportException + { + File outputDir = new File( getOutputDirectory() ); + outputDir.mkdirs(); + PluginOverviewRenderer r = new PluginOverviewRenderer( getSink(), locale ); + r.render(); + } + + /** + * @param locale not null + * @return the bundle for this report + */ + protected static ResourceBundle getBundle( Locale locale ) + { + return ResourceBundle.getBundle( "plugin-report", locale, DummyReport.class.getClassLoader() ); + } + + /** + * Generates an overview page with the list of goals + * and a link to the goal's page. + */ + static class PluginOverviewRenderer + extends AbstractMavenReportRenderer + { + private final Locale locale; + + /** + * @param project not null + * @param sink not null + * @param locale not null + */ + public PluginOverviewRenderer( Sink sink, + Locale locale ) + { + super( sink ); + + this.locale = locale; + } + + /** {@inheritDoc} */ + public String getTitle() + { + return getBundle( locale ).getString( "report.plugin.title" ); + } + + /** {@inheritDoc} */ + public void renderBody() + { + startSection( getTitle() ); + paragraph( "This is a report." ); + endSection(); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/MyMojo.java new file mode 100644 index 000000000..6b8b6865c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/src/main/java/org/MyMojo.java @@ -0,0 +1,67 @@ +package org; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; + +/** + * Does nothing. + * + * @goal noop + * @phase process-sources + * @requiresDependencyResolution test + * @requiresDirectInvocation true + * @requiresOnline + * @inheritByDefault false + * @execute phase="compile" + * @aggregator + * @since 1.0 + * + * @deprecated You don't use test goals, do you? + */ +public class MyMojo + extends AbstractMojo +{ + + /** + * This is a test. + * + * @parameter + * @required + */ + @SuppressWarnings( "unused" ) + private String required; + + /** + * This is a test. + * + * @parameter expression="${string}" default-value="${project.version}/" + * @deprecated Just testing. + * @since 1.1 + */ + @SuppressWarnings( "unused" ) + private String string; + + public void execute() + { + // intentional do nothing + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/verify.bsh b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/verify.bsh new file mode 100644 index 000000000..091a10a04 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/plugin-report/verify.bsh @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.*; +import java.util.*; +import java.util.regex.*; + +try +{ + File siteDir = new File( basedir, "target/site" ); + System.out.println( "Checking for existence of site directory: " + siteDir ); + if ( !siteDir.isDirectory() ) + { + System.out.println( "FAILED!" ); + return false; + } + + String[] expectedFiles = { + "noop-mojo.html", + "noop-mojo.html", + "report-mojo.html", + }; + for ( String path : expectedFiles ) + { + File file = new File( siteDir, path ); + System.out.println( "Checking for existence of doc file: " + file ); + if ( !file.isFile() || file.length() <= 0 ) + { + System.out.println( "FAILED!" ); + return false; + } + } +} +catch( Throwable t ) +{ + t.printStackTrace(); + return false; +} + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/settings.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/settings.xml new file mode 100644 index 000000000..44480e37e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/settings.xml @@ -0,0 +1,62 @@ + + + + + + + + + it-repo + + true + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/invoker.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/invoker.properties new file mode 100644 index 000000000..8e51f7198 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/invoker.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +invoker.goals = install -DskipTests +invoker.mavenOpts = -Dmaven.plugin.skip=true \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/pom.xml new file mode 100644 index 000000000..c9aa73727 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/pom.xml @@ -0,0 +1,56 @@ + + + + + + 4.0.0 + + org.apache.maven.its.it0013 + mplugin-174 + 1.0-SNAPSHOT + maven-plugin + + MPLUGIN-174 + + Test the skip property + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java new file mode 100644 index 000000000..69354f68a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/CoreIt0013Mojo.java @@ -0,0 +1,67 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + * @goal it0013 + */ +public class CoreIt0013Mojo + extends AbstractMojo +{ + + /** + * @parameter expression="${project.build.directory}" + * @required + */ + private String outputDirectory; + + public void execute() + throws MojoExecutionException + { + getLog().info( "outputDirectory = " + outputDirectory ); + + File f = new File( outputDirectory ); + + if ( !f.exists() ) + { + f.mkdirs(); + } + + File touch = new File( f, "touch.txt" ); + + try + { + touch.createNewFile(); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Error writing verification file.", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 000000000..18ce947e0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,72 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; +import java.io.IOException; + +/** + * Touches a test file. + * + * @goal first + * @requiresDependencyResolution test + * @phase integration-test + * @execute phase="generate-sources" lifecycle="cobertura" + * @deprecated Don't use! + * @since 1.2 + */ +public class FirstMojo + extends AbstractMojo +{ + + /** + * Project directory. + * @parameter default-value="${basedir}" + * @readonly + */ + private File basedir; + + /** + * @parameter expression="${first.touchFile}" default-value="${project.build.directory}/touch.txt" + * @required + */ + private File touchFile; + + /** + * @parameter alias="alias" + * @deprecated As of 0.2 + * @since 0.1 + */ + private String aliasedParam; + + /** + * @component role="org.apache.maven.project.MavenProjectHelper" roleHint="test" + */ + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java new file mode 100644 index 000000000..ef12e162a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/src/main/java/org/apache/maven/plugin/coreit/SecondMojo.java @@ -0,0 +1,39 @@ +package org.apache.maven.plugin.coreit; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; + +/** + * Does nothing special. + * + * @goal second + * @requiresDependencyCollection compile + * @threadSafe + */ +public class SecondMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/verify.groovy new file mode 100644 index 000000000..e386564fd --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/skip/verify.groovy @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert !descriptorFile.isFile() + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml new file mode 100644 index 000000000..e21d6caea --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/pom.xml @@ -0,0 +1,66 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + latin-1 + 1.0-SNAPSHOT + maven-plugin + + Latin-1 + + Test that source files using Latin-1 are properly parsed. + + + + ISO-8859-1 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..97d8ef853 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/latin-1/src/main/java/test/MyMojo.java @@ -0,0 +1,39 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// NOTE: This source file is by design encoded using ISO-8859-1! + +import org.apache.maven.plugin.AbstractMojo; + +/** + * TEST-CHARS: ÄÖÜäöüß + * + * @goal test + */ +public class MyMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/pom.xml new file mode 100644 index 000000000..57cff57c5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/pom.xml @@ -0,0 +1,39 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + aggregator + 1.0-SNAPSHOT + pom + + Aggregator + + Test that the character encoding of source files is respected by the metadata extractor. + + + + utf-8 + latin-1 + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml new file mode 100644 index 000000000..a8ddf7f0e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/pom.xml @@ -0,0 +1,66 @@ + + + + + + 4.0.0 + + org.apache.maven.its.plugin + utf-8 + 1.0-SNAPSHOT + maven-plugin + + UTF-8 + + Test that source files using UTF-8 are properly parsed. + + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/src/main/java/test/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/src/main/java/test/MyMojo.java new file mode 100644 index 000000000..08a0fea1d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/utf-8/src/main/java/test/MyMojo.java @@ -0,0 +1,39 @@ +package test; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// NOTE: This source file is by design encoded using UTF-8! + +import org.apache.maven.plugin.AbstractMojo; + +/** + * TEST-CHARS: ßıΣЯ×€ + * + * @goal test + */ +public class MyMojo + extends AbstractMojo +{ + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/verify.groovy b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/verify.groovy new file mode 100644 index 000000000..e5bac1cba --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/it/source-encoding/verify.groovy @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +def latin1File = new File(basedir, 'latin-1/target/classes/META-INF/maven/plugin.xml') +assert latin1File.exists() +def latin1Chars = new XmlParser().parse(latin1File).mojos.mojo.description.text() +println latin1Chars +assert "TEST-CHARS: \u00C4\u00D6\u00DC\u00E4\u00F6\u00FC\u00DF".equals( latin1Chars ) + +def utf8File = new File(basedir, 'utf-8/target/classes/META-INF/maven/plugin.xml') +assert utf8File.exists() +def utf8Chars = new XmlParser().parse(utf8File).mojos.mojo.description.text() +println utf8Chars +assert "TEST-CHARS: \u00DF\u0131\u03A3\u042F\u05D0\u20AC".equals( utf8Chars ) + +return true; diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/filtered-resources/META-INF/plexus/components.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/filtered-resources/META-INF/plexus/components.xml new file mode 100644 index 000000000..0996c75e1 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/filtered-resources/META-INF/plexus/components.xml @@ -0,0 +1,93 @@ + + + + + + + + + org.apache.maven.artifact.handler.ArtifactHandler + maven-plugin + org.apache.maven.artifact.handler.DefaultArtifactHandler + + maven-plugin + jar + java + true + + + + + + + org.apache.maven.lifecycle.mapping.LifecycleMapping + maven-plugin + org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping + + + + default + + + + org.apache.maven.plugins:maven-resources-plugin:3.1.0:resources + + + org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile + + + org.apache.maven.plugins:maven-plugin-plugin:${project.version}:descriptor + + + org.apache.maven.plugins:maven-resources-plugin:3.1.0:testResources + + + org.apache.maven.plugins:maven-compiler-plugin:3.8.0:testCompile + + + org.apache.maven.plugins:maven-surefire-plugin:2.22.0:test + + + org.apache.maven.plugins:maven-jar-plugin:3.1.0:jar, + org.apache.maven.plugins:maven-plugin-plugin:${project.version}:addPluginArtifactMetadata + + + org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install + + + org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java new file mode 100644 index 000000000..849ea2e64 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java @@ -0,0 +1,322 @@ +package org.apache.maven.plugin.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; +import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.generator.Generator; +import org.apache.maven.tools.plugin.generator.GeneratorException; +import org.apache.maven.tools.plugin.generator.GeneratorUtils; +import org.apache.maven.tools.plugin.scanner.MojoScanner; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.util.ReaderFactory; + +import java.io.File; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * Abstract class for this Plugin. + * + * @author Jason van Zyl + * + */ +public abstract class AbstractGeneratorMojo + extends AbstractMojo +{ + /** + * The project currently being built. + */ + @Parameter( defaultValue = "${project}", readonly = true ) + protected MavenProject project; + + /** + * The component used for scanning the source tree for mojos. + */ + @Component + protected MojoScanner mojoScanner; + + /** + * The file encoding of the source files. + * + * @since 2.5 + */ + @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" ) + protected String encoding; + + /** + * The goal prefix that will appear before the ":". + */ + @Parameter + protected String goalPrefix; + + /** + * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the + * descriptor generator mojo is bound to generate-resources phase. + * But for annotations, the compiled classes are needed, so skip error + * + * @since 3.0 + */ + @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" ) + protected boolean skipErrorNoDescriptorsFound; + + /** + *

    + * The role names of mojo extractors to use. + *

    + *

    + * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors + * will be used. + *

    + * Example: + *
    +     *  <!-- Use all mojo extractors -->
    +     *  <extractors/>
    +     *
    +     *  <!-- Use no mojo extractors -->
    +     *  <extractors>
    +     *      <extractor/>
    +     *  </extractors>
    +     *
    +     *  <!-- Use only bsh mojo extractor -->
    +     *  <extractors>
    +     *      <extractor>bsh</extractor>
    +     *  </extractors>
    +     * 
    + */ + @Parameter + protected Set extractors; + + /** + * Set this to "true" to skip invoking any goals or reports of the plugin. + * + * @since 2.8 + */ + @Parameter( defaultValue = "false", property = "maven.plugin.skip" ) + protected boolean skip; + + /** + * The set of dependencies for the current project + * + * @since 3.0 + */ + @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true ) + protected Set dependencies; + + /** + * Specify the dependencies as {@code groupId:artifactId} containing (abstract) Mojos, to filter + * dependencies scanned at runtime and focus on dependencies that are really useful to Mojo analysis. + * By default, the value is {@code null} and all dependencies are scanned (as before this parameter was added). + * If specified in the configuration with no children, no dependencies are scanned. + * + * @since 3.5 + */ + @Parameter + private List mojoDependencies; + + /** + * List of Remote Repositories used by the resolver + * + * @since 3.0 + */ + @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true ) + protected List remoteRepos; + + /** + * Location of the local repository. + * + * @since 3.0 + */ + @Parameter( defaultValue = "${localRepository}", required = true, readonly = true ) + protected ArtifactRepository local; + + /** + * Maven plugin packaging types. Default is single "maven-plugin". + * + * @since 3.3 + */ + @Parameter + protected List packagingTypes = Arrays.asList( "maven-plugin" ); + + /** + * @return the output directory where files will be generated. + */ + protected abstract File getOutputDirectory(); + + /** + * @return the wanted Generator implementation. + */ + protected abstract Generator createGenerator(); + + /** + * {@inheritDoc} + */ + public void execute() + throws MojoExecutionException + { + if ( !packagingTypes.contains( project.getPackaging() ) ) + { + getLog().warn( "Unsupported packaging type " + project.getPackaging() + ", execution skipped" ); + return; + } + if ( skip ) + { + getLog().warn( "Execution skipped" ); + return; + } + + if ( project.getArtifactId().toLowerCase().startsWith( "maven-" ) + && project.getArtifactId().toLowerCase().endsWith( "-plugin" ) && !"org.apache.maven.plugins".equals( + project.getGroupId() ) ) + { + getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n" + + "plugins in the Group Id org.apache.maven.plugins\n" + + "Please change your artifactId to the format ___-maven-plugin\n" + + "In the future this error will break the build.\n\n" ); + } + + String defaultGoalPrefix = PluginDescriptor.getGoalPrefixFromArtifactId( project.getArtifactId() ); + if ( goalPrefix == null ) + { + goalPrefix = defaultGoalPrefix; + } + else if ( !goalPrefix.equals( defaultGoalPrefix ) ) + { + getLog().warn( + "\n\nGoal prefix is specified as: '" + goalPrefix + "'. " + "Maven currently expects it to be '" + + defaultGoalPrefix + "'.\n" ); + } + + mojoScanner.setActiveExtractors( extractors ); + + // TODO: could use this more, eg in the writing of the plugin descriptor! + PluginDescriptor pluginDescriptor = new PluginDescriptor(); + + pluginDescriptor.setGroupId( project.getGroupId() ); + + pluginDescriptor.setArtifactId( project.getArtifactId() ); + + pluginDescriptor.setVersion( project.getVersion() ); + + pluginDescriptor.setGoalPrefix( goalPrefix ); + + pluginDescriptor.setName( project.getName() ); + + pluginDescriptor.setDescription( project.getDescription() ); + + if ( encoding == null || encoding.length() < 1 ) + { + getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING + + " actually) to read mojo source files, i.e. build is platform dependent!" ); + } + else + { + getLog().info( "Using '" + encoding + "' encoding to read mojo source files." ); + } + + try + { + List deps = GeneratorUtils.toComponentDependencies( project.getRuntimeDependencies() ); + pluginDescriptor.setDependencies( deps ); + + PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor ); + request.setEncoding( encoding ); + request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound ); + request.setDependencies( filterMojoDependencies() ); + request.setLocal( this.local ); + request.setRemoteRepos( this.remoteRepos ); + + mojoScanner.populatePluginDescriptor( request ); + + getOutputDirectory().mkdirs(); + + createGenerator().execute( getOutputDirectory(), request ); + } + catch ( GeneratorException e ) + { + throw new MojoExecutionException( "Error writing plugin descriptor", e ); + } + catch ( InvalidPluginDescriptorException e ) + { + throw new MojoExecutionException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'", + e ); + } + catch ( ExtractionException e ) + { + throw new MojoExecutionException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'", + e ); + } + catch ( LinkageError e ) + { + throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version." + + " Please check the plugin dependencies configured in the POM and ensure the versions match.", e ); + } + } + + /** + * Get dependencies filtered with mojoDependencies configuration. + * + * @return eventually filtered dependencies, or even null if configured with empty mojoDependencies + * list + * @see #mojoDependencies + */ + private Set filterMojoDependencies() + { + Set filteredDependencies; + if ( mojoDependencies == null ) + { + filteredDependencies = dependencies; + } + else if ( mojoDependencies.size() == 0 ) + { + filteredDependencies = null; + } + else + { + filteredDependencies = new LinkedHashSet<>(); + + ArtifactFilter filter = new IncludesArtifactFilter( mojoDependencies ); + + for ( Artifact artifact : dependencies ) + { + if ( filter.include( artifact ) ) + { + filteredDependencies.add( artifact ); + } + } + } + + return filteredDependencies; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java new file mode 100644 index 000000000..a0bcf5c7c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java @@ -0,0 +1,94 @@ +package org.apache.maven.plugin.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.tools.plugin.generator.Generator; +import org.apache.maven.tools.plugin.generator.PluginDescriptorGenerator; + +/** + *

    + * Generate a plugin descriptor. + *

    + *

    + * Note: Since 3.0, for Java plugin annotations support, + * default phase + * defined by this goal is after the "compilation" of any scripts. This doesn't override + * the default binding coded + * at generate-resources phase in Maven core. + *

    + * @author Jason van Zyl + * @since 2.0 + */ +@Mojo( name = "descriptor", defaultPhase = LifecyclePhase.PROCESS_CLASSES, + requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true ) +public class DescriptorGeneratorMojo + extends AbstractGeneratorMojo +{ + /** + * The directory where the generated plugin.xml file will be put. + */ + @Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/maven" ) + protected File outputDirectory; + + /** + * A flag to disable generation of the plugin.xml in favor of a hand authored plugin descriptor. + * + * @since 2.6 + */ + @Parameter( defaultValue = "false" ) + private boolean skipDescriptor; + + /** + * {@inheritDoc} + */ + protected File getOutputDirectory() + { + return outputDirectory; + } + + /** + * {@inheritDoc} + */ + protected Generator createGenerator() + { + return new PluginDescriptorGenerator( getLog() ); + } + + /** + * {@inheritDoc} + */ + public void execute() + throws MojoExecutionException + { + if ( skipDescriptor ) + { + return; + } + + super.execute(); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java new file mode 100644 index 000000000..767567bbd --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java @@ -0,0 +1,101 @@ +package org.apache.maven.plugin.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.tools.plugin.generator.Generator; +import org.apache.maven.tools.plugin.generator.PluginHelpGenerator; +import org.codehaus.plexus.velocity.VelocityComponent; + +/** + * Generates a HelpMojo class. + * + * @author Vincent Siveton + * + * @since 2.4 + */ +@Mojo( name = "helpmojo", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true, + requiresDependencyResolution = ResolutionScope.COMPILE ) +public class HelpGeneratorMojo + extends AbstractGeneratorMojo +{ + /** + * The directory where the generated HelpMojo file will be put. + */ + @Parameter( defaultValue = "${project.build.directory}/generated-sources/plugin" ) + protected File outputDirectory; + + /** + * The name of the package for the generated HelpMojo. By default, the package will be calculated based + * on the packages of the other plugin goals. + * + * @since 2.6 + */ + @Parameter + private String helpPackageName; + + /** + * Velocity component. + */ + @Component + private VelocityComponent velocity; + + /** + * {@inheritDoc} + */ + protected File getOutputDirectory() + { + return outputDirectory; + } + + /** + * {@inheritDoc} + */ + protected Generator createGenerator() + { + return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setVelocityComponent( this.velocity ); + } + + /** + * {@inheritDoc} + */ + public void execute() + throws MojoExecutionException + { + // force value for this plugin + skipErrorNoDescriptorsFound = true; + + super.execute(); + + if ( !project.getCompileSourceRoots().contains( outputDirectory.getAbsolutePath() ) && !skip ) + { + project.addCompileSourceRoot( outputDirectory.getAbsolutePath() ); + } + + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java new file mode 100644 index 000000000..886951f1e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java @@ -0,0 +1,828 @@ +package org.apache.maven.plugin.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.doxia.siterenderer.Renderer; +import org.apache.maven.execution.RuntimeInformation; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.plugin.descriptor.MNG6109PluginDescriptorBuilder; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.AbstractMavenReport; +import org.apache.maven.reporting.AbstractMavenReportRenderer; +import org.apache.maven.reporting.MavenReportException; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.generator.GeneratorException; +import org.apache.maven.tools.plugin.generator.GeneratorUtils; +import org.apache.maven.tools.plugin.generator.PluginXdocGenerator; +import org.apache.maven.tools.plugin.scanner.MojoScanner; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.configuration.PlexusConfigurationException; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; + +/** + * Generates the Plugin's documentation report: plugin-info.html plugin overview page, + * and one goal-mojo.html per goal. + * + * @author Stephane Nicoll + * @author Vincent Siveton + * @since 2.0 + */ +@Mojo( name = "report", threadSafe = true ) +@Execute( phase = LifecyclePhase.PROCESS_CLASSES ) +public class PluginReport + extends AbstractMavenReport +{ + /** + * Report output directory for mojos' documentation. + */ + @Parameter( defaultValue = "${project.build.directory}/generated-site/xdoc" ) + private File outputDirectory; + + /** + * Doxia Site Renderer. + */ + @Component + private Renderer siteRenderer; + + /** + * The Maven Project. + */ + @Parameter( defaultValue = "${project}", readonly = true ) + private MavenProject project; + + /** + * Mojo scanner tools. + */ + @Component + protected MojoScanner mojoScanner; + + /** + * The file encoding of the source files. + * + * @since 2.7 + */ + @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" ) + private String encoding; + + /** + * Specify some requirements to execute this plugin. + * Example: + *
    +     * <requirements>
    +     *   <maven>2.0</maven>
    +     *   <jdk>1.4</jdk>
    +     *   <memory>256m</memory>
    +     *   <diskSpace>1m</diskSpace>
    +     *   <others>
    +     *     <property>
    +     *       <name>SVN</name>
    +     *       <value>1.4.6</value>
    +     *     </property>
    +     *   </others>
    +     * </requirements>
    +     * 
    + * + * If not is specified, Maven requirement is extracted from + * <project><prerequisites><maven> + * and JDK requirement is extracted from maven-compiler-plugin configuration. + */ + @Parameter + private Requirements requirements; + + /** + *

    + * The goal prefix that will appear before the ":". + * By default, this plugin applies a heuristic to derive a heuristic from + * the plugin's artifactId. + *

    + *

    + * It removes any occurrences of the regular expression -?maven-?, + * and then removes any occurrences of -?plugin-?. + *

    + *

    + * For example, horsefeature-maven-plugin becomes horsefeature. + *

    + *

    + * (There is a special case for maven-plugin-plugin: it is mapped to 'plugin') + *

    + * + * @since 2.4 + */ + @Parameter( property = "goalPrefix" ) + protected String goalPrefix; + + /** + * Set this to "true" to skip invoking any goals or reports of the plugin. + * + * @since 2.8 + */ + @Parameter( defaultValue = "false", property = "maven.plugin.skip" ) + private boolean skip; + + /** + * Set this to "true" to skip generating the report. + * + * @since 2.8 + */ + @Parameter( defaultValue = "false", property = "maven.plugin.report.skip" ) + private boolean skipReport; + + /** + * The set of dependencies for the current project + * + * @since 3.0 + */ + @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true ) + protected Set dependencies; + + /** + * List of Remote Repositories used by the resolver + * + * @since 3.0 + */ + @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true ) + protected List remoteRepos; + + /** + * Location of the local repository. + * + * @since 3.0 + */ + @Parameter( defaultValue = "${localRepository}", required = true, readonly = true ) + protected ArtifactRepository local; + + /** + * @since 3.5.1 + */ + @Component + private RuntimeInformation rtInfo; + + /** + * Path to {@code plugin.xml} plugin descriptor to generate the report from. + * + * @since 3.5.1 + */ + @Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/maven/plugin.xml", required = true, + readonly = true ) + private File pluginXmlFile; + + /** + * {@inheritDoc} + */ + @Override + protected Renderer getSiteRenderer() + { + return siteRenderer; + } + + /** + * {@inheritDoc} + */ + @Override + protected String getOutputDirectory() + { + // PLUGIN-191: output directory of plugin.html, not *-mojo.xml + return project.getReporting().getOutputDirectory(); + } + + /** + * {@inheritDoc} + */ + @Override + protected MavenProject getProject() + { + return project; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean canGenerateReport() + { + return pluginXmlFile != null && pluginXmlFile.isFile() && pluginXmlFile.canRead(); + } + + /** + * {@inheritDoc} + */ + @Override + protected void executeReport( Locale locale ) + throws MavenReportException + { + if ( !canGenerateReport() ) + { + return; + } + if ( skip || skipReport ) + { + getLog().info( "Maven Plugin Plugin Report generation skipped." ); + return; + } + + PluginDescriptor pluginDescriptor = extractPluginDescriptor(); + + // Generate the mojos' documentation + generateMojosDocumentation( pluginDescriptor, locale ); + + // Write the overview + PluginOverviewRenderer r = + new PluginOverviewRenderer( project, requirements, getSink(), pluginDescriptor, locale ); + r.render(); + } + + private PluginDescriptor extractPluginDescriptor() + throws MavenReportException + { + PluginDescriptorBuilder builder = getPluginDescriptorBuilder(); + + try + { + return builder.build( new FileReader( pluginXmlFile ) ); + } + catch ( FileNotFoundException | PlexusConfigurationException e ) + { + getLog().debug( "Failed to read " + pluginXmlFile + ", fall back to mojoScanner" ); + } + + // Copy from AbstractGeneratorMojo#execute() + String defaultGoalPrefix = PluginDescriptor.getGoalPrefixFromArtifactId( project.getArtifactId() ); + if ( goalPrefix == null ) + { + goalPrefix = defaultGoalPrefix; + } + else + { + getLog().warn( "\n\nGoal prefix is specified as: '" + goalPrefix + "'. Maven currently expects it to be '" + + defaultGoalPrefix + "'.\n" ); + } + + // TODO: could use this more, eg in the writing of the plugin descriptor! + PluginDescriptor pluginDescriptor = new PluginDescriptor(); + + pluginDescriptor.setGroupId( project.getGroupId() ); + + pluginDescriptor.setArtifactId( project.getArtifactId() ); + + pluginDescriptor.setVersion( project.getVersion() ); + + pluginDescriptor.setGoalPrefix( goalPrefix ); + + try + { + List deps = GeneratorUtils.toComponentDependencies( project.getRuntimeDependencies() ); + pluginDescriptor.setDependencies( deps ); + + PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor ); + request.setEncoding( encoding ); + request.setSkipErrorNoDescriptorsFound( true ); + request.setDependencies( dependencies ); + request.setLocal( this.local ); + request.setRemoteRepos( this.remoteRepos ); + + try + { + mojoScanner.populatePluginDescriptor( request ); + } + catch ( InvalidPluginDescriptorException e ) + { + // this is OK, it happens to lifecycle plugins. Allow generation to proceed. + getLog().debug( "Plugin without mojos.", e ); + } + } + catch ( ExtractionException e ) + { + throw new MavenReportException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'", + e ); + } + return pluginDescriptor; + } + + /** + * Return the pluginDescriptorBuilder to use based on the Maven version: either use the original from the + * maven-plugin-api or a patched version for Maven versions before the MNG-6109 fix + * (because of Maven MNG-6109 bug that won't give accurate 'since' info when reading plugin.xml). + * + * @return the proper pluginDescriptorBuilder + * @see https://issues.apache.org/jira/browse/MNG-6109 + * @see https://issues.apache.org/jira/browse/MPLUGIN-319 + */ + private PluginDescriptorBuilder getPluginDescriptorBuilder() + { + PluginDescriptorBuilder pluginDescriptorBuilder; + try + { + VersionRange versionRange = VersionRange.createFromVersionSpec( "(3.3.9,)" ); + if ( versionRange.containsVersion( rtInfo.getApplicationVersion() ) ) + { + pluginDescriptorBuilder = new PluginDescriptorBuilder(); + } + else + { + pluginDescriptorBuilder = new MNG6109PluginDescriptorBuilder(); + } + } + catch ( InvalidVersionSpecificationException e ) + { + return new MNG6109PluginDescriptorBuilder(); + } + + return pluginDescriptorBuilder; + } + + /** + * {@inheritDoc} + */ + @Override + public String getDescription( Locale locale ) + { + return getBundle( locale ).getString( "report.plugin.description" ); + } + + /** + * {@inheritDoc} + */ + @Override + public String getName( Locale locale ) + { + return getBundle( locale ).getString( "report.plugin.name" ); + } + + /** + * {@inheritDoc} + */ + @Override + public String getOutputName() + { + return "plugin-info"; + } + + /** + * Generate the mojos documentation, as xdoc files. + * + * @param pluginDescriptor not null + * @param locale not null + * @throws MavenReportException if any + */ + private void generateMojosDocumentation( PluginDescriptor pluginDescriptor, Locale locale ) + throws MavenReportException + { + try + { + File outputDir = outputDirectory; + outputDir.mkdirs(); + + PluginXdocGenerator generator = new PluginXdocGenerator( project, locale ); + PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest( project, pluginDescriptor ); + generator.execute( outputDir, pluginToolsRequest ); + } + catch ( GeneratorException e ) + { + throw new MavenReportException( "Error writing plugin documentation", e ); + } + + } + + /** + * @param locale not null + * @return the bundle for this report + */ + protected static ResourceBundle getBundle( Locale locale ) + { + return ResourceBundle.getBundle( "plugin-report", locale, PluginReport.class.getClassLoader() ); + } + + /** + * Generates an overview page with the list of goals + * and a link to the goal's page. + */ + static class PluginOverviewRenderer + extends AbstractMavenReportRenderer + { + private final MavenProject project; + + private final Requirements requirements; + + private final PluginDescriptor pluginDescriptor; + + private final Locale locale; + + /** + * @param project not null + * @param requirements not null + * @param sink not null + * @param pluginDescriptor not null + * @param locale not null + */ + PluginOverviewRenderer( MavenProject project, Requirements requirements, Sink sink, + PluginDescriptor pluginDescriptor, Locale locale ) + { + super( sink ); + + this.project = project; + + this.requirements = ( requirements == null ? new Requirements() : requirements ); + + this.pluginDescriptor = pluginDescriptor; + + this.locale = locale; + } + + /** + * {@inheritDoc} + */ + @Override + public String getTitle() + { + return getBundle( locale ).getString( "report.plugin.title" ); + } + + /** + * {@inheritDoc} + */ + @Override + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public void renderBody() + { + startSection( getTitle() ); + + if ( !( pluginDescriptor.getMojos() != null && pluginDescriptor.getMojos().size() > 0 ) ) + { + paragraph( getBundle( locale ).getString( "report.plugin.goals.nogoal" ) ); + endSection(); + return; + } + + paragraph( getBundle( locale ).getString( "report.plugin.goals.intro" ) ); + + boolean hasMavenReport = false; + for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); ) + { + MojoDescriptor mojo = i.next(); + + if ( GeneratorUtils.isMavenReport( mojo.getImplementation(), project ) ) + { + hasMavenReport = true; + } + } + + startTable(); + + String goalColumnName = getBundle( locale ).getString( "report.plugin.goals.column.goal" ); + String isMavenReport = getBundle( locale ).getString( "report.plugin.goals.column.isMavenReport" ); + String descriptionColumnName = getBundle( locale ).getString( "report.plugin.goals.column.description" ); + if ( hasMavenReport ) + { + tableHeader( new String[]{ goalColumnName, isMavenReport, descriptionColumnName } ); + } + else + { + tableHeader( new String[]{ goalColumnName, descriptionColumnName } ); + } + + List mojos = new ArrayList<>(); + mojos.addAll( pluginDescriptor.getMojos() ); + PluginUtils.sortMojos( mojos ); + for ( MojoDescriptor mojo : mojos ) + { + String goalName = mojo.getFullGoalName(); + + /* + * Added ./ to define a relative path + * @see AbstractMavenReportRenderer#getValidHref(java.lang.String) + */ + String goalDocumentationLink = "./" + mojo.getGoal() + "-mojo.html"; + + String description; + if ( StringUtils.isNotEmpty( mojo.getDeprecated() ) ) + { + description = + "" + getBundle( locale ).getString( "report.plugin.goal.deprecated" ) + " " + + GeneratorUtils.makeHtmlValid( mojo.getDeprecated() ); + } + else if ( StringUtils.isNotEmpty( mojo.getDescription() ) ) + { + description = GeneratorUtils.makeHtmlValid( mojo.getDescription() ); + } + else + { + description = getBundle( locale ).getString( "report.plugin.goal.nodescription" ); + } + + sink.tableRow(); + tableCell( createLinkPatternedText( goalName, goalDocumentationLink ) ); + if ( hasMavenReport ) + { + if ( GeneratorUtils.isMavenReport( mojo.getImplementation(), project ) ) + { + sink.tableCell(); + sink.text( getBundle( locale ).getString( "report.plugin.isReport" ) ); + sink.tableCell_(); + } + else + { + sink.tableCell(); + sink.text( getBundle( locale ).getString( "report.plugin.isNotReport" ) ); + sink.tableCell_(); + } + } + tableCell( description, true ); + sink.tableRow_(); + } + + endTable(); + + startSection( getBundle( locale ).getString( "report.plugin.systemrequirements" ) ); + + paragraph( getBundle( locale ).getString( "report.plugin.systemrequirements.intro" ) ); + + startTable(); + + String maven = discoverMavenRequirement( project, requirements ); + sink.tableRow(); + tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.maven" ) ); + tableCell( ( maven != null + ? maven + : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); + sink.tableRow_(); + + String jdk = discoverJdkRequirement( project, requirements ); + sink.tableRow(); + tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.jdk" ) ); + tableCell( + ( jdk != null ? jdk : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); + sink.tableRow_(); + + sink.tableRow(); + tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.memory" ) ); + tableCell( ( StringUtils.isNotEmpty( requirements.getMemory() ) + ? requirements.getMemory() + : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); + sink.tableRow_(); + + sink.tableRow(); + tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.diskspace" ) ); + tableCell( ( StringUtils.isNotEmpty( requirements.getDiskSpace() ) + ? requirements.getDiskSpace() + : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); + sink.tableRow_(); + + if ( requirements.getOthers() != null && requirements.getOthers().size() > 0 ) + { + for ( Iterator it = requirements.getOthers().keySet().iterator(); it.hasNext(); ) + { + String key = it.next().toString(); + + sink.tableRow(); + tableCell( key ); + tableCell( ( StringUtils.isNotEmpty( requirements.getOthers().getProperty( key ) ) + ? requirements.getOthers().getProperty( key ) + : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) ); + sink.tableRow_(); + } + } + endTable(); + + endSection(); + + renderUsageSection( hasMavenReport ); + + endSection(); + } + + /** + * Render the section about the usage of the plugin. + * + * @param hasMavenReport If the plugin has a report or not + */ + private void renderUsageSection( boolean hasMavenReport ) + { + startSection( getBundle( locale ).getString( "report.plugin.usage" ) ); + + // Configuration + sink.paragraph(); + text( getBundle( locale ).getString( "report.plugin.usage.intro" ) ); + sink.paragraph_(); + + StringBuilder sb = new StringBuilder(); + sb.append( "" ).append( '\n' ); + sb.append( " ..." ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( + " " ).append( + '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( + "" ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " ..." ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( + '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( + "" ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " ..." ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + + if ( hasMavenReport ) + { + sb.append( " ..." ).append( '\n' ); + sb.append( + " " ).append( + '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( + "" ).append( '\n' ); + sb.append( " " ).append( pluginDescriptor.getVersion() ).append( "" ).append( + '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " ..." ).append( '\n' ); + sb.append( " " ).append( '\n' ); + sb.append( " " ).append( '\n' ); + } + + sb.append( " ..." ).append( '\n' ); + sb.append( "" ).append( '\n' ); + + verbatimText( sb.toString() ); + + sink.paragraph(); + linkPatternedText( getBundle( locale ).getString( "report.plugin.configuration.end" ) ); + sink.paragraph_(); + + endSection(); + } + + /** + * Try to lookup on the Maven prerequisites property. + * If not specified, uses the value defined by the user. + * + * @param project not null + * @param requirements not null + * @return the Maven version + */ + private static String discoverMavenRequirement( MavenProject project, Requirements requirements ) + { + String maven = requirements.getMaven(); + if ( maven == null ) + { + maven = ( project.getPrerequisites() != null ? project.getPrerequisites().getMaven() : null ); + } + if ( maven == null ) + { + maven = "2.0"; + } + + return maven; + } + + /** + *
      + *
    1. use configured jdk requirement
    2. + *
    3. use target configuration of org.apache.maven.plugins:maven-compiler-plugin
    4. + *
    5. use target configuration of org.apache.maven.plugins:maven-compiler-plugin in + * pluginManagement
    6. + *
    7. use maven.compiler.target property
    8. + *
    + * + * @param project not null + * @param requirements not null + * @return the JDK version + */ + private static String discoverJdkRequirement( MavenProject project, Requirements requirements ) + { + String jdk = requirements.getJdk(); + + if ( jdk != null ) + { + return jdk; + } + + Plugin compiler = getCompilerPlugin( project.getBuild().getPluginsAsMap() ); + if ( compiler == null ) + { + compiler = getCompilerPlugin( project.getPluginManagement().getPluginsAsMap() ); + } + + jdk = getPluginParameter( compiler, "target" ); + if ( jdk != null ) + { + return jdk; + } + + jdk = getPluginParameter( compiler, "release" ); + if ( jdk != null ) + { + return jdk; + } + + // default value + jdk = project.getProperties().getProperty( "maven.compiler.target" ); + if ( jdk != null ) + { + return jdk; + } + + // return "1.5" by default? + + String version = ( compiler == null ) ? null : compiler.getVersion(); + + if ( version != null ) + { + return "Default target for maven-compiler-plugin version " + version; + } + + return "Unknown"; + } + + private static Plugin getCompilerPlugin( Map pluginsAsMap ) + { + return pluginsAsMap.get( "org.apache.maven.plugins:maven-compiler-plugin" ); + } + + private static String getPluginParameter( Plugin plugin, String parameter ) + { + if ( plugin != null ) + { + Xpp3Dom pluginConf = (Xpp3Dom) plugin.getConfiguration(); + + if ( pluginConf != null ) + { + Xpp3Dom target = pluginConf.getChild( parameter ); + + if ( target != null ) + { + return target.getValue(); + } + } + } + + return null; + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/metadata/AddPluginArtifactMetadataMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/metadata/AddPluginArtifactMetadataMojo.java new file mode 100644 index 000000000..3afd87ef2 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/metadata/AddPluginArtifactMetadataMojo.java @@ -0,0 +1,109 @@ +package org.apache.maven.plugin.plugin.metadata; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata; +import org.apache.maven.artifact.repository.metadata.GroupRepositoryMetadata; +import org.apache.maven.artifact.repository.metadata.Versioning; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; + +/** + * Inject any plugin-specific + * artifact metadata to the project's + * artifact, for subsequent installation and deployment. + * It is used: + *
      + *
    1. to add the latest metadata (which is plugin-specific) for shipping alongside the plugin's + * artifact
    2. + *
    3. to define plugin mapping in the group
    4. + *
    + * + * @see ArtifactRepositoryMetadata + * @see GroupRepositoryMetadata + * + * @since 2.0 + */ +@Mojo( name = "addPluginArtifactMetadata", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true ) +public class AddPluginArtifactMetadataMojo + extends AbstractMojo +{ + /** + * The project artifact, which should have the latest metadata added to it. + */ + @Parameter( defaultValue = "${project}", readonly = true ) + private MavenProject project; + + /** + * The prefix for the plugin goal. + */ + @Parameter + private String goalPrefix; + + /** + * Set this to "true" to skip invoking any goals or reports of the plugin. + * + * @since 2.8 + */ + @Parameter( defaultValue = "false", property = "maven.plugin.skip" ) + private boolean skip; + + /** {@inheritDoc} */ + public void execute() + throws MojoExecutionException + { + if ( skip ) + { + getLog().warn( "Execution skipped" ); + return; + } + Artifact projectArtifact = project.getArtifact(); + + Versioning versioning = new Versioning(); + versioning.setLatest( projectArtifact.getVersion() ); + versioning.updateTimestamp(); + ArtifactRepositoryMetadata metadata = new ArtifactRepositoryMetadata( projectArtifact, versioning ); + projectArtifact.addMetadata( metadata ); + + GroupRepositoryMetadata groupMetadata = new GroupRepositoryMetadata( project.getGroupId() ); + groupMetadata.addPluginMapping( getGoalPrefix(), project.getArtifactId(), project.getName() ); + + projectArtifact.addMetadata( groupMetadata ); + } + + /** + * @return the goal prefix parameter or the goal prefix from the Plugin artifactId. + */ + private String getGoalPrefix() + { + if ( goalPrefix == null ) + { + goalPrefix = PluginDescriptor.getGoalPrefixFromArtifactId( project.getArtifactId() ); + } + + return goalPrefix; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/MNG6109PluginDescriptorBuilder.java b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/MNG6109PluginDescriptorBuilder.java new file mode 100644 index 000000000..09743023c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/MNG6109PluginDescriptorBuilder.java @@ -0,0 +1,62 @@ +package org.apache.maven.plugins.plugin.descriptor; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.PlexusConfigurationException; + +/** + * Reads the plugin descriptor and adds the fix for MNG-6109 when using Maven-3.3.9 and before. + * Class can be removed once Maven 3.5.0 is the prerequisite for this plugin. + * + * @author Robert Scholte + * @since 3.5.1 + */ +public class MNG6109PluginDescriptorBuilder extends PluginDescriptorBuilder +{ + + @Override + public MojoDescriptor buildComponentDescriptor( PlexusConfiguration c, PluginDescriptor pluginDescriptor ) + throws PlexusConfigurationException + { + MojoDescriptor mojoDescriptor = super.buildComponentDescriptor( c, pluginDescriptor ); + + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + + PlexusConfiguration[] parameterConfigurations = c.getChild( "parameters" ).getChildren( "parameter" ); + + for ( PlexusConfiguration d : parameterConfigurations ) + { + String parameterName = d.getChild( "name" ).getValue(); + Parameter pd = (Parameter) mojoDescriptor.getParameterMap().get( parameterName ); + + String parameterSince = d.getChild( "since" ).getValue(); + pd.setSince( parameterSince ); + } + + return mojoDescriptor; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/mdo/pluginRequirements.mdo b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/mdo/pluginRequirements.mdo new file mode 100644 index 000000000..9516b8153 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/mdo/pluginRequirements.mdo @@ -0,0 +1,78 @@ + + + + + + pluginRequirements + PluginRequirements + + + + package + org.apache.maven.plugin.plugin + + + + + Requirements + Plugin requirements. + 1.0.0 + + + maven + The minimum version of Maven to run this plugin. + 1.0.0 + String + true + + + jdk + The minimum version of the JDK to run this plugin. + 1.0.0 + String + true + + + memory + The minimum memory needed to run this plugin. + 1.0.0 + String + + + diskSpace + The minimum diskSpace needed to run this plugin. + 1.0.0 + String + + + others + Others requirements properties. + 1.0.0 + Properties + + String + * + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report.properties new file mode 100644 index 000000000..01ee9b388 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report.properties @@ -0,0 +1,48 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +report.plugin.name=Plugin Documentation +report.plugin.description=This report provides goals and parameters documentation of a plugin. +report.plugin.title=Plugin Documentation + +report.plugin.goals.nogoal=No goals defined in this plugin. +report.plugin.goals.intro=Goals available for this plugin: +report.plugin.goals.column.goal=Goal +report.plugin.goals.column.isMavenReport=Report? +report.plugin.goals.column.description=Description +report.plugin.goal.nodescription=No description. +report.plugin.goal.deprecated=Deprecated. + +report.plugin.systemrequirements=System Requirements +report.plugin.systemrequirements.intro=The following specifies the minimum requirements to run this Maven plugin: +report.plugin.systemrequirements.nominimum= No minimum requirement. +report.plugin.systemrequirements.maven=Maven +report.plugin.systemrequirements.jdk=JDK +report.plugin.systemrequirements.memory=Memory +report.plugin.systemrequirements.diskspace=Disk Space + +report.plugin.usage=Usage +report.plugin.usage.intro=You should specify the version in your project's plugin configuration: +report.plugin.usage.pluginManagement=To define the plugin version in your parent POM +report.plugin.usage.plugins=To use the plugin goals in your POM or parent POM +report.plugin.usage.reporting=To use the report goals in your POM or parent POM +report.plugin.configuration.end=For more information, see {"Guide to Configuring Plug-ins", http://maven.apache.org/guides/mini/guide-configuring-plugins.html} + +report.plugin.isReport=Yes +report.plugin.isNotReport=No diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_de.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_de.properties new file mode 100644 index 000000000..01736e112 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_de.properties @@ -0,0 +1,48 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +report.plugin.name=Plugin-Dokumentation +report.plugin.description=Dieser Bericht dokumentiert die Goals des Plugins und deren Parameter. +report.plugin.title=Plugin-Dokumentation + +report.plugin.goals.nogoal=Keine Goals verf\u00fcgbar. +report.plugin.goals.intro=Verf\u00fcgbare Goals dieses Plugins: +report.plugin.goals.column.goal=Goal +report.plugin.goals.column.isMavenReport=Bericht? +report.plugin.goals.column.description=Beschreibung +report.plugin.goal.nodescription=Keine Beschreibung. +report.plugin.goal.deprecated=Missbilligt. + +report.plugin.systemrequirements=Systemvoraussetzungen +report.plugin.systemrequirements.intro=Die folgende Tabelle listet die Mindestanforderungen zum Ausf\u00fchren dieses Plugins auf: +report.plugin.systemrequirements.nominimum=Keine Mindestanforderung. +report.plugin.systemrequirements.maven=Maven +report.plugin.systemrequirements.jdk=JDK +report.plugin.systemrequirements.memory=Arbeitsspeicher +report.plugin.systemrequirements.diskspace=Festplatte + +report.plugin.usage=Gebrauch +report.plugin.usage.intro=Geben Sie die gew\u00fcnschte Version einfach in der Plugin-Konfiguration Ihres Projekts an: +report.plugin.usage.pluginManagement=Zum Definieren der Plugin-Version in der Eltern-POM +report.plugin.usage.plugins=Zum Verwenden der Plugin-Goals w\u00e4hrend des Build-Vorgangs eines Projekts +report.plugin.usage.reporting=Zum Erzeugen der Berichte f\u00fcr die Projektdokumentation +report.plugin.configuration.end=F\u00fcr weitergehende Informationen lesen Sie bitte den Artikel {"Guide to Configuring Plug-ins", http://maven.apache.org/guides/mini/guide-configuring-plugins.html}. + +report.plugin.isReport=Ja +report.plugin.isNotReport=Nein diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_en.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_en.properties new file mode 100644 index 000000000..96cf40750 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_en.properties @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# NOTE: +# This bundle is intentionally empty because English strings are provided by the base bundle via the parent chain. It +# must be provided nevertheless such that a request for locale "en" will not errorneously pick up the bundle for the +# JVM's default locale (which need not be "en"). See the method javadoc about +# ResourceBundle.getBundle(String, Locale, ClassLoader) +# for a full description of the lookup strategy. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_fr.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_fr.properties new file mode 100644 index 000000000..d71d840f9 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_fr.properties @@ -0,0 +1,48 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +report.plugin.name=Documentation du plugin +report.plugin.description=Ce rapport fournit de la documentation sur les goals et les param\u00eatres d'un plugin. +report.plugin.title=Documentation du plugin + +report.plugin.goals.nogoal=Aucun goal disponible. +report.plugin.goals.intro=Goals disponibles pour ce plugin : +report.plugin.goals.column.goal=Goal +report.plugin.goals.column.isMavenReport=Rapport? +report.plugin.goals.column.description=Description +report.plugin.goal.nodescription=Pas de description. +report.plugin.goal.deprecated=Obsol\u00e8te. + +report.plugin.systemrequirements=Exigences Syst\u00e8mes +report.plugin.systemrequirements.intro=Ce qui suit sp\u00e9cifie les exigences minimales pour ex\u00e9cuter ce plugin Maven : +report.plugin.systemrequirements.nominimum= Aucune exigence minimale. +report.plugin.systemrequirements.maven=Maven +report.plugin.systemrequirements.jdk=JDK +report.plugin.systemrequirements.memory=M\u00e9moire +report.plugin.systemrequirements.diskspace=Espace Disque + +report.plugin.usage=Utilisation +report.plugin.usage.intro=Vous devez sp\u00e9cifier la version dans la configuration de votre projet : +report.plugin.usage.pluginManagement=Pour d\u00e9finir la version du plugin dans le POM parent +report.plugin.usage.plugins=Pour utiliser les goals du plugin dans votre POM ou POM parent +report.plugin.usage.reporting=Pour utiliser les goals de rapports dans votre POM ou POM parent +report.plugin.configuration.end=Pour plus d'informations, consultez {"Guide to Configuring Plug-ins", http://maven.apache.org/guides/mini/guide-configuring-plugins.html} + +report.plugin.isReport=Oui +report.plugin.isNotReport=Non diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_sv.properties b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_sv.properties new file mode 100644 index 000000000..cf04795ad --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/main/resources/plugin-report_sv.properties @@ -0,0 +1,48 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +report.plugin.name=Plugindokumentation +report.plugin.description=Denna rapport tillhandahåller mål- och parameterdokumentation för en plugin. +report.plugin.title=Plugindokumentation + +report.plugin.goals.nogoal=Inga mål tillgängliga ännu. +report.plugin.goals.intro=Tillgängliga mål för denna plugin: +report.plugin.goals.column.goal=Mål +report.plugin.goals.column.isMavenReport=Rapport? +report.plugin.goals.column.description=Beskrivning +report.plugin.goal.nodescription=Ingen beskrivning. +report.plugin.goal.deprecated=Föråldrat. + +report.plugin.systemrequirements=Systemkrav +report.plugin.systemrequirements.intro=Följande minimikrav ställs för att köra denna Maven plugin: +report.plugin.systemrequirements.nominimum= Inga minimikrav. +report.plugin.systemrequirements.maven=Maven +report.plugin.systemrequirements.jdk=JDK +report.plugin.systemrequirements.memory=Minne +report.plugin.systemrequirements.diskspace=Diskutrymme + +report.plugin.usage=Användning +report.plugin.usage.intro=Du bör specificera versionen i ditt projekts pluginkonfiguration: +report.plugin.usage.pluginManagement=För att definiera pluginversion i din föräldra-POM +report.plugin.usage.plugins=För att använda plugin-målen i din POM eller föräldra-POM +report.plugin.usage.reporting=För att använda rapport-målen i din POM eller föräldra-POM +report.plugin.configuration.end=För mer information, läs {"Guide to Configuring Plug-ins", http://maven.apache.org/guides/mini/guide-configuring-plugins.html} (på engelska). + +report.plugin.isReport=Ja +report.plugin.isNotReport=Nej diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/ant-mojo.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/ant-mojo.apt.vm new file mode 100644 index 000000000..a5be6d8cd --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/ant-mojo.apt.vm @@ -0,0 +1,80 @@ + ------ + Writing an Ant Maven Plugin + ------ + Olivier Lamy + ------ + 2012-05-14 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Writing an Ant Maven Plugin + + You can write Maven plugins based on Ant scripts. + +* Pom configuration + ++------------+ + + ... + + + org.apache.maven + maven-script-ant + 2.2.1 + + + ... + + + + org.apache.maven.plugins + maven-plugin-plugin + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-ant + ${project.version} + + + + + + ... + ++------------+ + +* Files structure + + The Ant plugin consists in two files. If you want to create a <<>> plugin, you must have: + + * <<>>: contains Mojo(s) descriptor informations, + + * <<>>: contains the Ant xml to execute. + +** Ant Mojos descriptor + +%{snippet|id=ant-mojo|url=http://svn.apache.org/repos/asf/maven/plugin-tools/trunk/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.mojos.xml} + +** Ant script + +%{snippet|id=ant-build|url=http://svn.apache.org/repos/asf/maven/plugin-tools/trunk/maven-plugin-plugin/src/it/ant-basic/src/main/scripts/touch.build.xml} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/beanshell-mojo.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/beanshell-mojo.apt.vm new file mode 100644 index 000000000..451f21b99 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/beanshell-mojo.apt.vm @@ -0,0 +1,73 @@ + ------ + Writing a Beanshell Maven Plugin + ------ + Olivier Lamy + ------ + 2012-05-14 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Writing a Beanshell Maven Plugin + + You can write a Maven plugin using {{{http://www.beanshell.org}Beanshell}}. + +* Pom configuration + ++------------------ + + + bsh + bsh + 1.3.0 + + + org.apache.maven + maven-script-beanshell + 2.2.1 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-beanshell + ${project.version} + + + + + ++------------------ + +* Beanshell plugin + + A Beanshell mojo uses same javadoc tags as a Java mojo with javadoc tags. + + Sample script content: + +%{snippet|id=beanshell-mojo|url=http://svn.apache.org/repos/asf/maven/plugin-tools/trunk/maven-plugin-plugin/src/it/beanshell-simple/src/main/scripts/touch.bsh} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-descriptor.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-descriptor.apt.vm new file mode 100644 index 000000000..83cc6bead --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-descriptor.apt.vm @@ -0,0 +1,118 @@ + ------ + Configuring Generation of Plugin Descriptor + ------ + Maria Odea Ching + ------ + 2008-02-01 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Configuring Generation of Plugin Descriptor + + To configure the generation of the plugin descriptor, add the following to the project's POM: + ++-----+ + + ... + + + + org.apache.maven.plugins + maven-plugin-plugin + ${project.version} + + plugin + target/dir + + + + ... + + ... + ++-----+ + + The <<>> parameter will set the goal prefix for the plugin that is specified in the descriptor. The <<>> + parameter, on the other hand, specifies the target location of the generated plugin descriptor. + +* Example + + For instance, if we make reference on <<>> from <<>> which is generated by the + Maven Archetype Plugin, i.e.: + +----- +mvn archetype:create \ + -DgroupId=org.apache.maven.plugin.my \ + -DartifactId=maven-my-plugin \ + -DarchetypeArtifactId=maven-archetype-mojo +----- + + The plugin descriptor generated by <<>> should be: + +----- + + + org.apache.maven.plugin.my + maven-my-plugin + 1.0-SNAPSHOT + my + false + true + + + touch + Goal which touches a timestamp file. + false + true + false + false + false + true + process-sources + org.apache.maven.plugin.my.MyMojo + java + per-lookup + once-per-session + + + outputDirectory + java.io.File + true + true + Location of the file. + + + + \${project.build.directory} + + + + + + org.apache.maven + maven-plugin-api + jar + 2.0 + + + +----- \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-help.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-help.apt.vm new file mode 100644 index 000000000..b6dfd976e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-help.apt.vm @@ -0,0 +1,58 @@ + ------ + Configuring Generation of Help Mojo + ------ + Vincent Siveton + ------ + 2008-01-01 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Configuring Generation of Help Mojo + + To configure the generation of a <<>> mojo, add the following to the project's POM: + ++-----+ + + ... + + + + org.apache.maven.plugins + maven-plugin-plugin + ${project.version} + + + generated-helpmojo + + helpmojo + + + + + + ... + + ... + ++-----+ + + The mojo is generated by default in <<<$\{project.build.directory\}/generated-sources/plugin>>>. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-report.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-report.apt.vm new file mode 100644 index 000000000..10d90f54b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/generate-report.apt.vm @@ -0,0 +1,50 @@ + ------ + Configuring Generation of Documentation Reports + ------ + Vincent Siveton + ------ + 2008-01-01 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Configuring Generation of Documentation Reports + + To configure the generation of the documentation reports, add the following to the project's POM: + ++-----+ + + ... + + + + org.apache.maven.plugins + maven-plugin-plugin + ${project.version} + + + ... + + ... + ++-----+ + + The documentation is generated by default in <<<$\{project.build.directory\}/site>>>. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm new file mode 100644 index 000000000..b18271d34 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm @@ -0,0 +1,126 @@ + ------ + Using Plugin Tools Java5 Annotations + ------ + Olivier Lamy + ------ + 2012-05-14 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ https://maven.apache.org/doxia/references/apt-format.html + +Using Plugin Tools Java Annotations + + Since version 3.0 of the maven-plugin-plugin, you can use Java5 annotations to generate the + plugin descriptor file. + + <> With annotations, your Mojo super class does not have to be in the same project. Provided that the super class also uses annotations, it + can now come from reactor projects or external dependencies. By default all dependencies are scanned, but this can be reduced with the <<>> + parameter. As javadoc doclets are still useful for <<<@since>>>, <<<@deprecated>>> and comments, the sources are still scanned. So if you use an external + dependency, you must still provide an artifact with sources (<<>> classifier) to provide documentation (the tooling will skip error if this artifact + sources is missing). + +* Annotations + + Information for plugin descriptor generation is specified using 4 annotations: + + * 2 class-level annotations: + + * <<<@Mojo>>>: This annotation will mark your class as a Mojo, + + * <<<@Execute>>>: Used if your Mojo needs to fork a lifecycle, + + [] + + * 2 field-level annotations: + + * <<<@Parameter>>>: Used to configure your Mojo parameters, + + * <<<@Component>>>: Used to configure injection of Plexus components or Maven context components. + + [] + + [] + + For more information on these annotations, see the + {{{../../maven-plugin-tools-annotations/index.html#Supported_Annotations}corresponding documentation}}. + + Notice that Plugin Tools Java Annotations are named after Plugin Tools Javadoc Tags + with following little differences: + +*-------------------------------+---------------+ +|| {{{../../maven-plugin-tools-java/index.html}Plugin Tools Javadoc Tags}} || {{{../../maven-plugin-tools-annotations/index.html}Plugin Tools Java Annotation}} || +*-------------------------------+---------------+ +| <<<@goal "goal-name">>> | <<<@Mojo( name = "goal-name" )>>> +*-------------------------------+---------------+ +| <<<@phase "\">>> | <<<@Mojo( defaultPhase = LifecyclePhase.\ )>>> +*-------------------------------+---------------+ + +* POM configuration + + To be able to use these Java annotations, you need to add some configuration to your plugin POM: + + * add <<>> dependency, preferably with <<>> scope, + + * override Maven core's <<>> execution phase to <<>>, + + [] + ++-----+ + + ... + maven-plugin + ... + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${project.version} + true + + + ... + + + + org.apache.maven.plugins + maven-plugin-plugin + ${project.version} + + + default-descriptor + process-classes + + + + help-goal + + helpmojo + + + + + + ... + + ... + ++-----+ diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/index.apt new file mode 100644 index 000000000..b4685d0de --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/index.apt @@ -0,0 +1,83 @@ + ------ + Introduction + ------ + Maria Odea Ching + ------ + 2008-01-01 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Plugin + + The Maven Plugin Plugin is used to create a {{{/ref/current/maven-plugin-api/plugin.html}Maven plugin descriptor}} for any + {{{/general.html#What_is_a_Mojo}Mojo}}'s found in the source tree, to include in the JAR. + It is also used to generate report files for the Mojos as well as the artifact metadata and generating a generic help goal. + +* Goals Overview + + The Plugin Plugin has six goals: + + * {{{./descriptor-mojo.html}plugin:descriptor}} generates a plugin descriptor, + + * {{{./report-mojo.html}plugin:report}} generates the plugin documentation: one overview report + (see {{{./plugin-info.html}example}}) and documentation for each plugin's goal (mojo), + + * {{{./addPluginArtifactMetadata-mojo.html}plugin:addPluginArtifactMetadata}} injects any plugin-specific artifact + metadata to the project's artifact, for subsequent installation and deployment, + + * {{{./helpmojo-mojo.html}plugin:helpmojo}} generates a help mojo which describes all mojos in a plugin. + + [] + +* Usage + + General instructions on how to use the Plugin Plugin can be found on the {{{./usage.html}usage page}}. Some more + specific use cases are described in the examples given below. Last but not least, users occasionally contribute + additional examples, tips or errata to the + {{{http://docs.codehaus.org/display/MAVENUSER/Plugin+Plugin}plugin's wiki page}}. + + In case you still have questions regarding the plugin's usage, please have a look at the {{{./faq.html}FAQ}} and feel + free to contact the {{{./mailing-lists.html}user mailing list}}. The posts to the mailing list are archived and could + already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching + the {{{./mailing-lists.html}mail archive}}. + + If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in our + {{{./issue-management.html}issue tracker}}. When creating a new issue, please provide a comprehensive description of your + concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason, + entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. + Of course, patches are welcome, too. Contributors can check out the project from our + {{{./scm.html}source repository}} and will find supplementary information in the + {{{/guides/development/guide-helping.html}guide to helping with Maven}}. + +* Examples + + The following examples shows how to use the Plugin Plugin in more advanced usecases: + + * {{{./examples/using-annotations.html}Using Plugin Tools Java5 annotations for your Mojo}} + + * {{{./examples/generate-descriptor.html}Configuring Generation of Plugin Descriptor}} + + * {{{./examples/generate-report.html}Configuring Generation of Documentation Reports}} + + * {{{./examples/generate-help.html}Configuring Generation of Help Mojo}} + + [] diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/multiple-language-support.apt b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/multiple-language-support.apt new file mode 100644 index 000000000..43e66e54b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/multiple-language-support.apt @@ -0,0 +1,53 @@ + --- + Multiple Language Support for the Plugin Plugin: Redesign Notes + --- + John Casey + --- + 2005-02-09 + --- + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +<> + +*Abstract + + The Plugin Plugin needs to be refactored in order to support multiple mojo + implementation languages. This document will detail the steps needed to + add this functionality. + +*Current Status + + The Plugin Plugin currently calls out to a set of generators in the + maven-plugin-tools library, which in turn uses QDox to generate various things + based on annotations in the java source code. + +*Refactored Design + + The new design will have a generator-manager which is a component that the + plugin mojos will lookup. This component will have access to a mapping of all + generators and the language they're registered for. It'll iterate through the + mappings, and extract mojo descriptors from all relevant scripts/sources using + each language's registered generator. Results from each generator will be + centrally aggregated by the generator-manager. After all generators have run, + the generator-manager will call another class (depending on what it's meant to + produce) to take all the aggregated mojo descriptors and produce a result + (such as <<>> file for the project). \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/usage.apt b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/usage.apt new file mode 100644 index 000000000..0e4241550 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/apt/usage.apt @@ -0,0 +1,87 @@ + ------ + Usage + ------ + Maria Odea Ching + Vincent Siveton + ------ + 2008-01-01 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Usage + + The Plugin Plugin is generally used for Maven plugins. Its goals are bound to different phases in the build life cycle. + So when you execute a specific phase, the Plugin Plugin goals bound to it are also executed. Aside from this, each goal can + also be explicitly executed from the command line. + +* The <<>> Goal + + The <<>> goal is bound to the <<>> phase since 3.0; it was bound to <<>> phase previously. + This goal generates the plugin descriptor, which is an xml file that contains information about the plugin + (see {{{/ref/current/maven-plugin-api/plugin.html}descriptor's reference}}). + + For example, you want to create an archive of your plugin and you execute + ++-----+ +mvn package ++-----+ + + You will see that the <<>> file is generated in the <<>> directory of your project. The file is + also bundled in the generated JAR file. + + To explicitly execute the <<>> goal, type the following in the command line: + ++-----+ +mvn plugin:descriptor ++-----+ + +* The <<>> Goal + + To generate the documentation of your plugin, execute the following on the command line: + ++-----+ +mvn plugin:report ++-----+ + + The xdoc files, one per goal, are generated by default in <<<$\{project.build.directory\}/generated-site/xdoc>>>, + and an overview is generated in the site output. + + If you add the plugin to the <<>> section of your pom, you'll get the full report as html with <<>>. + +* The <<>> Goal + + The <<>> goal, on the other hand, is bound to the <<>> phase of the build life cycle. + This goal will add the metadata to the project artifact. To do this, execute + ++-----+ +mvn package ++-----+ + +* The <<>> Goal + + To generate a <<>> for the mojos of your plugin, execute the following on the command line: + ++-----+ +mvn plugin:helpmojo ++-----+ + + The mojo is generated by default in <<<$\{project.build.directory\}/generated-sources/plugin>>>. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/site.xml new file mode 100644 index 000000000..367b87bd5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-plugin/src/site/site.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/pom.xml new file mode 100644 index 000000000..e928d17fa --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/pom.xml @@ -0,0 +1,159 @@ + + + + 4.0.0 + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.6.1-SNAPSHOT + + + maven-plugin-tools-annotations + + Maven Plugin Tool for Java with Annotations + Descriptor extractor for plugins written in Java with Java annotations. + + + + + org.apache.maven + maven-plugin-api + + + org.apache.maven + maven-core + + + org.apache.maven + maven-model + + + org.apache.maven + maven-artifact + + + org.apache.maven + maven-compat + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + org.apache.maven.plugin-tools + maven-plugin-annotations + + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-component-annotations + + + junit + junit + + + + + org.sonatype.sisu + sisu-inject-plexus + 1.4.2 + + + org.codehaus.plexus + plexus-archiver + + + + org.ow2.asm + asm + + + + com.thoughtworks.qdox + qdox + + + + org.codehaus.plexus + plexus-compiler-manager + 1.8.6 + + + org.codehaus.plexus + plexus-component-api + + + test + + + org.mockito + mockito-core + test + + + junit + junit + test + + + org.easytesting + fest-assert + 1.4 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + org.codehaus.plexus + plexus-component-metadata + + + org.apache.maven.plugins + maven-source-plugin + + + + test-jar-no-fork + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java new file mode 100644 index 000000000..7b9afe7ab --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java @@ -0,0 +1,740 @@ +package org.apache.maven.tools.plugin.extractor.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.plugin.descriptor.DuplicateParameterException; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScannerRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.manager.ArchiverManager; +import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; + +/** + * JavaMojoDescriptorExtractor, a MojoDescriptor extractor to read descriptors from java classes with annotations. + * Notice that source files are also parsed to get description, since and deprecation information. + * + * @author Olivier Lamy + * @since 3.0 + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-annotations" ) +public class JavaAnnotationsMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor +{ + + @org.codehaus.plexus.component.annotations.Requirement + private MojoAnnotationsScanner mojoAnnotationsScanner; + + @org.codehaus.plexus.component.annotations.Requirement + private ArtifactResolver artifactResolver; + + @org.codehaus.plexus.component.annotations.Requirement + private ArtifactFactory artifactFactory; + + @org.codehaus.plexus.component.annotations.Requirement + private ArchiverManager archiverManager; + + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Map mojoAnnotatedClasses = scanAnnotations( request ); + + Map javaClassesMap = scanJavadoc( request, mojoAnnotatedClasses.values() ); + + populateDataFromJavadoc( mojoAnnotatedClasses, javaClassesMap ); + + return toMojoDescriptors( mojoAnnotatedClasses, request.getPluginDescriptor() ); + } + + private Map scanAnnotations( PluginToolsRequest request ) + throws ExtractionException + { + MojoAnnotationsScannerRequest mojoAnnotationsScannerRequest = new MojoAnnotationsScannerRequest(); + + File output = new File( request.getProject().getBuild().getOutputDirectory() ); + mojoAnnotationsScannerRequest.setClassesDirectories( Arrays.asList( output ) ); + + mojoAnnotationsScannerRequest.setDependencies( request.getDependencies() ); + + mojoAnnotationsScannerRequest.setProject( request.getProject() ); + + return mojoAnnotationsScanner.scan( mojoAnnotationsScannerRequest ); + } + + private Map scanJavadoc( PluginToolsRequest request, + Collection mojoAnnotatedClasses ) + throws ExtractionException + { + // found artifact from reactors to scan sources + // we currently only scan sources from reactors + List mavenProjects = new ArrayList<>(); + + // if we need to scan sources from external artifacts + Set externalArtifacts = new HashSet<>(); + + for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses ) + { + if ( StringUtils.equals( mojoAnnotatedClass.getArtifact().getArtifactId(), + request.getProject().getArtifact().getArtifactId() ) ) + { + continue; + } + + if ( !isMojoAnnnotatedClassCandidate( mojoAnnotatedClass ) ) + { + // we don't scan sources for classes without mojo annotations + continue; + } + + MavenProject mavenProject = + getFromProjectReferences( mojoAnnotatedClass.getArtifact(), request.getProject() ); + + if ( mavenProject != null ) + { + mavenProjects.add( mavenProject ); + } + else + { + externalArtifacts.add( mojoAnnotatedClass.getArtifact() ); + } + } + + Map javaClassesMap = new HashMap(); + + // try to get artifact with sources classifier, extract somewhere then scan for @since, @deprecated + for ( Artifact artifact : externalArtifacts ) + { + // parameter for test-sources too ?? olamy I need that for it test only + if ( StringUtils.equalsIgnoreCase( "tests", artifact.getClassifier() ) ) + { + javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "test-sources" ) ); + } + else + { + javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "sources" ) ); + } + + } + + for ( MavenProject mavenProject : mavenProjects ) + { + javaClassesMap.putAll( discoverClasses( request.getEncoding(), mavenProject ) ); + } + + javaClassesMap.putAll( discoverClasses( request ) ); + + return javaClassesMap; + } + + private boolean isMojoAnnnotatedClassCandidate( MojoAnnotatedClass mojoAnnotatedClass ) + { + return mojoAnnotatedClass != null && mojoAnnotatedClass.hasAnnotations(); + } + + protected Map discoverClassesFromSourcesJar( Artifact artifact, PluginToolsRequest request, + String classifier ) + throws ExtractionException + { + try + { + Artifact sourcesArtifact = + artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(), + artifact.getVersion(), artifact.getType(), classifier ); + + artifactResolver.resolve( sourcesArtifact, request.getRemoteRepos(), request.getLocal() ); + + if ( sourcesArtifact.getFile() == null || !sourcesArtifact.getFile().exists() ) + { + // could not get artifact sources + return Collections.emptyMap(); + } + + // extract sources to target/maven-plugin-plugin-sources/${groupId}/${artifact}/sources + File extractDirectory = new File( request.getProject().getBuild().getDirectory(), + "maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/" + + sourcesArtifact.getArtifactId() + "/" + sourcesArtifact.getVersion() + + "/" + sourcesArtifact.getClassifier() ); + extractDirectory.mkdirs(); + + UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" ); + unArchiver.setSourceFile( sourcesArtifact.getFile() ); + unArchiver.setDestDirectory( extractDirectory ); + unArchiver.extract(); + + return discoverClasses( request.getEncoding(), Arrays.asList( extractDirectory ), + request.getDependencies() ); + } + catch ( ArtifactResolutionException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + catch ( ArtifactNotFoundException e ) + { + //throw new ExtractionException( e.getMessage(), e ); + getLogger().debug( "skip ArtifactNotFoundException:" + e.getMessage() ); + getLogger().warn( + "Unable to get sources artifact for " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + + artifact.getVersion() + ". Some javadoc tags (@since, @deprecated and comments) won't be used" ); + return Collections.emptyMap(); + } + catch ( NoSuchArchiverException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + } + + /** + * from sources scan to get @since and @deprecated and description of classes and fields. + * + * @param mojoAnnotatedClasses + * @param javaClassesMap + */ + protected void populateDataFromJavadoc( Map mojoAnnotatedClasses, + Map javaClassesMap ) + { + + for ( Map.Entry entry : mojoAnnotatedClasses.entrySet() ) + { + JavaClass javaClass = javaClassesMap.get( entry.getKey() ); + if ( javaClass == null ) + { + continue; + } + + // populate class-level content + MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo(); + if ( mojoAnnotationContent != null ) + { + mojoAnnotationContent.setDescription( javaClass.getComment() ); + + DocletTag since = findInClassHierarchy( javaClass, "since" ); + if ( since != null ) + { + mojoAnnotationContent.setSince( since.getValue() ); + } + + DocletTag deprecated = findInClassHierarchy( javaClass, "deprecated" ); + if ( deprecated != null ) + { + mojoAnnotationContent.setDeprecated( deprecated.getValue() ); + } + } + + Map fieldsMap = extractFieldParameterTags( javaClass, javaClassesMap ); + + // populate parameters + Map parameters = + getParametersParentHierarchy( entry.getValue(), new HashMap(), + mojoAnnotatedClasses ); + parameters = new TreeMap<>( parameters ); + for ( Map.Entry parameter : parameters.entrySet() ) + { + JavaField javaField = fieldsMap.get( parameter.getKey() ); + if ( javaField == null ) + { + continue; + } + + ParameterAnnotationContent parameterAnnotationContent = parameter.getValue(); + parameterAnnotationContent.setDescription( javaField.getComment() ); + + DocletTag deprecated = javaField.getTagByName( "deprecated" ); + if ( deprecated != null ) + { + parameterAnnotationContent.setDeprecated( deprecated.getValue() ); + } + + DocletTag since = javaField.getTagByName( "since" ); + if ( since != null ) + { + parameterAnnotationContent.setSince( since.getValue() ); + } + } + + // populate components + Map components = entry.getValue().getComponents(); + for ( Map.Entry component : components.entrySet() ) + { + JavaField javaField = fieldsMap.get( component.getKey() ); + if ( javaField == null ) + { + continue; + } + + ComponentAnnotationContent componentAnnotationContent = component.getValue(); + componentAnnotationContent.setDescription( javaField.getComment() ); + + DocletTag deprecated = javaField.getTagByName( "deprecated" ); + if ( deprecated != null ) + { + componentAnnotationContent.setDeprecated( deprecated.getValue() ); + } + + DocletTag since = javaField.getTagByName( "since" ); + if ( since != null ) + { + componentAnnotationContent.setSince( since.getValue() ); + } + } + + } + + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass, + Map javaClassesMap ) + { + Map rawParams = new TreeMap(); + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + if ( superClass.getFields().size() > 0 ) + { + rawParams = extractFieldParameterTags( superClass, javaClassesMap ); + } + // maybe sources comes from scan of sources artifact + superClass = javaClassesMap.get( superClass.getFullyQualifiedName() ); + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass, javaClassesMap ); + } + } + else + { + + rawParams = new TreeMap<>(); + } + + for ( JavaField field : javaClass.getFields() ) + { + rawParams.put( field.getName(), field ); + } + + return rawParams; + } + + protected Map discoverClasses( final PluginToolsRequest request ) + { + return discoverClasses( request.getEncoding(), request.getProject() ); + } + + @SuppressWarnings( "unchecked" ) + protected Map discoverClasses( final String encoding, final MavenProject project ) + { + List sources = new ArrayList<>(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + sources.add( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) + && generatedPlugin.exists() ) + { + sources.add( generatedPlugin ); + } + + return discoverClasses( encoding, sources, project.getArtifacts() ); + } + + protected Map discoverClasses( final String encoding, List sourceDirectories, + Set artifacts ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( encoding ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( artifacts.size() ); + for ( Artifact artifact : artifacts ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + for ( File source : sourceDirectories ) + { + builder.addSourceTree( source ); + } + + Collection javaClasses = builder.getClasses(); + + if ( javaClasses == null || javaClasses.size() < 1 ) + { + return Collections.emptyMap(); + } + + Map javaClassMap = new HashMap<>( javaClasses.size() ); + + for ( JavaClass javaClass : javaClasses ) + { + javaClassMap.put( javaClass.getFullyQualifiedName(), javaClass ); + } + + return javaClassMap; + } + + private List toMojoDescriptors( Map mojoAnnotatedClasses, + PluginDescriptor pluginDescriptor ) + throws DuplicateParameterException, InvalidParameterException + { + List mojoDescriptors = new ArrayList<>( mojoAnnotatedClasses.size() ); + for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() ) + { + // no mojo so skip it + if ( mojoAnnotatedClass.getMojo() == null ) + { + continue; + } + + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + + //mojoDescriptor.setRole( mojoAnnotatedClass.getClassName() ); + //mojoDescriptor.setRoleHint( "default" ); + mojoDescriptor.setImplementation( mojoAnnotatedClass.getClassName() ); + mojoDescriptor.setLanguage( "java" ); + + MojoAnnotationContent mojo = mojoAnnotatedClass.getMojo(); + + mojoDescriptor.setDescription( mojo.getDescription() ); + mojoDescriptor.setSince( mojo.getSince() ); + mojo.setDeprecated( mojo.getDeprecated() ); + + mojoDescriptor.setProjectRequired( mojo.requiresProject() ); + + mojoDescriptor.setRequiresReports( mojo.requiresReports() ); + + mojoDescriptor.setComponentConfigurator( mojo.configurator() ); + + mojoDescriptor.setInheritedByDefault( mojo.inheritByDefault() ); + + mojoDescriptor.setInstantiationStrategy( mojo.instantiationStrategy().id() ); + + mojoDescriptor.setAggregator( mojo.aggregator() ); + mojoDescriptor.setDependencyResolutionRequired( mojo.requiresDependencyResolution().id() ); + mojoDescriptor.setDependencyCollectionRequired( mojo.requiresDependencyCollection().id() ); + + mojoDescriptor.setDirectInvocationOnly( mojo.requiresDirectInvocation() ); + mojoDescriptor.setDeprecated( mojo.getDeprecated() ); + mojoDescriptor.setThreadSafe( mojo.threadSafe() ); + + ExecuteAnnotationContent execute = findExecuteInParentHierarchy( mojoAnnotatedClass, mojoAnnotatedClasses ); + if ( execute != null ) + { + mojoDescriptor.setExecuteGoal( execute.goal() ); + mojoDescriptor.setExecuteLifecycle( execute.lifecycle() ); + if ( execute.phase() != null ) + { + mojoDescriptor.setExecutePhase( execute.phase().id() ); + } + } + + mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() ); + // ??? + //mojoDescriptor.alwaysExecute(mojo.a) + + mojoDescriptor.setGoal( mojo.name() ); + mojoDescriptor.setOnlineRequired( mojo.requiresOnline() ); + + mojoDescriptor.setPhase( mojo.defaultPhase().id() ); + + // Parameter annotations + Map parameters = + getParametersParentHierarchy( mojoAnnotatedClass, new HashMap(), + mojoAnnotatedClasses ); + + for ( ParameterAnnotationContent parameterAnnotationContent : new TreeSet<>( parameters.values() ) ) + { + org.apache.maven.plugin.descriptor.Parameter parameter = + new org.apache.maven.plugin.descriptor.Parameter(); + String name = + StringUtils.isEmpty( parameterAnnotationContent.name() ) ? parameterAnnotationContent.getFieldName() + : parameterAnnotationContent.name(); + parameter.setName( name ); + parameter.setAlias( parameterAnnotationContent.alias() ); + parameter.setDefaultValue( parameterAnnotationContent.defaultValue() ); + parameter.setDeprecated( parameterAnnotationContent.getDeprecated() ); + parameter.setDescription( parameterAnnotationContent.getDescription() ); + parameter.setEditable( !parameterAnnotationContent.readonly() ); + String property = parameterAnnotationContent.property(); + if ( StringUtils.contains( property, '$' ) || StringUtils.contains( property, '{' ) + || StringUtils.contains( property, '}' ) ) + { + throw new InvalidParameterException( + "Invalid property for parameter '" + parameter.getName() + "', " + "forbidden characters ${}: " + + property, null ); + } + parameter.setExpression( StringUtils.isEmpty( property ) ? "" : "${" + property + "}" ); + parameter.setType( parameterAnnotationContent.getClassName() ); + parameter.setSince( parameterAnnotationContent.getSince() ); + parameter.setRequired( parameterAnnotationContent.required() ); + + mojoDescriptor.addParameter( parameter ); + } + + // Component annotations + Map components = + getComponentsParentHierarchy( mojoAnnotatedClass, new HashMap(), + mojoAnnotatedClasses ); + + for ( ComponentAnnotationContent componentAnnotationContent : new TreeSet<>( components.values() ) ) + { + org.apache.maven.plugin.descriptor.Parameter parameter = + new org.apache.maven.plugin.descriptor.Parameter(); + parameter.setName( componentAnnotationContent.getFieldName() ); + + // recognize Maven-injected objects as components annotations instead of parameters + String expression = PluginUtils.MAVEN_COMPONENTS.get( componentAnnotationContent.getRoleClassName() ); + if ( expression == null ) + { + // normal component + parameter.setRequirement( new Requirement( componentAnnotationContent.getRoleClassName(), + componentAnnotationContent.hint() ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property: deprecated + getLogger().warn( "Deprecated @Component annotation for '" + parameter.getName() + "' field in " + + mojoAnnotatedClass.getClassName() + + ": replace with @Parameter( defaultValue = \"" + expression + + "\", readonly = true )" ); + parameter.setDefaultValue( expression ); + parameter.setType( componentAnnotationContent.getRoleClassName() ); + parameter.setRequired( true ); + } + parameter.setDeprecated( componentAnnotationContent.getDeprecated() ); + parameter.setSince( componentAnnotationContent.getSince() ); + + // same behaviour as JavaMojoDescriptorExtractor + //parameter.setRequired( ... ); + parameter.setEditable( false ); + + mojoDescriptor.addParameter( parameter ); + } + + mojoDescriptor.setPluginDescriptor( pluginDescriptor ); + + mojoDescriptors.add( mojoDescriptor ); + } + return mojoDescriptors; + } + + protected ExecuteAnnotationContent findExecuteInParentHierarchy( MojoAnnotatedClass mojoAnnotatedClass, + Map mojoAnnotatedClasses ) + { + if ( mojoAnnotatedClass.getExecute() != null ) + { + return mojoAnnotatedClass.getExecute(); + } + String parentClassName = mojoAnnotatedClass.getParentClassName(); + if ( StringUtils.isEmpty( parentClassName ) ) + { + return null; + } + MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); + if ( parent == null ) + { + return null; + } + return findExecuteInParentHierarchy( parent, mojoAnnotatedClasses ); + } + + + protected Map getParametersParentHierarchy( + MojoAnnotatedClass mojoAnnotatedClass, Map parameters, + Map mojoAnnotatedClasses ) + { + List parameterAnnotationContents = new ArrayList<>(); + + parameterAnnotationContents = + getParametersParent( mojoAnnotatedClass, parameterAnnotationContents, mojoAnnotatedClasses ); + + // move to parent first to build the Map + Collections.reverse( parameterAnnotationContents ); + + Map map = new HashMap<>( parameterAnnotationContents.size() ); + + for ( ParameterAnnotationContent parameterAnnotationContent : parameterAnnotationContents ) + { + map.put( parameterAnnotationContent.getFieldName(), parameterAnnotationContent ); + } + return map; + } + + protected List getParametersParent( MojoAnnotatedClass mojoAnnotatedClass, + List parameterAnnotationContents, + Map mojoAnnotatedClasses ) + { + parameterAnnotationContents.addAll( mojoAnnotatedClass.getParameters().values() ); + String parentClassName = mojoAnnotatedClass.getParentClassName(); + if ( parentClassName != null ) + { + MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); + if ( parent != null ) + { + return getParametersParent( parent, parameterAnnotationContents, mojoAnnotatedClasses ); + } + } + return parameterAnnotationContents; + } + + protected Map getComponentsParentHierarchy( + MojoAnnotatedClass mojoAnnotatedClass, Map components, + Map mojoAnnotatedClasses ) + { + List componentAnnotationContents = new ArrayList<>(); + + componentAnnotationContents = + getComponentParent( mojoAnnotatedClass, componentAnnotationContents, mojoAnnotatedClasses ); + + // move to parent first to build the Map + Collections.reverse( componentAnnotationContents ); + + Map map = new HashMap<>( componentAnnotationContents.size() ); + + for ( ComponentAnnotationContent componentAnnotationContent : componentAnnotationContents ) + { + map.put( componentAnnotationContent.getFieldName(), componentAnnotationContent ); + } + return map; + } + + protected List getComponentParent( MojoAnnotatedClass mojoAnnotatedClass, + List componentAnnotationContents, + Map mojoAnnotatedClasses ) + { + componentAnnotationContents.addAll( mojoAnnotatedClass.getComponents().values() ); + String parentClassName = mojoAnnotatedClass.getParentClassName(); + if ( parentClassName != null ) + { + MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); + if ( parent != null ) + { + return getComponentParent( parent, componentAnnotationContents, mojoAnnotatedClasses ); + } + } + return componentAnnotationContents; + } + + protected MavenProject getFromProjectReferences( Artifact artifact, MavenProject project ) + { + if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() ) + { + return null; + } + @SuppressWarnings( "unchecked" ) Collection mavenProjects = + project.getProjectReferences().values(); + for ( MavenProject mavenProject : mavenProjects ) + { + if ( StringUtils.equals( mavenProject.getId(), artifact.getId() ) ) + { + return mavenProject; + } + } + return null; + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedContent.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedContent.java new file mode 100644 index 000000000..54494e0a4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedContent.java @@ -0,0 +1,65 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class AnnotatedContent +{ + + private String description; + + private String since; + + private String deprecated; + + public String getDescription() + { + return description; + } + + public void setDescription( String description ) + { + this.description = description; + } + + public String getSince() + { + return since; + } + + public void setSince( String since ) + { + this.since = since; + } + + public String getDeprecated() + { + return deprecated; + } + + public void setDeprecated( String deprecated ) + { + this.deprecated = deprecated; + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedField.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedField.java new file mode 100644 index 000000000..9ac1ed0d4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/AnnotatedField.java @@ -0,0 +1,61 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class AnnotatedField + extends AnnotatedContent + implements Comparable +{ + private String fieldName; + + public AnnotatedField( String fieldName ) + { + this.fieldName = fieldName; + } + + public String getFieldName() + { + return fieldName; + } + + public void setFieldName( String name ) + { + this.fieldName = name; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "AnnotatedField" ); + sb.append( "{fieldName='" ).append( fieldName ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + + public int compareTo( AnnotatedField annotatedField ) + { + return getFieldName().compareTo( annotatedField.getFieldName() ); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ComponentAnnotationContent.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ComponentAnnotationContent.java new file mode 100644 index 000000000..4eabbb61b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ComponentAnnotationContent.java @@ -0,0 +1,92 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Component; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ComponentAnnotationContent + extends AnnotatedField + implements Component +{ + private String roleClassName; + + private String hint; + + public ComponentAnnotationContent( String fieldName ) + { + super( fieldName ); + } + + public ComponentAnnotationContent( String fieldName, String role, String hint ) + { + this( fieldName ); + this.roleClassName = role; + this.hint = hint; + } + + public Class role() + { + // not used + return null; + } + + public void setRoleClassName( String roleClassName ) + { + this.roleClassName = roleClassName; + } + + public String getRoleClassName() + { + return roleClassName; + } + + public String hint() + { + return hint == null ? "" : hint; + } + + public void hint( String hint ) + { + this.hint = hint; + } + + public Class annotationType() + { + return null; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( super.toString() ); + sb.append( "ComponentAnnotationContent" ); + sb.append( "{role='" ).append( roleClassName ).append( '\'' ); + sb.append( ", hint='" ).append( hint ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java new file mode 100644 index 000000000..f95ed3d2d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java @@ -0,0 +1,88 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ExecuteAnnotationContent + implements Execute +{ + private String goal; + + private String lifecycle; + + private LifecyclePhase phase; + + public LifecyclePhase phase() + { + return this.phase; + } + + public String goal() + { + return this.goal; + } + + public String lifecycle() + { + return this.lifecycle; + } + + + public void phase( String phase ) + { + this.phase = LifecyclePhase.valueOf( phase ); + } + + public void goal( String goal ) + { + this.goal = goal; + } + + public void lifecycle( String lifecycle ) + { + this.lifecycle = lifecycle; + } + + + public Class annotationType() + { + return null; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "ExecuteAnnotationContent" ); + sb.append( "{goal='" ).append( goal ).append( '\'' ); + sb.append( ", lifecycle='" ).append( lifecycle ).append( '\'' ); + sb.append( ", phase=" ).append( phase ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java new file mode 100644 index 000000000..33104cb84 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java @@ -0,0 +1,232 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.InstantiationStrategy; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotationContent + extends AnnotatedContent + implements Mojo +{ + private String name; + + private LifecyclePhase defaultPhase = LifecyclePhase.NONE; + + private ResolutionScope requiresDependencyResolution = ResolutionScope.NONE; + + private ResolutionScope requiresDependencyCollection = ResolutionScope.NONE; + + private InstantiationStrategy instantiationStrategy = InstantiationStrategy.PER_LOOKUP; + + private String executionStrategy = "once-per-session"; + + private boolean requiresProject = true; + + private boolean requiresReports = false; + + private boolean aggregator = false; + + private boolean requiresDirectInvocation = false; + + private boolean requiresOnline = false; + + private boolean inheritByDefault = true; + + private String configurator; + + private boolean threadSafe = false; + + public Class annotationType() + { + return null; + } + + public LifecyclePhase defaultPhase() + { + return defaultPhase; + } + + public void defaultPhase( String phase ) + { + this.defaultPhase = LifecyclePhase.valueOf( phase ); + } + + public ResolutionScope requiresDependencyResolution() + { + return requiresDependencyResolution; + } + + public void requiresDependencyResolution( String requiresDependencyResolution ) + { + this.requiresDependencyResolution = ResolutionScope.valueOf( requiresDependencyResolution ); + } + + public ResolutionScope requiresDependencyCollection() + { + return requiresDependencyCollection; + } + + public void requiresDependencyCollection( String requiresDependencyCollection ) + { + this.requiresDependencyCollection = ResolutionScope.valueOf( requiresDependencyCollection ); + } + + public InstantiationStrategy instantiationStrategy() + { + return instantiationStrategy; + } + + public void instantiationStrategy( String instantiationStrategy ) + { + this.instantiationStrategy = InstantiationStrategy.valueOf( instantiationStrategy ); + } + + public String executionStrategy() + { + return executionStrategy; + } + + public void executionStrategy( String executionStrategy ) + { + this.executionStrategy = executionStrategy; + } + + public boolean requiresProject() + { + return requiresProject; + } + + public void requiresProject( boolean requiresProject ) + { + this.requiresProject = requiresProject; + } + + public boolean requiresReports() + { + return requiresReports; + } + + public void requiresReports( boolean requiresReports ) + { + this.requiresReports = requiresReports; + } + + public boolean aggregator() + { + return aggregator; + } + + public void aggregator( boolean aggregator ) + { + this.aggregator = aggregator; + } + + public boolean requiresDirectInvocation() + { + return requiresDirectInvocation; + } + + public void requiresDirectInvocation( boolean requiresDirectInvocation ) + { + this.requiresDirectInvocation = requiresDirectInvocation; + } + + public boolean requiresOnline() + { + return requiresOnline; + } + + public void requiresOnline( boolean requiresOnline ) + { + this.requiresOnline = requiresOnline; + } + + public boolean inheritByDefault() + { + return inheritByDefault; + } + + public void inheritByDefault( boolean inheritByDefault ) + { + this.inheritByDefault = inheritByDefault; + } + + public String configurator() + { + return configurator; + } + + public void configurator( String configurator ) + { + this.configurator = configurator; + } + + public boolean threadSafe() + { + return threadSafe; + } + + public void threadSafe( boolean threadSafe ) + { + this.threadSafe = threadSafe; + } + + public String name() + { + return this.name; + } + + public void name( String name ) + { + this.name = name; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "MojoAnnotationContent" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", defaultPhase=" ).append( defaultPhase ); + sb.append( ", requiresDependencyResolution='" ).append( requiresDependencyResolution ).append( '\'' ); + sb.append( ", requiresDependencyCollection='" ).append( requiresDependencyCollection ).append( '\'' ); + sb.append( ", instantiationStrategy='" ).append( instantiationStrategy ).append( '\'' ); + sb.append( ", executionStrategy='" ).append( executionStrategy ).append( '\'' ); + sb.append( ", requiresProject=" ).append( requiresProject ); + sb.append( ", requiresReports=" ).append( requiresReports ); + sb.append( ", aggregator=" ).append( aggregator ); + sb.append( ", requiresDirectInvocation=" ).append( requiresDirectInvocation ); + sb.append( ", requiresOnline=" ).append( requiresOnline ); + sb.append( ", inheritByDefault=" ).append( inheritByDefault ); + sb.append( ", configurator='" ).append( configurator ).append( '\'' ); + sb.append( ", threadSafe=" ).append( threadSafe ); + sb.append( '}' ); + return sb.toString(); + } +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java new file mode 100644 index 000000000..919aaa4bf --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java @@ -0,0 +1,212 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Parameter; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ParameterAnnotationContent + extends AnnotatedField + implements Parameter +{ + + private String name; + + private String alias; + + private String property; + + private String defaultValue; + + private boolean required = false; + + private boolean readonly = false; + + private String className; + + public ParameterAnnotationContent( String fieldName, String className ) + { + super( fieldName ); + this.className = className; + } + + public ParameterAnnotationContent( String fieldName, String alias, String property, String defaultValue, + boolean required, boolean readonly, String className ) + { + this( fieldName, className ); + this.alias = alias; + this.property = property; + this.defaultValue = defaultValue; + this.required = required; + this.readonly = readonly; + } + + public String name() + { + return name; + } + + public void name( String name ) + { + this.name = name; + } + + public String alias() + { + return alias; + } + + public void alias( String alias ) + { + this.alias = alias; + } + + public String property() + { + return property; + } + + public void property( String property ) + { + this.property = property; + } + + public String defaultValue() + { + return defaultValue; + } + + public void defaultValue( String defaultValue ) + { + this.defaultValue = defaultValue; + } + + public boolean required() + { + return required; + } + + public void required( boolean required ) + { + this.required = required; + } + + public boolean readonly() + { + return readonly; + } + + public void readonly( boolean readonly ) + { + this.readonly = readonly; + } + + public Class annotationType() + { + return null; + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( super.toString() ); + sb.append( "ParameterAnnotationContent" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", alias='" ).append( alias ).append( '\'' ); + sb.append( ", property='" ).append( property ).append( '\'' ); + sb.append( ", defaultValue='" ).append( defaultValue ).append( '\'' ); + sb.append( ", required=" ).append( required ); + sb.append( ", readonly=" ).append( readonly ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( !( o instanceof ParameterAnnotationContent ) ) + { + return false; + } + + ParameterAnnotationContent that = (ParameterAnnotationContent) o; + + if ( readonly != that.readonly ) + { + return false; + } + if ( required != that.required ) + { + return false; + } + + if ( getFieldName() != null ? !getFieldName().equals( that.getFieldName() ) : that.getFieldName() != null ) + { + return false; + } + + if ( alias != null ? !alias.equals( that.alias ) : that.alias != null ) + { + return false; + } + if ( defaultValue != null ? !defaultValue.equals( that.defaultValue ) : that.defaultValue != null ) + { + return false; + } + if ( property != null ? !property.equals( that.property ) : that.property != null ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = alias != null ? alias.hashCode() : 0; + result = 31 * result + ( getFieldName() != null ? getFieldName().hashCode() : 0 ); + result = 31 * result + ( property != null ? property.hashCode() : 0 ); + result = 31 * result + ( defaultValue != null ? defaultValue.hashCode() : 0 ); + result = 31 * result + ( required ? 1 : 0 ); + result = 31 * result + ( readonly ? 1 : 0 ); + return result; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java new file mode 100644 index 000000000..2eab39174 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java @@ -0,0 +1,340 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoClassVisitor; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.reflection.Reflector; +import org.codehaus.plexus.util.reflection.ReflectorException; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Type; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@org.codehaus.plexus.component.annotations.Component( role = MojoAnnotationsScanner.class ) +public class DefaultMojoAnnotationsScanner + extends AbstractLogEnabled + implements MojoAnnotationsScanner +{ + // classes with a dash must be ignored + private static final Pattern SCANNABLE_CLASS = Pattern.compile( "[^-]+\\.class" ); + + private Reflector reflector = new Reflector(); + + public Map scan( MojoAnnotationsScannerRequest request ) + throws ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + try + { + for ( Artifact dependency : request.getDependencies() ) + { + scan( mojoAnnotatedClasses, dependency.getFile(), request.getIncludePatterns(), dependency, true ); + } + + for ( File classDirectory : request.getClassesDirectories() ) + { + scan( mojoAnnotatedClasses, classDirectory, request.getIncludePatterns(), + request.getProject().getArtifact(), false ); + } + } + catch ( IOException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + + return mojoAnnotatedClasses; + } + + protected void scan( Map mojoAnnotatedClasses, File source, + List includePatterns, Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + if ( source == null || ! source.exists() ) + { + return; + } + + Map scanResult; + if ( source.isDirectory() ) + { + scanResult = scanDirectory( source, includePatterns, artifact, excludeMojo ); + } + else + { + scanResult = scanArchive( source, artifact, excludeMojo ); + } + + mojoAnnotatedClasses.putAll( scanResult ); + } + + /** + * @param archiveFile + * @param artifact + * @param excludeMojo for dependencies, we exclude Mojo annotations found + * @return annotated classes found + * @throws IOException + * @throws ExtractionException + */ + protected Map scanArchive( File archiveFile, Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + String zipEntryName = null; + try ( ZipInputStream archiveStream = new ZipInputStream( new FileInputStream( archiveFile ) ) ) + { + String archiveFilename = archiveFile.getAbsolutePath(); + for ( ZipEntry zipEntry = archiveStream.getNextEntry(); zipEntry != null; + zipEntry = archiveStream.getNextEntry() ) + { + zipEntryName = zipEntry.getName(); + if ( !SCANNABLE_CLASS.matcher( zipEntryName ).matches() ) + { + continue; + } + analyzeClassStream( mojoAnnotatedClasses, archiveStream, artifact, excludeMojo, archiveFilename, + zipEntry.getName() ); + } + } + catch ( IllegalArgumentException e ) + { + // In case of a class with newer specs an IllegalArgumentException can be thrown + getLogger().error( "Failed to analyze " + archiveFile.getAbsolutePath() + "!/" + zipEntryName ); + + throw e; + } + + return mojoAnnotatedClasses; + } + + /** + * @param classDirectory + * @param includePatterns + * @param artifact + * @param excludeMojo for dependencies, we exclude Mojo annotations found + * @return annotated classes found + * @throws IOException + * @throws ExtractionException + */ + protected Map scanDirectory( File classDirectory, List includePatterns, + Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir( classDirectory ); + scanner.addDefaultExcludes(); + if ( includePatterns != null ) + { + scanner.setIncludes( includePatterns.toArray( new String[includePatterns.size()] ) ); + } + scanner.scan(); + String[] classFiles = scanner.getIncludedFiles(); + String classDirname = classDirectory.getAbsolutePath(); + + for ( String classFile : classFiles ) + { + if ( !SCANNABLE_CLASS.matcher( classFile ).matches() ) + { + continue; + } + + try ( InputStream is = // + new BufferedInputStream( new FileInputStream( new File( classDirectory, classFile ) ) ) ) + { + analyzeClassStream( mojoAnnotatedClasses, is, artifact, excludeMojo, classDirname, classFile ); + } + } + return mojoAnnotatedClasses; + } + + private void analyzeClassStream( Map mojoAnnotatedClasses, InputStream is, + Artifact artifact, boolean excludeMojo, String source, String file ) + throws IOException, ExtractionException + { + MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() ); + + try + { + ClassReader rdr = new ClassReader( is ); + rdr.accept( mojoClassVisitor, ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG ); + } + catch ( ArrayIndexOutOfBoundsException aiooe ) + { + getLogger().warn( "Error analyzing class " + file + " in " + source + ": ignoring class", + getLogger().isDebugEnabled() ? aiooe : null ); + return; + } + catch ( IllegalArgumentException iae ) + { + if ( iae.getMessage() == null ) + { + getLogger().warn( "Error analyzing class " + file + " in " + source + ": ignoring class", + getLogger().isDebugEnabled() ? iae : null ); + return; + } + else + { + throw iae; + } + } + + analyzeVisitors( mojoClassVisitor ); + + MojoAnnotatedClass mojoAnnotatedClass = mojoClassVisitor.getMojoAnnotatedClass(); + + if ( excludeMojo ) + { + mojoAnnotatedClass.setMojo( null ); + } + + if ( mojoAnnotatedClass != null ) // see MPLUGIN-206 we can have intermediate classes without annotations + { + if ( getLogger().isDebugEnabled() && mojoAnnotatedClass.hasAnnotations() ) + { + getLogger().debug( "found MojoAnnotatedClass:" + mojoAnnotatedClass.getClassName() + ":" + + mojoAnnotatedClass ); + } + mojoAnnotatedClass.setArtifact( artifact ); + mojoAnnotatedClasses.put( mojoAnnotatedClass.getClassName(), mojoAnnotatedClass ); + } + } + + protected void populateAnnotationContent( Object content, MojoAnnotationVisitor mojoAnnotationVisitor ) + throws ReflectorException + { + for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() ) + { + reflector.invoke( content, entry.getKey(), new Object[] { entry.getValue() } ); + } + } + + protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor ) + throws ExtractionException + { + final MojoAnnotatedClass mojoAnnotatedClass = mojoClassVisitor.getMojoAnnotatedClass(); + + try + { + // @Mojo annotation + MojoAnnotationVisitor mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitor( Mojo.class ); + if ( mojoAnnotationVisitor != null ) + { + MojoAnnotationContent mojoAnnotationContent = new MojoAnnotationContent(); + populateAnnotationContent( mojoAnnotationContent, mojoAnnotationVisitor ); + mojoAnnotatedClass.setMojo( mojoAnnotationContent ); + } + + // @Execute annotation + mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitor( Execute.class ); + if ( mojoAnnotationVisitor != null ) + { + ExecuteAnnotationContent executeAnnotationContent = new ExecuteAnnotationContent(); + populateAnnotationContent( executeAnnotationContent, mojoAnnotationVisitor ); + mojoAnnotatedClass.setExecute( executeAnnotationContent ); + } + + // @Parameter annotations + List mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation( Parameter.class ); + for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors ) + { + ParameterAnnotationContent parameterAnnotationContent = + new ParameterAnnotationContent( mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName() ); + if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null ) + { + populateAnnotationContent( parameterAnnotationContent, + mojoFieldVisitor.getMojoAnnotationVisitor() ); + } + + mojoAnnotatedClass.getParameters().put( parameterAnnotationContent.getFieldName(), + parameterAnnotationContent ); + } + + // @Component annotations + mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation( Component.class ); + for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors ) + { + ComponentAnnotationContent componentAnnotationContent = + new ComponentAnnotationContent( mojoFieldVisitor.getFieldName() ); + + MojoAnnotationVisitor annotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor(); + if ( annotationVisitor != null ) + { + for ( Map.Entry entry : annotationVisitor.getAnnotationValues().entrySet() ) + { + String methodName = entry.getKey(); + if ( StringUtils.equals( "role", methodName ) ) + { + Type type = (Type) entry.getValue(); + componentAnnotationContent.setRoleClassName( type.getClassName() ); + } + else + { + reflector.invoke( componentAnnotationContent, entry.getKey(), + new Object[]{ entry.getValue() } ); + } + } + + if ( StringUtils.isEmpty( componentAnnotationContent.getRoleClassName() ) ) + { + componentAnnotationContent.setRoleClassName( mojoFieldVisitor.getClassName() ); + } + } + mojoAnnotatedClass.getComponents().put( componentAnnotationContent.getFieldName(), + componentAnnotationContent ); + } + } + catch ( ReflectorException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java new file mode 100644 index 000000000..ab5f5b150 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java @@ -0,0 +1,168 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotatedClass +{ + private String className; + + private String parentClassName; + + private MojoAnnotationContent mojo; + + private ExecuteAnnotationContent execute; + + /** + * key is field name + */ + private Map parameters; + + /** + * key is field name + */ + private Map components; + + /** + * artifact which contains this annotation + */ + private Artifact artifact; + + public MojoAnnotatedClass() + { + // no op + } + + public String getClassName() + { + return className; + } + + public MojoAnnotatedClass setClassName( String className ) + { + this.className = className; + return this; + } + + public MojoAnnotationContent getMojo() + { + return mojo; + } + + public MojoAnnotatedClass setMojo( MojoAnnotationContent mojo ) + { + this.mojo = mojo; + return this; + } + + public ExecuteAnnotationContent getExecute() + { + return execute; + } + + public MojoAnnotatedClass setExecute( ExecuteAnnotationContent execute ) + { + this.execute = execute; + return this; + } + + public Map getParameters() + { + if ( this.parameters == null ) + { + this.parameters = new HashMap<>(); + } + return parameters; + } + + public MojoAnnotatedClass setParameters( Map parameters ) + { + this.parameters = parameters; + return this; + } + + public Map getComponents() + { + if ( this.components == null ) + { + this.components = new HashMap<>(); + } + return components; + } + + public MojoAnnotatedClass setComponents( Map components ) + { + this.components = components; + return this; + } + + public String getParentClassName() + { + return parentClassName; + } + + public MojoAnnotatedClass setParentClassName( String parentClassName ) + { + this.parentClassName = parentClassName; + return this; + } + + public Artifact getArtifact() + { + return artifact; + } + + public void setArtifact( Artifact artifact ) + { + this.artifact = artifact; + } + + public boolean hasAnnotations() + { + return !( getComponents().isEmpty() && getParameters().isEmpty() && execute == null && mojo == null ); + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "MojoAnnotatedClass" ); + sb.append( "{className='" ).append( className ).append( '\'' ); + sb.append( ", parentClassName='" ).append( parentClassName ).append( '\'' ); + sb.append( ", mojo=" ).append( mojo ); + sb.append( ", execute=" ).append( execute ); + sb.append( ", parameters=" ).append( parameters ); + sb.append( ", components=" ).append( components ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java new file mode 100644 index 000000000..a5add2f9a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java @@ -0,0 +1,53 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.extractor.ExtractionException; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public interface MojoAnnotationsScanner +{ + String ROLE = MojoAnnotationsScanner.class.getName(); + + List CLASS_LEVEL_ANNOTATIONS = Arrays.asList( Mojo.class.getName(), Execute.class.getName() ); + + List FIELD_LEVEL_ANNOTATIONS = Arrays.asList( Parameter.class.getName(), Component.class.getName() ); + + /** + * Scan classes for mojo annotations. + * + * @param request + * @return map of mojo-annotated classes keyed by full class name + * @throws ExtractionException + */ + Map scan( MojoAnnotationsScannerRequest request ) + throws ExtractionException; +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java new file mode 100644 index 000000000..5a27cbd55 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java @@ -0,0 +1,102 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotationsScannerRequest +{ + private List classesDirectories = new ArrayList<>(); + + private Set dependencies = new HashSet<>(); + + private List includePatterns = Arrays.asList( "**/*.class" ); + + private List sourceDirectories = new ArrayList<>(); + + private MavenProject project; + + public MojoAnnotationsScannerRequest() + { + // no o + } + + public List getClassesDirectories() + { + return classesDirectories; + } + + public void setClassesDirectories( List classesDirectories ) + { + this.classesDirectories = classesDirectories; + } + + public Set getDependencies() + { + return dependencies; + } + + public void setDependencies( Set dependencies ) + { + this.dependencies = dependencies; + } + + public List getIncludePatterns() + { + return includePatterns; + } + + public void setIncludePatterns( List includePatterns ) + { + this.includePatterns = includePatterns; + } + + public List getSourceDirectories() + { + return sourceDirectories; + } + + public void setSourceDirectories( List sourceDirectories ) + { + this.sourceDirectories = sourceDirectories; + } + + public MavenProject getProject() + { + return project; + } + + public void setProject( MavenProject project ) + { + this.project = project; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java new file mode 100644 index 000000000..2199de517 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java @@ -0,0 +1,83 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.logging.Logger; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Opcodes; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoAnnotationVisitor + extends AnnotationVisitor +{ + private Logger logger; + + private String annotationClassName; + + private Map annotationValues = new HashMap<>(); + + MojoAnnotationVisitor( Logger logger, String annotationClassName ) + { + super( Opcodes.ASM7 ); + this.logger = logger; + this.annotationClassName = annotationClassName; + } + + public Map getAnnotationValues() + { + return annotationValues; + } + + public void visit( String name, Object value ) + { + annotationValues.put( name, value ); + } + + public void visitEnum( String name, String desc, String value ) + { + annotationValues.put( name, value ); + } + + public AnnotationVisitor visitAnnotation( String name, String desc ) + { + return new MojoAnnotationVisitor( logger, this.annotationClassName ); + } + + public AnnotationVisitor visitArray( String s ) + { + return new MojoAnnotationVisitor( logger, this.annotationClassName ); + } + + public void visitEnd() + { + // no op + } + + public String getAnnotationClassName() + { + return annotationClassName; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java new file mode 100644 index 000000000..2191a4707 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java @@ -0,0 +1,174 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoClassVisitor + extends ClassVisitor +{ + private Logger logger; + + private MojoAnnotatedClass mojoAnnotatedClass; + + private Map annotationVisitorMap = new HashMap<>(); + + private List fieldVisitors = new ArrayList<>(); + + public MojoClassVisitor( Logger logger ) + { + super( Opcodes.ASM7 ); + this.logger = logger; + } + + public MojoAnnotatedClass getMojoAnnotatedClass() + { + return mojoAnnotatedClass; + } + + public void setMojoAnnotatedClass( MojoAnnotatedClass mojoAnnotatedClass ) + { + this.mojoAnnotatedClass = mojoAnnotatedClass; + } + + public Map getAnnotationVisitorMap() + { + return annotationVisitorMap; + } + + public MojoAnnotationVisitor getAnnotationVisitor( Class annotation ) + { + return annotationVisitorMap.get( annotation.getName() ); + } + + public void setAnnotationVisitorMap( Map annotationVisitorMap ) + { + this.annotationVisitorMap = annotationVisitorMap; + } + + public List getFieldVisitors() + { + return fieldVisitors; + } + + public void setFieldVisitors( List fieldVisitors ) + { + this.fieldVisitors = fieldVisitors; + } + + public List findFieldWithAnnotation( Class annotation ) + { + String annotationClassName = annotation.getName(); + + List mojoFieldVisitors = new ArrayList(); + + for ( MojoFieldVisitor mojoFieldVisitor : this.fieldVisitors ) + { + MojoAnnotationVisitor mojoAnnotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor(); + if ( mojoAnnotationVisitor != null && StringUtils.equals( annotationClassName, + mojoAnnotationVisitor.getAnnotationClassName() ) ) + { + mojoFieldVisitors.add( mojoFieldVisitor ); + } + } + + return mojoFieldVisitors; + } + + public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) + { + mojoAnnotatedClass = new MojoAnnotatedClass(); + mojoAnnotatedClass.setClassName( Type.getObjectType( name ).getClassName() ); + if ( superName != null ) + { + mojoAnnotatedClass.setParentClassName( Type.getObjectType( superName ).getClassName() ); + } + } + + public AnnotationVisitor visitAnnotation( String desc, boolean visible ) + { + String annotationClassName = Type.getType( desc ).getClassName(); + if ( !MojoAnnotationsScanner.CLASS_LEVEL_ANNOTATIONS.contains( annotationClassName ) ) + { + return null; + } + MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName ); + annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor ); + return mojoAnnotationVisitor; + } + + public FieldVisitor visitField( int access, String name, String desc, String signature, Object value ) + { + MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( logger, name, Type.getType( desc ).getClassName() ); + fieldVisitors.add( mojoFieldVisitor ); + return mojoFieldVisitor; + } + + public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) + { + // we don't need methods informations + return null; + } + + public void visitAttribute( Attribute attr ) + { + // no op + } + + public void visitSource( String source, String debug ) + { + // no op + } + + public void visitOuterClass( String owner, String name, String desc ) + { + // no op + } + + public void visitInnerClass( String name, String outerName, String innerName, int access ) + { + // no op + } + + public void visitEnd() + { + // no op + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java new file mode 100644 index 000000000..80afcb608 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java @@ -0,0 +1,93 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner; +import org.codehaus.plexus.logging.Logger; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class MojoFieldVisitor + extends FieldVisitor +{ + private Logger logger; + + private String fieldName; + + private MojoAnnotationVisitor mojoAnnotationVisitor; + + private String className; + + MojoFieldVisitor( Logger logger, String fieldName, String className ) + { + super( Opcodes.ASM7 ); + this.logger = logger; + this.fieldName = fieldName; + this.className = className; + } + + public MojoAnnotationVisitor getMojoAnnotationVisitor() + { + return mojoAnnotationVisitor; + } + + public String getFieldName() + { + return fieldName; + } + + public AnnotationVisitor visitAnnotation( String desc, boolean visible ) + { + String annotationClassName = Type.getType( desc ).getClassName(); + if ( !MojoAnnotationsScanner.FIELD_LEVEL_ANNOTATIONS.contains( annotationClassName ) ) + { + return null; + } + mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName ); + return mojoAnnotationVisitor; + } + + public void visitAttribute( Attribute attribute ) + { + // no op + } + + public void visitEnd() + { + // no op + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/apt/index.apt new file mode 100644 index 000000000..29f46e772 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/apt/index.apt @@ -0,0 +1,134 @@ + ------ + Introduction + ------ + Hervé Boutemy + ------ + 2012-05-12 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Tool for Annotations + + The Maven Plugin Tool for Annotations is the <<>> implementation of + {{{../maven-plugin-tools-api/index.html}maven-plugin-tools-api}} + to extract descriptors from plugins written in Java with + {{{../maven-plugin-annotations/index.html}Maven Plugin Tools Java Annotations}}. + +* Supported Annotations + ++---------+ +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.InstantiationStrategy; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; + +/** + * Mojo Description. @Mojo( name = "" ) is the minimal required annotation. + * @since + * @deprecated + */ +@Mojo( name = "", + aggregator = , + configurator = "", + executionStrategy = "", + inheritByDefault = , + instantiationStrategy = InstantiationStrategy., + defaultPhase = LifecyclePhase., + requiresDependencyResolution = ResolutionScope., + requiresDependencyCollection = ResolutionScope., // (since Maven 3.0) + requiresDirectInvocation = , + requiresOnline = , + requiresProject = , + requiresReports = , // (unsupported since Maven 3.0) + threadSafe = ) // (since Maven 3.0) +@Execute( goal = "", + phase = LifecyclePhase., + lifecycle = "" ) +public class MyMojo + extends AbstractMojo +{ + /** + * @since + * @deprecated + */ + @Parameter( name = "parameter", + alias = "myAlias", + property = "a.property", + defaultValue = "an expression, possibly with ${variables}", + readonly = , + required = ) + private String parameter; + + @Component( role = MyComponentExtension.class, + hint = "..." ) + private MyComponent component; + + // sample objects taken from Maven API through PluginParameterExpressionEvaluator + + @Parameter( defaultValue = "${session}", readonly = true ) + private MavenSession session; + + @Parameter( defaultValue = "${project}", readonly = true ) + private MavenProject project; + + @Parameter( defaultValue = "${mojoExecution}", readonly = true ) + private MojoExecution mojo; + + @Parameter( defaultValue = "${plugin}", readonly = true ) // Maven 3 only + private PluginDescriptor plugin; + + @Parameter( defaultValue = "${settings}", readonly = true ) + private Settings settings; + + @Parameter( defaultValue = "${project.basedir}", readonly = true ) + private File basedir; + + @Parameter( defaultValue = "${project.build.directory}", readonly = true ) + private File target; + + public void execute() + { + ... + } +} ++---------+ + + +* See also + + * {{{../maven-plugin-annotations/index.html}Maven Plugin Tools Java Annotations}} + + * {{{/developers/mojo-api-specification.html#The_Descriptor_and_Annotations}Mojo API Specification}} + + * {{{/ref/current/maven-plugin-api/plugin.html}META-INF/maven/plugin.xml plugin descriptor}} + + * {{{/ref/current/maven-core/apidocs/org/apache/maven/plugin/PluginParameterExpressionEvaluator.html}PluginParameterExpressionEvaluator}}, + used to evaluate plugin parameters values during Mojo configuration, diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/AbstractFooMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/AbstractFooMojo.java new file mode 100644 index 000000000..2cfd97d14 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/AbstractFooMojo.java @@ -0,0 +1,30 @@ +package org.apache.maven.tools.plugin.extractor.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; + +@Mojo(name = "abstract", requiresDependencyResolution = ResolutionScope.COMPILE, requiresDependencyCollection = ResolutionScope.COMPILE) +public abstract class AbstractFooMojo + extends AbstractMojo +{ +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java new file mode 100644 index 000000000..95b339d02 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java @@ -0,0 +1,72 @@ +package org.apache.maven.tools.plugin.extractor.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.compiler.manager.CompilerManager; + +/** + * @author Olivier Lamy + */ +@Mojo( name = "foo", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true ) +@Execute( goal = "compiler", lifecycle = "my-lifecycle", phase = LifecyclePhase.PACKAGE ) +public class FooMojo + extends AbstractFooMojo +{ + /** + * the cool bar to go + * @since 1.0 + */ + @Parameter( property = "thebar", required = true, defaultValue = "coolbar" ) + protected String bar; + + /** + * beer for non french folks + * @deprecated wine is better + */ + @Parameter( property = "thebeer", defaultValue = "coolbeer" ) + protected String beer; + + /** + * Plexus compiler manager. + */ + @Component + protected CompilerManager compilerManager; + + /** + * + */ + @Component( role = ArtifactMetadataSource.class, hint = "maven" ) + protected ArtifactMetadataSource artifactMetadataSource; + + public void execute() + throws MojoExecutionException, MojoFailureException + { + // nothing + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java new file mode 100644 index 000000000..b7702df63 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java @@ -0,0 +1,89 @@ +package org.apache.maven.tools.plugin.extractor.annotations; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScannerRequest; +import org.codehaus.plexus.PlexusTestCase; +import org.fest.assertions.Assertions; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +/** + * @author Olivier Lamy + */ +public class TestAnnotationsReader + extends PlexusTestCase +{ + public void testReadMojoClass() + throws Exception + { + MojoAnnotationsScanner mojoAnnotationsScanner = (MojoAnnotationsScanner) lookup( MojoAnnotationsScanner.ROLE ); + + MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest(); + request.setClassesDirectories( Collections.singletonList( new File( getBasedir(), "target/test-classes" ) ) ); + request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) ); + request.setProject( new MavenProject() ); + + Map mojoAnnotatedClasses = mojoAnnotationsScanner.scan( request ); + + System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses ); + + Assertions.assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 ); + + MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next(); + + assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() ); + assertEquals( AbstractFooMojo.class.getName(), mojoAnnotatedClass.getParentClassName() ); + + Mojo mojo = mojoAnnotatedClass.getMojo(); + + assertEquals( "foo", mojo.name() ); + assertTrue( mojo.threadSafe() ); + assertFalse( mojo.aggregator() ); + assertEquals( LifecyclePhase.COMPILE, mojo.defaultPhase() ); + + Execute execute = mojoAnnotatedClass.getExecute(); + + assertEquals( "compiler", execute.goal() ); + assertEquals( "my-lifecycle", execute.lifecycle() ); + assertEquals( LifecyclePhase.PACKAGE, execute.phase() ); + + Collection components = mojoAnnotatedClass.getComponents().values(); + Assertions.assertThat( components ).isNotNull().isNotEmpty().hasSize( 2 ); + + Collection parameters = mojoAnnotatedClass.getParameters().values(); + Assertions.assertThat( parameters ).isNotNull().isNotEmpty().hasSize( 2 ).contains( + new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", true, false, String.class.getName() ), + new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", false, false, + String.class.getName() ) ); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java new file mode 100644 index 000000000..11508b833 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java @@ -0,0 +1,46 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.mockito.Mockito.mock; + +import java.io.File; + +import org.codehaus.plexus.logging.Logger; +import org.junit.Test; + +public class DefaultMojoAnnotationsScannerTest +{ + private DefaultMojoAnnotationsScanner scanner = new DefaultMojoAnnotationsScanner(); + + @Test + public void testSkipModuleInfoClassInArchive() throws Exception + { + scanner.scanArchive( new File( "target/test-classes/java9-module.jar"), null, false ); + } + + @Test + public void testJava8Annotations() throws Exception + { + scanner.enableLogging( mock( Logger.class ) ); + scanner.scanArchive( new File( "target/test-classes/java8-annotations.jar"), null, false ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/resources/java8-annotations.jar b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/resources/java8-annotations.jar new file mode 100644 index 0000000000000000000000000000000000000000..35955942a86c3b7ba63dc4a7681ffd96d9d2b9b1 GIT binary patch literal 539 zcmWIWW@h1H00G-&Ql4N2lwbqWS&3zd7Wx5DH5_0yg0(a3Oc@y%P6DwQT#XkQ(5?RD5e#CGyBU+Kkbd;43t1!FSA(;hEcz!4-cCE(z+ycpkC0n3+6o-|YB zkB+#~jt|U#G(P%8X_Oh3KfCjJ$Kk&}|Ndet=yaCXJH)1SXw{n%9@^NTp8;dy_Jb-<+{rd7gK7 zxbO8nUb&XP|L1*4$ku-vbvdJcg6PkPJD%D(>sE5F=6#T??I3E}c5PYZ)u?xm4QF<3 zJjl8B+|tlX2Cti#`vZCl=DuT-mDforx$Z5xnRx|U%dREcdhY*ZdA)((;(d!u&UC%@ ztf`x9-(1j+(7Ncd`piw;sc-EAycwB9m~lr3BxVE{-a3L8dczW Y&?76rn-vt>3`{^+0i=6@QOm#p09LNPvj6}9 literal 0 HcmV?d00001 diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/resources/java9-module.jar b/Java-base/maven-plugin-tools/src/maven-plugin-tools-annotations/src/test/resources/java9-module.jar new file mode 100644 index 0000000000000000000000000000000000000000..5a7edc016613a0a95601d4f2b03bd1bc1f858d66 GIT binary patch literal 266 zcmWIWW@Zs#VBp|j@C(1}p_(o&(Z;~QunULg0Sr$Bc(byB O + + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.6.1-SNAPSHOT + + + maven-plugin-tools-api + + Maven Plugin Tools Extractor API + The Maven Plugin Tools Extractor API provides an API to extract descriptor information from Maven Plugins. + + + + + org.apache.maven + maven-core + + + org.apache.maven + maven-model + + + org.apache.maven + maven-plugin-api + + + org.apache.maven + maven-artifact + + + org.apache.maven + maven-settings + + + + + org.codehaus.plexus + plexus-utils + + + org.sonatype.sisu + sisu-inject-plexus + 1.4.2 + + + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + test + + + junit + junit + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.build.outputDirectory} + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java new file mode 100644 index 000000000..8f7014506 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java @@ -0,0 +1,179 @@ +package org.apache.maven.tools.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.StringUtils; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Default implementation of {@link PluginToolsRequest}, which is used to pass parameters to components used to extract + * {@link org.apache.maven.plugin.descriptor.MojoDescriptor MojoDescriptor} instances from different types of metadata + * for a given plugin. + * + * @author jdcasey + * @since 2.5 + */ +public class DefaultPluginToolsRequest + implements PluginToolsRequest +{ + + private static final String DEFAULT_ENCODING = ReaderFactory.FILE_ENCODING; + + private PluginDescriptor pluginDescriptor; + + private MavenProject project; + + private String encoding = DEFAULT_ENCODING; + + private boolean skipErrorNoDescriptorsFound; + + private Set dependencies; + + private List remoteRepos; + + private ArtifactRepository local; + + public DefaultPluginToolsRequest( MavenProject project, PluginDescriptor pluginDescriptor ) + { + this.project = project; + this.pluginDescriptor = pluginDescriptor; + } + + /** + * {@inheritDoc} + */ + public PluginDescriptor getPluginDescriptor() + { + return pluginDescriptor; + } + + /** + * {@inheritDoc} + */ + public PluginToolsRequest setPluginDescriptor( PluginDescriptor pluginDescriptor ) + { + this.pluginDescriptor = pluginDescriptor; + return this; + } + + /** + * {@inheritDoc} + */ + public MavenProject getProject() + { + return project; + } + + /** + * {@inheritDoc} + */ + public PluginToolsRequest setProject( MavenProject project ) + { + this.project = project; + return this; + } + + /** + * {@inheritDoc} + */ + public String getEncoding() + { + return this.encoding; + } + + /** + * {@inheritDoc} + */ + public PluginToolsRequest setEncoding( String encoding ) + { + if ( StringUtils.isNotEmpty( encoding ) ) + { + this.encoding = encoding; + } + else + { + this.encoding = DEFAULT_ENCODING; + } + + return this; + } + + /** + * {@inheritDoc} + */ + public boolean isSkipErrorNoDescriptorsFound() + { + return skipErrorNoDescriptorsFound; + } + + /** + * {@inheritDoc} + */ + public PluginToolsRequest setSkipErrorNoDescriptorsFound( boolean skipErrorNoDescriptorsFound ) + { + this.skipErrorNoDescriptorsFound = skipErrorNoDescriptorsFound; + return this; + } + + public Set getDependencies() + { + if ( this.dependencies == null ) + { + this.dependencies = new HashSet<>(); + } + return dependencies; + } + + public PluginToolsRequest setDependencies( Set dependencies ) + { + this.dependencies = dependencies; + return this; + } + + public List getRemoteRepos() + { + return remoteRepos; + } + + public PluginToolsRequest setRemoteRepos( List remoteRepos ) + { + this.remoteRepos = remoteRepos; + return this; + } + + public ArtifactRepository getLocal() + { + return local; + } + + public PluginToolsRequest setLocal( ArtifactRepository local ) + { + this.local = local; + return this; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java new file mode 100644 index 000000000..b905b0a8f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java @@ -0,0 +1,54 @@ +package org.apache.maven.tools.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.MojoDescriptor; + +/** + * Extensions to MojoDescriptor added to Maven 3, then are not available when run under Maven2. + * @author Kristian Rosenvold + */ +public class ExtendedMojoDescriptor + extends MojoDescriptor +{ + private boolean threadSafe = false; + + private String requiresDependencyCollection = null; + + public boolean isThreadSafe() + { + return threadSafe; + } + + public void setThreadSafe( boolean threadSafe ) + { + this.threadSafe = threadSafe; + } + + public String getDependencyCollectionRequired() + { + return requiresDependencyCollection; + } + + public void setDependencyCollectionRequired( String requiresDependencyCollection ) + { + this.requiresDependencyCollection = requiresDependencyCollection; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java new file mode 100644 index 000000000..f609a83b7 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java @@ -0,0 +1,143 @@ +package org.apache.maven.tools.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; + +import java.util.List; +import java.util.Set; + +/** + * Request that encapsulates all information relevant to the process of extracting + * {@link org.apache.maven.plugin.descriptor.MojoDescriptor MojoDescriptor} + * instances from metadata for a certain type of mojo. + * + * @author jdcasey + * @since 2.5 + */ +public interface PluginToolsRequest +{ + + /** + * @return Return the current {@link MavenProject} instance in use. + */ + MavenProject getProject(); + + /** + * @param project the current {@link MavenProject} + * @see PluginToolsRequest#getProject() + * @return This request. + */ + PluginToolsRequest setProject( MavenProject project ); + + /** + * @return Return the {@link PluginDescriptor} currently being populated as part of the build of the + * current plugin project. + */ + PluginDescriptor getPluginDescriptor(); + + /** + * @see PluginToolsRequest#getPluginDescriptor() + * @param pluginDescriptor the {@link PluginDescriptor} + * @return This request. + */ + PluginToolsRequest setPluginDescriptor( PluginDescriptor pluginDescriptor ); + + /** + * Gets the file encoding of the source files. + * + * @return The file encoding of the source files, never null. + */ + String getEncoding(); + + /** + * Sets the file encoding of the source files. + * + * @param encoding The file encoding of the source files, may be empty or null to use the platform's + * default encoding. + * @return This request. + */ + PluginToolsRequest setEncoding( String encoding ); + + /** + * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the + * descriptor generator mojo is bound to generate-resources phase. + * But for annotations, the compiled classes are needed, so skip error + * @param skipErrorNoDescriptorsFound true to skip errors because of not found descriptors + * @return This request. + * @since 3.0 + */ + PluginToolsRequest setSkipErrorNoDescriptorsFound( boolean skipErrorNoDescriptorsFound ); + + /** + * @return true if no descriptor found should not cause a failure + * @since 3.0 + */ + boolean isSkipErrorNoDescriptorsFound(); + + /** + * Returns the list of {@link Artifact} used in class path scanning for annotations + * + * @return the dependencies + * @since 3.0 + */ + Set getDependencies(); + + /** + * @param dependencies the dependencies + * @return This request. + * @since 3.0 + */ + PluginToolsRequest setDependencies( Set dependencies ); + + /** + * + * @return the remote repositories + * @since 3.0 + */ + List getRemoteRepos(); + + /** + * + * @param remoteRepos the remote repositories + * @return This request. + * @since 3.0 + */ + PluginToolsRequest setRemoteRepos( List remoteRepos ); + + /** + * + * @return the local artifact repository + * @since 3.0 + */ + ArtifactRepository getLocal(); + + /** + * + * @param local the local repository + * @return This request. + * @since 3.0 + */ + PluginToolsRequest setLocal( ArtifactRepository local ); + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java new file mode 100644 index 000000000..8787a08b6 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java @@ -0,0 +1,233 @@ +package org.apache.maven.tools.plugin.extractor; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; + +/** + * @author jdcasey + */ +public abstract class AbstractScriptedMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor +{ + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + getLogger().debug( "Running: " + getClass().getName() ); + String metadataExtension = getMetadataFileExtension( request ); + String scriptExtension = getScriptFileExtension( request ); + + MavenProject project = request.getProject(); + + @SuppressWarnings( "unchecked" ) + Map> scriptFilesKeyedByBasedir = + gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request ); + + List mojoDescriptors; + if ( !StringUtils.isEmpty( metadataExtension ) ) + { + @SuppressWarnings( "unchecked" ) + Map> metadataFilesKeyedByBasedir = + gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), metadataExtension, + request ); + + mojoDescriptors = extractMojoDescriptorsFromMetadata( metadataFilesKeyedByBasedir, request ); + } + else + { + mojoDescriptors = extractMojoDescriptors( scriptFilesKeyedByBasedir, request ); + } + + copyScriptsToOutputDirectory( scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request ); + + return mojoDescriptors; + } + + /** + * @param scriptFilesKeyedByBasedir not null + * @param outputDirectory not null + * @param request the request + * @throws ExtractionException if any + */ + protected void copyScriptsToOutputDirectory( Map> scriptFilesKeyedByBasedir, + String outputDirectory, PluginToolsRequest request ) + throws ExtractionException + { + File outputDir = new File( outputDirectory ); + + if ( !outputDir.exists() ) + { + outputDir.mkdirs(); + } + + for ( Map.Entry> entry : scriptFilesKeyedByBasedir.entrySet() ) + { + File sourceDir = new File( entry.getKey() ); + + Set scripts = entry.getValue(); + + for ( File scriptFile : scripts ) + { + String relativePath = scriptFile.getPath().substring( sourceDir.getPath().length() ); + + if ( relativePath.charAt( 0 ) == File.separatorChar ) + { + relativePath = relativePath.substring( 1 ); + } + + File outputFile = new File( outputDir, relativePath ).getAbsoluteFile(); + + if ( !outputFile.getParentFile().exists() ) + { + outputFile.getParentFile().mkdirs(); + } + + try + { + FileUtils.copyFile( scriptFile, outputFile ); + } + catch ( IOException e ) + { + throw new ExtractionException( + "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e ); + } + } + } + } + + /** + * @param basedir not null + * @param directories not null + * @param scriptFileExtension not null + * @param request the request + * @return map with subdirs paths as key + */ + protected Map> gatherFilesByBasedir( File basedir, List directories, + String scriptFileExtension, PluginToolsRequest request ) + { + Map> sourcesByBasedir = new TreeMap<>(); + + for ( String resourceDir : directories ) + { + Set sources = new HashSet<>(); + + getLogger().debug( "Scanning script dir: " + resourceDir + " with extractor: " + getClass().getName() ); + File dir = new File( resourceDir ); + if ( !dir.isAbsolute() ) + { + dir = new File( basedir, resourceDir ).getAbsoluteFile(); + } + + resourceDir = dir.getPath(); + + if ( dir.exists() ) + { + DirectoryScanner scanner = new DirectoryScanner(); + + scanner.setBasedir( dir ); + scanner.addDefaultExcludes(); + scanner.setIncludes( new String[]{"**/*" + scriptFileExtension} ); + scanner.scan(); + + String[] relativePaths = scanner.getIncludedFiles(); + + for ( String relativePath : relativePaths ) + { + File scriptFile = new File( dir, relativePath ).getAbsoluteFile(); + + if ( scriptFile.isFile() && relativePath.endsWith( scriptFileExtension ) ) + { + sources.add( scriptFile ); + } + } + + sourcesByBasedir.put( resourceDir, sources ); + } + } + + return sourcesByBasedir; + } + + /** + * Should be implemented in the sub classes. + * + * @param metadataFilesByBasedir could be null + * @param request The plugin request, never null. + * @return always null + * @throws ExtractionException if any + * @throws InvalidPluginDescriptorException if any + */ + protected List extractMojoDescriptorsFromMetadata( Map> metadataFilesByBasedir, + PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + return null; + } + + /** + * Should be implemented in the sub classes. + * @param request the request + * @return always null + */ + protected String getMetadataFileExtension( PluginToolsRequest request ) + { + return null; + } + + /** + * Should be implemented in the sub classes. + * + * @param scriptFilesKeyedByBasedir could be null + * @param request The plugin request, never null. + * @return always null + * @throws ExtractionException if any + * @throws InvalidPluginDescriptorException if any + */ + protected List extractMojoDescriptors( Map> scriptFilesKeyedByBasedir, + PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + return null; + } + + /** + * @param request the request + * @return the file extension like .bsh for BeanShell. + */ + protected abstract String getScriptFileExtension( PluginToolsRequest request ); + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/ExtractionException.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/ExtractionException.java new file mode 100644 index 000000000..e71bd1f2b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/ExtractionException.java @@ -0,0 +1,49 @@ +package org.apache.maven.tools.plugin.extractor; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Wrap errors when extraction exception occurred. + * + * @author Vincent Siveton + */ +public class ExtractionException + extends Exception +{ + /** serialVersionUID */ + static final long serialVersionUID = 9074953540861573535L; + + /** + * @param message given message + * @param cause given cause + */ + public ExtractionException( String message, Throwable cause ) + { + super( message, cause ); + } + + /** + * @param message a given message + */ + public ExtractionException( String message ) + { + super( message ); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java new file mode 100644 index 000000000..ec3625f2b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java @@ -0,0 +1,47 @@ +package org.apache.maven.tools.plugin.extractor; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; + +import java.util.List; + +/** + * @author jdcasey + */ +public interface MojoDescriptorExtractor +{ + /** Plexus role for lookup */ + String ROLE = MojoDescriptorExtractor.class.getName(); + + /** + * Execute the mojo extraction. + * + * @param request The {@link PluginToolsRequest} containing information for the extraction process. + * @return a list of mojo descriptors. + * @throws ExtractionException if any + * @throws InvalidPluginDescriptorException if any + * @since 2.5 + */ + List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException; +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java new file mode 100644 index 000000000..942a26b6a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java @@ -0,0 +1,157 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.codehaus.plexus.util.StringUtils; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author jdcasey + */ +public class DefaultMojoScanner + extends AbstractLogEnabled + implements MojoScanner +{ + + private Map mojoDescriptorExtractors; + + /** + * The names of the active extractors + */ + private Set activeExtractors; + + /** + * Default constructor + * + * @param extractors not null + */ + public DefaultMojoScanner( Map extractors ) + { + this.mojoDescriptorExtractors = extractors; + + this.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "standalone-scanner-logger" ) ); + } + + /** + * Empty constructor + */ + public DefaultMojoScanner() + { + // nop + } + + /** + * {@inheritDoc} + */ + public void populatePluginDescriptor( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Logger logger = getLogger(); + Set activeExtractorsInternal = getActiveExtractors(); + + logger.debug( "Using " + activeExtractorsInternal.size() + " mojo extractors." ); + + int numMojoDescriptors = 0; + + for ( String extractorId : activeExtractorsInternal ) + { + MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get( extractorId ); + + if ( extractor == null ) + { + throw new ExtractionException( "No mojo extractor with '" + extractorId + "' id." ); + } + + logger.debug( "Applying " + extractorId + " mojo extractor" ); + + List extractorDescriptors = extractor.execute( request ); + + logger.info( extractorId + " mojo extractor found " + extractorDescriptors.size() + + " mojo descriptor" + ( extractorDescriptors.size() > 1 ? "s" : "" ) + "." ); + numMojoDescriptors += extractorDescriptors.size(); + + for ( MojoDescriptor descriptor : extractorDescriptors ) + { + logger.debug( "Adding mojo: " + descriptor + " to plugin descriptor." ); + + descriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + request.getPluginDescriptor().addMojo( descriptor ); + } + } + + if ( numMojoDescriptors == 0 && !request.isSkipErrorNoDescriptorsFound() ) + { + throw new InvalidPluginDescriptorException( + "No mojo definitions were found for plugin: " + request.getPluginDescriptor().getPluginLookupKey() + + "." ); + } + } + + /** + * Gets the name of the active extractors. + * + * @return A Set containing the names of the active extractors. + */ + protected Set getActiveExtractors() + { + Set result = activeExtractors; + + if ( result == null ) + { + result = new HashSet<>( mojoDescriptorExtractors.keySet() ); + } + + return result; + } + + public void setActiveExtractors( Set extractors ) + { + if ( extractors == null ) + { + this.activeExtractors = null; + } + else + { + this.activeExtractors = new HashSet<>(); + + for ( String extractor : extractors ) + { + if ( StringUtils.isNotEmpty( extractor ) ) + { + this.activeExtractors.add( extractor ); + } + } + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/MojoScanner.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/MojoScanner.java new file mode 100644 index 000000000..3a4f36cc1 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/MojoScanner.java @@ -0,0 +1,59 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; + +import java.util.Set; + +/** + * @author jdcasey + * + */ +public interface MojoScanner +{ + /** Plexus role for lookup */ + String ROLE = MojoScanner.class.getName(); + + /** + * @param request not null + * @throws ExtractionException if any + * @throws InvalidPluginDescriptorException if any + * @since 2.5 + */ + void populatePluginDescriptor( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException; + + /** + *

    + * Sets the active extractors. + *

    + *

    + * Only the specified extractors will be used, all others will be skipped. + *

    + * @param extractors The names of the active extractors. If this parameter is null, + * all the scanner's extractors are considered active. Set entries that are null or + * empty ("") will be ignored. + */ + void setActiveExtractors( Set extractors ); + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java new file mode 100644 index 000000000..378b5f7f7 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java @@ -0,0 +1,146 @@ +package org.apache.maven.tools.plugin.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; + +/** + * Convenience methods to play with Maven plugins. + * + * @author jdcasey + * + */ +public final class PluginUtils +{ + private PluginUtils() + { + // nop + } + + /** + * Expression associated with class types to recognize Maven objects (injected in fact as parameters by + * maven-core's PluginParameterExpressionEvaluator) like components ("real" components are injected by Plexus). + * + * @deprecated wrong approach (fake components), documented parameter default values instead to learn people how to + * discover them + */ + public static final Map MAVEN_COMPONENTS; + static + { + Map mavenComponents = new HashMap<>(); + + mavenComponents.put( "org.apache.maven.execution.MavenSession", "${session}" ); + mavenComponents.put( "org.apache.maven.project.MavenProject", "${project}" ); + mavenComponents.put( "org.apache.maven.plugin.MojoExecution", "${mojoExecution}" ); + mavenComponents.put( "org.apache.maven.plugin.descriptor.PluginDescriptor", "${plugin}" ); + mavenComponents.put( "org.apache.maven.settings.Settings", "${settings}" ); + + MAVEN_COMPONENTS = Collections.unmodifiableMap( mavenComponents ); + } + + /** + * @param basedir not null + * @param include not null + * @return list of included files with default SCM excluded files + */ + public static String[] findSources( String basedir, String include ) + { + return PluginUtils.findSources( basedir, include, null ); + } + + /** + * @param basedir not null + * @param include not null + * @param exclude could be null + * @return list of included files + */ + public static String[] findSources( String basedir, String include, String exclude ) + { + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir( basedir ); + scanner.setIncludes( new String[] { include } ); + if ( !StringUtils.isEmpty( exclude ) ) + { + scanner.setExcludes( new String[] { exclude, StringUtils.join( FileUtils.getDefaultExcludes(), "," ) } ); + } + else + { + scanner.setExcludes( FileUtils.getDefaultExcludes() ); + } + + scanner.scan(); + + return scanner.getIncludedFiles(); + } + + /** + * Sorts the specified mojo descriptors by goal name. + * + * @param mojoDescriptors The mojo descriptors to sort, may be null. + * @see MojoDescriptor#getGoal() + */ + public static void sortMojos( List mojoDescriptors ) + { + if ( mojoDescriptors != null ) + { + Collections.sort( mojoDescriptors, new Comparator() + { + /** {@inheritDoc} */ + public int compare( MojoDescriptor mojo0, MojoDescriptor mojo1 ) + { + return mojo0.getGoal().compareToIgnoreCase( mojo1.getGoal() ); + } + } ); + } + } + + /** + * Sorts the specified mojo parameters by name. + * + * @param parameters The mojo parameters to sort, may be null. + * @see Parameter#getName() + * @since 2.4.4 + */ + public static void sortMojoParameters( List parameters ) + { + if ( parameters != null ) + { + Collections.sort( parameters, new Comparator() + { + /** {@inheritDoc} */ + public int compare( Parameter parameter1, Parameter parameter2 ) + { + return parameter1.getName().compareToIgnoreCase( parameter2.getName() ); + } + } ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/resources/META-INF/plexus/components.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 000000000..bea45db20 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,42 @@ + + + + + + + + org.apache.maven.tools.plugin.scanner.MojoScanner + org.apache.maven.tools.plugin.scanner.DefaultMojoScanner + per-lookup + + + org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor + mojoDescriptorExtractors + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/apt/index.apt new file mode 100644 index 000000000..72644a073 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/apt/index.apt @@ -0,0 +1,36 @@ + ------ + Introduction + ------ + Vincent Siveton + ------ + 2012-05-14 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Tool API + + The Maven Plugin Tool API is the API to extract descriptors for all supported Maven plugins. + + Main component is {{{./apidocs/org/apache/maven/tools/plugin/scanner/MojoScanner.html}MojoScanner}}. + + Each descriptor extractor needs to implement + {{{./apidocs/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.html}MojoDescriptorExtractor}}. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScannerTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScannerTest.java new file mode 100644 index 000000000..eeb1031fd --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScannerTest.java @@ -0,0 +1,207 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.model.Build; +import org.apache.maven.model.Model; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author jdcasey + */ +public class DefaultMojoScannerTest +{ + private Map extractors; + + private Build build; + + private Model model; + + private MojoScanner scanner; + + private MavenProject project; + + @Before + public void setUp() + { + extractors = new HashMap<>(); + extractors.put( "one", new ScannerTestExtractor( "one" ) ); + extractors.put( "two", new ScannerTestExtractor( "two" ) ); + extractors.put( "three", new ScannerTestExtractor( "three" ) ); + + scanner = new DefaultMojoScanner( extractors ); + + build = new Build(); + build.setSourceDirectory( "testdir" ); + + model = new Model(); + model.setBuild( build ); + + project = new MavenProject( model ); + project.setFile( new File( "." ) ); + } + + @Test + public void testUnspecifiedExtractors() + throws Exception + { + PluginDescriptor pluginDescriptor = createPluginDescriptor(); + + scanner.populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + + checkResult( pluginDescriptor, extractors.keySet() ); + } + + @Test + public void testSpecifiedExtractors() + throws Exception + { + Set activeExtractors = new HashSet<>(); + activeExtractors.add( "one" ); + activeExtractors.add( "" ); + activeExtractors.add( null ); + activeExtractors.add( "three" ); + + PluginDescriptor pluginDescriptor = createPluginDescriptor(); + + scanner.setActiveExtractors( activeExtractors ); + scanner.populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + + checkResult( pluginDescriptor, Arrays.asList( "one", "three" ) ); + } + + @Test + public void testAllExtractorsThroughNull() + throws Exception + { + PluginDescriptor pluginDescriptor = createPluginDescriptor(); + + scanner.setActiveExtractors( null ); + scanner.populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + + checkResult( pluginDescriptor, extractors.keySet() ); + } + + @Test + public void testNoExtractorsThroughEmptySet() + throws Exception + { + PluginDescriptor pluginDescriptor = createPluginDescriptor(); + + scanner.setActiveExtractors( Collections.emptySet() ); + try + { + scanner.populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + fail( "Expected exception" ); + } + catch (InvalidPluginDescriptorException e) + { + // Ok + } + + checkResult( pluginDescriptor, Collections.emptySet() ); + } + + @Test + public void testUnknownExtractor() + throws Exception + { + Set activeExtractors = new HashSet<>(); + activeExtractors.add( "four" ); + + PluginDescriptor pluginDescriptor = createPluginDescriptor(); + + scanner.setActiveExtractors( activeExtractors ); + + try + { + scanner.populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + fail( "No error for unknown extractor" ); + } + catch ( ExtractionException e ) + { + // Ok + } + + checkResult( pluginDescriptor, Collections.emptySet() ); + } + + private PluginDescriptor createPluginDescriptor() + { + PluginDescriptor pluginDescriptor = new PluginDescriptor(); + pluginDescriptor.setGroupId( "groupId" ); + pluginDescriptor.setArtifactId( "artifactId" ); + pluginDescriptor.setVersion( "version" ); + pluginDescriptor.setGoalPrefix( "testId" ); + return pluginDescriptor; + } + + /** + * Checks if the {@link PluginDescriptor} contains exactly the {@link MojoDescriptor}s with the + * supplied goal names. + * + * @param pluginDescriptor The {@link PluginDescriptor} to check. + * @param expectedGoals The goal names of the {@link MojoDescriptor}s. + */ + protected void checkResult( PluginDescriptor pluginDescriptor, Collection expectedGoals ) + { + Set remainingGoals = new HashSet<>( expectedGoals ); + @SuppressWarnings( "unchecked" ) + List descriptors = pluginDescriptor.getMojos(); + + if ( descriptors == null ) + { + // TODO Maybe getMojos should be more user friendly and not return null + descriptors = Collections.emptyList(); + } + + for ( MojoDescriptor desc : descriptors ) + { + assertEquals( pluginDescriptor, desc.getPluginDescriptor() ); + assertTrue( "Unexpected goal in PluginDescriptor: " + desc.getGoal(), + remainingGoals.remove( desc.getGoal() ) ); + } + + assertEquals( "Expected goals missing from PluginDescriptor: " + remainingGoals, 0, remainingGoals.size() ); + } + +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java new file mode 100644 index 000000000..4a7a526e0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java @@ -0,0 +1,63 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; + +import java.util.Collections; +import java.util.List; + +/** + * @author jdcasey + */ +public class ScannerTestExtractor + implements MojoDescriptorExtractor +{ + private final String goal; + + public ScannerTestExtractor( String goal ) + { + this.goal = goal; + } + + public List execute( MavenProject project, PluginDescriptor pluginDescriptor ) + throws InvalidPluginDescriptorException, ExtractionException + { + return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + } + + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + MojoDescriptor desc = new MojoDescriptor(); + desc.setPluginDescriptor( request.getPluginDescriptor() ); + desc.setGoal( goal ); + + return Collections.singletonList( desc ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java new file mode 100644 index 000000000..d228a49c0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java @@ -0,0 +1,53 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; + +import java.util.Collections; +import java.util.List; + +/** + * @author jdcasey + */ +public class TestExtractor + implements MojoDescriptorExtractor +{ + + public List execute( MavenProject project, PluginDescriptor pluginDescriptor ) + { + return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); + } + + public List execute( PluginToolsRequest request ) + { + MojoDescriptor desc = new MojoDescriptor(); + desc.setPluginDescriptor( request.getPluginDescriptor() ); + desc.setGoal( "testGoal" ); + + return Collections.singletonList( desc ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java new file mode 100644 index 000000000..a5c740b89 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java @@ -0,0 +1,66 @@ +package org.apache.maven.tools.plugin.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.testing.AbstractMojoTestCase; + +/** + * @author jdcasey + */ +public class PluginUtilsTest + extends AbstractMojoTestCase +{ + public void testShouldTrimArtifactIdToFindPluginId() + { + assertEquals( "artifactId", PluginDescriptor.getGoalPrefixFromArtifactId( "maven-artifactId-plugin" ) ); + assertEquals( "artifactId", PluginDescriptor.getGoalPrefixFromArtifactId( "maven-plugin-artifactId" ) ); + assertEquals( "artifactId", PluginDescriptor.getGoalPrefixFromArtifactId( "artifactId-maven-plugin" ) ); + assertEquals( "artifactId", PluginDescriptor.getGoalPrefixFromArtifactId( "artifactId" ) ); + assertEquals( "artifactId", PluginDescriptor.getGoalPrefixFromArtifactId( "artifactId-plugin" ) ); + assertEquals( "plugin", PluginDescriptor.getGoalPrefixFromArtifactId( "maven-plugin-plugin" ) ); + } + + public void testShouldFindTwoScriptsWhenNoExcludesAreGiven() + { + String testScript = "test.txt"; + + String basedir = TestUtils.dirname( testScript ); + + String includes = "**/*.txt"; + + String[] files = PluginUtils.findSources( basedir, includes ); + assertEquals( 2, files.length ); + } + + public void testShouldFindOneScriptsWhenAnExcludeIsGiven() + { + String testScript = "test.txt"; + + String basedir = TestUtils.dirname( testScript ); + + String includes = "**/*.txt"; + String excludes = "**/*Excludes.txt"; + + String[] files = PluginUtils.findSources( basedir, includes, excludes ); + assertEquals( 1, files.length ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/TestUtils.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/TestUtils.java new file mode 100644 index 000000000..b96d871ac --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/TestUtils.java @@ -0,0 +1,72 @@ +package org.apache.maven.tools.plugin.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.junit.Test; + +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; + +import static org.junit.Assert.assertEquals; + +/** + * @author jdcasey + */ +public class TestUtils +{ + + @Test + public void testDirnameFunction_METATEST() throws UnsupportedEncodingException + { + String classname = getClass().getName().replace( '.', '/' ) + ".class"; + String basedir = TestUtils.dirname( classname ); + + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + URL resource = cl.getResource( classname ); + + assertEquals( URLDecoder.decode( resource.getPath(), "UTF-8" ), basedir + classname ); + } + + public static String dirname( String file ) + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + URL fileResource = cl.getResource( file ); + + String fullPath = fileResource.getPath(); + + String path = fullPath.substring( 0, fullPath.length() - file.length() ); + + try + { + /* + * FIXME: URL encoding and HTML form encoding are not the same. Use FileUtils.toFile(URL) from plexus-utils + * once PLXUTILS-56 is released. + */ + // necessary for JDK 1.5+, where spaces are escaped to %20 + return URLDecoder.decode( path, "UTF-8" ); + } + catch ( UnsupportedEncodingException e ) + { + throw new Error( "Broken JVM, UTF-8 must be supported", e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MojoStub.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MojoStub.java new file mode 100644 index 000000000..00abbaede --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MojoStub.java @@ -0,0 +1,99 @@ +package org.apache.maven.tools.plugin.util.stubs; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Map; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; + +/** + * Dummy Mojo. + * + * @goal dummy + */ +public class MojoStub + extends AbstractMojo +{ + /** {@inheritDoc} */ + public Log getLog() + { + return super.getLog(); + } + + /** {@inheritDoc} */ + public Map getPluginContext() + { + return super.getPluginContext(); + } + + /** {@inheritDoc} */ + public void setLog( Log log ) + { + super.setLog( log ); + } + + /** {@inheritDoc} */ + public void setPluginContext( Map pluginContext ) + { + super.setPluginContext( pluginContext ); + } + + /** {@inheritDoc} */ + protected Object clone() + throws CloneNotSupportedException + { + return super.clone(); + } + + /** {@inheritDoc} */ + public boolean equals( Object obj ) + { + return super.equals( obj ); + } + + /** {@inheritDoc} */ + protected void finalize() + throws Throwable + { + super.finalize(); + } + + /** {@inheritDoc} */ + public int hashCode() + { + return super.hashCode(); + } + + /** {@inheritDoc} */ + public String toString() + { + return super.toString(); + } + + /** {@inheritDoc} */ + public void execute() + throws MojoExecutionException, MojoFailureException + { + + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/META-INF/plexus/scannerTestComponents.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/META-INF/plexus/scannerTestComponents.xml new file mode 100644 index 000000000..d8ebcb15a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/META-INF/plexus/scannerTestComponents.xml @@ -0,0 +1,41 @@ + + + + + + + org.apache.maven.tools.plugin.scanner.MojoScanner + org.apache.maven.tools.plugin.scanner.DefaultMojoScanner + per-lookup + + + org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor + mojoDescriptorExtractors + + + + + org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor + test + org.apache.maven.tools.plugin.scanner.TestExtractor + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/test.txt b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/test.txt new file mode 100644 index 000000000..72b5523b3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/test.txt @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +This is a test. \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/testExcludes.txt b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/testExcludes.txt new file mode 100644 index 000000000..72b5523b3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-api/src/test/resources/testExcludes.txt @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +This is a test. \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/pom.xml new file mode 100644 index 000000000..9bbbc0d04 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/pom.xml @@ -0,0 +1,129 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.6.1-SNAPSHOT + + + maven-plugin-tools-generators + + Maven Plugin Tools Generators + + The Maven Plugin Tools Generators provide content generation (XML descriptor, documentation, help goal) from + plugin descriptor extracted from plugin sources. + + + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + + + org.apache.maven + maven-model + + + + org.apache.maven.reporting + maven-reporting-api + 3.0 + + + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-velocity + + + velocity + velocity + + + + + + + org.apache.velocity + velocity + + + + org.ow2.asm + asm + + + org.ow2.asm + asm-commons + + + + + net.sf.jtidy + jtidy + r938 + + + + + org.apache.maven.reporting + maven-reporting-impl + 2.1 + test + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + test + + + + + + reporting + + + + org.codehaus.mojo + l10n-maven-plugin + 1.0-alpha-2 + + + de + fr + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java new file mode 100644 index 000000000..eea91940d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/Generator.java @@ -0,0 +1,45 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.tools.plugin.PluginToolsRequest; + +import java.io.File; + +/** + * Generate something, for instance a plugin report, from a plugin descriptor. + * + * @author Jason van Zyl + */ +public interface Generator +{ + + /** + * Execute the generation for a given plugin descriptor. + * + * @param destinationDirectory required + * @param request required + * @throws GeneratorException if any + * + * @since 2.5 + */ + void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException; +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java new file mode 100644 index 000000000..1672c5f30 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorException.java @@ -0,0 +1,33 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class GeneratorException + extends Exception +{ + public GeneratorException( String s, Throwable throwable ) + { + super( s, throwable ); + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java new file mode 100644 index 000000000..f829d60a7 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java @@ -0,0 +1,711 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.html.HTML; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.parser.ParserDelegator; + +import org.apache.maven.artifact.DependencyResolutionRequiredException; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReport; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.XMLWriter; +import org.w3c.tidy.Tidy; + +/** + * Convenience methods to play with Maven plugins. + * + * @author jdcasey + */ +public final class GeneratorUtils +{ + private GeneratorUtils() + { + // nop + } + + /** + * @param w not null writer + * @param pluginDescriptor not null + */ + public static void writeDependencies( XMLWriter w, PluginDescriptor pluginDescriptor ) + { + w.startElement( "dependencies" ); + + @SuppressWarnings( "unchecked" ) + List deps = pluginDescriptor.getDependencies(); + for ( ComponentDependency dep : deps ) + { + w.startElement( "dependency" ); + + element( w, "groupId", dep.getGroupId() ); + + element( w, "artifactId", dep.getArtifactId() ); + + element( w, "type", dep.getType() ); + + element( w, "version", dep.getVersion() ); + + w.endElement(); + } + + w.endElement(); + } + + /** + * @param w not null writer + * @param name not null + * @param value could be null + */ + public static void element( XMLWriter w, String name, String value ) + { + w.startElement( name ); + + if ( value == null ) + { + value = ""; + } + + w.writeText( value ); + + w.endElement(); + } + + public static void element( XMLWriter w, String name, String value, boolean asText ) + { + element( w, name, asText ? GeneratorUtils.toText( value ) : value ); + } + + /** + * @param dependencies not null list of Dependency + * @return list of component dependencies + */ + public static List toComponentDependencies( List dependencies ) + { + List componentDeps = new LinkedList<>(); + + for ( Dependency dependency : dependencies ) + { + ComponentDependency cd = new ComponentDependency(); + + cd.setArtifactId( dependency.getArtifactId() ); + cd.setGroupId( dependency.getGroupId() ); + cd.setVersion( dependency.getVersion() ); + cd.setType( dependency.getType() ); + + componentDeps.add( cd ); + } + + return componentDeps; + } + + /** + * Returns a literal replacement String for the specified String. This method + * produces a String that will work as a literal replacement s in the + * appendReplacement method of the {@link Matcher} class. The String produced will + * match the sequence of characters in s treated as a literal sequence. Slashes ('\') and dollar + * signs ('$') will be given no special meaning. TODO: copied from Matcher class of Java 1.5, remove once target + * platform can be upgraded + * + * @see java.util.regex.Matcher + * @param s The string to be literalized + * @return A literal string replacement + */ + private static String quoteReplacement( String s ) + { + if ( ( s.indexOf( '\\' ) == -1 ) && ( s.indexOf( '$' ) == -1 ) ) + { + return s; + } + + StringBuilder sb = new StringBuilder(); + for ( int i = 0; i < s.length(); i++ ) + { + char c = s.charAt( i ); + if ( c == '\\' ) + { + sb.append( '\\' ); + sb.append( '\\' ); + } + else if ( c == '$' ) + { + sb.append( '\\' ); + sb.append( '$' ); + } + else + { + sb.append( c ); + } + } + + return sb.toString(); + } + + /** + * Decodes javadoc inline tags into equivalent HTML tags. For instance, the inline tag "{@code }" should be + * rendered as "<A&B>". + * + * @param description The javadoc description to decode, may be null. + * @return The decoded description, never null. + */ + static String decodeJavadocTags( String description ) + { + if ( StringUtils.isEmpty( description ) ) + { + return ""; + } + + StringBuffer decoded = new StringBuffer( description.length() + 1024 ); + + Matcher matcher = Pattern.compile( "\\{@(\\w+)\\s*([^\\}]*)\\}" ).matcher( description ); + while ( matcher.find() ) + { + String tag = matcher.group( 1 ); + String text = matcher.group( 2 ); + text = StringUtils.replace( text, "&", "&" ); + text = StringUtils.replace( text, "<", "<" ); + text = StringUtils.replace( text, ">", ">" ); + if ( "code".equals( tag ) ) + { + text = "" + text + ""; + } + else if ( "link".equals( tag ) || "linkplain".equals( tag ) || "value".equals( tag ) ) + { + String pattern = "(([^#\\.\\s]+\\.)*([^#\\.\\s]+))?" + "(#([^\\(\\s]*)(\\([^\\)]*\\))?\\s*(\\S.*)?)?"; + final int label = 7; + final int clazz = 3; + final int member = 5; + final int args = 6; + Matcher link = Pattern.compile( pattern ).matcher( text ); + if ( link.matches() ) + { + text = link.group( label ); + if ( StringUtils.isEmpty( text ) ) + { + text = link.group( clazz ); + if ( StringUtils.isEmpty( text ) ) + { + text = ""; + } + if ( StringUtils.isNotEmpty( link.group( member ) ) ) + { + if ( StringUtils.isNotEmpty( text ) ) + { + text += '.'; + } + text += link.group( member ); + if ( StringUtils.isNotEmpty( link.group( args ) ) ) + { + text += "()"; + } + } + } + } + if ( !"linkplain".equals( tag ) ) + { + text = "" + text + ""; + } + } + matcher.appendReplacement( decoded, ( text != null ) ? quoteReplacement( text ) : "" ); + } + matcher.appendTail( decoded ); + + return decoded.toString(); + } + + /** + * Fixes some javadoc comment to become a valid XHTML snippet. + * + * @param description Javadoc description with HTML tags, may be null. + * @return The description with valid XHTML tags, never null. + */ + public static String makeHtmlValid( String description ) + { + if ( StringUtils.isEmpty( description ) ) + { + return ""; + } + + String commentCleaned = decodeJavadocTags( description ); + + // Using jTidy to clean comment + Tidy tidy = new Tidy(); + tidy.setDocType( "loose" ); + tidy.setXHTML( true ); + tidy.setXmlOut( true ); + tidy.setInputEncoding( "UTF-8" ); + tidy.setOutputEncoding( "UTF-8" ); + tidy.setMakeClean( true ); + tidy.setNumEntities( true ); + tidy.setQuoteNbsp( false ); + tidy.setQuiet( true ); + tidy.setShowWarnings( false ); + try + { + ByteArrayOutputStream out = new ByteArrayOutputStream( commentCleaned.length() + 256 ); + tidy.parse( new ByteArrayInputStream( commentCleaned.getBytes( UTF_8 ) ), out ); + commentCleaned = out.toString( "UTF-8" ); + } + catch ( UnsupportedEncodingException e ) + { + // cannot happen as every JVM must support UTF-8, see also class javadoc for java.nio.charset.Charset + } + + if ( StringUtils.isEmpty( commentCleaned ) ) + { + return ""; + } + + // strip the header/body stuff + String ls = System.getProperty( "line.separator" ); + int startPos = commentCleaned.indexOf( "" + ls ) + 6 + ls.length(); + int endPos = commentCleaned.indexOf( ls + "" ); + commentCleaned = commentCleaned.substring( startPos, endPos ); + + return commentCleaned; + } + + /** + * Converts a HTML fragment as extracted from a javadoc comment to a plain text string. This method tries to retain + * as much of the text formatting as possible by means of the following transformations: + *
      + *
    • List items are converted to leading tabs (U+0009), followed by the item number/bullet, another tab and + * finally the item contents. Each tab denotes an increase of indentation.
    • + *
    • Flow breaking elements as well as literal line terminators in preformatted text are converted to a newline + * (U+000A) to denote a mandatory line break.
    • + *
    • Consecutive spaces and line terminators from character data outside of preformatted text will be normalized + * to a single space. The resulting space denotes a possible point for line wrapping.
    • + *
    • Each space in preformatted text will be converted to a non-breaking space (U+00A0).
    • + *
    + * + * @param html The HTML fragment to convert to plain text, may be null. + * @return A string with HTML tags converted into pure text, never null. + * @since 2.4.3 + */ + public static String toText( String html ) + { + if ( StringUtils.isEmpty( html ) ) + { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + + HTMLEditorKit.Parser parser = new ParserDelegator(); + HTMLEditorKit.ParserCallback htmlCallback = new MojoParserCallback( sb ); + + try + { + parser.parse( new StringReader( makeHtmlValid( html ) ), htmlCallback, true ); + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + + return sb.toString().replace( '\"', '\'' ); // for CDATA + } + + /** + * ParserCallback implementation. + */ + private static class MojoParserCallback + extends HTMLEditorKit.ParserCallback + { + /** + * Holds the index of the current item in a numbered list. + */ + class Counter + { + int value; + } + + /** + * A flag whether the parser is currently in the body element. + */ + private boolean body; + + /** + * A flag whether the parser is currently processing preformatted text, actually a counter to track nesting. + */ + private int preformatted; + + /** + * The current indentation depth for the output. + */ + private int depth; + + /** + * A stack of {@link Counter} objects corresponding to the nesting of (un-)ordered lists. A + * null element denotes an unordered list. + */ + private Stack numbering = new Stack<>(); + + /** + * A flag whether an implicit line break is pending in the output buffer. This flag is used to postpone the + * output of implicit line breaks until we are sure that are not to be merged with other implicit line + * breaks. + */ + private boolean pendingNewline; + + /** + * A flag whether we have just parsed a simple tag. + */ + private boolean simpleTag; + + /** + * The current buffer. + */ + private final StringBuilder sb; + + /** + * @param sb not null + */ + MojoParserCallback( StringBuilder sb ) + { + this.sb = sb; + } + + /** {@inheritDoc} */ + public void handleSimpleTag( HTML.Tag t, MutableAttributeSet a, int pos ) + { + simpleTag = true; + if ( body && HTML.Tag.BR.equals( t ) ) + { + newline( false ); + } + } + + /** {@inheritDoc} */ + public void handleStartTag( HTML.Tag t, MutableAttributeSet a, int pos ) + { + simpleTag = false; + if ( body && ( t.breaksFlow() || t.isBlock() ) ) + { + newline( true ); + } + if ( HTML.Tag.OL.equals( t ) ) + { + numbering.push( new Counter() ); + } + else if ( HTML.Tag.UL.equals( t ) ) + { + numbering.push( null ); + } + else if ( HTML.Tag.LI.equals( t ) ) + { + Counter counter = numbering.peek(); + if ( counter == null ) + { + text( "-\t" ); + } + else + { + text( ++counter.value + ".\t" ); + } + depth++; + } + else if ( HTML.Tag.DD.equals( t ) ) + { + depth++; + } + else if ( t.isPreformatted() ) + { + preformatted++; + } + else if ( HTML.Tag.BODY.equals( t ) ) + { + body = true; + } + } + + /** {@inheritDoc} */ + public void handleEndTag( HTML.Tag t, int pos ) + { + if ( HTML.Tag.OL.equals( t ) || HTML.Tag.UL.equals( t ) ) + { + numbering.pop(); + } + else if ( HTML.Tag.LI.equals( t ) || HTML.Tag.DD.equals( t ) ) + { + depth--; + } + else if ( t.isPreformatted() ) + { + preformatted--; + } + else if ( HTML.Tag.BODY.equals( t ) ) + { + body = false; + } + if ( body && ( t.breaksFlow() || t.isBlock() ) && !HTML.Tag.LI.equals( t ) ) + { + if ( ( HTML.Tag.P.equals( t ) || HTML.Tag.PRE.equals( t ) || HTML.Tag.OL.equals( t ) + || HTML.Tag.UL.equals( t ) || HTML.Tag.DL.equals( t ) ) + && numbering.isEmpty() ) + { + pendingNewline = false; + newline( pendingNewline ); + } + else + { + newline( true ); + } + } + } + + /** {@inheritDoc} */ + public void handleText( char[] data, int pos ) + { + /* + * NOTE: Parsers before JRE 1.6 will parse XML-conform simple tags like
    as "
    " followed by + * the text event ">..." so we need to watch out for the closing angle bracket. + */ + int offset = 0; + if ( simpleTag && data[0] == '>' ) + { + simpleTag = false; + for ( ++offset; offset < data.length && data[offset] <= ' '; ) + { + offset++; + } + } + if ( offset < data.length ) + { + String text = new String( data, offset, data.length - offset ); + text( text ); + } + } + + /** {@inheritDoc} */ + public void flush() + { + flushPendingNewline(); + } + + /** + * Writes a line break to the plain text output. + * + * @param implicit A flag whether this is an explicit or implicit line break. Explicit line breaks are + * always written to the output whereas consecutive implicit line breaks are merged into a single + * line break. + */ + private void newline( boolean implicit ) + { + if ( implicit ) + { + pendingNewline = true; + } + else + { + flushPendingNewline(); + sb.append( '\n' ); + } + } + + /** + * Flushes a pending newline (if any). + */ + private void flushPendingNewline() + { + if ( pendingNewline ) + { + pendingNewline = false; + if ( sb.length() > 0 ) + { + sb.append( '\n' ); + } + } + } + + /** + * Writes the specified character data to the plain text output. If the last output was a line break, the + * character data will automatically be prefixed with the current indent. + * + * @param data The character data, must not be null. + */ + private void text( String data ) + { + flushPendingNewline(); + if ( sb.length() <= 0 || sb.charAt( sb.length() - 1 ) == '\n' ) + { + for ( int i = 0; i < depth; i++ ) + { + sb.append( '\t' ); + } + } + String text; + if ( preformatted > 0 ) + { + text = data; + } + else + { + text = data.replace( '\n', ' ' ); + } + sb.append( text ); + } + } + + /** + * Find the best package name, based on the number of hits of actual Mojo classes. + * + * @param pluginDescriptor not null + * @return the best name of the package for the generated mojo + */ + public static String discoverPackageName( PluginDescriptor pluginDescriptor ) + { + Map packageNames = new HashMap<>(); + + List mojoDescriptors = pluginDescriptor.getMojos(); + if ( mojoDescriptors == null ) + { + return ""; + } + for ( MojoDescriptor descriptor : mojoDescriptors ) + { + + String impl = descriptor.getImplementation(); + if ( StringUtils.equals( descriptor.getGoal(), "help" ) && StringUtils.equals( "HelpMojo", impl ) ) + { + continue; + } + if ( impl.lastIndexOf( '.' ) != -1 ) + { + String name = impl.substring( 0, impl.lastIndexOf( '.' ) ); + if ( packageNames.get( name ) != null ) + { + int next = ( packageNames.get( name ) ).intValue() + 1; + packageNames.put( name, Integer.valueOf( next ) ); + } + else + { + packageNames.put( name, Integer.valueOf( 1 ) ); + } + } + else + { + packageNames.put( "", Integer.valueOf( 1 ) ); + } + } + + String packageName = ""; + int max = 0; + for ( Map.Entry entry : packageNames.entrySet() ) + { + int value = entry.getValue().intValue(); + if ( value > max ) + { + max = value; + packageName = entry.getKey(); + } + } + + return packageName; + } + + /** + * @param impl a Mojo implementation, not null + * @param project a MavenProject instance, could be null + * @return true is the Mojo implementation implements MavenReport, + * false otherwise. + * @throws IllegalArgumentException if any + */ + @SuppressWarnings( "unchecked" ) + public static boolean isMavenReport( String impl, MavenProject project ) + throws IllegalArgumentException + { + if ( impl == null ) + { + throw new IllegalArgumentException( "mojo implementation should be declared" ); + } + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if ( project != null ) + { + List classPathStrings; + try + { + classPathStrings = project.getCompileClasspathElements(); + if ( project.getExecutionProject() != null ) + { + classPathStrings.addAll( project.getExecutionProject().getCompileClasspathElements() ); + } + } + catch ( DependencyResolutionRequiredException e ) + { + throw new IllegalArgumentException( e ); + } + + List urls = new ArrayList<>( classPathStrings.size() ); + for ( String classPathString : classPathStrings ) + { + try + { + urls.add( new File( classPathString ).toURL() ); + } + catch ( MalformedURLException e ) + { + throw new IllegalArgumentException( e ); + } + } + + classLoader = new URLClassLoader( urls.toArray( new URL[urls.size()] ), classLoader ); + } + + try + { + Class clazz = Class.forName( impl, false, classLoader ); + + return MavenReport.class.isAssignableFrom( clazz ); + } + catch ( ClassNotFoundException e ) + { + return false; + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java new file mode 100644 index 000000000..736d301b7 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java @@ -0,0 +1,616 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w, boolean helpDescriptor ) + { + w.startElement( "mojo" ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "goal" ); + w.writeText( mojoDescriptor.getGoal() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + String description = mojoDescriptor.getDescription(); + + if ( StringUtils.isNotEmpty( description ) ) + { + w.startElement( "description" ); + if ( helpDescriptor ) + { + w.writeText( GeneratorUtils.toText( mojoDescriptor.getDescription() ) ); + } + else + { + w.writeText( mojoDescriptor.getDescription() ); + } + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.isDependencyResolutionRequired() ) ) + { + GeneratorUtils.element( w, "requiresDependencyResolution", + mojoDescriptor.isDependencyResolutionRequired() ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresDirectInvocation", + String.valueOf( mojoDescriptor.isDirectInvocationOnly() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresProject", String.valueOf( mojoDescriptor.isProjectRequired() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresReports", String.valueOf( mojoDescriptor.isRequiresReports() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "aggregator", String.valueOf( mojoDescriptor.isAggregator() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresOnline", String.valueOf( mojoDescriptor.isOnlineRequired() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "inheritedByDefault", String.valueOf( mojoDescriptor.isInheritedByDefault() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getPhase() ) ) + { + GeneratorUtils.element( w, "phase", mojoDescriptor.getPhase() ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) ) + { + GeneratorUtils.element( w, "executePhase", mojoDescriptor.getExecutePhase() ); + } + + if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteGoal() ) ) + { + GeneratorUtils.element( w, "executeGoal", mojoDescriptor.getExecuteGoal() ); + } + + if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteLifecycle() ) ) + { + GeneratorUtils.element( w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle() ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "implementation" ); + w.writeText( mojoDescriptor.getImplementation() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "language" ); + w.writeText( mojoDescriptor.getLanguage() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentConfigurator() ) ) + { + w.startElement( "configurator" ); + w.writeText( mojoDescriptor.getComponentConfigurator() ); + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentComposer() ) ) + { + w.startElement( "composer" ); + w.writeText( mojoDescriptor.getComponentComposer() ); + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "instantiationStrategy" ); + w.writeText( mojoDescriptor.getInstantiationStrategy() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement( "executionStrategy" ); + w.writeText( mojoDescriptor.getExecutionStrategy() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( mojoDescriptor.getSince() != null ) + { + w.startElement( "since" ); + + if ( StringUtils.isEmpty( mojoDescriptor.getSince() ) ) + { + w.writeText( "No version given" ); + } + else + { + w.writeText( mojoDescriptor.getSince() ); + } + + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( mojoDescriptor.getDeprecated() != null ) + { + w.startElement( "deprecated" ); + + if ( StringUtils.isEmpty( mojoDescriptor.getDeprecated() ) ) + { + w.writeText( "No reason given" ); + } + else + { + w.writeText( mojoDescriptor.getDeprecated() ); + } + + w.endElement(); + } + + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + + if ( mojoDescriptor instanceof ExtendedMojoDescriptor ) + { + ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor; + if ( extendedMojoDescriptor.getDependencyCollectionRequired() != null ) + { + GeneratorUtils.element( w, "requiresDependencyCollection", + extendedMojoDescriptor.getDependencyCollectionRequired() ); + } + + GeneratorUtils.element( w, "threadSafe", String.valueOf( extendedMojoDescriptor.isThreadSafe() ) ); + } + + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + + @SuppressWarnings( "unchecked" ) List parameters = mojoDescriptor.getParameters(); + + w.startElement( "parameters" ); + + Map requirements = new LinkedHashMap<>(); + + Set configuration = new LinkedHashSet<>(); + + if ( parameters != null ) + { + if ( helpDescriptor ) + { + PluginUtils.sortMojoParameters( parameters ); + } + + for ( Parameter parameter : parameters ) + { + String expression = getExpression( parameter ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + // treat it as a component...a requirement, in other words. + + // remove "component." plus expression delimiters + String role = expression.substring( "${component.".length(), expression.length() - 1 ); + + String roleHint = null; + + int posRoleHintSeparator = role.indexOf( '#' ); + if ( posRoleHintSeparator > 0 ) + { + roleHint = role.substring( posRoleHintSeparator + 1 ); + + role = role.substring( 0, posRoleHintSeparator ); + } + + // TODO: remove deprecated expression + requirements.put( parameter.getName(), new Requirement( role, roleHint ) ); + } + else if ( parameter.getRequirement() != null ) + { + requirements.put( parameter.getName(), parameter.getRequirement() ); + } + else if ( !helpDescriptor || parameter.isEditable() ) // don't show readonly parameters in help + { + // treat it as a normal parameter. + + w.startElement( "parameter" ); + + GeneratorUtils.element( w, "name", parameter.getName() ); + + if ( parameter.getAlias() != null ) + { + GeneratorUtils.element( w, "alias", parameter.getAlias() ); + } + + GeneratorUtils.element( w, "type", parameter.getType() ); + + if ( parameter.getSince() != null ) + { + w.startElement( "since" ); + + if ( StringUtils.isEmpty( parameter.getSince() ) ) + { + w.writeText( "No version given" ); + } + else + { + w.writeText( parameter.getSince() ); + } + + w.endElement(); + } + + if ( parameter.getDeprecated() != null ) + { + if ( StringUtils.isEmpty( parameter.getDeprecated() ) ) + { + GeneratorUtils.element( w, "deprecated", "No reason given" ); + } + else + { + GeneratorUtils.element( w, "deprecated", parameter.getDeprecated() ); + } + } + + if ( parameter.getImplementation() != null ) + { + GeneratorUtils.element( w, "implementation", parameter.getImplementation() ); + } + + GeneratorUtils.element( w, "required", Boolean.toString( parameter.isRequired() ) ); + + GeneratorUtils.element( w, "editable", Boolean.toString( parameter.isEditable() ) ); + + GeneratorUtils.element( w, "description", parameter.getDescription(), helpDescriptor ); + + if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) || StringUtils.isNotEmpty( + parameter.getExpression() ) ) + { + configuration.add( parameter ); + } + + w.endElement(); + } + + } + } + + w.endElement(); + + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + + if ( !configuration.isEmpty() ) + { + w.startElement( "configuration" ); + + for ( Parameter parameter : configuration ) + { + if ( helpDescriptor && !parameter.isEditable() ) + { + // don't show readonly parameters in help + continue; + } + + w.startElement( parameter.getName() ); + + String type = parameter.getType(); + if ( StringUtils.isNotEmpty( type ) ) + { + w.addAttribute( "implementation", type ); + } + + if ( parameter.getDefaultValue() != null ) + { + w.addAttribute( "default-value", parameter.getDefaultValue() ); + } + + if ( StringUtils.isNotEmpty( parameter.getExpression() ) ) + { + w.writeText( parameter.getExpression() ); + } + + w.endElement(); + } + + w.endElement(); + } + + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + + if ( !requirements.isEmpty() && !helpDescriptor ) + { + w.startElement( "requirements" ); + + for ( Map.Entry entry : requirements.entrySet() ) + { + String key = entry.getKey(); + Requirement requirement = entry.getValue(); + + w.startElement( "requirement" ); + + GeneratorUtils.element( w, "role", requirement.getRole() ); + + if ( StringUtils.isNotEmpty( requirement.getRoleHint() ) ) + { + GeneratorUtils.element( w, "role-hint", requirement.getRoleHint() ); + } + + GeneratorUtils.element( w, "field-name", key ); + + w.endElement(); + } + + w.endElement(); + } + + w.endElement(); + } + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java new file mode 100644 index 000000000..d86144de2 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java @@ -0,0 +1,437 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.velocity.VelocityContext; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.PropertyUtils; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.velocity.VelocityComponent; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.commons.ClassRemapper; +import org.objectweb.asm.commons.Remapper; +import org.objectweb.asm.commons.SimpleRemapper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Properties; + +/** + * Generates an HelpMojo class from help-class-source.vm template. + * The generated mojo reads help content from META-INF/maven/${groupId}/${artifactId}/plugin-help.xml + * resource, which is generated by this {@link PluginDescriptorGenerator}. + *

    Notice that the help mojo source needs to be generated before compilation, but when Java annotations are used, + * plugin descriptor content is available only after compilation (detecting annotations in .class files): + * help mojo source can be generated with empty package only (and no plugin descriptor available yet), then needs + * to be updated after compilation - through {@link #rewriteHelpMojo(PluginToolsRequest, Log)} which is called from + * plugin descriptor XML generation.

    + * + * @author Vincent Siveton + * @since 2.4 + */ +public class PluginHelpGenerator + extends AbstractLogEnabled + implements Generator +{ + /** + * Default generated class name + */ + private static final String HELP_MOJO_CLASS_NAME = "HelpMojo"; + + /** + * Help properties file, to store data about generated source. + */ + private static final String HELP_PROPERTIES_FILENAME = "maven-plugin-help.properties"; + + /** + * Default goal + */ + private static final String HELP_GOAL = "help"; + + private String helpPackageName; + + private boolean useAnnotations; + + private VelocityComponent velocityComponent; + + /** + * Default constructor + */ + public PluginHelpGenerator() + { + this.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "PluginHelpGenerator" ) ); + } + + // ---------------------------------------------------------------------- + // Public methods + // ---------------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + String helpImplementation = getImplementation( pluginDescriptor ); + + @SuppressWarnings( "unchecked" ) List mojoDescriptors = pluginDescriptor.getMojos(); + + if ( mojoDescriptors != null ) + { + // Verify that no help goal already exists + MojoDescriptor descriptor = pluginDescriptor.getMojo( HELP_GOAL ); + + if ( ( descriptor != null ) && !descriptor.getImplementation().equals( helpImplementation ) ) + { + if ( getLogger().isWarnEnabled() ) + { + getLogger().warn( "\n\nA help goal (" + descriptor.getImplementation() + + ") already exists in this plugin. SKIPPED THE " + helpImplementation + + " GENERATION.\n" ); + } + + return; + } + } + + writeHelpPropertiesFile( request, destinationDirectory ); + + useAnnotations = request.getProject().getArtifactMap().containsKey( + "org.apache.maven.plugin-tools:maven-plugin-annotations" ); + + try + { + String sourcePath = helpImplementation.replace( '.', File.separatorChar ) + ".java"; + + File helpClass = new File( destinationDirectory, sourcePath ); + helpClass.getParentFile().mkdirs(); + + String helpClassSources = + getHelpClassSources( getPluginHelpPath( request.getProject() ), pluginDescriptor ); + + FileUtils.fileWrite( helpClass, request.getEncoding(), helpClassSources ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + public PluginHelpGenerator setHelpPackageName( String helpPackageName ) + { + this.helpPackageName = helpPackageName; + return this; + } + + public VelocityComponent getVelocityComponent() + { + return velocityComponent; + } + + public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent ) + { + this.velocityComponent = velocityComponent; + return this; + } + + // ---------------------------------------------------------------------- + // Private methods + // ---------------------------------------------------------------------- + + private String getHelpClassSources( String pluginHelpPath, PluginDescriptor pluginDescriptor ) + throws IOException + { + Properties properties = new Properties(); + VelocityContext context = new VelocityContext( properties ); + if ( this.helpPackageName != null ) + { + properties.put( "helpPackageName", this.helpPackageName ); + } + else + { + properties.put( "helpPackageName", "" ); + } + properties.put( "pluginHelpPath", pluginHelpPath ); + properties.put( "artifactId", pluginDescriptor.getArtifactId() ); + properties.put( "goalPrefix", pluginDescriptor.getGoalPrefix() ); + properties.put( "useAnnotations", useAnnotations ); + + StringWriter stringWriter = new StringWriter(); + + // plugin-tools sources are UTF-8 (and even ASCII in this case)) + try ( InputStream is = // + Thread.currentThread().getContextClassLoader().getResourceAsStream( "help-class-source.vm" ); // + InputStreamReader isReader = new InputStreamReader( is, UTF_8 ) ) + { + //isReader = + velocityComponent.getEngine().evaluate( context, stringWriter, "", isReader ); + } + return stringWriter.toString(); + } + + /** + * @param pluginDescriptor The descriptor of the plugin for which to generate a help goal, must not be + * null. + * @return The implementation. + */ + private String getImplementation( PluginDescriptor pluginDescriptor ) + { + if ( StringUtils.isEmpty( helpPackageName ) ) + { + helpPackageName = GeneratorUtils.discoverPackageName( pluginDescriptor ); + } + + return StringUtils.isEmpty( helpPackageName ) + ? HELP_MOJO_CLASS_NAME + : helpPackageName + '.' + HELP_MOJO_CLASS_NAME; + } + + /** + * Write help properties files for later use to eventually rewrite Help Mojo. + * + * @param request + * @throws GeneratorException + * @see {@link #rewriteHelpMojo(PluginToolsRequest, Log)} + */ + private void writeHelpPropertiesFile( PluginToolsRequest request, File destinationDirectory ) + throws GeneratorException + { + Properties properties = new Properties(); + properties.put( "helpPackageName", helpPackageName == null ? "" : helpPackageName ); + properties.put( "destinationDirectory", destinationDirectory.getAbsolutePath() ); + + File tmpPropertiesFile = new File( request.getProject().getBuild().getDirectory(), HELP_PROPERTIES_FILENAME ); + + if ( tmpPropertiesFile.exists() ) + { + tmpPropertiesFile.delete(); + } + else if ( !tmpPropertiesFile.getParentFile().exists() ) + { + tmpPropertiesFile.getParentFile().mkdirs(); + } + + try ( FileOutputStream fos = new FileOutputStream( tmpPropertiesFile ) ) + { + properties.store( fos, "maven plugin help mojo generation informations" ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + static String getPluginHelpPath( MavenProject mavenProject ) + { + return "META-INF/maven/" + mavenProject.getGroupId() + "/" + mavenProject.getArtifactId() + "/plugin-help.xml"; + } + + /** + * Rewrite Help Mojo to match actual Mojos package name if it was not available at source generation + * time. This is used at descriptor generation time. + * + * @param request + * @throws GeneratorException + */ + static void rewriteHelpMojo( PluginToolsRequest request, Log log ) + throws GeneratorException + { + File tmpPropertiesFile = new File( request.getProject().getBuild().getDirectory(), HELP_PROPERTIES_FILENAME ); + + if ( !tmpPropertiesFile.exists() ) + { + return; + } + + Properties properties; + try + { + properties = PropertyUtils.loadProperties( tmpPropertiesFile ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + + String helpPackageName = properties.getProperty( "helpPackageName" ); + + // if helpPackageName property is empty, we have to rewrite the class with a better package name than empty + if ( StringUtils.isEmpty( helpPackageName ) ) + { + String destDir = properties.getProperty( "destinationDirectory" ); + File destinationDirectory; + if ( StringUtils.isEmpty( destDir ) ) + { + // writeHelpPropertiesFile() creates 2 properties: find one without the other should not be possible + log.warn( "\n\nUnexpected situation: destinationDirectory not defined in " + HELP_PROPERTIES_FILENAME + + " during help mojo source generation but expected during XML descriptor generation." ); + log.warn( "Please check helpmojo goal version used in previous build phase." ); + log.warn( "If you just upgraded to plugin-tools >= 3.2 you must run a clean build at least once." ); + destinationDirectory = new File( "target/generated-sources/plugin" ); + log.warn( "Trying default location: " + destinationDirectory ); + } + else + { + destinationDirectory = new File( destDir ); + } + String helpMojoImplementation = rewriteHelpClassToMojoPackage( request, destinationDirectory, log ); + + if ( helpMojoImplementation != null ) + { + // rewrite plugin descriptor with new HelpMojo implementation class + updateHelpMojoDescriptor( request.getPluginDescriptor(), helpMojoImplementation ); + } + } + } + + private static String rewriteHelpClassToMojoPackage( PluginToolsRequest request, File destinationDirectory, + Log log ) + throws GeneratorException + { + String destinationPackage = GeneratorUtils.discoverPackageName( request.getPluginDescriptor() ); + if ( StringUtils.isEmpty( destinationPackage ) ) + { + return null; + } + String packageAsDirectory = StringUtils.replace( destinationPackage, '.', '/' ); + + String outputDirectory = request.getProject().getBuild().getOutputDirectory(); + File helpClassFile = new File( outputDirectory, HELP_MOJO_CLASS_NAME + ".class" ); + if ( !helpClassFile.exists() ) + { + return null; + } + + // rewrite help mojo source + File helpSourceFile = new File( destinationDirectory, HELP_MOJO_CLASS_NAME + ".java" ); + if ( !helpSourceFile.exists() ) + { + log.warn( "HelpMojo.java not found in default location: " + helpSourceFile.getAbsolutePath() ); + log.warn( "Help goal source won't be moved to package: " + destinationPackage ); + } + else + { + File helpSourceFileNew = + new File( destinationDirectory, packageAsDirectory + '/' + HELP_MOJO_CLASS_NAME + ".java" ); + if ( !helpSourceFileNew.getParentFile().exists() ) + { + helpSourceFileNew.getParentFile().mkdirs(); + } + Charset encoding = Charset.forName( request.getEncoding() ); + try ( Reader sourceReader = new InputStreamReader( new FileInputStream( helpSourceFile ), // + encoding ); // + PrintWriter sourceWriter = new PrintWriter( + new OutputStreamWriter( new FileOutputStream( helpSourceFileNew ), // + encoding ) ) ) + { + sourceWriter.println( "package " + destinationPackage + ";" ); + IOUtil.copy( sourceReader, sourceWriter ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + helpSourceFileNew.setLastModified( helpSourceFile.lastModified() ); + helpSourceFile.delete(); + } + + // rewrite help mojo .class + File rewriteHelpClassFile = + new File( outputDirectory + '/' + packageAsDirectory, HELP_MOJO_CLASS_NAME + ".class" ); + if ( !rewriteHelpClassFile.getParentFile().exists() ) + { + rewriteHelpClassFile.getParentFile().mkdirs(); + } + + ClassReader cr; + try ( FileInputStream fileInputStream = new FileInputStream( helpClassFile ) ) + { + cr = new ClassReader( fileInputStream ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + + ClassWriter cw = new ClassWriter( 0 ); + + Remapper packageRemapper = + new SimpleRemapper( HELP_MOJO_CLASS_NAME, packageAsDirectory + '/' + HELP_MOJO_CLASS_NAME ); + ClassVisitor cv = new ClassRemapper( cw, packageRemapper ); + + try + { + cr.accept( cv, ClassReader.EXPAND_FRAMES ); + } + catch ( Throwable e ) + { + throw new GeneratorException( "ASM issue processing class-file " + helpClassFile.getPath(), e ); + } + + byte[] renamedClass = cw.toByteArray(); + try ( FileOutputStream fos = new FileOutputStream( rewriteHelpClassFile ) ) + { + fos.write( renamedClass ); + } + catch ( IOException e ) + { + throw new GeneratorException( "Error rewriting help class: " + e.getMessage(), e ); + } + + helpClassFile.delete(); + + return destinationPackage + ".HelpMojo"; + } + + private static void updateHelpMojoDescriptor( PluginDescriptor pluginDescriptor, String helpMojoImplementation ) + { + MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( HELP_GOAL ); + + if ( mojoDescriptor != null ) + { + mojoDescriptor.setImplementation( helpMojoImplementation ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java new file mode 100644 index 000000000..8d3aefa54 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java @@ -0,0 +1,823 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * Generate xdoc documentation for each mojo. + */ +public class PluginXdocGenerator + implements Generator +{ + /** + * locale + */ + private final Locale locale; + + /** + * project + */ + private final MavenProject project; + + /** + * Default constructor using Locale.ENGLISH as locale. + * Used only in test cases. + */ + public PluginXdocGenerator() + { + this.project = null; + this.locale = Locale.ENGLISH; + } + + /** + * Constructor using Locale.ENGLISH as locale. + * + * @param project not null Maven project. + */ + public PluginXdocGenerator( MavenProject project ) + { + this.project = project; + this.locale = Locale.ENGLISH; + } + + /** + * @param project not null. + * @param locale not null wanted locale. + */ + public PluginXdocGenerator( MavenProject project, Locale locale ) + { + this.project = project; + if ( locale == null ) + { + this.locale = Locale.ENGLISH; + } + else + { + this.locale = locale; + } + } + + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + try + { + if ( request.getPluginDescriptor().getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List mojos = request.getPluginDescriptor().getMojos(); + + for ( MojoDescriptor descriptor : mojos ) + { + processMojoDescriptor( descriptor, destinationDirectory ); + } + } + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + + } + + /** + * @param mojoDescriptor not null + * @param destinationDirectory not null + * @throws IOException if any + */ + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, File destinationDirectory ) + throws IOException + { + File outputFile = new File( destinationDirectory, getMojoFilename( mojoDescriptor, "xml" ) ); + try ( Writer writer = new OutputStreamWriter( new FileOutputStream( outputFile ), UTF_8 ) ) + { + XMLWriter w = new PrettyPrintXMLWriter( new PrintWriter( writer ), UTF_8.name(), null ); + writeBody( mojoDescriptor, w ); + + writer.flush(); + } + } + + /** + * @param mojo not null + * @param ext not null + * @return the output file name + */ + private String getMojoFilename( MojoDescriptor mojo, String ext ) + { + return mojo.getGoal() + "-mojo." + ext; + } + + /** + * @param mojoDescriptor not null + * @param w not null + */ + private void writeBody( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + w.startElement( "document" ); + w.addAttribute( "xmlns", "http://maven.apache.org/XDOC/2.0" ); + w.addAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + w.addAttribute( "xsi:schemaLocation", + "http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd" ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "properties" ); + + w.startElement( "title" ); + w.writeText( mojoDescriptor.getFullGoalName() ); + w.endElement(); // title + + w.endElement(); // properties + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "body" ); + + w.startElement( "section" ); + + w.addAttribute( "name", mojoDescriptor.getFullGoalName() ); + + writeReportNotice( mojoDescriptor, w ); + + w.startElement( "p" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.fullname" ) ); + w.endElement(); //p + w.startElement( "p" ); + w.writeMarkup( mojoDescriptor.getPluginDescriptor().getGroupId() + ":" + + mojoDescriptor.getPluginDescriptor().getArtifactId() + ":" + + mojoDescriptor.getPluginDescriptor().getVersion() + ":" + mojoDescriptor.getGoal() ); + w.endElement(); //p + + if ( StringUtils.isNotEmpty( mojoDescriptor.getDeprecated() ) ) + { + w.startElement( "p" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.deprecated" ) ); + w.endElement(); // p + w.startElement( "div" ); + w.writeMarkup( GeneratorUtils.makeHtmlValid( mojoDescriptor.getDeprecated() ) ); + w.endElement(); // div + } + + w.startElement( "p" ); + w.writeMarkup( getString( "pluginxdoc.description" ) ); + w.endElement(); //p + w.startElement( "div" ); + if ( StringUtils.isNotEmpty( mojoDescriptor.getDescription() ) ) + { + w.writeMarkup( GeneratorUtils.makeHtmlValid( mojoDescriptor.getDescription() ) ); + } + else + { + w.writeText( getString( "pluginxdoc.nodescription" ) ); + } + w.endElement(); // div + + writeGoalAttributes( mojoDescriptor, w ); + + writeGoalParameterTable( mojoDescriptor, w ); + + w.endElement(); // section + + w.endElement(); // body + + w.endElement(); // document + } + + /** + * @param mojoDescriptor not null + * @param w not null + */ + private void writeReportNotice( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + if ( GeneratorUtils.isMavenReport( mojoDescriptor.getImplementation(), project ) ) + { + w.startElement( "p" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.notice.note" ) ); + w.writeText( getString( "pluginxdoc.mojodescriptor.notice.isMavenReport" ) ); + w.endElement(); //p + } + } + + /** + * @param mojoDescriptor not null + * @param w not null + */ + private void writeGoalAttributes( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + w.startElement( "p" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.attributes" ) ); + w.endElement(); //p + + boolean addedUl = false; + String value; + if ( mojoDescriptor.isProjectRequired() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.projectRequired" ) ); + w.endElement(); //li + } + + if ( mojoDescriptor.isRequiresReports() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.reportingMojo" ) ); + w.endElement(); // li + } + + if ( mojoDescriptor.isAggregator() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.aggregator" ) ); + w.endElement(); //li + } + + if ( mojoDescriptor.isDirectInvocationOnly() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.directInvocationOnly" ) ); + w.endElement(); //li + } + + value = mojoDescriptor.isDependencyResolutionRequired(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.dependencyResolutionRequired", value ) ); + w.endElement(); //li + } + + if ( mojoDescriptor instanceof ExtendedMojoDescriptor ) + { + ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor; + + value = extendedMojoDescriptor.getDependencyCollectionRequired(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.dependencyCollectionRequired", value ) ); + w.endElement(); //li + } + + if ( extendedMojoDescriptor.isThreadSafe() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.threadSafe" ) ); + w.endElement(); //li + } + + } + + value = mojoDescriptor.getSince(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.since", value ) ); + w.endElement(); //li + } + + value = mojoDescriptor.getPhase(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.phase", value ) ); + w.endElement(); //li + } + + value = mojoDescriptor.getExecutePhase(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.executePhase", value ) ); + w.endElement(); //li + } + + value = mojoDescriptor.getExecuteGoal(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.executeGoal", value ) ); + w.endElement(); //li + } + + value = mojoDescriptor.getExecuteLifecycle(); + if ( StringUtils.isNotEmpty( value ) ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.executeLifecycle", value ) ); + w.endElement(); //li + } + + if ( mojoDescriptor.isOnlineRequired() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.onlineRequired" ) ); + w.endElement(); //li + } + + if ( !mojoDescriptor.isInheritedByDefault() ) + { + addedUl = addUl( w, addedUl ); + w.startElement( "li" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.inheritedByDefault" ) ); + w.endElement(); //li + } + + if ( addedUl ) + { + w.endElement(); //ul + } + } + + /** + * @param mojoDescriptor not null + * @param w not null + */ + private void writeGoalParameterTable( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + List parameterList = mojoDescriptor.getParameters(); + + // remove components and read-only parameters + List list = filterParameters( parameterList ); + + if ( !list.isEmpty() ) + { + writeParameterSummary( mojoDescriptor, list, w ); + + writeParameterDetails( mojoDescriptor, list, w ); + } + else + { + w.startElement( "subsection" ); + w.addAttribute( "name", getString( "pluginxdoc.mojodescriptor.parameters" ) ); + + w.startElement( "p" ); + w.writeMarkup( getString( "pluginxdoc.mojodescriptor.noParameter" ) ); + w.endElement(); //p + + w.endElement(); + } + } + + /** + * Filter parameters to only retain those which must be documented, ie not components nor readonly. + * + * @param parameterList not null + * @return the parameters list without components. + */ + private List filterParameters( List parameterList ) + { + List filtered = new ArrayList<>(); + + if ( parameterList != null ) + { + for ( Parameter parameter : parameterList ) + { + if ( parameter.isEditable() ) + { + String expression = parameter.getExpression(); + + if ( expression == null || !expression.startsWith( "${component." ) ) + { + filtered.add( parameter ); + } + } + } + } + + return filtered; + } + + /** + * @param mojoDescriptor not null + * @param parameterList not null + * @param w not null + */ + private void writeParameterDetails( MojoDescriptor mojoDescriptor, List parameterList, XMLWriter w ) + { + w.startElement( "subsection" ); + w.addAttribute( "name", getString( "pluginxdoc.mojodescriptor.parameter.details" ) ); + + for ( Iterator parameters = parameterList.iterator(); parameters.hasNext(); ) + { + Parameter parameter = parameters.next(); + + w.startElement( "h4" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.name_internal", parameter.getName() ) ); + w.endElement(); + + if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) ) + { + w.startElement( "div" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.deprecated", + GeneratorUtils.makeHtmlValid( parameter.getDeprecated() ) ) ); + w.endElement(); // div + } + + w.startElement( "div" ); + if ( StringUtils.isNotEmpty( parameter.getDescription() ) ) + { + w.writeMarkup( GeneratorUtils.makeHtmlValid( parameter.getDescription() ) ); + } + else + { + w.writeMarkup( getString( "pluginxdoc.nodescription" ) ); + } + w.endElement(); // div + + boolean addedUl = false; + addedUl = addUl( w, addedUl, parameter.getType() ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.type" ), parameter.getType(), w ); + + if ( StringUtils.isNotEmpty( parameter.getSince() ) ) + { + addedUl = addUl( w, addedUl ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.since" ), parameter.getSince(), w ); + } + else + { + if ( StringUtils.isNotEmpty( mojoDescriptor.getSince() ) ) + { + addedUl = addUl( w, addedUl ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.since" ), mojoDescriptor.getSince(), + w ); + } + } + + if ( parameter.isRequired() ) + { + addedUl = addUl( w, addedUl ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), getString( "pluginxdoc.yes" ), + w ); + } + else + { + addedUl = addUl( w, addedUl ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), getString( "pluginxdoc.no" ), + w ); + } + + String expression = parameter.getExpression(); + addedUl = addUl( w, addedUl, expression ); + String property = getPropertyFromExpression( expression ); + if ( property == null ) + { + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.expression" ), expression, w ); + } + else + { + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.property" ), property, w ); + } + + addedUl = addUl( w, addedUl, parameter.getDefaultValue() ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.default" ), + escapeXml( parameter.getDefaultValue() ), w ); + + addedUl = addUl( w, addedUl, parameter.getAlias() ); + writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.alias" ), escapeXml( parameter.getAlias() ), + w ); + + if ( addedUl ) + { + w.endElement(); //ul + } + + if ( parameters.hasNext() ) + { + w.writeMarkup( "
    " ); + } + } + + w.endElement(); + } + + private boolean addUl( XMLWriter w, boolean addedUl, String content ) + { + if ( StringUtils.isNotEmpty( content ) ) + { + return addUl( w, addedUl ); + } + return addedUl; + } + + private boolean addUl( XMLWriter w, boolean addedUl ) + { + if ( !addedUl ) + { + w.startElement( "ul" ); + addedUl = true; + } + return addedUl; + } + + private String getPropertyFromExpression( String expression ) + { + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${" ) && expression.endsWith( "}" ) + && !expression.substring( 2 ).contains( "${" ) ) + { + // expression="${xxx}" -> property="xxx" + return expression.substring( 2, expression.length() - 1 ); + } + // no property can be extracted + return null; + } + + /** + * @param param not null + * @param value could be null + * @param w not null + */ + private void writeDetail( String param, String value, XMLWriter w ) + { + if ( StringUtils.isNotEmpty( value ) ) + { + w.startElement( "li" ); + w.writeMarkup( format( "pluginxdoc.detail", new String[]{ param, value } ) ); + w.endElement(); //li + } + } + + /** + * @param mojoDescriptor not null + * @param parameterList not null + * @param w not null + */ + private void writeParameterSummary( MojoDescriptor mojoDescriptor, List parameterList, XMLWriter w ) + { + List requiredParams = getParametersByRequired( true, parameterList ); + if ( requiredParams.size() > 0 ) + { + writeParameterList( mojoDescriptor, getString( "pluginxdoc.mojodescriptor.requiredParameters" ), + requiredParams, w ); + } + + List optionalParams = getParametersByRequired( false, parameterList ); + if ( optionalParams.size() > 0 ) + { + writeParameterList( mojoDescriptor, getString( "pluginxdoc.mojodescriptor.optionalParameters" ), + optionalParams, w ); + } + } + + /** + * @param mojoDescriptor not null + * @param title not null + * @param parameterList not null + * @param w not null + */ + private void writeParameterList( MojoDescriptor mojoDescriptor, String title, List parameterList, + XMLWriter w ) + { + w.startElement( "subsection" ); + w.addAttribute( "name", title ); + + w.startElement( "table" ); + w.addAttribute( "border", "0" ); + + w.startElement( "tr" ); + w.startElement( "th" ); + w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.name" ) ); + w.endElement(); //th + w.startElement( "th" ); + w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.type" ) ); + w.endElement(); //th + w.startElement( "th" ); + w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.since" ) ); + w.endElement(); //th + w.startElement( "th" ); + w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.description" ) ); + w.endElement(); //th + w.endElement(); //tr + + for ( Parameter parameter : parameterList ) + { + w.startElement( "tr" ); + + // name + w.startElement( "td" ); + w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.name_link", parameter.getName() ) ); + w.endElement(); //td + + //type + w.startElement( "td" ); + int index = parameter.getType().lastIndexOf( "." ); + w.writeMarkup( "" + parameter.getType().substring( index + 1 ) + "" ); + w.endElement(); //td + + // since + w.startElement( "td" ); + if ( StringUtils.isNotEmpty( parameter.getSince() ) ) + { + w.writeMarkup( "" + parameter.getSince() + "" ); + } + else + { + if ( StringUtils.isNotEmpty( mojoDescriptor.getSince() ) ) + { + w.writeMarkup( "" + mojoDescriptor.getSince() + "" ); + } + else + { + w.writeMarkup( "-" ); + } + } + w.endElement(); //td + + // description + w.startElement( "td" ); + String description; + if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) ) + { + description = format( "pluginxdoc.mojodescriptor.parameter.deprecated", + GeneratorUtils.makeHtmlValid( parameter.getDeprecated() ) ); + } + else if ( StringUtils.isNotEmpty( parameter.getDescription() ) ) + { + description = GeneratorUtils.makeHtmlValid( parameter.getDescription() ); + } + else + { + description = getString( "pluginxdoc.nodescription" ); + } + w.writeMarkup( description + "
    " ); + + if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) ) + { + w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.defaultValue", + escapeXml( parameter.getDefaultValue() ) ) ); + w.writeMarkup( "
    " ); + } + + String property = getPropertyFromExpression( parameter.getExpression() ); + if ( property != null ) + { + w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.property.description", property ) ); + w.writeMarkup( "
    " ); + } + + if ( StringUtils.isNotEmpty( parameter.getAlias() ) ) + { + w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.alias.description", + escapeXml( parameter.getAlias() ) ) ); + } + + w.endElement(); //td + w.endElement(); //tr + } + + w.endElement(); //table + w.endElement(); //section + } + + /** + * @param required true for required parameters, false otherwise. + * @param parameterList not null + * @return list of parameters depending the value of required + */ + private List getParametersByRequired( boolean required, List parameterList ) + { + List list = new ArrayList<>(); + + for ( Parameter parameter : parameterList ) + { + if ( parameter.isRequired() == required ) + { + list.add( parameter ); + } + } + + return list; + } + + /** + * Gets the resource bundle for the locale instance variable. + * + * @return The resource bundle for the locale instance variable. + */ + private ResourceBundle getBundle() + { + return ResourceBundle.getBundle( "pluginxdoc", locale, getClass().getClassLoader() ); + } + + /** + * @param key not null + * @return Localized, text identified by key. + * @see #getBundle() + */ + private String getString( String key ) + { + return getBundle().getString( key ); + } + + /** + * Convenience method. + * + * @param key not null + * @param arg1 not null + * @return Localized, formatted text identified by key. + * @see #format(String, Object[]) + */ + private String format( String key, Object arg1 ) + { + return format( key, new Object[]{ arg1 } ); + } + + /** + * Looks up the value for key in the ResourceBundle, + * then formats that value for the specified Locale using args. + * + * @param key not null + * @param args not null + * @return Localized, formatted text identified by key. + */ + private String format( String key, Object[] args ) + { + String pattern = getString( key ); + // we don't need quoting so spare us the confusion in the resource bundle to double them up in some keys + pattern = StringUtils.replace( pattern, "'", "''" ); + + MessageFormat messageFormat = new MessageFormat( "" ); + messageFormat.setLocale( locale ); + messageFormat.applyPattern( pattern ); + + return messageFormat.format( args ); + } + + /** + * @param text the string to escape + * @return A string escaped with XML entities + */ + private String escapeXml( String text ) + { + if ( text != null ) + { + text = text.replaceAll( "&", "&" ); + text = text.replaceAll( "<", "<" ); + text = text.replaceAll( ">", ">" ); + text = text.replaceAll( "\"", """ ); + text = text.replaceAll( "\'", "'" ); + } + return text; + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/help-class-source.vm b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/help-class-source.vm new file mode 100644 index 000000000..b46787367 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/help-class-source.vm @@ -0,0 +1,490 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. + +#if ($helpPackageName.length()>0) +package ${helpPackageName}; +#end + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +#if ( $useAnnotations ) +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +#end + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Display help information on ${artifactId}.
    + * Call mvn ${goalPrefix}:help -Ddetail=true -Dgoal=<goal-name> to display parameter details. + * @author maven-plugin-tools +#if ( !$useAnnotations ) + * @goal help + * @requiresProject false + * @threadSafe +#end + */ +#if ( $useAnnotations ) +@Mojo( name = "help", requiresProject = false, threadSafe = true ) +#end +public class HelpMojo + extends AbstractMojo +{ + /** + * If true, display all settable properties for each goal. + * +#if ( !$useAnnotations ) + * @parameter property="detail" default-value="false" +#end + */ +#if ( $useAnnotations ) + @Parameter( property = "detail", defaultValue = "false" ) +#end + private boolean detail; + + /** + * The name of the goal for which to show help. If unspecified, all goals will be displayed. + * +#if ( !$useAnnotations ) + * @parameter property="goal" +#end + */ +#if ( $useAnnotations ) + @Parameter( property = "goal" ) +#end + private java.lang.String goal; + + /** + * The maximum length of a display line, should be positive. + * +#if ( !$useAnnotations ) + * @parameter property="lineLength" default-value="80" +#end + */ +#if ( $useAnnotations ) + @Parameter( property = "lineLength", defaultValue = "80" ) +#end + private int lineLength; + + /** + * The number of spaces per indentation level, should be positive. + * +#if ( !$useAnnotations ) + * @parameter property="indentSize" default-value="2" +#end + */ +#if ( $useAnnotations ) + @Parameter( property = "indentSize", defaultValue = "2" ) +#end + private int indentSize; + + // groupId/artifactId/plugin-help.xml + private static final String PLUGIN_HELP_PATH = + "/${pluginHelpPath}"; + + private static final int DEFAULT_LINE_LENGTH = 80; + + private Document build() + throws MojoExecutionException + { + getLog().debug( "load plugin-help.xml: " + PLUGIN_HELP_PATH ); + try ( InputStream is = getClass().getResourceAsStream( PLUGIN_HELP_PATH ) ) + { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + return dBuilder.parse( is ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( e.getMessage(), e ); + } + catch ( ParserConfigurationException e ) + { + throw new MojoExecutionException( e.getMessage(), e ); + } + catch ( SAXException e ) + { + throw new MojoExecutionException( e.getMessage(), e ); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void execute() + throws MojoExecutionException + { + if ( lineLength <= 0 ) + { + getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." ); + lineLength = DEFAULT_LINE_LENGTH; + } + if ( indentSize <= 0 ) + { + getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." ); + indentSize = 2; + } + + Document doc = build(); + + StringBuilder sb = new StringBuilder(); + Node plugin = getSingleChild( doc, "plugin" ); + + + String name = getValue( plugin, "name" ); + String version = getValue( plugin, "version" ); + String id = getValue( plugin, "groupId" ) + ":" + getValue( plugin, "artifactId" ) + ":" + version; + if ( isNotEmpty( name ) && !name.contains( id ) ) + { + append( sb, name + " " + version, 0 ); + } + else + { + if ( isNotEmpty( name ) ) + { + append( sb, name, 0 ); + } + else + { + append( sb, id, 0 ); + } + } + append( sb, getValue( plugin, "description" ), 1 ); + append( sb, "", 0 ); + + //plugin + String goalPrefix = getValue( plugin, "goalPrefix" ); + + Node mojos1 = getSingleChild( plugin, "mojos" ); + + List mojos = findNamedChild( mojos1, "mojo" ); + + if ( goal == null || goal.length() <= 0 ) + { + append( sb, "This plugin has " + mojos.size() + ( mojos.size() > 1 ? " goals:" : " goal:" ), 0 ); + append( sb, "", 0 ); + } + + for ( Node mojo : mojos ) + { + writeGoal( sb, goalPrefix, (Element) mojo ); + } + + if ( getLog().isInfoEnabled() ) + { + getLog().info( sb.toString() ); + } + } + + + private static boolean isNotEmpty( String string ) + { + return string != null && string.length() > 0; + } + + private static String getValue( Node node, String elementName ) + throws MojoExecutionException + { + return getSingleChild( node, elementName ).getTextContent(); + } + + private static Node getSingleChild( Node node, String elementName ) + throws MojoExecutionException + { + List namedChild = findNamedChild( node, elementName ); + if ( namedChild.isEmpty() ) + { + throw new MojoExecutionException( "Could not find " + elementName + " in plugin-help.xml" ); + } + if ( namedChild.size() > 1 ) + { + throw new MojoExecutionException( "Multiple " + elementName + " in plugin-help.xml" ); + } + return namedChild.get( 0 ); + } + + private static List findNamedChild( Node node, String elementName ) + { + List result = new ArrayList(); + NodeList childNodes = node.getChildNodes(); + for ( int i = 0; i < childNodes.getLength(); i++ ) + { + Node item = childNodes.item( i ); + if ( elementName.equals( item.getNodeName() ) ) + { + result.add( item ); + } + } + return result; + } + + private static Node findSingleChild( Node node, String elementName ) + throws MojoExecutionException + { + List elementsByTagName = findNamedChild( node, elementName ); + if ( elementsByTagName.isEmpty() ) + { + return null; + } + if ( elementsByTagName.size() > 1 ) + { + throw new MojoExecutionException( "Multiple " + elementName + "in plugin-help.xml" ); + } + return elementsByTagName.get( 0 ); + } + + private void writeGoal( StringBuilder sb, String goalPrefix, Element mojo ) + throws MojoExecutionException + { + String mojoGoal = getValue( mojo, "goal" ); + Node configurationElement = findSingleChild( mojo, "configuration" ); + Node description = findSingleChild( mojo, "description" ); + if ( goal == null || goal.length() <= 0 || mojoGoal.equals( goal ) ) + { + append( sb, goalPrefix + ":" + mojoGoal, 0 ); + Node deprecated = findSingleChild( mojo, "deprecated" ); + if ( ( deprecated != null ) && isNotEmpty( deprecated.getTextContent() ) ) + { + append( sb, "Deprecated. " + deprecated.getTextContent(), 1 ); + if ( detail && description != null ) + { + append( sb, "", 0 ); + append( sb, description.getTextContent(), 1 ); + } + } + else if ( description != null ) + { + append( sb, description.getTextContent(), 1 ); + } + append( sb, "", 0 ); + + if ( detail ) + { + Node parametersNode = getSingleChild( mojo, "parameters" ); + List parameters = findNamedChild( parametersNode, "parameter" ); + append( sb, "Available parameters:", 1 ); + append( sb, "", 0 ); + + for ( Node parameter : parameters ) + { + writeParameter( sb, parameter, configurationElement ); + } + } + } + } + + private void writeParameter( StringBuilder sb, Node parameter, Node configurationElement ) + throws MojoExecutionException + { + String parameterName = getValue( parameter, "name" ); + String parameterDescription = getValue( parameter, "description" ); + + Element fieldConfigurationElement = null; + if ( configurationElement != null ) + { + fieldConfigurationElement = (Element) findSingleChild( configurationElement, parameterName ); + } + + String parameterDefaultValue = ""; + if ( fieldConfigurationElement != null && fieldConfigurationElement.hasAttribute( "default-value" ) ) + { + parameterDefaultValue = " (Default: " + fieldConfigurationElement.getAttribute( "default-value" ) + ")"; + } + append( sb, parameterName + parameterDefaultValue, 2 ); + Node deprecated = findSingleChild( parameter, "deprecated" ); + if ( ( deprecated != null ) && isNotEmpty( deprecated.getTextContent() ) ) + { + append( sb, "Deprecated. " + deprecated.getTextContent(), 3 ); + append( sb, "", 0 ); + } + append( sb, parameterDescription, 3 ); + if ( "true".equals( getValue( parameter, "required" ) ) ) + { + append( sb, "Required: Yes", 3 ); + } + if ( ( fieldConfigurationElement != null ) && isNotEmpty( fieldConfigurationElement.getTextContent() ) ) + { + String property = getPropertyFromExpression( fieldConfigurationElement.getTextContent() ); + append( sb, "User property: " + property, 3 ); + } + + append( sb, "", 0 ); + } + + /** + *

    Repeat a String n times to form a new string.

    + * + * @param str String to repeat + * @param repeat number of times to repeat str + * @return String with repeated String + * @throws NegativeArraySizeException if repeat < 0 + * @throws NullPointerException if str is null + */ + private static String repeat( String str, int repeat ) + { + StringBuilder buffer = new StringBuilder( repeat * str.length() ); + + for ( int i = 0; i < repeat; i++ ) + { + buffer.append( str ); + } + + return buffer.toString(); + } + + /** + * Append a description to the buffer by respecting the indentSize and lineLength parameters. + * Note: The last character is always a new line. + * + * @param sb The buffer to append the description, not null. + * @param description The description, not null. + * @param indent The base indentation level of each line, must not be negative. + */ + private void append( StringBuilder sb, String description, int indent ) + { + for ( String line : toLines( description, indent, indentSize, lineLength ) ) + { + sb.append( line ).append( '\n' ); + } + } + + /** + * Splits the specified text into lines of convenient display length. + * + * @param text The text to split into lines, must not be null. + * @param indent The base indentation level of each line, must not be negative. + * @param indentSize The size of each indentation, must not be negative. + * @param lineLength The length of the line, must not be negative. + * @return The sequence of display lines, never null. + * @throws NegativeArraySizeException if indent < 0 + */ + private static List toLines( String text, int indent, int indentSize, int lineLength ) + { + List lines = new ArrayList(); + + String ind = repeat( "\t", indent ); + + String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" ); + + for ( String plainLine : plainLines ) + { + toLines( lines, ind + plainLine, indentSize, lineLength ); + } + + return lines; + } + + /** + * Adds the specified line to the output sequence, performing line wrapping if necessary. + * + * @param lines The sequence of display lines, must not be null. + * @param line The line to add, must not be null. + * @param indentSize The size of each indentation, must not be negative. + * @param lineLength The length of the line, must not be negative. + */ + private static void toLines( List lines, String line, int indentSize, int lineLength ) + { + int lineIndent = getIndentLevel( line ); + StringBuilder buf = new StringBuilder( 256 ); + + String[] tokens = line.split( " +" ); + + for ( String token : tokens ) + { + if ( buf.length() > 0 ) + { + if ( buf.length() + token.length() >= lineLength ) + { + lines.add( buf.toString() ); + buf.setLength( 0 ); + buf.append( repeat( " ", lineIndent * indentSize ) ); + } + else + { + buf.append( ' ' ); + } + } + + for ( int j = 0; j < token.length(); j++ ) + { + char c = token.charAt( j ); + if ( c == '\t' ) + { + buf.append( repeat( " ", indentSize - buf.length() % indentSize ) ); + } + else if ( c == '\u00A0' ) + { + buf.append( ' ' ); + } + else + { + buf.append( c ); + } + } + } + lines.add( buf.toString() ); + } + + /** + * Gets the indentation level of the specified line. + * + * @param line The line whose indentation level should be retrieved, must not be null. + * @return The indentation level of the line. + */ + private static int getIndentLevel( String line ) + { + int level = 0; + for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ ) + { + level++; + } + for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ ) + { + if ( line.charAt( i ) == '\t' ) + { + level++; + break; + } + } + return level; + } + + private static String getPropertyFromExpression( String expression ) + { + if ( expression != null && expression.startsWith( "${" ) && expression.endsWith( "}" ) + && !expression.substring( 2 ).contains( "${" ) ) + { + // expression="${xxx}" -> property="xxx" + return expression.substring( 2, expression.length() - 1 ); + } + // no property can be extracted + return null; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties new file mode 100644 index 000000000..273fe2b4d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties @@ -0,0 +1,62 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +pluginxdoc.yes=Yes +pluginxdoc.no=No +pluginxdoc.detail={0}: {1} + +pluginxdoc.description=Description: +pluginxdoc.nodescription=(no description) +pluginxdoc.mojodescriptor.notice.note=Note: +pluginxdoc.mojodescriptor.notice.isMavenReport=This goal should be used as a Maven report. +pluginxdoc.mojodescriptor.fullname=Full name: +pluginxdoc.mojodescriptor.attributes=Attributes: +pluginxdoc.mojodescriptor.deprecated=This plugin goal has been deprecated: +pluginxdoc.mojodescriptor.projectRequired=Requires a Maven project to be executed. +pluginxdoc.mojodescriptor.aggregator=Executes as an aggregator plugin. +pluginxdoc.mojodescriptor.directInvocationOnly=Executes by direct invocation only. +pluginxdoc.mojodescriptor.reportingMojo=Executes only as a reportSet (reporting goal). +pluginxdoc.mojodescriptor.dependencyResolutionRequired=Requires dependency resolution of artifacts in scope: {0}. +pluginxdoc.mojodescriptor.dependencyCollectionRequired=Requires dependency collection of artifacts in scope: {0}. +pluginxdoc.mojodescriptor.since=Since version: {0}. +pluginxdoc.mojodescriptor.phase=Binds by default to the lifecycle phase: {0}. +pluginxdoc.mojodescriptor.executePhase=Invokes the execution of the lifecycle phase {0} prior to executing itself. +pluginxdoc.mojodescriptor.executeGoal=Invokes the execution of this plugin's goal {0} prior to executing itself. +pluginxdoc.mojodescriptor.executeLifecycle=Executes in its own lifecycle: {0}. +pluginxdoc.mojodescriptor.onlineRequired=Requires that Maven runs in online mode. +pluginxdoc.mojodescriptor.inheritedByDefault=Is NOT inherited by default in multi-project builds. +pluginxdoc.mojodescriptor.parameter.details=Parameter Details +pluginxdoc.mojodescriptor.parameter.deprecated=Deprecated. {0} +pluginxdoc.mojodescriptor.parameter.name=Name +pluginxdoc.mojodescriptor.parameter.name_link=<{0}> +pluginxdoc.mojodescriptor.parameter.name_internal=<{0}> +pluginxdoc.mojodescriptor.parameter.description=Description +pluginxdoc.mojodescriptor.parameter.type=Type +pluginxdoc.mojodescriptor.parameter.since=Since +pluginxdoc.mojodescriptor.parameter.required=Required +pluginxdoc.mojodescriptor.parameter.expression=Expression +pluginxdoc.mojodescriptor.parameter.property=User Property +pluginxdoc.mojodescriptor.parameter.property.description=User property is: {0}. +pluginxdoc.mojodescriptor.parameter.default=Default +pluginxdoc.mojodescriptor.parameter.defaultValue=Default value is: {0}. +pluginxdoc.mojodescriptor.parameter.alias=Alias +pluginxdoc.mojodescriptor.parameter.alias.description=Alias is: {0}. +pluginxdoc.mojodescriptor.requiredParameters=Required Parameters +pluginxdoc.mojodescriptor.optionalParameters=Optional Parameters +pluginxdoc.mojodescriptor.parameters=Parameters +pluginxdoc.mojodescriptor.noParameter=(no parameters) +pluginxdoc.mojodescriptor.threadSafe=The goal is thread-safe and supports parallel builds. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties new file mode 100644 index 000000000..c326151e2 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties @@ -0,0 +1,56 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +pluginxdoc.yes=Ja +pluginxdoc.no=Nein + +pluginxdoc.description=Beschreibung: +pluginxdoc.nodescription=(keine Beschreibung) +pluginxdoc.mojodescriptor.notice.note=Anmerkung: +pluginxdoc.mojodescriptor.notice.isMavenReport=Dieses Goal erzeugt einen Maven-Bericht. +pluginxdoc.mojodescriptor.fullname=Vollst\u00e4ndiger Name: +pluginxdoc.mojodescriptor.attributes=Attribute: +pluginxdoc.mojodescriptor.deprecated=Dieses Plugin-Goal ist missbilligt: +pluginxdoc.mojodescriptor.projectRequired=Erfordert ein Maven Projekt zur Ausf\u00fchrung. +pluginxdoc.mojodescriptor.aggregator=Wird als Aggregator ausgef\u00fchrt. +pluginxdoc.mojodescriptor.directInvocationOnly=Wird nur per direktem Aufruf ausgef\u00fchrt. +pluginxdoc.mojodescriptor.dependencyResolutionRequired=Erfordert Abh\u00e4ngigkeitsaufl\u00f6sung von Artefakten mit Geltungsbereich: {0}. +pluginxdoc.mojodescriptor.dependencyCollectionRequired=Erfordert Abh\u00e4ngigkeitsermittlung von Artefakten mit Geltungsbereich: {0}. +pluginxdoc.mojodescriptor.since=Seit Version: {0}. +pluginxdoc.mojodescriptor.phase=Bindet automatisch an die Lebenszyklusphase: {0}. +pluginxdoc.mojodescriptor.executePhase=Bedingt die Ausf\u00fchrung der Lebenszyklusphase {0} vor seiner eigenen Ausf\u00fchrung. +pluginxdoc.mojodescriptor.executeGoal=Bedingt die Ausf\u00fchrung des Plugin-Goals {0} vor seiner eigenen Ausf\u00fchrung. +pluginxdoc.mojodescriptor.executeLifecycle=Wird in seinem eigenen Lebenszyklus ausgef\u00fchrt: {0}. +pluginxdoc.mojodescriptor.onlineRequired=Erfordert die Ausf\u00fchrung von Maven im Online-Modus. +pluginxdoc.mojodescriptor.inheritedByDefault=Wird bei einem Multi-Projekt-Build standardm\u00e4\u00dfig nicht vererbt. +pluginxdoc.mojodescriptor.parameter.details=Parameter-Details +pluginxdoc.mojodescriptor.parameter.deprecated=Missbilligt. {0} +pluginxdoc.mojodescriptor.parameter.name=Name +pluginxdoc.mojodescriptor.parameter.description=Beschreibung +pluginxdoc.mojodescriptor.parameter.type=Typ +pluginxdoc.mojodescriptor.parameter.since=Seit +pluginxdoc.mojodescriptor.parameter.required=Erforderlich +pluginxdoc.mojodescriptor.parameter.expression=Ausdruck +pluginxdoc.mojodescriptor.parameter.default=Standard +pluginxdoc.mojodescriptor.parameter.defaultValue=Standardwert ist: {0}. +pluginxdoc.mojodescriptor.parameter.alias=Alias +pluginxdoc.mojodescriptor.parameter.alias.description=Alias ist: {0}. +pluginxdoc.mojodescriptor.requiredParameters=Erforderliche Parameter +pluginxdoc.mojodescriptor.optionalParameters=Optionale Parameter +pluginxdoc.mojodescriptor.parameters=Parameter +pluginxdoc.mojodescriptor.noParameter=(keine Parameter) +pluginxdoc.mojodescriptor.threadSafe=Dieses Goal is thread-sicher und unterst\u00fctzt paralleles Bauen. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties new file mode 100644 index 000000000..96cf40750 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# NOTE: +# This bundle is intentionally empty because English strings are provided by the base bundle via the parent chain. It +# must be provided nevertheless such that a request for locale "en" will not errorneously pick up the bundle for the +# JVM's default locale (which need not be "en"). See the method javadoc about +# ResourceBundle.getBundle(String, Locale, ClassLoader) +# for a full description of the lookup strategy. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties new file mode 100644 index 000000000..f4aee286d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties @@ -0,0 +1,60 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +pluginxdoc.yes=Oui +pluginxdoc.no=Non +pluginxdoc.detail={0} : {1} + +pluginxdoc.description=Description : +pluginxdoc.nodescription=(aucune description) +pluginxdoc.mojodescriptor.notice.note=Note : +pluginxdoc.mojodescriptor.notice.isMavenReport=Ce goal doit \u00eatre utilis\u00e9 comme un rapport de Maven. +pluginxdoc.mojodescriptor.fullname=Nom complet : +pluginxdoc.mojodescriptor.attributes=Attributs : +pluginxdoc.mojodescriptor.deprecated=Le goal de ce plugin est obsol\u00e8te : +pluginxdoc.mojodescriptor.projectRequired=Exige un projet Maven pour \u00eatre ex\u00e9cut\u00e9. +pluginxdoc.mojodescriptor.aggregator=S'ex\u00e9cute comme un plugin agr\u00e9g\u00e9. +pluginxdoc.mojodescriptor.directInvocationOnly=S'ex\u00e9cute par l'invocation directe seulement. +pluginxdoc.mojodescriptor.reportingMojo=S'ex\u00e9cute seulement comme un reportSet (goal de reporting). +pluginxdoc.mojodescriptor.dependencyResolutionRequired=Exige une r\u00e9solution des d\u00e9pendances des artefacts dans le scope : {0}. +pluginxdoc.mojodescriptor.dependencyCollectionRequired=Exige une collecte des d\u00e9pendances des artefacts dans le scope : {0}. +pluginxdoc.mojodescriptor.since=Depuis la version : {0}. +pluginxdoc.mojodescriptor.phase=S'associe par d\u00e9faut dans la phase du cycle de vie : {0}. +pluginxdoc.mojodescriptor.executePhase=Appelle l'ex\u00e9cution de la phase du cycle de vie {0} avant de s'ex\u00e9cuter. +pluginxdoc.mojodescriptor.executeGoal=Appelle l'ex\u00e9cution du goal de ce plugin {0} avant de s'ex\u00e9cuter. +pluginxdoc.mojodescriptor.executeLifecycle=S'ex\u00e9cute dans son propre cycle de vie : {0}. +pluginxdoc.mojodescriptor.onlineRequired=Exige que Maven s'ex\u00e9cute en ligne. +pluginxdoc.mojodescriptor.inheritedByDefault=N'est PAS h\u00e9rit\u00e9 par d\u00e9faut dans une construction multi-projet. +pluginxdoc.mojodescriptor.parameter.details=D\u00e9tails des param\u00e8tres +pluginxdoc.mojodescriptor.parameter.deprecated=Obsol\u00e8te. {0} +pluginxdoc.mojodescriptor.parameter.name=Nom +pluginxdoc.mojodescriptor.parameter.description=Description +pluginxdoc.mojodescriptor.parameter.type=Type +pluginxdoc.mojodescriptor.parameter.since=Depuis +pluginxdoc.mojodescriptor.parameter.required=Exig\u00e9 +pluginxdoc.mojodescriptor.parameter.expression=Expression +pluginxdoc.mojodescriptor.parameter.property=Propri\u00e9t\u00e9 utilisateur +pluginxdoc.mojodescriptor.parameter.property.description=Propri\u00e9t\u00e9 utilisateur : {0}. +pluginxdoc.mojodescriptor.parameter.default=D\u00e9faut +pluginxdoc.mojodescriptor.parameter.defaultValue=Valeur par d\u00e9faut : {0}. +pluginxdoc.mojodescriptor.parameter.alias=Alias +pluginxdoc.mojodescriptor.parameter.alias.description=Alias : {0}. +pluginxdoc.mojodescriptor.requiredParameters=Param\u00e8tres requis +pluginxdoc.mojodescriptor.optionalParameters=Param\u00e8tres optionnels +pluginxdoc.mojodescriptor.parameters=Param\u00e8tres +pluginxdoc.mojodescriptor.noParameter=(aucun param\u00e8tre) +pluginxdoc.mojodescriptor.threadSafe=Le goal est thread-safe et supporte des constructions parall\u00e8les. diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/site/site.xml new file mode 100644 index 000000000..e942a4c5f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/site/site.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java new file mode 100644 index 000000000..e98b1283a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java @@ -0,0 +1,170 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.model.Build; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.codehaus.plexus.PlexusTestCase; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.util.FileUtils; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author Jason van Zyl + */ +public abstract class AbstractGeneratorTestCase + extends PlexusTestCase +{ + protected Generator generator; + + protected String basedir; + + protected void setUp() + throws Exception + { + super.setUp(); + basedir = System.getProperty( "basedir" ); + } + + public void testGenerator() + throws Exception + { + setupGenerator(); + + MojoDescriptor mojoDescriptor = new MojoDescriptor(); + mojoDescriptor.setGoal( "testGoal" ); + mojoDescriptor.setImplementation( "org.apache.maven.tools.plugin.generator.TestMojo" ); + mojoDescriptor.setDependencyResolutionRequired( "compile" ); + + List params = new ArrayList(); + + Parameter param = new Parameter(); + param.setExpression( "${project.build.directory}" ); + param.setDefaultValue( "" ); + param.setName( "dir" ); + param.setRequired( true ); + param.setType( "java.lang.String" ); + param.setDescription( "Test parameter description" ); + param.setAlias( "some.alias" ); + + params.add( param ); + + mojoDescriptor.setParameters( params ); + + PluginDescriptor pluginDescriptor = new PluginDescriptor(); + mojoDescriptor.setPluginDescriptor( pluginDescriptor ); + + pluginDescriptor.addMojo( mojoDescriptor ); + + pluginDescriptor.setArtifactId( "maven-unitTesting-plugin" ); + pluginDescriptor.setGoalPrefix( "test" ); + + ComponentDependency dependency = new ComponentDependency(); + dependency.setGroupId( "testGroup" ); + dependency.setArtifactId( "testArtifact" ); + dependency.setVersion( "0.0.0" ); + + pluginDescriptor.setDependencies( Collections.singletonList( dependency ) ); + + File destinationDirectory = Files.createTempDirectory( "testGenerator-outDir" ).toFile(); + destinationDirectory.mkdir(); + + MavenProject mavenProject = new MavenProject(); + mavenProject.setGroupId( "foo" ); + mavenProject.setArtifactId( "bar" ); + mavenProject.setBuild( new Build() + { + @Override + public String getDirectory() + { + return basedir + "/target"; + } + + @Override + public String getOutputDirectory() + { + return basedir + "/target"; + } + } ); + + generator.execute( destinationDirectory, new DefaultPluginToolsRequest( mavenProject, pluginDescriptor ) ); + + validate( destinationDirectory ); + + FileUtils.deleteDirectory( destinationDirectory ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + protected void setupGenerator() + throws Exception + { + String generatorClassName = getClass().getName(); + + generatorClassName = generatorClassName.substring( 0, generatorClassName.length() - 4 ); + + try + { + Class generatorClass = Thread.currentThread().getContextClassLoader().loadClass( generatorClassName ); + + Log log = new SystemStreamLog(); + try + { + Constructor constructor = generatorClass.getConstructor( Log.class ); + generator = (Generator) constructor.newInstance( log ); + } + catch ( NoSuchMethodException ignore ) + { + generator = (Generator) generatorClass.newInstance(); + + } + } + catch ( Exception e ) + { + throw new Exception( "Cannot find " + generatorClassName + + "! Make sure your test case is named in the form ${generatorClassName}Test " + + "or override the setupPlugin() method to instantiate the mojo yourself." ); + } + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + protected void validate( File destinationDirectory ) + throws Exception + { + // empty + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java new file mode 100644 index 000000000..d8d469ec3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java @@ -0,0 +1,205 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.testing.AbstractMojoTestCase; +import org.apache.maven.plugin.testing.stubs.MavenProjectStub; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.util.xml.CompactXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +import java.io.StringWriter; +import java.util.Collections; + +/** + * @author jdcasey + */ +public class GeneratorUtilsTest + extends AbstractMojoTestCase +{ + public void testShouldWriteDependencies() + throws Exception + { + ComponentDependency dependency = new ComponentDependency(); + dependency.setArtifactId( "testArtifactId" ); + dependency.setGroupId( "testGroupId" ); + dependency.setType( "pom" ); + dependency.setVersion( "0.0.0" ); + + PluginDescriptor descriptor = new PluginDescriptor(); + descriptor.setDependencies( Collections.singletonList( dependency ) ); + + StringWriter sWriter = new StringWriter(); + XMLWriter writer = new CompactXMLWriter( sWriter ); + + GeneratorUtils.writeDependencies( writer, descriptor ); + + String output = sWriter.toString(); + + String pattern = + "" + "" + "testGroupId" + + "testArtifactId" + "pom" + "0.0.0" + + "" + ""; + + assertEquals( pattern, output ); + } + + public void testMakeHtmlValid() + { + String javadoc = null; + assertEquals( "", GeneratorUtils.makeHtmlValid( javadoc ) ); + javadoc = ""; + assertEquals( "", GeneratorUtils.makeHtmlValid( javadoc ) ); + + // true HTML + javadoc = "Generates something for the project."; + assertEquals( "Generates something for the project.", GeneratorUtils.makeHtmlValid( javadoc ) ); + + // wrong HTML + javadoc = "Generates something for the project."; + assertEquals( "Generates something for the project.", GeneratorUtils.makeHtmlValid( javadoc ) ); + + // wrong XHTML + javadoc = "Line1
    Line2"; + assertEquals( "Line1
    Line2", GeneratorUtils.makeHtmlValid( javadoc ).replaceAll( "\\s", "" ) ); + + // special characters + javadoc = "& & < > \u00A0"; + assertEquals( "& & < > \u00A0", GeneratorUtils.makeHtmlValid( javadoc ) ); + + // non ASCII characters + javadoc = "\u00E4 \u00F6 \u00FC \u00DF"; + assertEquals( javadoc, GeneratorUtils.makeHtmlValid( javadoc ) ); + + // non Latin1 characters + javadoc = "\u0130 \u03A3 \u05D0 \u06DE"; + assertEquals( javadoc, GeneratorUtils.makeHtmlValid( javadoc ) ); + } + + public void testDecodeJavadocTags() + { + String javadoc = null; + assertEquals( "", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = ""; + assertEquals( "", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@code text}"; + assertEquals( "text", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@code }"; + assertEquals( "<A&B>", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@literal text}"; + assertEquals( "text", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@literal text} {@literal text}"; + assertEquals( "text text", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@literal }"; + assertEquals( "<A&B>", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@link Class}"; + assertEquals( "Class", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain Class}"; + assertEquals( "Class", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain #field}"; + assertEquals( "field", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain Class#field}"; + assertEquals( "Class.field", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain #method()}"; + assertEquals( "method()", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain #method(Object arg)}"; + assertEquals( "method()", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain #method(Object, String)}"; + assertEquals( "method()", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain #method(Object, String) label}"; + assertEquals( "label", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain Class#method(Object, String)}"; + assertEquals( "Class.method()", GeneratorUtils.decodeJavadocTags( javadoc ) ); + + javadoc = "{@linkplain Class#method(Object, String) label}"; + assertEquals( "label", GeneratorUtils.decodeJavadocTags( javadoc ) ); + } + + public void testToText() + throws Exception + { + String javadoc = null; + assertEquals( "", GeneratorUtils.toText( javadoc ) ); + javadoc = ""; + assertEquals( "", GeneratorUtils.toText( javadoc ) ); + + // line breaks + javadoc = "Line1\nLine2"; + assertEquals( "Line1 Line2", GeneratorUtils.toText( javadoc ) ); + javadoc = "Line1\rLine2"; + assertEquals( "Line1 Line2", GeneratorUtils.toText( javadoc ) ); + javadoc = "Line1\r\nLine2"; + assertEquals( "Line1 Line2", GeneratorUtils.toText( javadoc ) ); + javadoc = "Line1
    Line2"; + assertEquals( "Line1\nLine2", GeneratorUtils.toText( javadoc ) ); + + // true HTML + javadoc = "Generates something for the project."; + assertEquals( "Generates something for the project.", GeneratorUtils.toText( javadoc ) ); + + // wrong HTML + javadoc = "Generates something for the project."; + assertEquals( "Generates something for the project.", GeneratorUtils.toText( javadoc ) ); + + // javadoc inline tags + javadoc = "Generates {@code something} for the project."; + assertEquals( "Generates something for the project.", GeneratorUtils.toText( javadoc ) ); + } + + public void testIsMavenReport() + throws Exception + { + try + { + GeneratorUtils.isMavenReport( null, null ); + } + catch ( IllegalArgumentException e ) + { + assertTrue( true ); + } + + String impl = "org.apache.maven.tools.plugin.generator.stubs.MavenReportStub"; + + MavenProjectStub stub = new MavenProjectStub(); + stub.setCompileSourceRoots( Collections.singletonList( getBasedir() + "/target/classes" ) ); + + assertTrue( GeneratorUtils.isMavenReport( impl, stub ) ); + + impl = "org.apache.maven.tools.plugin.util.stubs.MojoStub"; + assertFalse( GeneratorUtils.isMavenReport( impl, stub ) ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGeneratorTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGeneratorTest.java new file mode 100644 index 000000000..c5f5c9e9d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGeneratorTest.java @@ -0,0 +1,127 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.util.ReaderFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.List; + +/** + * @author Jason van Zyl + */ +public class PluginDescriptorGeneratorTest + extends AbstractGeneratorTestCase +{ + protected void validate( File destinationDirectory ) + throws Exception + { + PluginDescriptorBuilder pdb = new PluginDescriptorBuilder(); + + File pluginDescriptorFile = new File( destinationDirectory, "plugin.xml" ); + + String pd = readFile( pluginDescriptorFile ); + + PluginDescriptor pluginDescriptor = pdb.build( new StringReader( pd ) ); + + assertEquals( 1, pluginDescriptor.getMojos().size() ); + + MojoDescriptor mojoDescriptor = (MojoDescriptor) pluginDescriptor.getMojos().get( 0 ); + + checkMojo( mojoDescriptor ); + + // ---------------------------------------------------------------------- + // Dependencies + // ---------------------------------------------------------------------- + + List dependencies = pluginDescriptor.getDependencies(); + + checkDependency( "testGroup", "testArtifact", "0.0.0", dependencies.get( 0 ) ); + + assertEquals( 1, dependencies.size() ); + + ComponentDependency dependency = dependencies.get( 0 ); + assertEquals( "testGroup", dependency.getGroupId() ); + assertEquals( "testArtifact", dependency.getArtifactId() ); + assertEquals( "0.0.0", dependency.getVersion() ); + } + + private String readFile( File pluginDescriptorFile ) + throws IOException + { + StringWriter sWriter = new StringWriter(); + + try (PrintWriter pWriter = new PrintWriter( sWriter ); // + BufferedReader reader = new BufferedReader( ReaderFactory.newXmlReader( pluginDescriptorFile ) )) + { + String line = null; + while ( ( line = reader.readLine() ) != null ) + { + pWriter.println( line ); + } + } + + return sWriter.toString(); + } + + private void checkMojo( MojoDescriptor mojoDescriptor ) + { + assertEquals( "test:testGoal", mojoDescriptor.getFullGoalName() ); + + assertEquals( "org.apache.maven.tools.plugin.generator.TestMojo", mojoDescriptor.getImplementation() ); + + // The following should be defaults + assertEquals( "per-lookup", mojoDescriptor.getInstantiationStrategy() ); + + assertNotNull( mojoDescriptor.isDependencyResolutionRequired() ); + + // check the parameter. + checkParameter( (Parameter) mojoDescriptor.getParameters().get( 0 ) ); + } + + private void checkParameter( Parameter parameter ) + { + assertEquals( "dir", parameter.getName() ); + assertEquals( String.class.getName(), parameter.getType() ); + assertTrue( parameter.isRequired() ); + assertEquals( "some.alias", parameter.getAlias() ); + } + + private void checkDependency( String groupId, String artifactId, String version, ComponentDependency dependency ) + { + assertNotNull( dependency ); + + assertEquals( groupId, dependency.getGroupId() ); + + assertEquals( artifactId, dependency.getArtifactId() ); + + assertEquals( version, dependency.getVersion() ); + } +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java new file mode 100644 index 000000000..bd5d3742a --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java @@ -0,0 +1,39 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.codehaus.plexus.velocity.VelocityComponent; + +/** + * @author Vincent Siveton + */ +public class PluginHelpGeneratorTest + extends AbstractGeneratorTestCase +{ + // inherits tests from base class + protected void setupGenerator() + throws Exception + { + + generator = + new PluginHelpGenerator().setVelocityComponent( (VelocityComponent) lookup( VelocityComponent.ROLE ) ); + + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java new file mode 100644 index 000000000..6429dc707 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java @@ -0,0 +1,46 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; + +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; + +/** + * @author Jason van Zyl + * @author Vincent Siveton + */ +public class PluginXdocGeneratorTest + extends AbstractGeneratorTestCase +{ + + // inherits tests from base class + + protected void validate( File destinationDirectory ) + throws Exception + { + File docFile = new File( destinationDirectory, "testGoal-mojo.xml" ); + + // sanity check: is the output well-formed? + Xpp3DomBuilder.build( ReaderFactory.newXmlReader( docFile ) ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java new file mode 100644 index 000000000..5f7ae4e50 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java @@ -0,0 +1,79 @@ +package org.apache.maven.tools.plugin.generator.stubs; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Locale; + +import org.apache.maven.doxia.siterenderer.Renderer; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.AbstractMavenReport; +import org.apache.maven.reporting.MavenReportException; + +/** + * Dummy report. + * + * @goal dummyReport + */ +public class MavenReportStub + extends AbstractMavenReport +{ + /** {@inheritDoc} */ + protected void executeReport( Locale locale ) + throws MavenReportException + { + + } + + /** {@inheritDoc} */ + protected String getOutputDirectory() + { + return null; + } + + /** {@inheritDoc} */ + protected MavenProject getProject() + { + return null; + } + + /** {@inheritDoc} */ + protected Renderer getSiteRenderer() + { + return null; + } + + /** {@inheritDoc} */ + public String getDescription( Locale locale ) + { + return null; + } + + /** {@inheritDoc} */ + public String getName( Locale locale ) + { + return null; + } + + /** {@inheritDoc} */ + public String getOutputName() + { + return null; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/pom.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/pom.xml new file mode 100644 index 000000000..8878ca73d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/pom.xml @@ -0,0 +1,92 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.6.1-SNAPSHOT + + + maven-plugin-tools-java + + Maven Plugin Tool for Java with Javadoc Tags + Descriptor extractor for plugins written in Java annotated with Mojo Javadoc Tags. + + + + org.apache.maven.plugin-tools + maven-plugin-tools-generators + test + + + + + org.apache.maven + maven-model + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-component-annotations + + + junit + junit + + + + + + + com.thoughtworks.qdox + qdox + + + + xmlunit + xmlunit + 1.3 + test + + + + + + + org.codehaus.plexus + plexus-component-metadata + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java new file mode 100644 index 000000000..5b5e493e8 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java @@ -0,0 +1,656 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavadocMojoAnnotation.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavadocMojoAnnotation.java new file mode 100644 index 000000000..3b9877c68 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavadocMojoAnnotation.java @@ -0,0 +1,506 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * List of all Javadoc annotations used to describe a java Mojo. + * + * @author Vincent Siveton + * @since 2.4 + */ +@SuppressWarnings( "checkstyle:interfaceistype" ) +public interface JavadocMojoAnnotation +{ + // ---------------------------------------------------------------------- + // Descriptor for type i.e. Mojo + // ---------------------------------------------------------------------- + + /** + *

    + * Flags this Mojo to run it in a multi module way, i.e. aggregate the build with the set of projects listed + * as modules. + *

    + *

    + * Refer to @aggregator. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String AGGREGATOR = "aggregator"; + + /** + *

    + * The configurator type to use when injecting parameter values into this Mojo. The value is normally deduced + * from the Mojo's implementation language, but can be specified to allow a custom ComponentConfigurator + * implementation to be used. + *

    + *

    + * Refer to @configurator <roleHint>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String CONFIGURATOR = "configurator"; + + /** + *

    + * The description for the Mojo. + *

    + *

    + * Refer to @description. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + *

    + * Note: Mojo's description is auto-detected. + *

    + */ + String DESCRIPTION = "description"; + + /** + *

    + * Refer to @execute .... + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String EXECUTE = "execute"; + + /** + *

    + * The Mojo goal will be executed in isolation. + *

    + *

    + * Refer to @execute goal="<goalName>". + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String EXECUTE_GOAL = "goal"; + + /** + *

    + * The Mojo will be invoked in a parallel lifecycle. + *

    + *

    + * Refer to @execute lifecycle="<lifecycleId>". + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String EXECUTE_LIFECYCLE = "lifecycle"; + + /** + *

    + * The Mojo will be invoked in a parallel lifecycle, ending at the given phase. + *

    + *

    + * Refer to @execute phase="<phaseName>". + *

    + *

    + * Refer to @execute lifecycle="<lifecycleId>" phase="<phaseName>". + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String EXECUTE_PHASE = "phase"; + + /** + *

    + * Refer to @executionStrategy <strategy>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String EXECUTION_STATEGY = "executionStrategy"; + + /** + *

    + * The name for the Mojo that users will reference to execute it. + *

    + *

    + * Refer to @goal <goalName>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String GOAL = "goal"; + + /** + *

    + * The Mojo's fully-qualified class name. + *

    + *

    + * Refer to @implementation. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + *

    + * Note: Mojo's implementation is auto-detected. + *

    + */ + String IMPLEMENTATION = "implementation"; + + /** + *

    + * Allow Mojo inheritance. + *

    + *

    + * Refer to @inheritByDefault <true|false>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String INHERIT_BY_DEFAULT = "inheritByDefault"; + + /** + *

    + * Refer to @instantiationStrategy <per-lookup>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String INSTANTIATION_STRATEGY = "instantiationStrategy"; + + /** + *

    + * The implementation language for the Mojo. + *

    + *

    + * Refer to @language. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + *

    + * Note: Mojo's implementation is auto-detected. + *

    + */ + String LANGUAGE = "language"; + + /** + *

    + * Specifies the execution strategy. + *

    + *

    + * Refer to @attainAlways. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + * @deprecated use @executionStrategy always instead + */ + String MULTI_EXECUTION_STRATEGY = "attainAlways"; + + /** + *

    + * Refer to @phase <phaseName>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String PHASE = "phase"; + + /** + *

    + * Flags this Mojo as requiring the dependencies in the specified scope (or an implied scope) to be resolved + * before it can execute. Currently supports compile, runtime, + * compile+runtime and test scopes. + *

    + *

    + * Refer to @requiresDependencyResolution <requiredScope>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String REQUIRES_DEPENDENCY_RESOLUTION = "requiresDependencyResolution"; + + /** + *

    + * Flags this Mojo as requiring the dependencies in the specified scope (or an implied scope) to be collected + * before it can execute. Currently supports compile, runtime, + * compile+runtime and test scopes. + *

    + *

    + * Refer to @requiresDependencyCollection <requiredScope>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String REQUIRES_DEPENDENCY_COLLECTION = "requiresDependencyCollection"; + + + /** + *

    + * Refer to @requiresDirectInvocation <true|false>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String REQUIRES_DIRECT_INVOCATION = "requiresDirectInvocation"; + + /** + *

    + * Flags this Mojo to run online. + *

    + *

    + * Refer to @requiresOnline <true|false>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String REQUIRES_ONLINE = "requiresOnline"; + + /** + *

    + * Flags this Mojo to run inside of a project. + *

    + *

    + * Refer to @requiresProject <true|false>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String REQUIRES_PROJECT = "requiresProject"; + + /** + *

    + * Flags this Mojo to run inside reports. + *

    + *

    + * Refer to @requiresReports <true|false>. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String REQUIRES_REPORTS = "requiresReports"; + + /** + *

    + * Indicates that this mojo is thread-safe and can be run in parallel. + *

    + *

    + * Note: Should be defined in a Mojo Type. + *

    + */ + String THREAD_SAFE = "threadSafe"; + + + // ---------------------------------------------------------------------- + // Descriptor for fields i.e. parameters + // ---------------------------------------------------------------------- + + /** + *

    + * Populate the field with an instance of a Plexus component. This is like declaring a requirement in a + * Plexus component. + *

    + *

    + * Refer to @component .... + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String COMPONENT = "component"; + + /** + *

    + * Refer to @component role="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String COMPONENT_ROLE = "role"; + + /** + *

    + * Refer to @component roleHint="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String COMPONENT_ROLEHINT = "roleHint"; + + /** + *

    + * Refer to @parameter ... + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String PARAMETER = "parameter"; + + /** + *

    + * This defines the name of the bean property used to get/set the field: by default, field name is used. + *

    + *

    + * Refer to @parameter name="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String PARAMETER_NAME = "name"; + + /** + *

    + * This defines an alias which can be used to configure a parameter. This is primarily useful to improve + * user-friendliness. + *

    + *

    + * Refer to @parameter alias="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String PARAMETER_ALIAS = "alias"; + + /** + *

    + * This defines the default value to be injected into this parameter of the Mojo at build time. + *

    + *

    + * Refer to @parameter default-value="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String PARAMETER_DEFAULT_VALUE = "default-value"; + + /** + *

    + * This defines the expression used to calculate the value to be injected into this parameter of the + * Mojo at build time. + *

    + *

    + * Refer to @parameter expression="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + * @deprecated use PARAMETER_PROPERTY instead + */ + String PARAMETER_EXPRESSION = "expression"; + + /** + *

    + * This defines the property used to calculate the value to be injected into this parameter of the + * Mojo at build time, which can come from -D execution, setting properties or pom properties. + *

    + *

    + * Refer to @parameter property="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String PARAMETER_PROPERTY = "property"; + + /** + *

    + * This defines the default implementation in the case the parameter type is an interface. + *

    + *

    + * Refer to @parameter implementation="...". + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String PARAMETER_IMPLEMENTATION = "implementation"; + + /** + *

    + * Specifies that this parameter cannot be configured directly by the user (as in the case of POM-specified + * configuration). + *

    + *

    + * Refer to @readonly. + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String READONLY = "readonly"; + + /** + *

    + * Specifies that this parameter is required for the Mojo to function. + *

    + *

    + * Refer to @required. + *

    + *

    + * Note: Should be defined in a Mojo Field. + *

    + */ + String REQUIRED = "required"; + + // ---------------------------------------------------------------------- + // Descriptor for type and fields + // ---------------------------------------------------------------------- + + /** + *

    + * Refer to @since <deprecated-text> + *

    + *

    + * Note: Could be defined in a Mojo Type or a Mojo Field. + *

    + */ + String SINCE = "since"; + + /** + *

    + * Refer to @deprecated <since-text> + *

    + *

    + * Note: Could be defined in a Mojo Type or a Mojo Field. + *

    + */ + String DEPRECATED = "deprecated"; + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/apt/index.apt new file mode 100644 index 000000000..ca520c47c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/apt/index.apt @@ -0,0 +1,145 @@ + ------ + Introduction + ------ + Vincent Siveton + Hervé Boutemy + ------ + 2011-10-23 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Tool for Java Annotated with Mojo Javadoc Tags + + The Maven Plugin Tool for Java is the <<>> implementation of + {{{../maven-plugin-tools-api/index.html}maven-plugin-tools-api}} + to extract descriptors for plugins written in Java annotated with Mojo Javadoc Tags. + +* Supported Mojo Javadoc Tags + ++---------+ +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; + +/** + * Mojo Description: goal is the only required annotation. + * + * @goal + * @aggregator + * @configurator + * @execute phase="" lifecycle="" goal="" + * @executionStrategy + * @inheritByDefault + * @instantiationStrategy + * @phase + * @requiresDependencyResolution + * @requiresDependencyCollection (since Maven 3.0) + * @requiresDirectInvocation + * @requiresOnline + * @requiresProject + * @requiresReports (unsupported since Maven 3.0) + * @threadSafe (since Maven 3.0) + * @since + * @deprecated + */ +public class MyMojo + extends AbstractMojo +{ + /** + * @parameter name="parameter" alias="myAlias" implementation="" property="aProperty" default-value="${anExpression}" + * @readonly + * @required + * @since + * @deprecated + */ + private String parameter; + + /** + * @component role="..." roleHint="..." + */ + private Component component; + + // sample objects taken from Maven API through PluginParameterExpressionEvaluator + + /** + * @parameter default-value="${session}" + * @readonly + */ + private MavenSession session; + + /** + * @parameter default-value="${project}" + * @readonly + */ + private MavenProject project; + + /** + * @parameter default-value="${mojoExecution}" + * @readonly + */ + private MojoExecution mojo; + + /** + * @parameter default-value="${plugin}" // Maven 3 only + * @readonly + */ + private PluginDescriptor plugin; + + /** + * @parameter default-value="${settings}" + * @readonly + */ + private Settings settings; + + /** + * @parameter default-value="${project.basedir}" + * @readonly + */ + private File basedir; + + /** + * @parameter default-value="${project.build.directory}" + * @readonly + */ + private File target; + + public void execute() + { + ... + } +} ++---------+ + + <>: before 3.0, <<>> was replaced by <<>>, with <<<$\{ }>>> required (<<>>), + but starting with 3.0, you can omit it (<<>>), or preferably use <<>>. + +* See also + + * {{{/developers/mojo-api-specification.html#The_Descriptor_and_Annotations}Mojo API Specification}} + + * {{{/ref/current/maven-plugin-api/plugin.html}<<>> plugin descriptor}} + + * {{{/ref/current/maven-core/apidocs/org/apache/maven/plugin/PluginParameterExpressionEvaluator.html}PluginParameterExpressionEvaluator}}, + used to evaluate plugin parameters values during Mojo configuration, diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java new file mode 100644 index 000000000..3f3001fcc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java @@ -0,0 +1,268 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.model.Build; +import org.apache.maven.model.Model; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.generator.Generator; +import org.apache.maven.tools.plugin.generator.PluginDescriptorGenerator; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.codehaus.plexus.util.FileUtils; + +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.Document; + +import static org.junit.Assert.*; + +/** + * @author jdcasey + */ +public class JavaMojoDescriptorExtractorTest +{ + private File root; + + @Before + public void setUp() + { + File sourceFile = fileOf( "dir-flag.txt" ); + root = sourceFile.getParentFile(); + } + + private File fileOf( String classpathResource ) + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + URL resource = cl.getResource( classpathResource ); + + File result = null; + if ( resource != null ) + { + result = FileUtils.toFile( resource ); + } + + return result; + } + + private PluginToolsRequest createRequest( String directory ) + { + Model model = new Model(); + model.setArtifactId( "maven-unitTesting-plugin" ); + + MavenProject project = new MavenProject( model ); + project.setBuild( new Build() + { + @Override + public String getOutputDirectory() + { + return new File( "target" ).getAbsolutePath(); + } + } ); + + project.setFile( new File( root, "pom.xml" ) ); + project.addCompileSourceRoot( new File( root, directory ).getPath() ); + + PluginDescriptor pluginDescriptor = new PluginDescriptor(); + pluginDescriptor.setGoalPrefix( "test" ); + pluginDescriptor.setDependencies( new ArrayList() ); + + return new DefaultPluginToolsRequest( project, pluginDescriptor ).setEncoding( "UTF-8" ); + } + + /** + * generate plugin.xml for a test resources directory content. + */ + protected PluginDescriptor generate( String directory ) + throws Exception + { + JavaJavadocMojoDescriptorExtractor extractor = new JavaJavadocMojoDescriptorExtractor(); + extractor.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "test" ) ); + PluginToolsRequest request = createRequest( directory ); + + List mojoDescriptors = extractor.execute( request ); + + // to ensure order against plugin-expected.xml + PluginUtils.sortMojos( mojoDescriptors ); + + for ( MojoDescriptor mojoDescriptor : mojoDescriptors ) + { + // to ensure order against plugin-expected.xml + PluginUtils.sortMojoParameters( mojoDescriptor.getParameters() ); + + request.getPluginDescriptor().addMojo( mojoDescriptor ); + } + + Generator descriptorGenerator = new PluginDescriptorGenerator( new SystemStreamLog() ); + + descriptorGenerator.execute( new File( root, directory ), request ); + + return request.getPluginDescriptor(); + } + + /** + * compare mojos from generated plugin.xml against plugin-expected.xml + */ + protected void checkExpected( String directory ) + throws Exception + { + File testDirectory = new File( root, directory ); + + XMLUnit.setIgnoreWhitespace( true ); + XMLUnit.setIgnoreComments( true ); + + Document expected = XMLUnit.buildControlDocument( + FileUtils.fileRead( new File( testDirectory, "plugin-expected.xml" ), "UTF-8" ) ); + Document actual = + XMLUnit.buildTestDocument( FileUtils.fileRead( new File( testDirectory, "plugin.xml" ), "UTF-8" ) ); + + Diff diff = XMLUnit.compareXML( expected, actual ); + + if ( !diff.identical() ) + { + fail( "generated plugin.xml is not identical as plugin-expected.xml for " + directory + ": " + diff ); + } + } + + /** + * extract plugin descriptor for test resources directory and check against plugin-expected.xml + */ + protected List extract( String directory ) + throws Exception + { + PluginDescriptor descriptor = generate( directory ); + + checkExpected( directory ); + + return descriptor.getMojos(); + } + + @Test + public void testShouldFindTwoMojoDescriptorsInTestSourceDirectory() + throws Exception + { + List results = extract( "source" ); + + assertEquals( "Extracted mojos", 2, results.size() ); + } + + @Test + public void testShouldPropagateImplementationParameter() + throws Exception + { + List results = extract( "source2" ); + + assertEquals( 1, results.size() ); + + MojoDescriptor mojoDescriptor = results.get( 0 ); + + List parameters = mojoDescriptor.getParameters(); + + assertEquals( 1, parameters.size() ); + + Parameter parameter = parameters.get( 0 ); + + assertEquals( "Implementation parameter", "source2.sub.MyBla", parameter.getImplementation() ); + } + + @Test + public void testMaven30Parameters() + throws Exception + { + List results = extract( "source2" ); + + assertEquals( 1, results.size() ); + + ExtendedMojoDescriptor mojoDescriptor = (ExtendedMojoDescriptor) results.get( 0 ); + assertTrue( mojoDescriptor.isThreadSafe() ); + assertEquals( "test", mojoDescriptor.getDependencyCollectionRequired() ); + } + + /** + * Check that the mojo descriptor extractor will ignore any annotations that are found. + * + * @throws Exception + */ + @Test + public void testAnnotationInPlugin() + throws Exception + { + List results = extract( "source3" ); + + assertNull( results ); + } + + /** + * Check that the mojo descriptor extractor will successfully parse sources with Java 1.5 language features like + * generics. + */ + @Test + public void testJava15SyntaxParsing() + throws Exception + { + List results = extract( "java-1.5" ); + + assertEquals( 1, results.size() ); + } + + @Test + public void testSingleTypeImportWithFullyQualifiedClassName() + throws Exception + { + List results = extract( "MPLUGIN-314" ); + + assertEquals( 1, results.size() ); + } + + @Test + public void testMethodReferenceInEnumConstructor() + throws Exception + { + List results = extract( "MPLUGIN-320" ); + + assertNull( results ); + } + + @Test + public void testEnumWithRegexPattern() + throws Exception + { + List results = extract( "MPLUGIN-290" ); + + assertNull( results ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/Test.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/Test.java new file mode 100644 index 000000000..3c3b5c6e8 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/Test.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.regex.Pattern; + +public enum Test +{ + + Test( Pattern.compile( "a" ) ); + + private Test( Pattern p ) + { + + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/plugin-expected.xml new file mode 100644 index 000000000..423409665 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-290/plugin-expected.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + test + false + true + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/MyMojo.java new file mode 100644 index 000000000..c9d2cdfa5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/MyMojo.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.plugin.AbstractMojo; + +/** + * Tests that using an import and the same fully qualified class name results in a correct requirement role generated. + * + * @goal test + */ +public class MyMojo + extends AbstractMojo +{ + + /** + * @component + */ + private org.apache.maven.artifact.resolver.ArtifactResolver resolver; + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/plugin-expected.xml new file mode 100644 index 000000000..1afd60bec --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-314/plugin-expected.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + test + false + true + + + test + Tests that using an import and the same fully qualified class name results in a correct requirement role generated. + false + true + false + false + false + true + MyMojo + java + per-lookup + once-per-session + false + + + + org.apache.maven.artifact.resolver.ArtifactResolver + resolver + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/Exceptions.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/Exceptions.java new file mode 100644 index 000000000..cf0a83245 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/Exceptions.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.function.Supplier; + +public enum Exceptions { + NPE(NullPointerException::new), + IAE(IllegalArgumentException::new); + + private final Supplier supplier; + + Exceptions(Supplier supplier) { + this.supplier = supplier; + } + +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/plugin-expected.xml new file mode 100644 index 000000000..423409665 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/MPLUGIN-320/plugin-expected.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + test + false + true + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/dir-flag.txt b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/dir-flag.txt new file mode 100644 index 000000000..053c56637 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/dir-flag.txt @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +This file is used by ClassLoader.getResource() to find the current path to the +test resources. Uses this code: + +URL resource = classloader.getResource("dir-flag.txt"); +File resourceFile = new File(resource.getPath()); +File testResourcesDir= resourceFile.getParentFile(); + +This way, the unit test can depend on a FileReader or somesuch, and still work +fine regardless of ${user.dir} as long as the classpath is right. Useful for +Eclipse... \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyEnum.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyEnum.java new file mode 100644 index 000000000..cb7801c0e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyEnum.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public enum MyEnum +{ + + @Deprecated( ) + SOME_VALUE, + + // cf. MPLUGIN-151 + @SuppressWarnings( "all" ) + ANOTHER_VALUE, + + @SuppressWarnings( value = { "all" } ) + YET_ANOTHER_VALUE; + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyMojo.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyMojo.java new file mode 100644 index 000000000..72a13cd89 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/MyMojo.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.*; + +import org.apache.maven.plugin.AbstractMojo; + +/** + * Test for gleaning of source files with Java 1.5 features + * + * @goal test + */ +public class MyMojo + extends AbstractMojo +{ + + // cf. MPLUGIN-152 + private static final Map map1 = Collections. emptyMap(); + + public void execute() + { + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/plugin-expected.xml new file mode 100644 index 000000000..51c0c83e5 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/java-1.5/plugin-expected.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + test + false + true + + + test + Test for gleaning of source files with Java 1.5 features + false + true + false + false + false + true + MyMojo + java + per-lookup + once-per-session + false + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Default.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Default.java new file mode 100644 index 000000000..a9594b4eb --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Default.java @@ -0,0 +1,59 @@ +package source; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.tools.plugin.scanner.MojoScanner; + +/** + * Test default values. + * + * @goal default-values + */ +public class Default + extends AbstractMojo +{ + /** + * A parameter. + * + * @parameter + */ + protected String[] parameter; + + /** + * An attribute not published as parameter. + */ + protected String[] attribute; + + /** + * A component. + * + * @component + */ + private MojoScanner component; + + public Default() + { + } + + public void execute() + { + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Full.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Full.java new file mode 100644 index 000000000..72d82bcbc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/Full.java @@ -0,0 +1,86 @@ +package source; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.tools.plugin.scanner.MojoScanner; + +/** + * Test defining every javadoc annotation. + * + * @goal full-annotations + * @aggregator + * @configurator "role-hint" + * @execute phase="site-deploy" lifecycle="site" + * @executionStrategy always + * @inheritByDefault false + * @instantiationStrategy singleton + * @phase install + * @requiresDependencyResolution compile+runtime + * @requiresDependencyCollection test + * @requiresDirectInvocation true + * @requiresOnline true + * @requiresProject false + * @requiresReports true + * @threadSafe + * @since now + * @deprecated deprecation text test + */ +public class Full + extends AbstractMojo +{ + /** + * A parameter. + * + * @parameter + */ + protected String[] parameter; + + /** + * @parameter alias="myAlias" property="aSystemProperty" default-value="${anExpression}" + * @readonly + * @required + * @since tomorrow + * @deprecated after tomorrow + */ + private File file; + + /** + * @parameter property="aSystemProperty" + */ + private String property; + + /** + * A component. + * + * @component role="role" roleHint="hint" + * @required + */ + private MojoScanner component; + + public Full() + { + } + + public void execute() + { + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/package-info.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/package-info.java new file mode 100644 index 000000000..6e2c43430 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/package-info.java @@ -0,0 +1,23 @@ +/** + * Regression test for MPLUGIN-39. + */ +package source; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/plugin-expected.xml new file mode 100644 index 000000000..f8991d105 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source/plugin-expected.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + test + false + true + + + default-values + Test default values. + false + true + false + false + false + true + source.Default + java + per-lookup + once-per-session + false + + + parameter + java.lang.String[] + false + true + A parameter. + + + + + org.apache.maven.tools.plugin.scanner.MojoScanner + component + + + + + full-annotations + Test defining every javadoc annotation. + compile+runtime + true + false + true + true + true + false + install + site-deploy + site + source.Full + java + "role-hint" + singleton + always + now + deprecation text test + test + true + + + file + myAlias + java.io.File + tomorrow + after tomorrow + true + false + + + + parameter + java.lang.String[] + false + true + A parameter. + + + property + java.lang.String + false + true + + + + + ${aSystemProperty} + ${aSystemProperty} + + + + role + hint + component + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/Bla.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/Bla.java new file mode 100644 index 000000000..83a14c074 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/Bla.java @@ -0,0 +1,24 @@ +package source2; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +public interface Bla +{ +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/JavaExtractorTestThree.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/JavaExtractorTestThree.java new file mode 100644 index 000000000..fe5f60d75 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/JavaExtractorTestThree.java @@ -0,0 +1,53 @@ +package source2; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.AbstractMojo; + +/** + * Tests the implementation argument of the parameter annotation. + * + * @goal ideaThree + * @requiresDependencyResolution compile + * @requiresDependencyCollection test + * @threadSafe + * + */ +public class JavaExtractorTestThree + extends AbstractMojo +{ + /** + * @parameter implementation=source2.sub.MyBla + * @required + */ + private Bla bla; + + public JavaExtractorTestThree() + { + } + + public void execute() + { + if ( getLog() != null ) + { + getLog().info( "bla: " + bla ); + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/plugin-expected.xml new file mode 100644 index 000000000..80170a1f0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/plugin-expected.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + test + false + true + + + ideaThree + Tests the implementation argument of the parameter annotation. + compile + false + true + false + false + false + true + source2.JavaExtractorTestThree + java + per-lookup + once-per-session + test + true + + + bla + source2.Bla + source2.sub.MyBla + true + true + + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/sub/MyBla.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/sub/MyBla.java new file mode 100644 index 000000000..347f53b9c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source2/sub/MyBla.java @@ -0,0 +1,27 @@ +package source2.sub; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import source2.Bla; + +public class MyBla + implements Bla +{ +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/TestAnnotation.java b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/TestAnnotation.java new file mode 100644 index 000000000..a231e685b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/TestAnnotation.java @@ -0,0 +1,27 @@ +package source3; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +@Retention( RetentionPolicy.RUNTIME ) +@Target( ElementType.ANNOTATION_TYPE ) +public @interface TestAnnotation +{ + +} diff --git a/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/plugin-expected.xml b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/plugin-expected.xml new file mode 100644 index 000000000..423409665 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-plugin-tools-java/src/test/resources/source3/plugin-expected.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + test + false + true + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/pom.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/pom.xml new file mode 100644 index 000000000..1792508d3 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/pom.xml @@ -0,0 +1,78 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-script + 3.6.1-SNAPSHOT + + + maven-plugin-tools-ant + + Maven Plugin Tool for Ant + Descriptor extractor for plugins written in Ant. + + + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + org.apache.maven.plugin-tools + maven-plugin-tools-model + + + junit + junit + test + + + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-component-annotations + + + junit + junit + + + + + + + + + org.codehaus.plexus + plexus-component-metadata + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java new file mode 100644 index 000000000..d0a1e681f --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java @@ -0,0 +1,244 @@ +package org.apache.maven.tools.plugin.extractor.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.path.PathTranslator; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException; +import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.util.StringUtils; + +/** + * Extracts Mojo descriptors from Ant sources. + * + */ +@Component( role = MojoDescriptorExtractor.class, hint = "ant" ) +public class AntMojoDescriptorExtractor + extends AbstractScriptedMojoDescriptorExtractor + implements MojoDescriptorExtractor +{ + /** Default metadata file extension */ + private static final String METADATA_FILE_EXTENSION = ".mojos.xml"; + + /** Default Ant build file extension */ + private static final String SCRIPT_FILE_EXTENSION = ".build.xml"; + + /** {@inheritDoc} */ + protected List extractMojoDescriptorsFromMetadata( + Map> metadataFilesKeyedByBasedir, + PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + List descriptors = new ArrayList<>(); + + PluginMetadataParser parser = new PluginMetadataParser(); + + for ( Map.Entry> entry : metadataFilesKeyedByBasedir.entrySet() ) + { + String basedir = entry.getKey(); + Set metadataFiles = entry.getValue(); + + for ( File metadataFile : metadataFiles ) + { + String basename = metadataFile.getName(); + basename = basename.substring( 0, basename.length() - METADATA_FILE_EXTENSION.length() ); + + File scriptFile = new File( metadataFile.getParentFile(), basename + SCRIPT_FILE_EXTENSION ); + + if ( !scriptFile.exists() ) + { + throw new InvalidPluginDescriptorException( + "Found orphaned plugin metadata file: " + metadataFile ); + } + + String relativePath = scriptFile.getPath().substring( basedir.length() ).replace( '\\', '/' ); + + if ( relativePath.startsWith( "/" ) ) + { + relativePath = relativePath.substring( 1 ); + } + + try + { + Set mojoDescriptors = parser.parseMojoDescriptors( metadataFile ); + + for ( MojoDescriptor descriptor : mojoDescriptors ) + { + @SuppressWarnings( "unchecked" ) + Map paramMap = descriptor.getParameterMap(); + + if ( !paramMap.containsKey( "basedir" ) ) + { + Parameter param = new Parameter(); + param.setName( "basedir" ); + param.setAlias( "ant.basedir" ); + param.setExpression( "${antBasedir}" ); + param.setDefaultValue( "${basedir}" ); + param.setType( "java.io.File" ); + param.setDescription( "The base directory from which to execute the Ant script." ); + param.setEditable( true ); + param.setRequired( true ); + + descriptor.addParameter( param ); + } + + if ( !paramMap.containsKey( "antMessageLevel" ) ) + { + Parameter param = new Parameter(); + param.setName( "messageLevel" ); + param.setAlias( "ant.messageLevel" ); + param.setExpression( "${antMessageLevel}" ); + param.setDefaultValue( "info" ); + param.setType( "java.lang.String" ); + param.setDescription( "The message-level used to tune the verbosity of Ant logging." ); + param.setEditable( true ); + param.setRequired( false ); + + descriptor.addParameter( param ); + } + + if ( !paramMap.containsKey( "project" ) ) + { + Parameter param = new Parameter(); + param.setName( "project" ); + param.setDefaultValue( "${project}" ); + param.setType( MavenProject.class.getName() ); + param.setDescription( "The current MavenProject instance, which contains classpath " + + "elements." ); + param.setEditable( false ); + param.setRequired( true ); + + descriptor.addParameter( param ); + } + + if ( !paramMap.containsKey( "session" ) ) + { + Parameter param = new Parameter(); + param.setName( "session" ); + param.setDefaultValue( "${session}" ); + param.setType( "org.apache.maven.execution.MavenSession" ); + param.setDescription( "The current MavenSession instance, which is used for " + + "plugin-style expression resolution." ); + param.setEditable( false ); + param.setRequired( true ); + + descriptor.addParameter( param ); + } + + if ( !paramMap.containsKey( "mojoExecution" ) ) + { + Parameter param = new Parameter(); + param.setName( "mojoExecution" ); + param.setDefaultValue( "${mojoExecution}" ); + param.setType( "org.apache.maven.plugin.MojoExecution" ); + param.setDescription( "The current Maven MojoExecution instance, which contains " + + "information about the mojo currently executing." ); + param.setEditable( false ); + param.setRequired( true ); + + descriptor.addParameter( param ); + } + + @SuppressWarnings( "unchecked" ) + List requirements = descriptor.getRequirements(); + Map reqMap = new HashMap<>(); + + if ( requirements != null ) + { + for ( ComponentRequirement req : requirements ) + { + reqMap.put( req.getRole(), req ); + } + } + + if ( !reqMap.containsKey( PathTranslator.class.getName() ) ) + { + ComponentRequirement req = new ComponentRequirement(); + req.setRole( PathTranslator.class.getName() ); + + descriptor.addRequirement( req ); + } + + String implementation = relativePath; + + String dImpl = descriptor.getImplementation(); + if ( StringUtils.isNotEmpty( dImpl ) ) + { + if ( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.equals( dImpl ) ) + { + implementation = relativePath; + } + else + { + implementation = + relativePath + + dImpl.substring( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.length() ); + } + } + + descriptor.setImplementation( implementation ); + + descriptor.setLanguage( "ant-mojo" ); + descriptor.setComponentComposer( "map-oriented" ); + descriptor.setComponentConfigurator( "map-oriented" ); + + descriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + descriptors.add( descriptor ); + } + } + catch ( PluginMetadataParseException e ) + { + throw new ExtractionException( "Error extracting mojo descriptor from script: " + metadataFile, e ); + } + } + } + + return descriptors; + } + + /** {@inheritDoc} */ + protected String getScriptFileExtension( PluginToolsRequest request ) + { + return SCRIPT_FILE_EXTENSION; + } + + /** {@inheritDoc} */ + protected String getMetadataFileExtension( PluginToolsRequest request ) + { + return METADATA_FILE_EXTENSION; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/apt/index.apt new file mode 100644 index 000000000..2b25f6850 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/apt/index.apt @@ -0,0 +1,37 @@ + ------ + Introduction + ------ + Vincent Siveton + ------ + 2008-07-15 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Tool for Ant + + The Maven Plugin Tool for Ant is the <<>> implementation of + {{{../maven-plugin-tools-api/index.html}maven-plugin-tools-api}} to + extract descriptors for plugins written in Ant. + + An Ant Maven Plugin has to be written in a file ending in <<<.build.xml>>> in <<>>, + with {{{../maven-plugin-tools-model/plugin-metadata.html}plugin metadata}} in corresponding <<<.mojos.xml>>> file + to generate the plugin descriptor. diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractorTest.java b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractorTest.java new file mode 100644 index 000000000..c11f23a75 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractorTest.java @@ -0,0 +1,141 @@ +package org.apache.maven.tools.plugin.extractor.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.path.PathTranslator; +import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class AntMojoDescriptorExtractorTest +{ + + @Test + public void testBasicMojoExtraction_CheckInjectedParametersAndRequirements() + throws InvalidPluginDescriptorException, ExtractionException + { + Map> scriptMap = buildTestMap( "basic" ); + + PluginDescriptor pd = new PluginDescriptor(); + + pd.setArtifactId( "test-plugin" ); + pd.setGroupId( "org.mytest" ); + pd.setVersion( "1" ); + pd.setGoalPrefix( "mytest" ); + + PluginToolsRequest request = new DefaultPluginToolsRequest( new MavenProject(), pd ); + + List metadata = new AntMojoDescriptorExtractor().extractMojoDescriptorsFromMetadata( scriptMap, request ); + + assertEquals( 2, metadata.size() ); + + for ( MojoDescriptor desc : metadata ) + { + if ( "test".equals( desc.getGoal() ) ) + { + assertFalse( desc.getImplementation().contains( ":" ) ); + } + else if ( "test2".equals( desc.getGoal() ) ) + { + assertTrue( desc.getImplementation().endsWith( ":test2" ) ); + } + + List params = desc.getParameters(); + Map paramMap = new HashMap<>(); + for ( Parameter param : params ) + { + paramMap.put( param.getName(), param ); + } + + assertNotNull( "Mojo descriptor: " + desc.getGoal() + " is missing 'basedir' parameter.", paramMap.get( "basedir" ) ); + assertNotNull( "Mojo descriptor: " + desc.getGoal() + " is missing 'messageLevel' parameter.", paramMap.get( "messageLevel" ) ); + assertNotNull( "Mojo descriptor: " + desc.getGoal() + " is missing 'project' parameter.", paramMap.get( "project" ) ); + assertNotNull( "Mojo descriptor: " + desc.getGoal() + " is missing 'session' parameter.", paramMap.get( "session" ) ); + assertNotNull( "Mojo descriptor: " + desc.getGoal() + " is missing 'mojoExecution' parameter.", paramMap.get( "mojoExecution" ) ); + + List components = desc.getRequirements(); + + assertNotNull( components ); + assertEquals( 1, components.size() ); + + ComponentRequirement req = components.get( 0 ); + assertEquals( "Mojo descriptor: " + desc.getGoal() + " is missing 'PathTranslator' component requirement.", PathTranslator.class.getName(), req.getRole() ); + } + } + + private Map> buildTestMap( String resourceDirName ) + { + try + { + Map> result = new HashMap<>(); + ClassLoader cloader = Thread.currentThread().getContextClassLoader(); + URL mojosXmlUrl = cloader.getResource( resourceDirName + "/test.mojos.xml" ); + + if ( mojosXmlUrl == null ) + { + fail( "No classpath resource named: '" + resourceDirName + "/test.mojos.xml' could be found." ); + } + + File mojosXml = Paths.get( mojosXmlUrl.toURI() ).toFile(); + File dir = mojosXml.getParentFile(); + + Set scripts = new HashSet<>(); + String[] listing = dir.list(); + for ( int i = 0; listing != null && i < listing.length; i++ ) + { + if ( listing[i].endsWith( ".mojos.xml" ) ) + { + File f = new File( dir, listing[i] ).getAbsoluteFile(); + + scripts.add( f ); + } + } + + result.put( dir.getAbsolutePath(), scripts ); + + return result; + } + catch ( final URISyntaxException e ) + { + throw new AssertionError( e ); + } + } + + // TODO + +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.build.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.build.xml new file mode 100644 index 000000000..b0bd1fbff --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.build.xml @@ -0,0 +1,29 @@ + + + + + + ${testDir} + + + + Another test target + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.mojos.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.mojos.xml new file mode 100644 index 000000000..f54c76586 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-ant/src/test/resources/basic/test.mojos.xml @@ -0,0 +1,74 @@ + + + + + + + test + + + testDir + testDir + true + java.lang.String + Test directory location. + + + Runs the default ("test") goal of the build script. + + + test2 + test2 + + + org.apache.maven.project.path.PathTranslator + + + + + testDir + testDir + true + java.lang.String + Test directory location. + + + project + project + true + org.apache.maven.project.MavenProject + + + session + session + true + org.apache.maven.execution.MavenSession + + + mojoExecution + mojoExecution + true + org.apache.maven.plugin.MojoExecution + + + Runs the default ("test2") goal of the build script. + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/pom.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/pom.xml new file mode 100644 index 000000000..f01e1131c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/pom.xml @@ -0,0 +1,74 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-script + 3.6.1-SNAPSHOT + + + maven-plugin-tools-beanshell + + Maven Plugin Tool for Beanshell + Descriptor extractor for plugins written in Beanshell. + + + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + + + org.apache.maven + maven-plugin-api + + + org.codehaus.plexus + plexus-component-annotations + + + junit + junit + + + + + + + org.beanshell + bsh + 1.3.0 + + + + + + + org.codehaus.plexus + plexus-component-metadata + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java new file mode 100644 index 000000000..9a12df17c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java @@ -0,0 +1,131 @@ +package org.apache.maven.tools.plugin.extractor.beanshell; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import bsh.EvalError; +import bsh.Interpreter; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.codehaus.plexus.component.annotations.Component; + +import java.io.File; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Extracts Mojo descriptors from BeanShell sources. + * + */ +@Component( role = MojoDescriptorExtractor.class, hint = "bsh" ) +public class BeanshellMojoDescriptorExtractor + extends AbstractScriptedMojoDescriptorExtractor + implements MojoDescriptorExtractor +{ + /** + * {@inheritDoc} + */ + protected String getScriptFileExtension( PluginToolsRequest request ) + { + return ".bsh"; + } + + /** + * {@inheritDoc} + */ + protected List extractMojoDescriptors( Map> scriptFilesKeyedByBasedir, + PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + List descriptors = new ArrayList<>(); + + for ( Map.Entry> entry : scriptFilesKeyedByBasedir.entrySet() ) + { + String basedir = entry.getKey(); + Set metadataFiles = entry.getValue(); + + for ( File scriptFile : metadataFiles ) + { + String relativePath = null; + + if ( basedir.endsWith( "/" ) ) + { + basedir = basedir.substring( 0, basedir.length() - 2 ); + } + + relativePath = scriptFile.getPath().substring( basedir.length() ); + + relativePath = relativePath.replace( '\\', '/' ); + + MojoDescriptor mojoDescriptor = createMojoDescriptor( basedir, relativePath, request ); + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param basedir not null + * @param resource not null + * @param request not null + * @return a new Mojo descriptor instance + * @throws InvalidPluginDescriptorException + * if any + */ + private MojoDescriptor createMojoDescriptor( String basedir, String resource, PluginToolsRequest request ) + throws InvalidPluginDescriptorException + { + MojoDescriptor mojoDescriptor = new MojoDescriptor(); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + mojoDescriptor.setLanguage( "bsh" ); + mojoDescriptor.setComponentConfigurator( "bsh" ); + + mojoDescriptor.setImplementation( resource ); + + Interpreter interpreter = new Interpreter(); + + try + { + interpreter.set( "file", new File( basedir, resource ) ); + + interpreter.set( "mojoDescriptor", mojoDescriptor ); + + interpreter.set( "encoding", "UTF-8" ); + + interpreter.eval( new InputStreamReader( getClass().getResourceAsStream( "/extractor.bsh" ), UTF_8 ) ); + } + catch ( EvalError evalError ) + { + throw new InvalidPluginDescriptorException( "Error scanning beanshell script", evalError ); + } + + return mojoDescriptor; + } +} \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/resources/extractor.bsh b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/resources/extractor.bsh new file mode 100644 index 000000000..d4b8947a0 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/main/resources/extractor.bsh @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import bsh.*; +import java.util.regex.Pattern; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import org.codehaus.plexus.util.StringUtils; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; + +// only on start of line +this.tag = "\\r?\\n\\s*\\*?\\s*@(\\w+)"; +// zero width lookahead to next tag or end of comment +this.tagOrEndComment = "(?=" + tag + "|\\*/)"; +this.commentTextPattern = Pattern.compile( "(?s)/\\*\\*(.*?)" + tagOrEndComment ); +this.tagsPattern = Pattern.compile( "(?s)" + tag + "\\s*(.*?)" + tagOrEndComment ); +this.descriptionPattern = Pattern.compile( "(?s)\\r?\\n\\s*\\*" ); +this.typePattern = Pattern.compile( "type\\s*=\\s*\"(.*?)\"" ); +this.expressionPattern = Pattern.compile( "expression\\s*=\\s*\"(.*?)\"" ); +this.defaultValuePattern = Pattern.compile( "default-value\\s*=\\s*\"(.*?)\"" ); +this.phasePattern = Pattern.compile( "phase\\s*=\\s*\"(.*?)\"" ); +this.goalPattern = Pattern.compile( "goal\\s*=\\s*\"(.*?)\"" ); +this.lifecyclePattern = Pattern.compile( "lifecycle\\s*=\\s*\"(.*?)\"" ); +this.rolePattern = Pattern.compile( "role\\s*=\\s*\"(.*?)\"" ); +this.roleHintPattern = Pattern.compile( "roleHint\\s*=\\s*\"(.*?)\"" ); + +setAccessibility( true ); + +createParameter( text, method ) +{ + if ( method.startsWith( "set" ) ) + { + this.name = StringUtils.uncapitalise( method.substring( 3 ) ); + this.desc = getDescription( text ); + this.tags = getTags( text ); + + this.parameter = new Parameter(); + parameter.setName( name ); + parameter.setDescription( desc ); + parameter.setRequired( tags.containsKey( "required" ) ); + parameter.setEditable( !tags.containsKey( "readonly" ) ); + this.deprecation = tags.get( "deprecated" ); + if ( deprecation != null ) + { + parameter.setDeprecated( deprecation ); + } + this.alias = tags.get( "alias" ); + if ( alias != null ) + { + parameter.setAlias( alias ); + } + this.value = tags.get( "parameter" ); + if ( value != null ) + { + m = typePattern.matcher( value ); + if ( m.find() ) + { + parameter.setType( m.group( 1 ) ); + } + else + { + parameter.setType( "java.lang.Object" ); + } + m = expressionPattern.matcher( value ); + if ( m.find() ) + { + parameter.setExpression( m.group( 1 ) ); + } + m = defaultValuePattern.matcher( value ); + if ( m.find() ) + { + parameter.setDefaultValue( m.group( 1 ) ); + } + } + value = tags.get( "component" ); + if ( value != null ) + { + m = rolePattern.matcher( value ); + if ( m.find() ) + { + role = m.group( 1 ); + } + m = roleHintPattern.matcher( value ); + if ( m.find() ) + { + roleHint = m.group( 1 ); + } + else + { + roleHint = null; + } + parameter.setRequirement( new Requirement( role, roleHint ) ); + } + return parameter; + } + return null; +} + +getTags( text ) +{ + this.matcher = tagsPattern.matcher( text ); + this.tags = new HashMap(); + while ( matcher.find() ) + { + this.tagname = matcher.group( 1 ); + this.tagvalue = matcher.group( 2 ); + tags.put( tagname, tagvalue.trim() ); + } + return tags; +} + +getDescription( text ) +{ + this.matcher = commentTextPattern.matcher( text ); + if ( matcher.find() ) + { + this.input = matcher.group( 1 ); + return descriptionPattern.matcher( input ).replaceAll( "" ).trim(); + } + else + { + return ""; + } +} + +extract( file, encoding, mojoDescriptor ) +{ + this.parser = new Parser( new InputStreamReader( new FileInputStream( file ), encoding ) ); + parser.setRetainComments( true ); + + this.lastNode = null; + this.firstComment = null; + while ( !parser.Line() ) + { + this.node = parser.popNode(); + + if ( node instanceof BSHFormalComment && firstComment == null ) + { + firstComment = node; + } + + if ( node instanceof BSHMethodDeclaration ) + { + if ( lastNode instanceof BSHFormalComment ) + { + this.text = lastNode.text; + + this.method = node.name; + + this.parameter = createParameter( text, method ); + if ( parameter != null ) + { + if ( "${reports}".equals( parameter.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + mojoDescriptor.addParameter( parameter ); + } + + if ( firstComment == lastNode ) + { + firstComment = null; + } + } + } + lastNode = node; + } + if ( firstComment != null ) + { + this.text = firstComment.text; + + mojoDescriptor.setDescription( getDescription( text ) ); + this.tags = getTags( text ); + mojoDescriptor.setGoal( tags.get( "goal" ) ); + mojoDescriptor.setPhase( tags.get( "phase" ) ); + this.value = tags.get( "requiresDependencyResolution" ); + // TODO: share with java extractor + if ( value == null || value.length() == 0 ) + { + value = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired( value ); + + mojoDescriptor.setProjectRequired( tags.containsKey( "requiresProject" ) ); + mojoDescriptor.setOnlineRequired( tags.containsKey( "requiresOnline" ) ); + + this.value = tags.get( "execute" ); + if ( value != null ) + { + m = phasePattern.matcher( value ); + if ( m.find() ) + { + mojoDescriptor.setExecutePhase( m.group( 1 ) ); + } + + m = goalPattern.matcher( value ); + if ( m.find() ) + { + mojoDescriptor.setExecuteGoal( m.group( 1 ) ); + } + + if ( mojoDescriptor.getExecutePhase() == null || mojoDescriptor.getExecuteGoal() == null ) + { + throw new InvalidPluginDescriptorException( "@execute must have a phase or goal" ); + } + + if ( mojoDescriptor.getExecutePhase() != null && mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( "@execute must have only one of a phase or goal" ); + } + + m = lifecyclePattern.matcher( value ); + if ( m.find() ) + { + mojoDescriptor.setExecuteLifecycle( m.group( 1 ) ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( "@execute lifecycle requires a phase instead of a goal" ); + } + } + } + } +} + +extract( file, encoding, mojoDescriptor ); diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/apt/index.apt new file mode 100644 index 000000000..ee629caec --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/apt/index.apt @@ -0,0 +1,33 @@ + ------ + Introduction + ------ + Vincent Siveton + ------ + 2008-07-15 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Tool for Beanshell + + The Maven Plugin Tool for Beanshell is the <<>> implementation of + {{{../maven-plugin-tools-api/index.html}maven-plugin-tools-api}} + to extract descriptors for plugins written in Beanshell. diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-beanshell/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/pom.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/pom.xml new file mode 100644 index 000000000..06cd4fb23 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/pom.xml @@ -0,0 +1,102 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-script + 3.6.1-SNAPSHOT + + + maven-plugin-tools-model + + Maven Plugin Metadata Model + The Maven Plugin Metadata Model provides an API to play with the Metadata model. + + + + + org.apache.maven + maven-plugin-api + + + + org.codehaus.plexus + plexus-utils + + + org.sonatype.sisu + sisu-inject-plexus + 1.4.2 + + + junit + junit + test + + + + + + + org.codehaus.modello + modello-maven-plugin + + + src/main/mdo/plugin-metadata.mdo + + 1.1.0 + 1.0.0 + + + + site-docs + pre-site + + xdoc + + + + xsd + pre-site + + xsd + + + ${project.reporting.outputDirectory} + + + + standard + + java + xpp3-reader + xpp3-writer + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParseException.java b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParseException.java new file mode 100644 index 000000000..f07803961 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParseException.java @@ -0,0 +1,78 @@ +package org.apache.maven.tools.plugin.extractor.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; + +/** + * Exception when plugin metadata parsing occurred. + * + */ +public class PluginMetadataParseException + extends Exception +{ + /** serialVersionUID */ + static final long serialVersionUID = 4022348153707995574L; + + private final File metadataFile; + + private final String originalMessage; + + /** + * @param metadataFile could be null + * @param message could be null + * @param cause could be null + */ + public PluginMetadataParseException( File metadataFile, String message, Throwable cause ) + { + super( "Error parsing file: " + metadataFile + ". Reason: " + message, cause ); + + this.metadataFile = metadataFile; + this.originalMessage = message; + } + + /** + * @param metadataFile could be null + * @param message could be null + */ + public PluginMetadataParseException( File metadataFile, String message ) + { + super( "Error parsing file: " + metadataFile + ". Reason: " + message ); + + this.metadataFile = metadataFile; + this.originalMessage = message; + } + + /** + * @return the metadata file + */ + public File getMetadataFile() + { + return metadataFile; + } + + /** + * @return the original message + */ + public String getOriginalMessage() + { + return originalMessage; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java new file mode 100644 index 000000000..e0596f499 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java @@ -0,0 +1,190 @@ +package org.apache.maven.tools.plugin.extractor.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.DuplicateParameterException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.tools.plugin.extractor.model.io.xpp3.PluginMetadataXpp3Reader; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Parser for plugin metadata. + */ +public class PluginMetadataParser +{ + /** + * Default implementation path which will be replaced in + * AbstractScriptedMojoDescriptorExtractor#extractMojoDescriptorsFromMetadata(Map, PluginDescriptor) + */ + public static final String IMPL_BASE_PLACEHOLDER = ""; + + /** + * @param metadataFile the metadata file to be parse + * @return a set of MojoDescriptor + * @throws PluginMetadataParseException if any + */ + public Set parseMojoDescriptors( File metadataFile ) + throws PluginMetadataParseException + { + Set descriptors = new HashSet<>(); + + try ( Reader reader = ReaderFactory.newXmlReader( metadataFile ) ) + { + + PluginMetadataXpp3Reader metadataReader = new PluginMetadataXpp3Reader(); + + PluginMetadata pluginMetadata = metadataReader.read( reader ); + + List mojos = pluginMetadata.getMojos(); + + if ( mojos != null ) + { + for ( Mojo mojo : mojos ) + { + MojoDescriptor descriptor = asDescriptor( metadataFile, mojo ); + + descriptors.add( descriptor ); + } + } + } + catch ( IOException | XmlPullParserException e ) + { + throw new PluginMetadataParseException( metadataFile, "Cannot parse plugin metadata from file.", e ); + } + + return descriptors; + } + + /** + * @param metadataFile not null + * @param mojo not null + * @return a mojo descriptor instance + * @throws PluginMetadataParseException if any + */ + private MojoDescriptor asDescriptor( File metadataFile, Mojo mojo ) + throws PluginMetadataParseException + { + MojoDescriptor descriptor = new MojoDescriptor(); + + if ( mojo.getCall() != null ) + { + descriptor.setImplementation( IMPL_BASE_PLACEHOLDER + ":" + mojo.getCall() ); + } + else + { + descriptor.setImplementation( IMPL_BASE_PLACEHOLDER ); + } + + descriptor.setGoal( mojo.getGoal() ); + descriptor.setPhase( mojo.getPhase() ); + descriptor.setDependencyResolutionRequired( mojo.getRequiresDependencyResolution() ); + descriptor.setAggregator( mojo.isAggregator() ); + descriptor.setInheritedByDefault( mojo.isInheritByDefault() ); + descriptor.setDirectInvocationOnly( mojo.isRequiresDirectInvocation() ); + descriptor.setOnlineRequired( mojo.isRequiresOnline() ); + descriptor.setProjectRequired( mojo.isRequiresProject() ); + descriptor.setRequiresReports( mojo.isRequiresReports() ); + descriptor.setDescription( mojo.getDescription() ); + descriptor.setDeprecated( mojo.getDeprecation() ); + descriptor.setSince( mojo.getSince() ); + + LifecycleExecution le = mojo.getExecution(); + if ( le != null ) + { + descriptor.setExecuteLifecycle( le.getLifecycle() ); + descriptor.setExecutePhase( le.getPhase() ); + descriptor.setExecuteGoal( le.getGoal() ); + } + + List parameters = mojo.getParameters(); + + if ( parameters != null && !parameters.isEmpty() ) + { + for ( org.apache.maven.tools.plugin.extractor.model.Parameter param : parameters ) + { + Parameter dParam = new Parameter(); + dParam.setAlias( param.getAlias() ); + dParam.setDeprecated( param.getDeprecation() ); + dParam.setDescription( param.getDescription() ); + dParam.setEditable( !param.isReadonly() ); + dParam.setExpression( param.getExpression() ); + dParam.setDefaultValue( param.getDefaultValue() ); + dParam.setSince( param.getSince() ); + + String property = param.getProperty(); + if ( StringUtils.isNotEmpty( property ) ) + { + dParam.setName( property ); + } + else + { + dParam.setName( param.getName() ); + } + + if ( StringUtils.isEmpty( dParam.getName() ) ) + { + throw new PluginMetadataParseException( metadataFile, "Mojo: \'" + mojo.getGoal() + + "\' has a parameter without either property or name attributes. Please specify one." ); + } + + dParam.setRequired( param.isRequired() ); + dParam.setType( param.getType() ); + + try + { + descriptor.addParameter( dParam ); + } + catch ( DuplicateParameterException e ) + { + throw new PluginMetadataParseException( metadataFile, + "Duplicate parameters detected for mojo: " + mojo.getGoal(), + e ); + } + } + } + + List components = mojo.getComponents(); + + if ( components != null && !components.isEmpty() ) + { + for ( Component component : components ) + { + ComponentRequirement cr = new ComponentRequirement(); + cr.setRole( component.getRole() ); + cr.setRoleHint( component.getHint() ); + + descriptor.addRequirement( cr ); + } + } + + return descriptor; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/mdo/plugin-metadata.mdo b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/mdo/plugin-metadata.mdo new file mode 100644 index 000000000..804e50e55 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/main/mdo/plugin-metadata.mdo @@ -0,0 +1,357 @@ + + + + + plugin-metadata + PluginMetadata + + + + package + org.apache.maven.tools.plugin.extractor.model + + + + + PluginMetadata + 1.0.0+ + Root element of a script-based mojo's plugin metadata bindings. + + + mojos + 1.0.0+ + true + The list of mojos contained in the accompanying script. + + Mojo + * + + + + + + Mojo + 1.0.0+ + Mojo descriptor definition. + + + 1.0.0+ + goal + String + true + The name of the goal used to invoke this mojo. + + + 1.0.0+ + phase + String + The phase to which this mojo should be bound by default. + + + 1.0.0+ + aggregator + boolean + Whether this mojo operates as an aggregator when the reactor is run. That is, only runs once. + + + + 1.0.0+ + requiresDependencyResolution + String + The scope of dependencies that this mojo requires to have resolved. + + + 1.0.0+ + requiresProject + boolean + Whether this mojo requires a project instance in order to execute. + + + 1.0.0+ + requiresReports + boolean + Whether this mojo requires a reports section in the POM. + + + 1.0.0+ + requiresOnline + boolean + Whether this mojo requires online mode to operate normally. + + + 1.0.0+ + inheritByDefault + boolean + Whether this mojo's configuration should propagate down the POM inheritance chain by default. + + + + 1.0.0+ + requiresDirectInvocation + boolean + If true, this mojo can only be directly invoked (eg. specified directly on the command line). + + + + 1.0.0+ + execution + Information about a sub-execution of the Maven lifecycle which should be processed. + + LifecycleExecution + + + + 1.0.0+ + components + List of plexus components required by this mojo. + + Component + * + + + + 1.0.0+ + parameters + List of parameters used by this mojo. + + Parameter + * + + + + description + 1.0.0+ + The description for this parameter. + String + + + deprecation + 1.0.0+ + A deprecation message for this mojo parameter. + String + + + 1.1.0+ + since + String + Version when the mojo was added to the API. + + + 1.0.0+ + call + String + The target/method within the script to call when this mojo executes. + + + + + LifecycleExecution + 1.0.0+ + + + + lifecycle + 1.0.0+ + String + The name of the overlay to apply to the sub-lifecycle before executing it. If specified, this + lifecycle overlay definition will be bundled with the plugin. + + + + phase + 1.0.0+ + The phase in the sub-lifecycle. + String + + + goal + 1.0.0+ + A goal, not attached to a lifecycle phase, which should be executed ahead of this mojo. + + String + + + + + Component + 1.0.0+ + + + + role + 1.0.0+ + The component role to lookup. + true + String + + + hint + 1.0.0+ + String + The role-hint to lookup. + + + + + Parameter + 1.0.0+ + + + + name + 1.0.0+ + The parameter name + true + String + + + alias + 1.0.0+ + String + An alternate name for the parameter. + + + property + 1.0.0+ + String + The JavaBeans property name to use to configure the mojo with this parameter. + + + required + 1.0.0+ + boolean + Whether this parameter is required. + + + readonly + 1.0.0+ + boolean + + + + expression + 1.0.0+ + String + + + + defaultValue + 1.0.0+ + String + + + + type + 1.0.0+ + String + true + + + + description + 1.0.0+ + The description for this parameter. + String + + + deprecation + 1.0.0+ + A deprecation message for this mojo parameter. + String + + + 1.1.0+ + since + String + Version when the parameter was added. + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/apt/index.apt b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/apt/index.apt new file mode 100644 index 000000000..77d128c14 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/apt/index.apt @@ -0,0 +1,41 @@ + ------ + Introduction + ------ + Vincent Siveton + ------ + 2008-07-15 + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/doxia/references/apt-format.html + +Maven Plugin Tool Model + + The Maven Plugin Tool Model is a model to extract descriptors information from plugins. + + The following are generated from this model: + + * {{{./apidocs/index.html}Java sources}} with Reader and Writers for the Xpp3 XML parser + + * A {{{./plugin-metadata.html}Descriptor Reference}} + + * An {{{./plugin-metadata-1.1.0.xsd}XSD}}. + + [] diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/site.xml new file mode 100644 index 000000000..aa167ffd4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/site/site.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParserTest.java b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParserTest.java new file mode 100644 index 000000000..763225525 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParserTest.java @@ -0,0 +1,80 @@ +package org.apache.maven.tools.plugin.extractor.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; +import java.util.Set; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PluginMetadataParserTest +{ + + @Test + public void testBasicDeclarationWithoutCall() + throws PluginMetadataParseException + { + File metadataFile = getMetadataFile( "test.mojos.xml" ); + Set descriptors = new PluginMetadataParser().parseMojoDescriptors( metadataFile ); + + assertEquals(1, descriptors.size()); + + MojoDescriptor desc = descriptors.iterator().next(); + assertFalse( desc.getImplementation().contains( ":" ) ); + assertEquals( "test", desc.getGoal() ); + } + + @Test + public void testBasicDeclarationWithCall() + throws PluginMetadataParseException + { + File metadataFile = getMetadataFile( "test2.mojos.xml" ); + Set descriptors = new PluginMetadataParser().parseMojoDescriptors( metadataFile ); + + assertEquals( 1, descriptors.size() ); + + MojoDescriptor desc = descriptors.iterator().next(); + assertTrue( desc.getImplementation().endsWith( ":test2" ) ); + assertEquals( "test2", desc.getGoal() ); + } + + private File getMetadataFile( String name ) + { + try + { + URL resource = Thread.currentThread().getContextClassLoader().getResource( name ); + if ( resource == null ) + { + fail( "Cannot find classpath resource: '" + name + "'." ); + } + return Paths.get( resource.toURI() ).toFile(); + } + catch ( final URISyntaxException e ) + { + throw new AssertionError( e ); + } + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test.mojos.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test.mojos.xml new file mode 100644 index 000000000..b7f819c32 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test.mojos.xml @@ -0,0 +1,37 @@ + + + + + + + test + + + testDir + testDir + true + java.lang.String + Test directory location. + + + Runs the default ("test") goal of the build script. + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test2.mojos.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test2.mojos.xml new file mode 100644 index 000000000..8707a4cef --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-plugin-tools-model/src/test/resources/test2.mojos.xml @@ -0,0 +1,38 @@ + + + + + + + test2 + test2 + + + testDir + testDir + true + java.lang.String + Test directory location. + + + Runs the default ("test2") goal of the build script. + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/pom.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/pom.xml new file mode 100644 index 000000000..99d0c6894 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/pom.xml @@ -0,0 +1,73 @@ + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-script + 3.6.1-SNAPSHOT + + + maven-script-ant + + Maven Ant Mojo Support + Maven Ant Mojo Support, ie write Maven plugins with Ant scripts. + + + + org.apache.ant + ant + ${antVersion} + + + org.apache.ant + ant-launcher + ${antVersion} + + + org.apache.maven + maven-plugin-api + + + org.codehaus.plexus + plexus-ant-factory + 1.0-alpha-2.1 + + + org.codehaus.plexus + plexus-archiver + + + org.apache.maven + maven-core + + + junit + junit + test + + + org.mockito + mockito-core + test + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoComponentFactory.java b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoComponentFactory.java new file mode 100644 index 000000000..6c5a91693 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoComponentFactory.java @@ -0,0 +1,42 @@ +package org.apache.maven.script.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.codehaus.classworlds.ClassRealm; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.factory.ComponentInstantiationException; +import org.codehaus.plexus.component.factory.ant.AntComponentFactory; +import org.codehaus.plexus.component.factory.ant.AntScriptInvoker; +import org.codehaus.plexus.component.repository.ComponentDescriptor; + +/** + * + */ +public class AntMojoComponentFactory + extends AntComponentFactory +{ + + public Object newInstance( ComponentDescriptor descriptor, ClassRealm realm, PlexusContainer container ) + throws ComponentInstantiationException + { + return new AntMojoWrapper( (AntScriptInvoker) super.newInstance( descriptor, realm, container ) ); + } + +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java new file mode 100644 index 000000000..56eba0807 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java @@ -0,0 +1,383 @@ +package org.apache.maven.script.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DependencyResolutionRequiredException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.ContextEnabled; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.path.PathTranslator; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.PropertyHelper; +import org.apache.tools.ant.types.Path; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.zip.ZipUnArchiver; +import org.codehaus.plexus.component.MapOrientedComponent; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.component.factory.ant.AntComponentExecutionException; +import org.codehaus.plexus.component.factory.ant.AntScriptInvoker; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.logging.LogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + */ +public class AntMojoWrapper + extends AbstractMojo + implements ContextEnabled, MapOrientedComponent, LogEnabled +{ + + private Map pluginContext; + + private final AntScriptInvoker scriptInvoker; + + private Project antProject; + + private MavenProject mavenProject; + + private MojoExecution mojoExecution; + + private MavenSession session; + + private PathTranslator pathTranslator; + + private Logger logger; + + private transient List unconstructedParts = new ArrayList<>(); + + public AntMojoWrapper( AntScriptInvoker scriptInvoker ) + { + this.scriptInvoker = scriptInvoker; + } + + public void execute() + throws MojoExecutionException + { + if ( antProject == null ) + { + antProject = scriptInvoker.getProject(); + } + + Map allConfig = new HashMap<>(); + if ( pluginContext != null && !pluginContext.isEmpty() ) + { + allConfig.putAll( pluginContext ); + } + + @SuppressWarnings( "unchecked" ) + Map refs = scriptInvoker.getReferences(); + if ( refs != null ) + { + allConfig.putAll( refs ); + + for ( Map.Entry entry : refs.entrySet() ) + { + if ( entry.getKey().startsWith( PathTranslator.class.getName() ) ) + { + pathTranslator = entry.getValue(); + } + } + } + + mavenProject = (MavenProject) allConfig.get( "project" ); + + mojoExecution = (MojoExecution) allConfig.get( "mojoExecution" ); + + session = (MavenSession) allConfig.get( "session" ); + + unpackFileBasedResources(); + + addClasspathReferences(); + + if ( logger.isDebugEnabled() && !unconstructedParts.isEmpty() ) + { + StringBuilder buffer = new StringBuilder(); + + buffer.append( "The following standard Maven Ant-mojo support objects could not be created:\n\n" ); + + for ( String part : unconstructedParts ) + { + buffer.append( "\n- " ).append( part ); + } + + buffer.append( "\n\nMaven project, session, mojo-execution, or path-translation parameter " + + "information is " ); + buffer.append( "\nmissing from this mojo's plugin descriptor." ); + buffer.append( "\n\nPerhaps this Ant-based mojo depends on maven-script-ant < 2.1.0, " ); + buffer.append( "or used maven-plugin-tools-ant < 2.2 during release?\n\n" ); + + logger.debug( buffer.toString() ); + } + + try + { + scriptInvoker.invoke(); + } + catch ( AntComponentExecutionException e ) + { + throw new MojoExecutionException( "Failed to execute: " + e.getMessage(), e ); + } + + unconstructedParts.clear(); + } + + public void setPluginContext( Map pluginContext ) + { + this.pluginContext = pluginContext; + } + + public Map getPluginContext() + { + return pluginContext; + } + + public void addComponentRequirement( ComponentRequirement requirementDescriptor, Object requirementValue ) + throws ComponentConfigurationException + { + scriptInvoker.addComponentRequirement( requirementDescriptor, requirementValue ); + } + + public void setComponentConfiguration( Map componentConfiguration ) + throws ComponentConfigurationException + { + scriptInvoker.setComponentConfiguration( componentConfiguration ); + antProject = scriptInvoker.getProject(); + } + + private void unpackFileBasedResources() + throws MojoExecutionException + { + if ( mojoExecution == null || mavenProject == null ) + { + unconstructedParts.add( "Unpacked Ant build scripts (in Maven build directory)." ); + + return; + } + + // What we need to write out any resources in the plugin to the target directory of the + // mavenProject using the Ant-based plugin: + // + // 1. Need a reference to the plugin JAR itself + // 2. Need a reference to the ${basedir} of the mavenProject + + PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + + File pluginJar = pluginDescriptor.getPluginArtifact().getFile(); + + String resourcesPath = pluginDescriptor.getArtifactId(); + + File outputDirectory = new File( mavenProject.getBuild().getDirectory() ); + + try + { + UnArchiver ua = new ZipUnArchiver( pluginJar ); + + ua.extract( resourcesPath, outputDirectory ); + } + catch ( ArchiverException e ) + { + throw new MojoExecutionException( "Error extracting resources from your Ant-based plugin.", e ); + } + } + + private void addClasspathReferences() + throws MojoExecutionException + { + try + { + if ( mavenProject != null && session != null && pathTranslator != null ) + { + ExpressionEvaluator exprEvaluator = + new PluginParameterExpressionEvaluator( session, mojoExecution, pathTranslator, logger, + mavenProject, mavenProject.getProperties() ); + + PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper( antProject ); + propertyHelper.setNext( new AntPropertyHelper( exprEvaluator, mavenProject.getArtifacts(), getLog() ) ); + } + else + { + unconstructedParts.add( "Maven parameter expression evaluator for Ant properties." ); + } + + @SuppressWarnings( "unchecked" ) + Map references = scriptInvoker.getReferences(); + + if ( mavenProject != null ) + { + + // Compile classpath + Path p = new Path( antProject ); + + p.setPath( StringUtils.join( mavenProject.getCompileClasspathElements().iterator(), + File.pathSeparator ) ); + + /* maven.dependency.classpath it's deprecated as it's equal to maven.compile.classpath */ + references.put( "maven.dependency.classpath", p ); + antProject.addReference( "maven.dependency.classpath", p ); + + references.put( "maven.compile.classpath", p ); + antProject.addReference( "maven.compile.classpath", p ); + + // Runtime classpath + p = new Path( antProject ); + + p.setPath( StringUtils.join( mavenProject.getRuntimeClasspathElements().iterator(), + File.pathSeparator ) ); + + references.put( "maven.runtime.classpath", p ); + antProject.addReference( "maven.runtime.classpath", p ); + + // Test classpath + p = new Path( antProject ); + + p.setPath( StringUtils.join( mavenProject.getTestClasspathElements().iterator(), + File.pathSeparator ) ); + + references.put( "maven.test.classpath", p ); + antProject.addReference( "maven.test.classpath", p ); + + } + else + { + unconstructedParts.add( "Maven standard project-based classpath references." ); + } + + if ( mojoExecution != null ) + { + // Plugin dependency classpath + Path p = + getPathFromArtifacts( mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifacts(), + antProject ); + + references.put( "maven.plugin.classpath", p ); + antProject.addReference( "maven.plugin.classpath", p ); + } + else + { + unconstructedParts.add( "Maven standard plugin-based classpath references." ); + } + } + catch ( DependencyResolutionRequiredException e ) + { + throw new MojoExecutionException( "Error creating classpath references for Ant-based plugin scripts.", e ); + } + } + + public Path getPathFromArtifacts( Collection artifacts, Project antProject ) + throws DependencyResolutionRequiredException + { + List list = new ArrayList<>( artifacts.size() ); + + for ( Artifact a : artifacts ) + { + File file = a.getFile(); + + if ( file == null ) + { + throw new DependencyResolutionRequiredException( a ); + } + + list.add( file.getPath() ); + } + + Path p = new Path( antProject ); + + p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) ); + + return p; + } + + public Project getAntProject() + { + return antProject; + } + + public void setAntProject( Project antProject ) + { + this.antProject = antProject; + } + + public MavenProject getMavenProject() + { + return mavenProject; + } + + public void setMavenProject( MavenProject mavenProject ) + { + this.mavenProject = mavenProject; + } + + public MojoExecution getMojoExecution() + { + return mojoExecution; + } + + public void setMojoExecution( MojoExecution mojoExecution ) + { + this.mojoExecution = mojoExecution; + } + + public MavenSession getSession() + { + return session; + } + + public void setSession( MavenSession session ) + { + this.session = session; + } + + public PathTranslator getPathTranslator() + { + return pathTranslator; + } + + public void setPathTranslator( PathTranslator pathTranslator ) + { + this.pathTranslator = pathTranslator; + } + + public AntScriptInvoker getScriptInvoker() + { + return scriptInvoker; + } + + public void enableLogging( Logger logger ) + { + this.logger = logger; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntPropertyHelper.java b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntPropertyHelper.java new file mode 100644 index 000000000..ee6c701bc --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntPropertyHelper.java @@ -0,0 +1,205 @@ +package org.apache.maven.script.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.tools.ant.PropertyHelper; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.util.introspection.ReflectionValueExtractor; + +/** + * Makes the ${expressions} used in Maven available to Ant as properties. + * + * @author Kenney Westerhof + */ +public class AntPropertyHelper + extends PropertyHelper +{ + private static final String DEPENDENCY_PREFIX = "maven.dependency."; + private Log log; + private ExpressionEvaluator exprEvaluator; + private MavenProject mavenProject; + private Map artifactMap = new HashMap(); + + /** + * @deprecated use the other constructor + * @param project + * @param l + */ + public AntPropertyHelper( MavenProject project, Log l ) + { + mavenProject = project; + log = l; + } + + /** + * @deprecated use {@link #AntPropertyHelper(ExpressionEvaluator, Set, Log)} to resolve maven.dependency.* + * properties + * @param exprEvaluator + * @param l + */ + public AntPropertyHelper( ExpressionEvaluator exprEvaluator, Log l ) + { + this( exprEvaluator, Collections.emptySet(), l ); + } + + /** + * @param exprEvaluator + * @param artifacts + * @param l + */ + public AntPropertyHelper( ExpressionEvaluator exprEvaluator, Set artifacts, Log l ) + { + this.mavenProject = null; + this.exprEvaluator = exprEvaluator; + this.log = l; + + for ( Artifact artifact : artifacts ) + { + String key = DEPENDENCY_PREFIX + artifact.getGroupId() + "." + artifact.getArtifactId() + + ( artifact.getClassifier() != null ? "." + artifact.getClassifier() : "" ) + + ( artifact.getType() != null ? "." + artifact.getType() : "" ) + ".path"; + + log.debug( "Storing: " + key + "=" + artifact.getFile().getPath() ); + + artifactMap.put( key, artifact.getFile().getPath() ); + } + } + + /** + * @see org.apache.tools.ant.PropertyHelper#getPropertyHook(java.lang.String, java.lang.String, boolean) + */ + public synchronized Object getPropertyHook( String ns, String name, boolean user ) + { + if ( log.isDebugEnabled() ) + { + log.debug( "getProperty(ns=" + ns + ", name=" + name + ", user=" + user + ")" ); + } + + /* keep old behaviour */ + if ( mavenProject != null ) + { + return getPropertyHook( ns, name, user, mavenProject ); + } + + + Object val = null; + + if ( name.startsWith( DEPENDENCY_PREFIX ) ) + { + val = artifactMap.get( name ); + } + + if ( val == null ) + { + try + { + val = exprEvaluator.evaluate( "${" + name + "}" ); + } + catch ( ExpressionEvaluationException e ) + { + if ( log.isErrorEnabled() ) + { + log.error( "Failed to evaluate expression", e ); + } + } + } + + if ( val == null ) + { + val = super.getPropertyHook( ns, name, user ); + + if ( val == null ) + { + val = System.getProperty( name ); + } + } + + return val; + } + + /** + * @deprecated added to keep backwards compatibility + * @param ns + * @param name + * @param user + * @param mavenProject + * @return The property value. + */ + private Object getPropertyHook( String ns, String name, boolean user, MavenProject mavenProject ) + { + Object val = null; + try + { + if ( name.startsWith( DEPENDENCY_PREFIX ) ) + { + val = artifactMap.get( name ); + } + else if ( name.startsWith( "project." ) ) + { + val = ReflectionValueExtractor.evaluate( + name, + mavenProject, + true + ); + } + else if ( name.equals( "basedir" ) ) + { + val = ReflectionValueExtractor.evaluate( + "basedir.path", + mavenProject, + false + ); + } + } + catch ( Exception e ) + { + if ( log.isWarnEnabled() ) + { + log.warn( "Error evaluating expression '" + name + "'", e ); + } + } + + if ( val == null ) + { + val = super.getPropertyHook( ns, name, user ); + if ( val == null ) + { + val = System.getProperty( name ); + } + } + + if ( val instanceof File ) + { + val = ( (File) val ).getAbsoluteFile(); + } + + return val; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/resources/META-INF/plexus/components.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 000000000..cadddea95 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,28 @@ + + + + + + org.codehaus.plexus.component.factory.ComponentFactory + org.apache.maven.script.ant.AntMojoComponentFactory + ant-mojo + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/site/site.xml new file mode 100644 index 000000000..3a16bf98b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/site/site.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/java/org/apache/maven/script/ant/AntMojoWrapperTest.java b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/java/org/apache/maven/script/ant/AntMojoWrapperTest.java new file mode 100644 index 000000000..2b50e997c --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/java/org/apache/maven/script/ant/AntMojoWrapperTest.java @@ -0,0 +1,293 @@ +package org.apache.maven.script.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.CoreMatchers.startsWith; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.Reader; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Build; +import org.apache.maven.model.Model; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.path.PathTranslator; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildListener; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.jar.JarArchiver; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.factory.ComponentInstantiationException; +import org.codehaus.plexus.component.factory.ant.AntScriptInvoker; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.configuration.PlexusConfigurationException; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +public class AntMojoWrapperTest +{ + + private BuildListener buildListener; + + @Before + public void setUp() + { + buildListener = mock( BuildListener.class ); + } + + @Test + public void test2xStylePlugin() + throws PlexusConfigurationException, IOException, ComponentInstantiationException, MojoExecutionException, + ComponentConfigurationException, ArchiverException, URISyntaxException + { + String pluginXml = "META-INF/maven/plugin-2.1.xml"; + + List messages = run( pluginXml, true ); + + assertPresence( messages, "Unpacked Ant build scripts (in Maven build directory).", false ); + assertPresence( messages, "Maven parameter expression evaluator for Ant properties.", false ); + assertPresence( messages, "Maven standard project-based classpath references.", false ); + assertPresence( messages, "Maven standard plugin-based classpath references.", false ); + assertPresence( messages, + "Maven project, session, mojo-execution, or path-translation parameter information is", false ); + assertPresence( messages, "maven-script-ant < 2.1.0, or used maven-plugin-tools-ant < 2.2 during release", + false ); + + ArgumentCaptor buildEvent = ArgumentCaptor.forClass(BuildEvent.class); + verify( buildListener, atLeastOnce() ).messageLogged( buildEvent.capture() ); + + // last message + assertThat( buildEvent.getValue().getMessage(), startsWith( "plugin classpath is: " ) ); + assertThat( buildEvent.getValue().getMessage(), endsWith( ".test.jar" ) ); + } + + @Test + public void test20StylePlugin() + throws PlexusConfigurationException, IOException, ComponentInstantiationException, MojoExecutionException, + ComponentConfigurationException, ArchiverException, URISyntaxException + { + String pluginXml = "META-INF/maven/plugin-2.0.xml"; + + List messages = run( pluginXml, false ); + + assertPresence( messages, "Unpacked Ant build scripts (in Maven build directory).", true ); + assertPresence( messages, "Maven parameter expression evaluator for Ant properties.", true ); + assertPresence( messages, "Maven standard project-based classpath references.", true ); + assertPresence( messages, "Maven standard plugin-based classpath references.", true ); + assertPresence( messages, + "Maven project, session, mojo-execution, or path-translation parameter information is", true ); + assertPresence( messages, "maven-script-ant < 2.1.0, or used maven-plugin-tools-ant < 2.2 during release", true ); + + ArgumentCaptor buildEvent = ArgumentCaptor.forClass(BuildEvent.class); + verify( buildListener, atLeastOnce() ).messageLogged( buildEvent.capture() ); + + // last message + assertThat( buildEvent.getValue().getMessage(), startsWith( "plugin classpath is: " ) ); + assertThat( buildEvent.getValue().getMessage(), endsWith( "path-is-missing" ) ); + } + + private void assertPresence( List messages, String test, boolean shouldBePresent ) + { + for ( String message : messages ) + { + if ( message.contains( test ) ) + { + if ( !shouldBePresent ) + { + fail( "Test string: '" + test + "' was found in output, but SHOULD NOT BE THERE." ); + } + return; + } + } + + if ( shouldBePresent ) + { + fail( "Test string: '" + test + "' was NOT found in output, but SHOULD BE THERE." ); + } + } + + private List run( String pluginXml, boolean includeImplied ) + throws PlexusConfigurationException, IOException, ComponentInstantiationException, MojoExecutionException, + ComponentConfigurationException, ArchiverException, URISyntaxException + { + StackTraceElement stack = new Throwable().getStackTrace()[1]; + System.out.println( "\n\nRunning: " + stack.getMethodName() + "\n\n" ); + + URL resource = Thread.currentThread().getContextClassLoader().getResource( pluginXml ); + + if ( resource == null ) + { + fail( "plugin descriptor not found: '" + pluginXml + "'." ); + } + + PluginDescriptor pd; + try ( Reader reader = new InputStreamReader( resource.openStream() ) ) + { + pd = new PluginDescriptorBuilder().build( reader, pluginXml ); + } + + Map config = new HashMap<>(); + config.put( "basedir", new File( "." ).getAbsoluteFile() ); + config.put( "messageLevel", "info" ); + + MojoDescriptor md = pd.getMojo( "test" ); + + AntMojoWrapper wrapper = + new AntMojoWrapper( new AntScriptInvoker( md, Thread.currentThread().getContextClassLoader() ) ); + + wrapper.enableLogging( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) ); + + Artifact artifact = mock( Artifact.class ); + PathTranslator pt = mock( PathTranslator.class ); + + if ( includeImplied ) + { + File pluginXmlFile = Paths.get( resource.toURI() ).toFile(); + + File jarFile = File.createTempFile( "AntMojoWrapperTest.", ".test.jar" ); + jarFile.deleteOnExit(); + + JarArchiver archiver = new JarArchiver(); + archiver.enableLogging( new ConsoleLogger( Logger.LEVEL_ERROR, "archiver" ) ); + archiver.setDestFile( jarFile ); + archiver.addFile( pluginXmlFile, pluginXml ); + archiver.createArchive(); + + when( artifact.getFile() ).thenReturn( jarFile ); + + Model model = new Model(); + + Build build = new Build(); + build.setDirectory( "target" ); + + model.setBuild( build ); + + MavenProject project = new MavenProject( model ); + project.setFile( new File( "pom.xml" ).getAbsoluteFile() ); + + pd.setPluginArtifact( artifact ); + pd.setArtifacts( Collections.singletonList( artifact ) ); + + config.put( "project", project ); + config.put( "session", new MavenSession( null, null, null, null, null, null, null, null, null, null ) ); + config.put( "mojoExecution", new MojoExecution( md ) ); + + ComponentRequirement cr = new ComponentRequirement(); + cr.setRole( PathTranslator.class.getName() ); + + wrapper.addComponentRequirement( cr, pt ); + } + + wrapper.setComponentConfiguration( config ); + + TestBuildListener tbl = new TestBuildListener(); + + wrapper.getAntProject().addBuildListener( buildListener ); + + PrintStream oldOut = System.out; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try + { + System.setOut( new PrintStream( baos ) ); + + wrapper.execute(); + } + finally + { + System.setOut( oldOut ); + } + + System.out.println( "\n\n" + stack.getMethodName() + " executed; verifying...\n\n" ); + + List messages = new ArrayList<>(); + if ( !tbl.messages.isEmpty() ) + { + messages.addAll( tbl.messages ); + } + + messages.add( new String( baos.toByteArray() ) ); + + return messages; + } + + private static final class TestBuildListener + implements BuildListener + { + private List messages = new ArrayList<>(); + + public void buildFinished( BuildEvent arg0 ) + { + } + + public void buildStarted( BuildEvent arg0 ) + { + } + + public void messageLogged( BuildEvent event ) + { + messages.add( event.getMessage() ); + } + + public void targetFinished( BuildEvent arg0 ) + { + } + + public void targetStarted( BuildEvent arg0 ) + { + } + + public void taskFinished( BuildEvent arg0 ) + { + } + + public void taskStarted( BuildEvent arg0 ) + { + } + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.0.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.0.xml new file mode 100644 index 000000000..63f8bf261 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.0.xml @@ -0,0 +1,63 @@ + + + + + Test Plugin + org.myplugin + my-plugin + 1 + myplugin + false + true + + + test + Build a JAR from the current project. + false + false + false + false + false + true + test.build.xml:test + ant + per-lookup + once-per-session + + + basedir + true + false + java.io.File + + + messageLevel + true + false + java.lang.String + + + + ${basedir} + ${messageLevel} + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.1.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.1.xml new file mode 100644 index 000000000..2de9c5f54 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/META-INF/maven/plugin-2.1.xml @@ -0,0 +1,89 @@ + + + + + Test Plugin + org.myplugin + my-plugin + 1 + myplugin + false + true + + + test + Build a JAR from the current project. + false + false + false + false + false + true + test.build.xml:test + ant + per-lookup + once-per-session + + + basedir + true + false + java.io.File + + + messageLevel + true + false + java.lang.String + + + project + true + false + org.apache.maven.project.MavenProject + + + session + true + false + org.apache.maven.execution.MavenSession + + + mojoExecution + true + false + org.apache.maven.plugin.MojoExecution + + + + ${project} + ${session} + ${mojoExecution} + ${basedir} + ${messageLevel} + + + + org.apache.maven.project.path.PathTranslator + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/test.build.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/test.build.xml new file mode 100644 index 000000000..6a07c7d32 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-ant/src/test/resources/test.build.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + plugin classpath is: ${cp} + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/pom.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/pom.xml new file mode 100644 index 000000000..65f82d2f4 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/pom.xml @@ -0,0 +1,50 @@ + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-script + 3.6.1-SNAPSHOT + + + maven-script-beanshell + + Maven Beanshell Mojo Support + Maven Beanshell Mojo Support, ie write Maven plugins with Beanshell scripts. + + + + org.apache.maven + maven-plugin-api + + + org.codehaus.plexus + plexus-bsh-factory + 1.0-alpha-7 + + + bsh + bsh + 1.3.0 + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/main/java/org/apache/maven/script/beanshell/BeanshellMojoAdapter.java b/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/main/java/org/apache/maven/script/beanshell/BeanshellMojoAdapter.java new file mode 100644 index 000000000..405458a99 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/main/java/org/apache/maven/script/beanshell/BeanshellMojoAdapter.java @@ -0,0 +1,70 @@ +package org.apache.maven.script.beanshell; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import bsh.EvalError; +import bsh.Interpreter; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.Mojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.codehaus.plexus.component.factory.bsh.BshComponent; + +/** + * Mojo adapter for a Beanshell Mojo. + * + * @author Brett Porter + */ +public class BeanshellMojoAdapter + extends AbstractMojo + implements BshComponent +{ + private Mojo mojo; + + private Interpreter interpreter; + + public BeanshellMojoAdapter( Mojo mojo, Interpreter interpreter ) + { + this.mojo = mojo; + this.interpreter = interpreter; + } + + public void execute() + throws MojoExecutionException, MojoFailureException + { + try + { + interpreter.set( "logger", getLog() ); + + // TODO: set out, err to a print stream that will log at info, error respectively + } + catch ( EvalError evalError ) + { + throw new MojoExecutionException( "Unable to establish mojo", evalError ); + } + + mojo.execute(); + } + + public Interpreter getInterpreter() + { + return interpreter; + } +} diff --git a/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/site/site.xml new file mode 100644 index 000000000..3a16bf98b --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/maven-script-beanshell/src/site/site.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/maven-script/pom.xml b/Java-base/maven-plugin-tools/src/maven-script/pom.xml new file mode 100644 index 000000000..ed37e2cbf --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/pom.xml @@ -0,0 +1,44 @@ + + + + 4.0.0 + + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.6.1-SNAPSHOT + + + maven-script + pom + + Maven Script Mojo Support + Maven Script Mojo Support lets developer write Maven plugins/goals with scripting languages instead of compiled Java. + + + maven-plugin-tools-ant + maven-script-ant + maven-plugin-tools-beanshell + maven-script-beanshell + maven-plugin-tools-model + + + + diff --git a/Java-base/maven-plugin-tools/src/maven-script/src/site/site.xml b/Java-base/maven-plugin-tools/src/maven-script/src/site/site.xml new file mode 100644 index 000000000..67aa11c18 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/maven-script/src/site/site.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/pom.xml b/Java-base/maven-plugin-tools/src/pom.xml new file mode 100644 index 000000000..e62baf872 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/pom.xml @@ -0,0 +1,417 @@ + + + + 4.0.0 + + + maven-parent + org.apache.maven + 34 + ../pom/maven/pom.xml + + + org.apache.maven.plugin-tools + maven-plugin-tools + 3.6.1-SNAPSHOT + pom + + Maven Plugin Tools + + The Maven Plugin Tools contains the necessary tools to produce Maven Plugins in scripting languages + and to generate content such as descriptor, help, and documentation. + + https://maven.apache.org/plugin-tools + 2004 + + + + Muminur Choudhury + + + Tinguaro Barreno + + + James Phillpotts + + + Slawomir Jaranowski + + + Mikolaj Izdebski + + + + + maven-plugin-tools-generators + maven-plugin-tools-api + maven-plugin-tools-java + maven-plugin-tools-annotations + maven-plugin-annotations + maven-script + maven-plugin-plugin + + + + scm:git:https://gitbox.apache.org/repos/asf/maven-plugin-tools.git + scm:git:https://gitbox.apache.org/repos/asf/maven-plugin-tools.git + https://github.com/apache/maven-plugin-tools/tree/${project.scm.tag} + master + + + jira + https://issues.apache.org/jira/browse/MPLUGIN + + + Jenkins + https://builds.apache.org/job/maven-plugin-tools/ + + + + apache.website + scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path} + + + + + 2.22.2 + 7 + 1.3 + 3.0 + 1.7.1 + 3.0.1 + plugin-tools-archives/plugin-tools-LATEST + 8.0 + 2020-04-07T21:04:00Z + + + + + + + org.apache.maven.plugin-tools + maven-plugin-tools-api + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-generators + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-model + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-java + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${project.version} + + + org.apache.maven.plugin-tools + maven-plugin-tools-beanshell + ${project.version} + + + org.apache.maven + maven-model + ${mavenVersion} + + + org.apache.maven + maven-plugin-api + ${mavenVersion} + + + org.apache.maven + maven-compat + ${mavenVersion} + + + org.apache.maven + maven-core + ${mavenVersion} + + + org.apache.maven + maven-artifact + ${mavenVersion} + + + org.apache.maven + maven-settings + ${mavenVersion} + + + + + org.codehaus.plexus + plexus-utils + 3.3.0 + + + org.codehaus.plexus + plexus-component-annotations + 2.1.0 + + + junit + junit + + + + + org.codehaus.plexus + plexus-archiver + 3.6.0 + + + org.codehaus.plexus + plexus-velocity + 1.2 + + + velocity + velocity + + + + + + + org.apache.velocity + velocity + 1.7 + + + + com.thoughtworks.qdox + qdox + 2.0.0 + + + + org.ow2.asm + asm + ${asmVersion} + + + org.ow2.asm + asm-commons + ${asmVersion} + + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + ${pluginTestingHarnessVersion} + test + + + org.mockito + mockito-core + 2.28.2 + test + + + junit + junit + 4.13 + test + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + false + + + + org.apache.maven.plugins + maven-site-plugin + 3.9.0 + + + org.apache.maven.plugins + maven-release-plugin + + https://svn.apache.org/repos/asf/maven/plugin-tools/tags + true + + + + org.codehaus.plexus + plexus-component-metadata + 2.1.0 + + + + generate-metadata + generate-test-metadata + + + + + + + + + maven-enforcer-plugin + + + enforce-bytecode-version + + + + + + org.ow2.asm:* + + + + + + + + + org.codehaus.mojo + extra-enforcer-rules + 1.2 + + + + + + + + + reporting + + + + org.apache.maven.plugins + maven-javadoc-plugin + + true + + + Plugin Tools' Maven Plugin Plugin + org.apache.maven.plugin.plugin* + + + Plugin Tools Extractor API + org.apache.maven.tools.plugin:org.apache.maven.tools.plugin.extractor:org.apache.maven.tools.plugin.scanner:org.apache.maven.tools.plugin.util + + + Plugin Tools Generators + org.apache.maven.tools.plugin.generator + + + Java Annotations Support: Annotations + Extractor + org.apache.maven.plugins.annotations:org.apache.maven.tools.plugin.extractor.annotations* + + + Javadoc Support: Javadoc Tags Extractor + Taglets + org.apache.maven.tools.plugin.extractor.javadoc:org.apache.maven.tools.plugin.javadoc + + + Beanshell Support: Extractor + Runtime + org.apache.maven.tools.plugin.extractor.beanshell:org.apache.maven.script.beanshell + + + Apache Ant Support : Metadata + Extractor + Runtime + org.apache.maven.tools.plugin.extractor.ant:org.apache.maven.script.ant:org.apache.maven.tools.plugin.extractor.model* + + + + + + non-aggregate + + javadoc + + + + aggregate + + aggregate + + + + + + org.apache.maven.plugins + maven-jxr-plugin + + + non-aggregate + + jxr + + + + aggregate + + aggregate + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + non-aggregate + + checkstyle + + + + aggregate + false + + checkstyle-aggregate + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/src/site/resources/download.cgi b/Java-base/maven-plugin-tools/src/src/site/resources/download.cgi new file mode 100644 index 000000000..1b178d2e6 --- /dev/null +++ b/Java-base/maven-plugin-tools/src/src/site/resources/download.cgi @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# Just call the standard mirrors.cgi script. It will use download.html +# as the input template. +exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $* \ No newline at end of file diff --git a/Java-base/maven-plugin-tools/src/src/site/resources/images/plugin-tools-deps.png b/Java-base/maven-plugin-tools/src/src/site/resources/images/plugin-tools-deps.png new file mode 100644 index 0000000000000000000000000000000000000000..0da46f962a240c79a4c6a5c4e078e95d3a6369b1 GIT binary patch literal 47339 zcmcG#WmH|wvNpPK5-dP)hXBFd-2%Z~g9iu%cXxL}aEA~G?(R--cXxNUJ6H1VbI#uP zJNNr_CxfxZnq$qL)zwu`Jyq2mA}=eB^cwdy2n0gyC6iv{kyvX;=W1A&mc!2b|&G{|_sO*s3HGGcHm5D;ikv_%|{{s)@R&3{7R#R86fIogIUWmPPrvqy>}5 zz3DF5Ly{$9Zjp-9xl&5 zA8%z8!oy1T3^uwLxI90F&4q`Lc(C9MmP+$L zwIT3Cki=dH6$?MywD;(LY(il(V{|Sii{tJete4p?*IMC4Z#j zuOi1EwTP>o;&F?!(prh&f%Sv!r1P!XcZ#MdV=V?1gs|VZ3<~k0*<&vl4|QkZf}(}ZNE<{` zY`h}obV*4A-AMN#Oi-vqL75DGOB+O_<1-kF2q=h2%;+AVOh#08IWON}_Esy2xyXs% z@ecX6(G`?f(a61B-3W|7GN7d2{VY4=K;FP?4qwg}xmL@_QD4A%c7lWI6RyaHZ?MD5 z5_1@*ctmKsIObU+h5%tmwq%3|$U#I#S$2y!!FEiKqgv)981AD(d9PQ`);w8#nLqA~ z%^==itl@WCtI=UTdfi@u{H?LIW0MJ@thOq!_=T32Spc8(v*F3Tv%TzMvB+~E24^l5 z?~c2Vjn9*w@fh5)()31oH1lNb(vPreoSWK>e|&+j_YL$dmr$Q7TH|w>+1*oFRwUMQ z%l+H^fMKTz)WoV^uQRBanTAE?&5F@_we+As3{1ae1L(akaUfYtvP?;vb*H9WkIP z%=FIL2JceObxcbdj2h{Uqh*`x8O{x#IG9xtzRLRG(8K*$Zi;Se`_evl{yN_t_N7Qg z2u1La9b!$yCw30+)M-lzdyh7-g_`i=9Cw=&?xSYlrl7XBk_o7d;F#XHSkAe`#~LK> zK!Fq|*|uf-VBKD$BWqR1lTyCR)xR*-@!DUIQ<@qZjfv9GkgP`#i+~xwA-#dJ; z{JMl(6q@et=>`IgC1T+DdE32M!P-qs>jtOeWt5nDtIoXInx-220SQt{tids%XLs`6 zQ>oTKS^jI=*@ZuT_q4DHWD*WXGc1Ji_*sk~rHyh-XF2qiLOY)CouctYczN=8-)o6) zbPYerlf6Z?y}9UQ>ryRah8un3lXufYGW(47t7Ia>pde5(2hRGL?J7BN`-!pICj?ti z9IEu06e08nBO64fqDZmDh30SE{L-&bj_c1l<{6EX&uFMji|DA@q>EVDtB9aQ$Q2)U z#_+Y@O?;da#x~^xN5Q99`i9%askGHXwwipa90Z;vup;z>yiA!K(eY}&EOBOS%T;zY zSBfYS+)gp_zAPBjZD)_x#1<+#7Xm!UKEzmnpcmpDiS9e5jeF|NlUtnXnQDkqJ+FwR9r|h@LV=?kmIlWJimY%$F3e&aw=l)Pi(KWtqU+6Pg~%LO$& zx_(PJvL?Jz%%Nc+=ZCXSNBTVtjxxUfwaD!voX>Xq~md;iWe2AA3>x>U^X6twzmXRFg zl}c$iKA(oou}Zo$OA2?}a_Uv5bR3avfqts!Pq(a*1hb+h&~8n+`dH`aXMWg?spbNwsLLLRAvVSt6}X`8idnMx_jlSqx(i7 zp)K8wG~3caEIwkX^4`$%hk)k*i+fW6p-ivS8Y1Y|is&Wt#y@_fFk{RO4}t2DWjfe% zV$~Enh#oikW#9UGbZ7Q)8k05Hk5PX(tqj!;P`4|oY`{m+$>PMUna;-3xK#Of{l%>Cg(%MJcGZBuI@@Ijkc45 zLX4Y%LG~y3#~>7<>zkV!0dwrzrKP2?+1LL(3nQDszoZ3!US3{478e&6DV#{e=V~8b zT51(3@veb_aupCUtg5O?ud~fcUw;gnkT9JX`q|stn-(1%9Z4%RICw2RIC%a&6_pJO z;)Ris5xs(ff{k$E&Bet)i>iJLStJ1uyLy&FEh2tlL0aZRvS`-;4*)2fC-C zl9Gt)&9R3jMJ!cEXD50`N5{7yL>${HniHtMTGoy^Kesg@8SL%q3a6*1KSoDIwGo8B zfPjF|SmJ^Q*40K$AaUHSydz<>bqh1uE3^CiJQ7Bg84h{4(2-7WS? zza=xXjf|O@S*H%d@%D5LjvOuI+PFkWLnA2+7-Mj75OsNZ*(K2Mrn#x<{LYeu)S!-% zbYF2eo$ufc78Vxy;1|2|&Hm@LwY68mi71GOgLQMAk6ZauW~LuLe8|*aoiVFM(|;c& zO`!x01CyJQltgtGN&07y2Frqig2RoC4YB~njD&<8x`YAr07jy>Z@&-EeWou3%LN!6 zu*CKC_59%J1^TqAmFk$NQ~hCu*|JJXN`^Ful_7xX@_RnsX2y_-QvlZX?%lgM{pbBD z!1i)~{tSfo(FIoN@aU+}KW{HED2Vd*?#}4u(n=^8%ngFW<+ZfFq7xAjQTg93E`G`= zD=YgXcO*SRoo}YFiW}BpFo5R$xlAb8{+{ntv@0 zslIykYE3v%!2Pz&%i7vH`OS7GU!Dz`qL!5F;xT`?JU#K7oO-16^IB^>4N-fd?R=pjiA}w#6gylRjHo zE_X>T;fIEXE+XwLg5T2G+WMm3*>-Y#tkWg=$IuiwMrUWgWXZq(+`)SRheC+Y?|ysg zC!Cl7`0DlMbt~(4oNMfsH+&`~k3PqoTKeiHV_P z?l>(M7nd}kN#M!Zm6ew=KpB8%6crWiYf$ay&(CY7Y;JBcW|@H3d2w-35;5rf_Wpi5 zxZ8jL&;>Y5s|n>QCjI>J!~eBDKL93OGcz3G@E1UG30G8He4tLXPs^Pqn;ILt@s;y? z-j5$$GKro_|HE%8H2-MS{uKa>$$(o?FM?81Q}MSqHezY~@A~@soCB#FmVf{L{RuEJ z3JQwfEG#VI&TeiyIFU;?=jXpoa{r)#D{I6D!*9vSxTOAfKYsj(@q&fk7j-BqJo`6LiYD1pLMYFkCr7LBV+a)sv~h864HnKYVy$+^qUrczC!V$siG@ zHE{IrFr{02^cw!kxb6n+1WQEL$^khbnG9M zXtNIz@j6@Ay#aKwLH2Ncr1jqaP9f*Rk&~k%y-99<-q^uaHsDr7`mbgGH}3%lEe?O# zJaiKyBN+IL!QS3p@$0>bJaudq0kg^cr;?JA+@iN*0n{`!1OYlv{{H@_mzS5sa&jX| z9dA?rhxY(Xc8o1+=0FS_6QY1%Mu3ja!VOr{@1db$QTU6ov9WSXOH1;iw=rj|xDg*! zRaLziVNAg8XlR%du$KDJ-rjEN{+k(WdSe(tcfcC!>Zjj5J={du+S?bgB3?AR-S7`d zqH5!biHRL|g!6(eyt1Cp`GS^Hs47^CLnP9a6Fb~8jEe(w+yuiB_j|a>O zNl|SzPtTSF0Gykecu!EtK77W7^~AzTVE+4FOX1!~0z7lU8tDSw3=W6twA1B(4199v@nS>(Du9>>(Azvu=X z-&9B&T=xD6ER2p|Hv=4Z(SMHva8`D9_Ua-`aFxb^>F(}MCs3adA|nr@9Nv>2m(ri=+=c*RQO&=$(uL)~jt^ z>OfKGZM7!dP+uQBE8?SOu_`IAj2aLaeSLk$!PEQaz1hCLkSLvurOMPphIT+KyQN6QmrBJPu1;7wH0Z!J2{VOHpB8%=2WKWHXCrah%v#@U zdw6)*fkhs>bZvgm!7 zNL*A~$H*u*XS6UQI{HmI;P9J!doI5L>p~`Y2Sne7U*ErfufqwvtEga30D}j~-~$lS zSO(F@h6HoQ67jk1zo;uJj!WntdIF0+)E7e*3r1EjXacsbSPTYE@FcP=v#P2l9bTTF za{L*+0K;4cQ=E=)_UGs4pgTq!(tWDoRIZ5u>-TbCR{=CsvNr3%FC7J7QU1Vt1_me0 z4tHtk!QJ)sb$&3I`ZE#%IN!}ECpszpOF20=FAoj})-yyjn+^XrIyQD9Nu1==pEVm} zQ&Uh_1K1rFx&IxodQo5uU4xxn>kJ~=JVX^0B}mA~I3eei;Q-T428I#0u3*%pK%bTF z?%eP=Fnee)GZ{&D2o4JiLo=@80?g;-^z;;(WDpJ()|hb+9n~TIUvc3tf~BNrg#Zz} z{!{wy!9hx=l~@R1c=Uw@1;6=$OA-FU#l>aWww_l3{z6Dd2n^x?9tZE@Dyjnm zIQjsw^b7WFwPvwsVvP8|xdPK7%c2s8s+yXK$7-7oJTS)Q=4~J#!0U@YbS5!5xd5O} z*(p-s_yC|ez@K>mGo=Iq_WQn}GdGv*V$6ZaS>3TR_?N42ByFE5&7RQ5`Ne_U1CkwS!(g3vXMw5s{0#pT{<>@FC zB&69TlK$PfKYwM)iW>`#=YW&_pQs0r>NFHSKDsjib`GYVU~d2~9ss*wHkS6(0FHEOMe5~W zj^?W?xrQj27L{nGrluS(c1B)4cLpNKf!bzty`Cmx<@oQ0;{5NxA(~_myfn>Vy#GZ- zMn<-A1h8;*8$eGQQ`6J)?uF+aBxADMa-zESIYk|JsKdC{40>*IRK7mpsucd9)~F9@p#tD;rVb>`vT$3WY}}~ za6Z70aSdj1Qz2_Da0R8MwVG95#zIE~ULG}oehKqqEs#d80{P$Nb;o17A6yXNw7@mq z*_k5f!$WU%pf1z`W}K%*N9HkPhZ%fK|g=S)K3#)Chp3*_i0(?G&q)yJ;<} zW|GI&++3s11*_KP&(Du{8K)51UDhjp_yAd3@2AXoqyQkXvDxe8YDV`YnbT(73OuQ} zI1FNG85h9$gZVw~-y-OHPUb5-q@|?|Xef}9X4B-U7UtsM;P?dk=oU^%0*;IF`n9Ch z!{n7pp(>sGS^$=6jkd0Ygv35zoopVnW%@zt+JSDWYZTLylb>5Y_kXJucs%Wd0bb=^ zzP0Rev!tf$vK41^u|1^q1T1|7hNU+Fo7tr2auU!RvOmIj`_>tIxIQB#&brX?0B~?;s5J)! zG6Saxs)ccuy04Eid>1P1M+~=!IU$hz>j}H0VuESd=SCDX+H+R94 z&;~esMJVEpJ-U41)VR~K%TBe?KzwsHkV0|aJAqv}D=Ui%T)t44Q39|8KwZ^rfJM;P z76GJa2<$^(c?Wm;FKG?pSGT{Vr5#~mV#YVw?~Ttyyt)Q4+HDVxC{xE#6-tPTPF}fR z&zZ3BpdI>bVT`nZRBZ9k(Xmo<`Pv(Zb@Y!DG+cv5A4-X zd!igju?J7SngoLodfK=nWE_%89!SISZ?g-E;8l#e^LdrL3n~nh<1p6DKaxQ9E`}{+ zxZ)U;`*$<1e(~uLgp$yH@r%Q5LCJ&`{kxm099;A}+k4r|0p)$;tb z*u1(}d)Erw#4HU;LZxkZUQ4&+wWHCxygnDRV$j9(1HcerB41_pZcDN55)XbQW@7}# z$;63amg~mYXBYBsTTh!U|Dz0(%QZ8mFLyY{BpSF!2d*K5FMwKsumAYk`6QEL38xAJ zH0+#NEA}n3XVyIz-5n@N0f(4gdtPn#>--9YPYrhP4YNc0gZc*{ZL&ozpcFK}u%M=) zr8PqbxE#!Y)2r#&GDevw2U8~avg5-z8iiY3E5g~C=3{Uzj6t-6r z{)<1=pTopR{BUw|Vz|HC$)K$KJ`=P3uEOwK0}e2xNP|4QtLSSM*TJXbrA8~3#}_b< zxmmOukwXg+#ly!>y*_Duxo%A7$rNbBAOiZ0hLa+k_Mf3@_%{Mvz>P-CwL3V9H4ZVR zsszpU?v~|--5DLtN#mj}wU@mJa4QmfFSHh`IZ}l3dOd{+cpy@6U*ieJtF&~{|He-& z(Wdv)KfT1ZR6SH<=mow0M~)ab)rIofmG)oijN@i^eR%N2kAIQPvYYdb7rLh43y8Bmwm=&+heH9}KVQyhGaq zI6MtQpDA}5Cpb?5;H+(Nv1xBioM@>CNU~;J;Y2Agf!5@cthw8nodnVSE2#~$^7Vr$ zZ1pn)&onnYPl4%Km!phU$PE5Q_+NRC);Cx%>I8OgqM!+SYBcO@@?k+gqLYK?=VULo zk7!^1)lFQ>xm8N!>Bh)?Wu?FLyZOtg?(@}9U}482BWV##6N% z8ZmT`RtBP^Q9PTG@^t10y3gl4)^*4P$AX99*Nu}k_yxP+j`cljgdof2tLf$h_Z*ry zW33u<7g1Ww@Db44f9(Z0NKH+p=6`v-Fe%k;!1A>xc<1C5&~FH-XJv|{^`hbY*^^VW zuV?w{Y&UgRE$9)6##$22dH4=;1M;DLFdL;Quc+6M#3w1j(x}Ys99{IT zLD+1~heRn|j0l88wP2&^!nW{JbS%DJf)?t2_!$;`bGeMMIbM@i}H;)!YdAg5QwI@~m+8t65;fW`=@oy?yC#q2KAB1iA6iu^8H- zJ&_q>5<4nZIK#CrnO$>`=X57<1DvL_l8)=xdL zPcZQ<7a-+EEd8n25whA3PGSznx2{^tCNh*U&HE6C)Cir4J2R_UJ9+IxRT~7sX=9#P zOYu7tIgfsYRtX1a$522)iMs(vK65t)lUM}M!@3)Q;7r8h_^$A#nk&tjnD{py#m=)X zWQx918-}3Lb;kRH@cm!s(Xkq@+VDJuJchC4HbE!-PVEIEG-qPot?2#};a$sxcP9mM zSvqzY3qSdNL>^>8ryXUZo9l1w z{z6Xs(Y&JoNos85l6m1PH)Jfk${LFpMURVwR_W3i<}66?BP_MbOnpR1aB!L>U-`sP zzGi{^`IGdc%WG?Qdm6$9mNzx=k=A(4_(~brptq&nHAh||hW2Ttdd+ODWC|C^I(O?{ zbq8Z}*iUUw)&Z!0m9h{YqQe>QTzzB<^T(?ro=^c*(ERS9j@z62ZCm)&j(rcwX=ge_ z(SQRq4U%_3tWK77ekJotRt?gdW)WYrHNL78f0#fsgwDM99W0&R_+#McudLQ&3ni@e z6-AJ>2tyvbgEjW#r=W3>d{w-9b2nOH#%oU^P@aumI**RWHq&F-mfL1p35PAwWd5+a zp9R8)^{ZFIi8SsO?DsnOP@v+1q5BdMJRpYfEV&xwr7%@1?~obppn{IEZBmGaOXu;M zKdivGf%0w+g%40U2=XhL4)~n9jia)nmJs0jryPlO#2&QmwYamiOWrL)dFzy7;atQ5 z<-CP4tTLeV;sUU_gk5{?v;J7hhaj=Yr=9s!(Lp`S`TMY7JKfkXxS3N99a6jBzbHa@ zQ%NtlcT=)E3HHv5L)(ZSi*jL*d?Tpck-z+5NHV9W)zQBPI-zIlvl4GUm zvnAXwY*4uRwE-JCPuoRFT%yCw>wGDeX!J_dhw0J}$In=2XJ4OAhkH>vkH7Ij&&}3u z!%cSLoEvG`n3NsWo9*KrWY!Z}NCVZCQJL92Oul+9>~!=9jdCXVFHQ^LdlCmfWNRT# z40hs6W8%tj+?d%7M}iDEqckIbSv7&Iw9bsK+k-Xtzsnau5X0b|MC%#4ElkS8<_`C9 z>yEh&>FZBBes{5hTOU{R6l~srUaWS;@C`)vZEmLfQ6O;IKMVYN)ocOS1~We9xc7Rk z1t{d5_2X)dZP}oYd`;Z?|>xS_MP~)|9kTq;1?yY?zgmXaT+ON`>7A3_ilX?%o%o%m|1ka7k0 z8>9{s88pyMzaoRb`UL?*=hMtJpTqxvmD)lq=+(cjf)#9%vmn8bmNkONi5^5UM1 zsnyVd2pT*jZeEKf@D0%vM+C+Y~DBdg*^UCG-_m}O%TZqyq~=qAt@m^Wt=eyF%!O)fWpJ=A)`Z< z4!ndkM9^_x->j9A*Xk!s@j~-J2_iF3AY_f1Y102FDf^2&hxU!qiEP>NXehTUdnl`% z%*d(cSBsD;!v;-ko^SZo8z8oNwl9V?OUDR;)#g0w0*`EqJ3UNIe|@#FvB>~;QcGLz z&0G_>gMy9ftmc$i&69%F$coBtf8E{ox-e4|FNN4Z(c5T{+j^fMyae%VE$7d%LokTV zuBXLmoO)cLBRZK`c5RnpXqCV`Cam4vVCn^T%bL3mBH4+_RB8P;*84A@A=xANCU2drAul2kb zV~NC2uGOw z27W5i?M(AK45o}5L@%G3-WuG1^~#0P*h~ZDudoOG>sdJKN3;3F;9!6<%hnFK)8i>g zQGGgjz^`?I5c`_9+MD=^H6K?Y_5rD;r3$h;?nT%(4Dnhq2VsuufUO4VtYF~;w`KrC z+YIvl;Ow17dpnD>si@W1xr1q%ea2~hiioBqe0d8~9;3%r?XBM9MqjN5KEvUnw-6?8 zu~RbrcuyoI=VP0E%*z$8PH=Du9FXapT#gu>VM{-(3-mo0a4C*QW(mQmBPNEQh0Uy8 zznR%y?hZ>`aftI;ujMc?ureV09^K(Nt1RuhCX}klh*`d6E4^d~(vR%;RrhMkO}G1} z+|1e+1wOrTgr{DHjwd;{^#r%$UZykk!R1=4&e82^>zI*vn)|`A)x%{C^~y`Bx9lM6 zWZxan`9P9*?-Ej2Hvtz6CZ^ZQ?2x2142bwFcupf}LG6*nIr>5I&9m30p)r+bFpuXO zrJOcDT?8AFwB83U-B27qj1XAw%8wrF(P`-@>8AK}F~qNyF1aZv|AN$mfm>N1aeE|K zVgbIl!1!NC=%pN$(zB!pWb4q>v?B^%^;-^V)|FHZ(RkI=^~f1f|D^ zbK&?*bpO62`-#4qE^VBifP+lE%i8L#3cI5K2Wl%(O?#cyIOCYsuG44^(;ZV2vm3(X z`APZX2Am$*b`T7Z-726U-vG{HS{A?58?J|nEfk^uf8X$dcnxHyGk(-~jV4#Uj}l&w z@g|&i_5Wl4$hwS1kr7GjOIK$s9k&~?+k;wzCn(uOzHwNFA&toKtS}~ruZYLk z=KVks3soEC(B6=44|2&%9eK>5L!V33ej?E4n3q;uH)z6bxqSq$Rcv^rdnk&h{19%W zEQslPZsyIt1yp*K#z6Y|HnyD{P+}FGbm-tiT^h9>VNe5#n8Cr8Xn!;Of9>j>j7$7< zg7rOk3>svNmTGkOi-##LGf;&X$el|L8&>2IK*-3*CO{4SP{VWI5iVTf$IPDnV^3JH zCAH%;Z%2!I{38;Gw_qwFJk5?x>7|)Yj}{V51(Lcm*mRQ2%vxXy!28G>NAC&A@?K;q|_=7O0c*W)W! z^{=dT0aosSt_ILUGTE5gg;aeT$jX0lxgz0&Q!e8LFOad5oR+9dw=Ch}^gHSMlONbA z`MaedNB;bo&B{&y2-gdg%25jimpHdOkA@#k@0$1O9(q^K9-UBc52)ZI5aZ>sh`PlY zouSWy?|0@rQBdzHbFN? zB|F>661OSblplDL)qY!Fkb9#u<4?A7(z8&gRK}Bwuc8Suu)9RT34NhW4^KF@2{6Lq z{M~Sr_%N^el;WNPFm-L!*ocT-zIdMoz8H)TLzjL>QKqvmM##gwgvdAX_N6pD;U>b< zt0|IJP0tex>TfK<<|jF&GwKL#4(U4L4^2+X8c|fu2_pD%3>Zy}se7LB16wFStZ}oq zgHFK;-1^JY4~)|a(4VZ)i($ppJi^z)n{P=t&|;os#+=VN`7@rlbXpkjOb=Gt z805H?POXQS{%l8|q*F)2g=PTVK470G55t{w5?OR|bhni`WpsV5ZEPD}MD!r*HCS>> z7gV9Z^pN-d5UhvAg|mQJpKZB=Ie6dlT60&v&Vgn7=~vHcx7@}OJVMpN-LgHdR!y4E zautz|t{sgf!IxJo=;*U3_`U&!Cv9)upY@J&;wvoQ;{L6DDbx~|R|n96l+|)HC(fl* zxI7=q@x57&8>Ubd{Sp^w#)+UH-af@dxMP4~xIVNn5lFeGoE{7o&&J1x&Q(?_oN%Bn zEMtQX!jKA?PJ(JD1Oh+Y;bJ0xtGcKBm4f#PBC`zi!oGBiYeOv!6wOHYF)slc5A1#u zB!#xw()f%C=}qUps0nAKgr!yoy3Naf(=Dl&PX(fpYie>p^CW12iV7frUJcpOvN~x) zYS2twCJHhlqSzP-SA5j^6a|~sF7TCg)X@jGd;f7l(u!^KBhc~P7 zk!0%q*knLK7XXaF=DEmmAGR-2+0fFs>Ou6H<_T=e$;;o;Wbk9!* zjItnX=T?DxDTrOOvxkm|Sxx;YoE16$#U)6QmhT&l3usIpLhm>6g4%PNZRpVK>gGWC zifiV6gl}}TwIheDey*8cG{R9Mbv`*%(#wo&_%;OKwDTR<1@uzH*nFauw?2`N>75Fi zb)Yq-0rtO(#;|Avl{i-C3Qhfje0=U^aJIZtV1-@^Ok2oVrL!O~@z~}KH<|GYA6Z%S zb_x;*aZ#wrmz@pTlX?viB~g^L0%ts$<38gky`&7c^D@}YGd6?;A6dKXH*zcx{J?J2 zg%H&gQc9_=%W1h(!0>FBfWhwZz`(B_A85SWTi6~9%bIU+P>_y{xH#fYxAP9 z=uu1XgJKRF5TgxwOYq_$>kw^pFDXiERKB4^JLxVyvM&xJ2wI)^ z0i$lyN~pV13oRRevF4!*X^+D1o%mhcIwcmqArzlBJ=veRQPBO_haoj!D%is2MqJ6d z(TI*+_6fp`dVbFyO=EppZb$#hknqdx$`1Ay9ym+X1yrvAkKj3e92(UC!$fVqnxz}G z!L%8DxuJ-{ba?L;9uJt@sgBMrQTu`%UGdkQwzE7EOWomm3Q@T6orbY}oWdi`s5>DP zcz9!Off-k%F%l!`4>ied$6T~|Im(WtF&Y>v;xnB2VaC{e%He!}kJxa$0(KpMuYW$k z+wlJFYpdhFqn=6`Jd3Y5S>Z8-Yw>X%5r>pVa4%)lNcu&~o@qfPqb4g9=@|84zA@LI zy>DRe)25&m;xOcUg-|-zv?}@bc?Qd>^ro$778_ceXF&0j5;EdV+EpZ9BL+lV2<07?me8Ng^5KTTmP-SU}!5!FG4K?__Vi-*rtW?f;OkR`T9sRrvc8FL*%D6(VrZ>;^6Yu zxAt^%2tjYcUOt3@D*F>(cH~a0p{tC%3{LW_47`dUF_2u_nizOH^9(wg65gy@LUfAf z;Zz>NIH(bdZ@=htl&m;zD4X(um}nO}nbv)B>vq<@%<5RG%@>xIV0OE$^bT8S#l)sX z!4iPV=~CUTI{SK8x{q?;+BYw8X#9wenZ4us~T<3D?u0zk28oj;A3TnX8PK)D^~cgjGy*cj$XIa z1{=)sIgo>kIjGlNl8Y={@bOEI@~XX`IVGeZ?(e-v-HSWddTz!S6*`8S&JRlvqqRy}4rdDPm+Pgs=HmRa)B6xoaL{t_ zy@e+$ksoywcWI*5HD035jHcw>V|n1@F46HmJ@gnhjZk!Pim#7|M6Iier+b(3P2jq@ zJy6H&euSG|pGOT5{ou9K&vb)D^D{)ujxm2F#Dc*Sc~3+@-}Doms(Ujo6pd$lshw5l zNiQx>sS>>x48MmXs-oQ8+A+iHGVX0+!dKkk7M0uU@<<>F5;oN8%CzmF1&wEx7B3U5 zdwPjZ@R=v4P#Q_}<&K6px3N*5+JL#!t6Rov6GT{$sG({R;Q?B*pWpK#kTbgTdM?uV z9yV{>a+YJBc--R`#m28!_7aL|{+cGXcW|FW5MZIU-Xy@8E`Gt8f3Sf$<>4p%V29Rp$VCcL zcX;ndx<2}`s^y|_ZHaz3#?RD&^-1>5Y21V#z`o;nx1nUWk6z^B$fOu1V*PS&;GXP^ zX7@9ZqT%uCW=qx zSVtQFf$W)K1?r@?HL4-dXqIUK`lZ)n7!eH`zo5qk z^CSBV^w+${;7RuCsW^fj77_p>kJ>g?S|bX2rf!{P)H#ptkZz!#P!>Y%-|*b)bx)6- znsfScu_!6LZ^HO@E*9VZ+`#2_UE~K8SI>6lpMY{|P9=BeQ#V7Le+h-e@$>80Ug);v zaon2c%G16_>)_~!=7WtfuCpxUJ3Q6Z@5raA7cf0A*M3Q2M9y*=QN6;yHC+!7*?*}Z zNT#@j{{P&PFfezO-y$}WqbDYa3<<;1lMsMQl#te+v%>G8bH!;^2s$j~7cZ}2csxOd zjSl!M79+$slg(|4{tUC~a+78qja@E_fkH-@!OP!xeWnqGju*e-kBrTD(~8Yk#33z1 zFvfGQ&3oo;krIYsxIg2cJv2gAuNX>lu_7Lv0QIA$lQ`vq`94&I^J;=)>GCmC^c=1+ zrT|KK#p~?_>7l-nKFo?6<;H=D%oy*lXn2E|vO^+?X-NGO0pEIC9`$4`{l3lqTi19P zTuoj6jZ^W3QyC`4!zIeI`6K!=77me>zH;@ObV~WS5HX^+nW&_*VzNCoVkP+t^)Qt! zrM{TlZ!MR?UAzjIoX;klIo8Kl_))K*5pNQZ*`y84?flzF#o+H#9Qp#3)hQua%o@O$n3+ zw9V&qSYqroRF9N}pPdJrW1SnZy(S6#{3>^S9~s~n--ra=Fy9J(@A$}%Gpwd?(8)vz zLi8V@L*7|fG9-!rv0HAuz|%8RAocmd_HbDjt_{OUbRGxai2~bt#~P8bX;dZNP|p0K zqBdv&cTx&+geS1GaEeJaa>bJtZZ*8o(!qa{IQug6vR4o!=JlCO7e?@NWQ>(`FWL&l zBexw*O>VBi^`ZIXgG^Tq2W(q%e|rAiY}2ig?s)9 zqu*EU$w74;Ls?f}KR*0k3%44+Le@zIS}cgLO`$T$0`m4|pHwyq5YDWqKy_ION-5l& zh`wyz0)n5M?A!aB4$< z=&h@*>_}EOp|n6-YU&5RK*z^B_DIJ5Yf1qw7jRM!*YA_&ik|*_A%`mjr+(RCOc>q4 zG=e4Qd_#SImI8xzlkFZdPz~ zV}^iwxF+SQIuRcm2@tasg{aNicv&SwZ=sS^_9#eLAp954GU;AJ8Q^uFFASC zKE?=-%_6}Nq0 zej(+12sd6{M^n+?wvF+QXHN0&uPruxHt^;$-q(4-(SoF~nG@Cfe3MfdrXG;cAas+u zS*Z8Lf-cp#jJNx`+Nu7b!;5KBe4;;_#fwt@XWxeM;=&As7t@+np0F1U@+?#4&AZ9L5g*B9ev%_fJvV{@qQgu}w8nE+_ z64;zXgW<~f@^HnaSOrTjnosvxOynU!PrPHLxtk5+oz9-FxWm^(VNfcc9 zSu-;M#&@}X^xvH!QuKdyhS;u~=xTh5F+i-D?Wa82GW_3KZ%d4NVCh&pdP3a{cRzE9 zMx05^Um)2YfJ*yoJ7wK54&MEV%iCwB`vD}+jzbnH+LqQYey_LATC*#r+*qYGUOa%?OT1=(Ga) z`W;|d@J*v%7D(P!HN3Iz=%TU&QJ)@^NcvfIR^8r|c5*`Ktv)^PGQeaOcAp?{7<>)j zGk&xp-8_am+fJ~pQ~hah@7wu)1HTI>QYM)A{I4fD=enN<2eEvz96^!9$BoUL3zPoy zsSdZt2g2%XBN1?E)@W#4tMQa3Z8)0vFPmKWeRKf@<=8F@KMm~SO)d_RXL8kka@=!5 zwF&e+HRA6FQs-a&++{OD%65h7KKQxr)NM0K^Ho0moWJGi@XhFfDevX!Xnd)6xJFI0 zPT&7`GpUDN7xdu+H$-38@l|VPQPwM@fQQqWZwqAuW`w?J5X5jvdjX?g*hWPl7h)#X z=;%fEv9#oAzL9)d&b#t4xa1B2=bt4m?wTD3{dc=ibdg@XSZ7?h@`cnkt}6q#+mz(~ z4=h)%h6g6dH{$%F`8kAlU(h?bxu#zYz86-lWdm;21Iv&eFIs zeU|!8j-C|!-a^vvu)ew5Qmuz zlg>Q(3Hb=Q>@prc4R~nJ>@*x7ECv~BQ2gc__p6{6D{rnJ|J>y_+4eg_q;>5A$>ifl z?#}6xor?}N)uszR_AoYv5&hpkMHMH$%{_Ixr$3NFt?(Kh^l5uEjurAAxy#!!=Ao7cTNaQ7k$0|zI;Z7iAiG_FGr|MyK>TPRl-O6#lPUOim8Cu=S{dgaN zs$gA8TBrGnEqh{?@W-HKZ{JTsL^n&&160S}X}^J{N>fL%YG>3wgV#uB1dW}eEH+uP zD^Q;-RwlYbbxP>d+3Raoo6Vh8hmF9KW~=QUJk$yGq}xARI{wMaX9H~n!k36e~!?T>{^412Sr?s8XcoPGB(we!KKk*r+oy@XaP^_piPgO@7!xEI7K`*w_L*mX$nTEL`kP|6)U9Hz&k9kNX0QX{@p578&)_BA8 z@(XldTQbt*RbaRB@@yb@VaVZ zXWC1adp(}_JW$v86jk;Sr-}9C758^g-#a#wlNLWOHhvwB#Iq=kq-j%D@o~y`U|NZ(g$9t_flmvxIgPSKn`Qn`f)_L-*TeVQ!?lD^2T?YeH62_g4Js# zNRLOa?;q~*oXf~+Eibasz0f(x6 zUxffYDCZ*5s#qudLVRQGL57cpQ#g{Q4`^o#{3g?Ql^<>L#no4W z&J-=Qg)lXeOy7yp4L%EhmZ%)?N>UU(QaVx+{gF7H!)W!2{`+ywcLnmEGQFM|=_6i} zhdqzu_V2Au*nF-L*+NE7m&+LBbo#aj*N3crcGhs*&C@A@Pd`KQJqkQRgBOjfc62r| zbNFsZZOLml(;p0k+>UddMiF~*{dz^)@(7rdDE2XtOkXTQ*>fJ z`q;HY8-|nYVkH(3nVC=iz-cI7{i?6OvIldvjwW9unIg&FZ%1_i=Q8Vuw9ns5qf)g1 zQvQ*ky%{V(@cTNf|ATx#)M;#^I#>}0fd(1A+7(dco@KWT?Xwu)rZV_{NPFwBxSFla z8%ZEQun^o5G`LIS5G1&}2X}XOclQJc?(P!Yn&9pZjYH!wojlKZ&zbYioSFGP{_5-6 zyV+H>Yj^GX-D}+|=I5)k%gYGaFJI1-{~UR@jz3#gM!QmuEpN;4rOQ3b z{|3xbHiaLlV%Otuw;&*Bte7a^d!@AOW4if@zw;#YCUh{#Y4Y%|6dKg z@PE58A_9{_6oGicfem^V3QYI3JD=x%6pfYgiTvs3`{c0IfBi~E(ZFcWPhJjlQ! zoYE4D%MCwG}!EjlzDGAk|Dc_w4`hbO~HlAVt~ zkyf~$!Amv6kPJ5z^GkDvpjjQIeiF!p4gV3@15$I7+mU-e(vCBirH?Z!pSP-&mY#li zb=+8M9um^%R-#cKD_GgVmAeCp8i#R$E^aS^%rD6JQCmE6v|*d0+4-n896yHJ=#&Y+ z$OVMT1waB!&!%)I40R4(r7ZQhEwpE)k%_jCr^qI4{D7Pg?AOM2rQATM0lb2LOCpp} z!?fx?^iXcc;>H2l%v$k3FFaw^>b&`GQzR%{gq;W92F$*d%DBjQc0q;XXp6WDfl@g) za|j5fh^e6=r*tax-bqo-IFn$3ClNv>Nrz)`zO{IK(xsk_02+-~rzCpZ^X2j#_s%np zgKmP;apu3{>W*pkElARS%nTzOnS6 zj@!FE;x&&$rO1%QwqvVj_xdD~1sx#=K9-zTXvk8&Y^!bt%B+p8h!We}!|~G>)=Pzx ztKN98^Yk$|QH!vXjV;)Xl%JBd$p>sF%HT=UIqrY~wr3{YOHDX3vlP}#%<3sAa=PlU zd1Wp7DtIC#*4W_|92?Z+MB}=f@XxoIHaJ4BGOnM z9Wq;hdt+>2kvZ&P)YTEU)w=k}AZfa`zM_DwyQVogcB0}TQpIRyvz;{_c^htr`zwPb zbtuYAf+)|)gY+!m6w@u_N^=#dr0JG~j06R2+h zFBSE$M+d%{m2SMw)HK<~-H;u)sQzPv%|+pUFCMgUCz}iP8_I?E2{dmSw&o?_L)Dz4 z&4jn7UmFIG?Htb(d)AraS`Az4ANOKOg+~7Lyf#A|FlpEgudsc&OOpze%^26(O1EKB zY3$j#_j!^w2kk|cfyC4KLZy(2hn+Y1t#6s3_X!|+p#ND~^yUppcG_s#XINaF^G{Q{ z*#ehy(eW@iGBTXd1TPtW=⪙J#oF{?LC{%9ghzW5-knsqo2{?%`S#MZ6>Vh+xakn z>7L_cV4V~6lpi5a=yMI}Q?no&!W60QyJrDH&lTSDikT2fIM!}G_>sbAnT@yC;slT8 zJYqH9JlCk|O7J5iG|`fXb0lu=3%_)5io2Nu5n#LA5pzuVbJec}GM9ylz^)AbzKO^V zfNY)Ex*wNoAn!8X*E>4tGHP4HO#qKgmvN|U5H@1iWg0grV#Lb8E-76&ze*p>&E$O; z`zzO`O}wiQ<-t+;nYBpbN7%L(=6Ts}*!aoE(1opL9F~kT{!g~7fGwisaFx$5Vz}}1 z=R14C8OOBTt;5Z}J9;*J6=K?p32Q%#IPjH<Ykg3;H6kS7+KE475vBknxxe zzpPau<3A&+WOR00i5%}Fn=)`nE!r861N>$Hsj8HX`9_#7S_FjW{0+a6e1=yp%x%P2#XR{sxXozZ%4zR@xAvF-mnyX&7{(UH+`~1+GL6K6 z>Z5Vpnv)I%kAil)xRuhDUBwfgRUG;SWdP*Y`^nxxhk;@1`se}S49Z-#JRf63TETT&r_p_XqIv;`k30m-)b-KHYy{?w3RIcT0iQiLPx$blG*oWu12{h#y&SDFHnSXg~9qSL* z+wZ2XoExcs`V~25AL(NNB_ZF^E3&h$iYfbn!WiF#7VYzNAws2l8(}0YqBbJ$Jpk=)I1(rgpqu$8rTmO`lj=9%$!a^O=C~e<$9Xn&l>Bt zyJ4RAryf&&OPFhOrM|g2e9Fsl&nrDKu#UyTg1e;(^vFjK*0x|ztr*9JSY6Gda$oTA zLt$^y^U1-1849Y8rRvSexRu#-(Sba~DyMYuF=_F!GEvuqcPV^vWXzI*Lk8<*>@J>b zB{vkgZ0IOKH`gIRU>L4xGr1vv9XhA>&~sJWjMJJkql95&40W!?^xD0@QfK^D5Dt@@ zXL!`C+zjL*@6jaX#`S(oJvP+;K{MdBLolX&d7&DMLQN;ZHYg|$R&QL-W^7Nd2f;+F z%d$J(ZNlV7&Q8Iqk)v(T80HtI1nVJ^n>m&;+@Xb1vI;&xqsB2O*xqP&UF;5gI#u}O zO3Ne<(f|ZtDpFRPT-#DaBN~tPTHk6>weJ#^rSilW!kF@a@rh8b`E=7~r^%SDo0(hv z?rc8=-hYR>R_SuxXiDGJe-Zm#)0#?1-D?(WIOmX6yqBts4$~JOo?&2)^9KI(;H0X-#M%rDpG^#r2g|mu#PcCv6vH{_9>0S)1d<>*8{w z;aB7(W4fO+Wbeb0I9egklvWDZ{_~FkjB5q~Dvde&Aw_T)x6AoB=EaFh0}tVS5@lHw zgUi|-Y^w^yc&*0YBTh(@TOM5tDA-WJoo+#_OA)5&v-^HszLAZbfn%NXe&ZB5mc`Ws z^^)vVt@m6KE^c^Pd5my=ydtX_8*HqB!P#UB9mYXh35SBRaKJ;H$*JpG~B*PmX(R4Z387)@2xeDx|(Dmrw( zRevm9T9Ms)`EKZ&V9(2^$F65~^UFWegz5@x-;<_Awewn!g74;1nyxVI`ktbO*v_ag z6FOgnrQ_IC;=ZF#lbc~#mdVX+17UqPxHR|oZgegOe`t+oT-FCf+L!q=?Kp?gVv?&2 z<$Il50Xlt(M~0-+A^RD$bItD3PH*9lxF(u-n?k}K(uXuN!z_HIxBMrb?EX;93pW!2 z&+`}o0Jd~k2X{sb3%53FC6%mUwD(X|IlM2K{qga>eTPy91C&!`Z-vFcdPBMoUu5`4 z4vheSx{2@k4SsqO_+fc2~sDc;{tBt<6m22_8gq)kd;&G zZ17cYh+U_2?rr3+(&k|FhXQ17XHNt};)pkxZUt4cfUT8te}EWE>YW`KORLX-)WD>Y zDQ{vSWwOacUQFD+Udywrylr#HY=B42%@~8)N-J5ZBoDCb&Y@^`CEj{URqi4$u8hDL zp8tpchI|-xIR#_BuFuI}Jz%cMY=n0$Z?lgtI4_$2qQloYip z?~U00Vq#Zc&woZo-a`{eE`Kf;8(_&7!$G0h0-OVt*in#-x14C@TZcF7cdRY=czO;x zZyzMb&z&0me~f@9+Sjk0UppNIi+(n(TlCb|&2JRdY$jifh_L9Ma*C)+!3WwF?hHJo z8D{mRzC2`7$E|B|r8@I+S6?Kha{^`cWl#Cjrp#VBc%JO;!G6B&Goh~(eHNbj=C(lo zPRp;t;GW6b6tnG0L_O}OMYiv?v+H}~Z3_Ik93a2`=CY!iwG3bRf8$naKW-!5uvOJt zE&UuBaeXSW(zVhFPyKtBUY%E-@8*WPWgl}Ltglu+`vudO=wApG|6;NOOPb4>WDern zrb;Y+!oeq&nEx42k(gip*?-$u0hNoV>IiU)xz#QfzcdhpLz4Q#Zmn`yj-nRwIj2d> zPJ3L7lZB^uA%Mj48}AKA64H-WIwPepCfd|wkQ1^9nMJVZfe^_z#Mr!LGNKXz-*{Kh;zdNw$}(GlH#*gsfJu28M( z{{l$;1L;6u-@hKUKXRZoM`+Nn8z0U0FOh+C{=xt!KUIoAMI5sFlYF3wfTE-{DExDz zLb!8_6hcN~dxejVN`BkDG^Y;r%DcE2lt>6!i!D0*VOReK=>BoNzsZ(D8360%t+9sP z#WlNVNr^~!F#a7`S)ijt78}Ml1?=W}H!k$O)8X^ngw6TZj|G0_6@$8NVjo?LA+I7* z$(R@d+Z3f0@^PA4!uwHPWKOoe6PiEhbBBC39&SGNH0=@2sGZAAdoy&)D^rj(vPeIQ zSbHgZE!+xV=6O#bA(AS)iD(Rd?J<3@m6xms|Ai3WWBiTL{)S%v)?x??`h(!!FH1s` z(HROsaEU2W0|jQ@ICc2lC;A-+(o3iF<_HU1h#kqFdq72jp-%V4R8YV=l10-Df*o)$ z)LeJDa&FwcX6a=3zba?CI_nKOJqTtyMtf;wH5LT_GMRxurjjNR;r!dM=xCJR<`SgZ zEsl4)g#IW>pz{7rHNDwssaE72UfWx@yvhY}ZsNgmbG{rb*jJVo|saT$~* z(4_WL_4JJS4xp)F4UuFTL`1~!)fOj6Na66A0_21qfmOVF>LnC9lY3Y=^zYIOI5zFuPqR&F zZTRMB6Ai>KpyzOPhQMDC4n;B@F#)S%BI{XT)w8k2i?e)2ze^0G)>k+NVN5*36`9%O zm(!Jx7v>l`X1fBykbgd<*N@^8)%ha1v-$7_B29=l7oL(HPRT?fUygd)6ovT_rk~G@ zDrb(>?UitR;pYsnApy>0kOs8!4a@ovQXXxN^R#BOZE0K_!bUITEaVfMMtbM8+aEG2{0iX80H9;q0}r~3{A{W@ zHYR^o19V9=@?)2N70KuILwUYD-DE**mar3PR8Qu+{9q}qSKFFb$HHa_&Pz42QYb^@ z3Fk4J!|8@fC?T-Z^zHwV7@hC0yYii|B}R#vUkoPZNom}1$WAW-Gx?t8ow2$QD8)!~ z99xVFFRx%a@M{z8131n%PQ~_bTt6`RbO>%gjEGn3W5@h|Ax3Ey3Wg8WDTCogd#R$r zGTH*h^IEGqS;Jxx$rA-2tXUb$?!duMqYYT5v!dQOOt^|EB9TulY3Eav3gpIu&h5vt zt+A{5YiT!HpN+?OrIJ44<8)Faa|}54KaR*z@NkFnnv6@oo&@mKV%oG{uyZf#Zuhy_ zdDie{q3(_SNZVteB~nQlB#wzSvdNmy*effiC8~{8@S3~qP7i3C{=r)K?3yII_7t?O zb#3XGh@+HbYsy_x&^EjN}%MZ=fxul;Bk-Yi>3z(A}< zo+`Z_!2H<{E>cob>te)StRGle9Tg!CI*si&s~$ZN6VL!_$CgYO2?dxBAN>L&?gPr2 zK6|e2eLlH3je`7mG@3)!9b_*aL|rIY+2F-A^(NRDd&SYKqJ6$tMOgCAX2u;Zmz3t0pefpJji@kUeVK9_Ah$8Rce{z7rE#YA69IY z!GW4pyyba7A1i_1+{O~BAMikbm2a6ka(?BXPnY##d}DA-_338P@h6^Y|JVXXrw81b zVW-@e%<*Mhc{LCpJF%JkV>LBaQ_8Gt-N&vT%(-vyW^9&ZJDJ*FG&+3~jF(2Ho3|Xf z_|!0Dv0d6Mz`J37(oFL}o2eHv?lumGi`Lag_g9ZOkHHnFbA3xIISO>E-v?MQKi*^P zjy{FFg}S6?r(J@TahbB7*DHDbuwiQ7&)bAq9{e1`Ojf-$G9Jdhq)zF)2SD#6BA#kf zp~_sLQOMJ@@%NpMy5#is27VRm*ha*7bV#TR^5k~L?GE5Dk)3QwCifmO?AV{m7B`ra zH@d~5c=itT)`ktc+q#aRm~N0pq?(DQnDGs$U9g+jPsOZFM27b>=PlA6o~Rho)R%rf zP75^dqcaq}X`o%y$pEr!rM7*g(LPxQrdLPZZ9hC2?&|P}bB{(NWU0F!>JZ_urd0%F z7bafTGt_CB#R(z7sOq3KX=A^J7|CL9-`se5|OASwMvt{bC1qB5y zE1|4Eh#yj3ps1B|zgEcBWiJd=^>6JzsnbeRKF4gC@av72x#xSb#9&2r7>IbDAdczX z1coiISRwFxux&l?62}|g1>X9&qi@tEG;&34R3B6uLIo#a$UqIe80(E^O+V|A*@>T4 zHRWJGq&x~2Lbr-@`aF?eI*i-#u!C)wTf}V7Mh$@kc!Ou*VrkD8uhMnfl0IGH*mN`{ zm7GR?0E3oj50A$D`Xb)=m|@$^T8w3UYGSBDJ7g`*JklKc!wk{BES=L7js~5f@4|u> z-@z*t7`J~z!Zf~>2ek1Lv1jFTIhiM|YdzXrlqWuQu!w!3|MK1h(A$6+;wv$2jW!x| z3g+DWjS2;RE|O=~%)423NTt5@?E$S|cz7el7zCk5>SXi>R<4rGFGRarXi&+vyUn_X z3Vbj+ssXvz5|Ejn%Y37~sVg1|QfyUd5%KW!+ZsuJmxI8$_BkXC!4o`(r4h8fl5BR- ziNWCen=KxfV|ZL@1++S3O?A`YxcJtJi31v&^kpGaiPxk;d~u4{cI{4F0~{D`U~ztU zhc32-je0Rg z{_2&9F$32o`6S`Z={8p&zxE;z>>iD~o4Sc`PZyYQ*=xgghY^o|tR%c%cl z&kgzc>WF}WxI(SC{OB|>Hcn5b*S?p#Iax7Drc&H>jUnPKs8FvhNP|E~L|!I!+}@Mb zVSMxv&Mye=-md&ET)J;&U+xUqF`oTmyBQb{4$ve#+-&#qVlJ-Fpg8Noy>qgf7^@|@ zfgk{76&L*F;dXLe*=BS^9%+Yi36r6MW=R}y+@?a`#2tLt0_)2b$4p8@ncIPFP4rxM z=)%wD8@MA6;+gA;kGb$ciuVhDOQ@6;zAEFY+7$6Ip{MA0bMRot=TbKNh&pOrwdF$L zv(0iljH{^t7%*NII_xAi25b|TF?@{^EWcgAtE1C@#KDhg^a(%KrH<)NsTYG2w=t#n z=l%h+j6Dy^hgbz~H~x`gEd!WT;7sF++tzX1k;OGi^g@70auAGi+YZi4KU89_V_3v+ zcO`YUfYc~EQ0>DT2pSC0^dj;E(X)@u_Ygmg)U;Zg9J2WYwrcW7{a_}-ah}!uWps2* z3^ax!*cn9dtx2Rih;N*DHQR^!g|j-W$??+xir&V*V^txQg1g+BhVL>UU@i74B)X$? z1O*WA^Ugs7G?t>J&UQFG$|inU9Lus%A$pAWoYIl)agoeI1&Uo$VmDE6eKdS;XDnvU z?v;&rYQ1?Dzms`z%j1nAFe?tGU3e8ZnQzt%YUxw4K1R-hIF=H{_fi|Rn(g?zRwFU+NfvFR8F;XN6hkcFNpOxk z7t4YC#Vz3Bh(d02({!h5*;eGA*z5U|AN^Q{!~g6=dSF zliF)ytIF_gI+$Y&UlwSGok62CTCxp$k`*V+ z39M~r_KikDR!jN6zANEKn|Eyx>YmFkJFvdB?Mgr6K5{k`yxuELt0f=!Yn`&n3eLWB>o>Ost2;#P}g3`F6BQeloCueqFKYkOSYTRy+$eOx1E_?1^f znmAKkH02m9nDjQgCDd+0N5 z<-!Lv$#dPfI#`SFvt0hPBf`X)FJ)be=I>6i3aNd3c6UUnl)lZYH&t6D&nYLNPrPV3 zE7{miBuq3m)@k}|CcDb|VF&qSCq1Qt$wcj=YKqy|m!S@}gFi%EHrDXJ6LIgTp>AXj z)en7AE#wi)t!=-FIP&TYr3r=2Ky?ZY3q1dDqfZXs@qj^C*w?vX+_F@zFy7J-7CR+I z0}AJ!fr7w{%i_lA%j@JU9aJ7Izr=zot&U*1H5%cue<$TW#unxZ-PX$38rkDnxFM1@};#;&60dp~!wl6|5HAYC|BK+H<~${-tQfpg`@!9m43gBJufcPo8JBMQ$qA# zkiE?-7JYlDnwpEZTyJ;pJhzJM(_dM+P zk9gDH;WF+ljsr4U>`R3kdbw2y8*h1L5SX(x3J~eS0*np*Hi}McaR0c>I$h&wHyvp zP>{gzs3ou2TH7eT>DojFn#f60@xtCNA&>ZZ6$$|D0hHo$8z70+eJ7y0TVa0EZiM_RY7 z`U^MCWE)BZYP!QUsb3RR)9t$9`~1~pd&IM{xpXL#uJ=OaAr{aNq4!(1*-Ht#+C8p$ zPRgqumoze(Q1A?Gyif{X#7EdPM>q%Xsn&LR2tOpe^-#q^WESH zU3^TRWgeVoj_6^^Q0t_^HSZ7@6PO}TXapfxepK1KBaRt<()H#ibFzMSkN(t&BZk}6 z_FKh)F0>C!gy9@34*c2CWsjv{-)#8(hk)CNI@+Maa|G5a5Y+>I%ZFH5?fD~jZPmuA zz`$2)%?^8f&L?XS2WC5n*Z8v~WUm`SmA}BMo}Diq77w*4x6^3jW5Lor7PecHTNGafbrK;mDTtHw%w{ zJt~?1Nx(S%RI1qMhgy}uwnk6MM;Fzr9p}k?j6<{#Bl6)$E7J7VZm$;oRqRkl4BW*) zHqL1A1VQRl03?yXgg z=p8Y`WXDmOqD^t;$~kT=zfQ=^hR!0NmyJw20Db0@+l3p29#mBXT}Dh?T$=tvN-7fR zc#2B?@m>7U^1~v4%JI|ZsIz{Y;?7#@1xGNM;E%JAGrOjt1P)Eg?=qN03vDD-Iay0G z*=t@Ycc<`eGhORH27>Lk(}~9{j)WxnBHnAD{mK>KqmaquWCQ>f@_sLQoew9i^bj|C zLC7zsS&nEF-jkDqqVW!Bje8zeu9aeD8CuL|kyjZjRR3gio@dEPksX+4d@#Z4^~?a& zeMg}x;Rc-=HvZJ6Ibvqq-Vt`2InK1?fkZ`@er_eEIC(?2y6Cns2JwjHfnHv=t>-wb zLKLFG5a5!zXl)_`tlPaHN!yjc|t9Of-W^X+gR5CE(| zq_kff4(-)~?s$c~>MX@r};m?)cr!Tu#fZRMkDa2rRmOn|!_kR>^)$KUOs8wjdx{)Lpi=gGjY zc}YI!X4SPS{vF{om_cq~<2`=iD8+=Sa6-Qzw$mnu{)O=+*>qBktfv614-Gse>Sm=^ zb^d_WW{mi$E$xVKvzWWw><$-0-F7Pk4MEc(Zev1x@FC?eZ13l*4R)|-)zDTU&-|&j zme!<=b4%IodvN7#)LzcY7k{c$RerNCp`^ZHCGFXUYRL1?!`P9jKK{3kNR)ZA7n55f z^KQ&21FbajC(CEM^3jEh9#AhAtMlaqU+Q9Q^-wWdeR?@h;rA8bKBNWCXQey<#kEh`;yIey92={1Wy#@hxZ@Xv7}(O}eEZ-AuItRU8k_sE z*OY7_c2OCaDgLott*weQ&l_ss-HqJQ#QEC;^x&RhSD7}JB*ANgO{}X&Z z-${;<2S%EH!>A33F*6@F_4X)48QB{3h4-G}MxXV0i^{7upU{{oUbHttd%pphm8Pa( zcY$KK-*Zw%Ry#G2>o(-_>MH1!Cu91Z>}y6+SS|l_yS10q!mYfS3SMoLsC`y26^fME zz+ktB_z+BE_=ck^1M{hnB#@+Um7`P7=`_BK{+ttbZ+uASsqN5Tz@kCcvhU1KjM3od zWi-&y^De;?`&ESo7(CssEy>X^*H=%ExZHGfxC<#05qYrGc)FdD6E8^|WOjkPz8bQ4 z{#06ipmh8*8Ly|6`Sg(~o?BOUuvf?CTu=&bU8wn2OQdHb?2AX)bP&8K?n&Ka6MsTk zEzYG+jw1QHOiB2u3KL3|4h4*XJ1Wq@6Qu)JlwP#oi*B2H*MCav=U#r!KuC z%sFYiTu@zHdo4>MHH%IQDyfK;aFPDy6eD6lO3Jx=J_U`)Tofo`r=a9; zq#wQn=h|j_${um|6g}8(oLj{rpSto3lDZ|16*0Yp9kZz>uzb9k+9^Gml++1cQU`x1 z`Lms&AsKq-v4e3tQ^xxc_rPl}HNQWB+J8^xLc#suw4k%|j{g3W(RXH>>K*RO5R<08xo8~#L4 z|E;I}BXaw1wTR58?-{8+8YTbX_O?JQ5RbmZI!-e~ABW>=DQ=aoV>eXpGr#pG`=e5y zyoV5f1f9d9Beq3GlB=@A+~bX0r*zQ=-2S&Rbr_$J zkOe7ZLHo~d85yccX*6U16<*&bAR!T+(ApaETN?Y_vAA5|*J@5q0KjZV=Pw2Ey;E^9 zm5jCZ$#1#uPiMoqY8Nc+ot=S7;=fY~AYUS(r=y!08XJ?Qx%s;(MUt|z902ZC(|`UO zh<|=Gq^=9@Kbrz676E8!`mLe;iS_UM&?M{PXlM7kdw*T11yV%GYUJ-!fIh#zud~?Z zB7efYzu3jb$LEUahyT@p&91N2`(kCn|2USOzPY`-Tao1P_gGD<(_+C>QWnxC1^zuU zn+gi?St~2NqyKDO$+lHC zA-Nnn)0b6-L%H0_34MxRbL&I3a+cunM2}IG4N__}%7Y~YyS@Aj|0^!O@msQp$+!3= zafrByC}>Uf55*EaoKLG3cHxV%4t+5CcOg03%5I79%1}8vh}m1{mko%#{d>0lHCn%Q zZOBcB{QaAZ`QP#;u$dr{ZD{6b=!^d4;(hzIiKq}y{Ite6NHrjmb9@1+qmGY*5WxWM zqPMcRg!8X?ZC{N+DU)bDSFs`s*{rLdHZ^g+XtE?7SU%gc3@~j7Q}as$1cbgns+hnn ziAMJ_QdFHqR=j?FW54xV>!hHG%TQ4ms6FG3G{{kz9gZCq6Ass2^P#!cZM4?asL*OQ zfTWa4LduU^nx!!tMTdlhFr;$3oERJ&9MCsPkzk-+_B{$qN%!D-#sz?LxvM8c*A{rbJaN~X|z zZT4a7X4V*wr5mf1&NQVRaMwB`M{E+9J_>oYfXn=;+^};hB`926ZFrlr`$b=gE&$4w zAF!RkfvPPTOmUsTKoqzJb)lIKqJfhq4m#1#fugxg? zgWZffIi`ENP{wY}cd3EKi)wD_VZsdfeb~IzEJcFOSt6`w8%ZXuRi=G>qkyogLQsVY zA4#M1T59PEXoV#}o#EA99X^NX6=U!(HTuDwwcI$l(>Ctbe*BMM|B~BiQ3u@!I$zI0ARjCI z`X4P_`as%(;o9x@6zG{i#t^vpy8HHpps?c7%|V)Et57;u0z~2snhPfPKsuGA#f2ZZ zw5$AX$)k`URzP4hIo#=%yXw4qbuiFS3njw|z`M(zV&l###6DX|{gH^@7KZA>FVr~z z(T*;WN!D~_!jWB$v`(^z;Y+b>;h`Wws>2f7IhVyJD6_YHqn<5n{IndVtk%RBa}>-c zTYjz;9tqVtj_|&W5?AU@V=v6g{8RXncg*>x@J0Q=9XtDo9l1N_UOn}?xM-jjSnf3awIl*zo;k(6wB8#I=>(h=p zkq9grhMUGbv6$dULT+%<;Y{f%A~N#I)kX+03YXoc@B#k2rGe)j6Uiw%w=-{z*La+- zRPtnLC`V~#&n%=WB4!PTQ7+2D5^>Kt(XZQWFV6~QjwcoZA-NV_{@`nm8xzfByi8fcBF?b zjRx`)vC)^W11UKeRvqX@lnMl5(OSp52dGV_o~;McXkFFyuGf#D1=#J`g}e)kGAtwV zM{#m`G)FJ@F-S-WX_@LA2|j)oF+7nu2wkH?r|y?W=x06`_$_=|*fuUc67{YjMB_?< z`?9GlH^j_{wQF_F;}Tn)>H%uRd&2e5rwX0%#4@Y(X45x5i4KeohR;`RUXu&tWn(x! zG>XqLVA&4g2w)8QzGuKd(NY@&oo>e?x@PoJo0~&B#NpjX?)Q@NU-Bje`43Lr!e7~n zo#nf8N+udNEfMi3z8ivEO($!pFW2K6YatB6~2Q`gbIxyU(G!!lNlEU0d#{V`+K?=MRFwU$0 zswOP8UXs(OSQZUTkU@+=0lUuVann2b%?=7~T}}U0-duDQT|4mRm%cF!;RSc=%f7i7 z{6As=vRt7DWJS?Ug6-#8LBiqn=F`P#r7O2egVr2MdCtf$lDgw7*_PIY(bJaqJeaF1 zy&L2sfT?r0M*`on1dw_S!kZuBQ}zp91v?+)BV1sNnhT|+>4jA*60IkQ*31$(J1nWr z$CdI7zt?-=KhTbRY^daUrL4eVyy*UjF`OWfy+MkKAiw| zEZ66*yot_NesaVug?S(H`Cn>rSSNyk^~oN;`F(`wLdEjr$oc3jbg!i^Ai$ayP=W;Puvq6Xd#M3cETy@R5pSGep(++f!Z-K?4E;rL7^O2%Cmca6 z-TD@d7Lj#ao0lfDEiDRBe*835fJHgI4fom1&eQjWoef-5ZzM%3;g=oDqywl$+i$-T zP#;bnebB=g=xVuzMxbOzPm!ru@9?!+o8=p^kIZ9&@=iQ!AU`SnvQtwL#38DE$#qda zld{MK&X6K-a^Wbz+K#C7dAe35)r>}h>=@lHhA2&VA;nFmAjNm;c^_sv#k69uQgGV? z#^((EoRE$mJ+$4sTKI1d)G*vr##@~=Q#L0_F?)zgS* z=vlvxnBC8vtz`4)C@SI3gwMTdOXRdR4}(+EQInVTpHvS1LSpGgC`&z2O$?Tc zhxtUse3ON=SsE}0J6Ii}d3d#9L`OF`vR5=U&$l=^IJdHsL1iiz; zYS?bx%g(@peCQn-I)JmZ9on3au~4%>-mWLCJa><3`3T)nxK&q?!M0q@;*LM^0dtAVwtKl9f#{vF0dGnplclwcd+j>VbWLXhW` z5o8PASWx1Q3)u>gQv%Q};9ig#-B>VC3}cX=XU?1hABi`<{@jK#G}=)I3`y__E|RmM z3yAA}ph%uFp^de$h$eR@tPV=c$|M%5cI$HZpQM=$6}#PomCV<5ptz%@TQ!7` zGhvS8_s-p?E#LQQ5{lV+PFY6(aPHX)cjN4zz<_d5Xb)G-{>b{&#VoV$kJbFz-{WDi z`14SRsm93q%TnuU5p@OK+x4|&iB`wBXg!f?|JRyj^9C{L^SQg6KjzzJAb$;+I$y0U8nY;Q#Q%nw{sT)^I4p|6lP~v z{_2i5MI0@}ZLM>YklK~*Crgc$bg}Brm)-Ehmbg5wXLykEVYPiuGU-eDw+B3WtA!{$ zQ4R}T^F-R3>3ZkE2J`Nvn0zj-wOfX}ba1BXvAX7V4Vj+JQAm_0MsDZAA&E#nq*%UY zy!?qHM|gDA{`CMT9_e`&MUQ;#RX;JnyZ!K@T{D<Qf6F*{e|D zw7t7WKVb#v`bCx3w(!_7CQ$)!2!$>rD8AZ9GF5T!ZI^gN!@$l9nyJ%ZM?{b65&` zZO#cLK>G~H3BP(zuH<z!R-L&0MEER_vwqn zqPZ>@0Zx>c8sac&OofWFE{0O#E>;I1<9?3z^eY-ALJ+FvK3cWw+i0B#KQ3OxMxkK6 zt=Amy7x3OGz;iCbbV+Nq62V6?Bj5$R1$!lbZ-zyy|N6$6Fh)Q_lzCIeE8u!f_Z5g= zaLt=7+Z$Oa*2nL*m)#J_;Bu1#&I-u$k}5>8z4mF3;LLzietw#1ty9aV`~ zU%4;5#+d!5LXal97JZjS`ZryLd6?e;*Z1S~cz#7}JU*jw4y|4AmVBG5bh*+@YBu`2;S}y=%T5zXho6*KksK zYpz@+bUp4ZQaFu1Pdtg9@HxM#jO~?nA#LzM)9jn55gkgZN&vpW-kbR<$JgvvYyQaZ zJe1BdeElMptMWV;@qW8KkQ3{sv4j8Zc~E;F z@Qo@`2m4j`yKIaXQQfx#z++y+Pdc=$zZeQy7h%1 zsiR{`2|mk=wdh{~`Q>_MQOC?9>@G7=gv#}c^fMf?zjW6zwY+#@?WoH1@ORf&^9v$( zy;qs>$lcmkH(hIy__%g^;WPG5-KD3CZArh?7VjBHFTzPf;AEa)j4vmKXoYv}vF*Ym zh8p6GPS~ETp{`Dz+|-HPjA6W@;iq2tplo~9*Ljbf@JPT~HrN~|a=gqxz6_h`aWfFK z`s5ZxJ(i*x@ZAxayW>D9l?K=*$elAza%Q>fyJ=SYQJ;7B9=X@*((l%CPeX})m%&s`Yj+5OJN^`yT zd9Rz(#;umDs8GaUFg}R*#!>~tXJz?5wS+okv)6MI+C8iurtC(|3dp*Zo41gZ76y>;l&Q^wHEa(|F8W5DND0M3LpiUGupgZzj{ zMED0x1kdkNAQ%6ueqO>~7QfVvWzE0ceW{hcD)0L2ghh(5tGtCyczAiTii8o8T2 z>5v9dV?YXw8Wj{6AI96#^FLjAJ+(M_<)+SK$jcjyK??pQAwWt(qDA!eJv-GYq)}+r znOY}6_SEGDm1y$vTZ4bjfM8>L78VgvyPScWH3qZ!Hn)+%!f#%$X7=%Q&RFXX*7VAL?6I}+I>VHb2q!<{t)Di(wVbp^<3h#R8K?)RB z)I<(x7&Aws9Om3PHeLEszG`Jh%E~e|Sv5y!QIqX$wog|MeyyL)2L8(PGPdE>boL(H#Grv2d1 zoPbXsDwoWJd;tsTJ-jSLM}w3}U8 zYjv5snA7F(h{9z#*9E^qXKF5d2YJz$iy8De>kdi5p(3HS?gJNd{%NY#mIGv7|Ddo(d-c-sfci2dDCuFr_=vv>#CySh?ec( zE<=I^cXxsZceelu?h*zKuECuUEVu>t;O_2Da0%}2@S5Da-p5<7f99jRr%#_cQeAsj zZH7*>ozbI@V;OCgaV^5)R8WA4lmK<$WW}^by|IH;KQI@a5{{c1q}WR-xI z{q$F0U~U+2x%_cq_rY?Le!3|)pzFCFUM;Rp4iudgVZ_1R>wk)8NIVi1dpW}c?tu01 z1!j<1;doK}YUvVA6(E~C+4|aT5t!h3SU{zQT}_R{Nrm|0pxnF~6*cwLR)r)Hn3x}0 z*plS)4i;+6qZ-|X+M>Y75@*a8isF|M8pYVyTSo3XqiIe89@lYG6^0a}toP#Gf74~- zm&``oJ~p6(RaDgIr%V9$v;>!*;FsCzgv~x5@9z0|t*+fS;8+j(kIC=9*!QihtlxDq znwf<~Tp#hT8kmF>{2I65B(JQukUUmO7ua^#?0vr|;vW>qcK+}0S6M=(O?D?X{ZGwb z+T;>#=77L_bp$Fn{;h1TDj+ibnKEaW!(7qwgXLs(7kiR?U;n>{#s6m3h|lOL4G9VR zp-~K$%bl!Cw+;?^-aNZKqo`{2LeMdo4lSVEAlHav0fdL69b9gta71 zPKUS8PLe6FH%Pd{bb~53P!UuMtj})1c(B=?s)g!UC@3g1i}Q7g`EN$jiKfYUT-S+3 zFkP$2vauqowlKjeg^4j)Kl-<9&BIohw7F)gYim_%EvJsDDHO!1h`s;?cmM z9_`-}ma7L8ItY9aEtSpvF`RPaba8dyv)qaJM#Zw@-}-gMj$28;RLH7XuD7RKWtIjE z4m4u+PI2|mz}gWKBKx6KgMxloq9jf>_v?BmuL8iWJBf^72FFtq0^32hDvRUa6>&AK z2klBD%Pwk#F(}oWy#~$lLtF7VEIFUy@p-uq}zJa{+AJ4JwaXa*ATcz89%u+l2Wn^v z+nki|i-(sznYJL&Qya=XLxZo1w!!Lr)Y1B zA!~PN%cG!n)^tC{ z$C;&)_}NDmtw&3P5PMvhU~jqiq8JAA&2gJBJo30Za7QFgZ@_D-({NQZBkgy=d#-mL z0e;pg6vy~r#D_8(GZ)UG$4?||yMQE7qG#yIgHHelTO%We z#N8?vf|o$2`JGWu5oFwHDXbhL*Z3@|#bW0xdLK?rw;#5la$D_cdXF)`cTx*3^X8~o zZ%+9etTCppXo@C-fx|ZioO^^gL=EA-te3zPhDr+h>ra7zq+`tWIi2YN*m4_GNrr>tkDKG> z#4jDGyZ*>NA4cQJTv%-V9?+Na`rEAr(YEg;ITPpLH@E zf9txaQ_yM0$w@3McI!2dUYjS$>R=sN`zF8r6SdU-03^hFxs>ON06epJ)y^3nloZI- z4mC^(CudJCqb)>DWZ`>Ie@#coG|Vy7YL+PzLchtZoyFOE_$#ilEfMj^T_%c(6J~>_ z3A4*1b&PH5S=v>0JTdqN7?mOL?<>CQ=26TRC-)XT%usRLN9ZYkgc~MNQLgEC+&1Sb zlCiISL|<00+-#J<9onNjy$|9C6%9RL7BdHk71*v1Ho$_g*SC&t$@~4V>75Utr#z2- z@mbAPyXhg3*IxENHqf}lT2oI2P-}-c zQUz&&eEI9`nV#M5!hdy|$n)oQ`qk)nN+hhlxetW`*$$AdseuFw}r> z5>tVEi3YVzg%YM4>_;itG`Cr~vCa4BWXzz8=hlQqN^{(NAJ{<3#MfLbJsm|3W`st} z8=-l=i`%{Rf}d}S;Mc%WQO=!lFIRoGDYa{}In~@2V#H^@(8#fx-G!u(aly_UR}d`% zzntYY1X9!?AjNpHeryb~^Hbw>tM&OYKjV)L5)kwcK-IHYkr`N2;G++aL6#V@ zA=*7+!$Y+da3H~V8*+cRUKN0W5#sNa#!|7oL01f<3yxuY;261Z_bkO~?4*sEH5bl> z2jQEr%*=#GlzeaNu!15dBT31%>GQ)`wxd`KW@6889llzcj7f(AO%m=rrjNJXAr zX?{4mt7W-z41xzK8tNjj&2Bk+nliF$IV)Xiycz-<`GVU!0v$d5ZY4h>ir3K6GJezo z3mp5PDg{$B>stco-&PL}H(De?V}X7BD2;=3xNv@bmjM;LAK%sE(~x8jb3(_CVT*_a z(a!Xb@5WpW5%_a4IrfrLph!!Alzkx=VM+bSHoDu!CW&t2-2v-^9ZozIR!C(;$pI2- zx~yMRgtX#*UJsJSLihLQu1*i|e%X=8V|@>uX&t6?O%fEn#gNWkPk+?Z*IewN8MdCn zy($u9=Vo@*+j^m^9Vj4BUlPm9^WIo5(a>K66LvjP@~B+5N!8}%`9nMovrcPx3?<-K z<*ITL_Z34O;F`W|{H2}LkXS=AOeK7*Rv$u!12uk76?uFxMJyIiQB+H7jzmgLY_G&A zoG?kKFpboWYv!m|gQ#JHlsk-#efX_nG5U;F4{aW=B}8oLBPEQmo2}LmC=;|;r00?i z{mXf!V7ZS#uQlqnsLw=zuL=oc@}VO;6G9u}SFNc}d_CJ9D8>7rK;VL}q_jX8&Qv;0fb{7Wd(lEmuUsGh~G5D;2%9`0V2qOH<#EhHHu>{ zDXx>ZJC%@y8OIoTW!eDJz_g2LoUUyjJ4#98G;IR(4DAE1-mxo7g0~_y9&l*G_GLi% ze)j*6ip6-93VP^9LUpOsBuwAkr2QYJwd)WgtK3;yuFHgd8{{}@$)r)f?o4E zim2+|I)~HC0-8;pc-(uo&A6R9K)kh%<7u1)> zVir^!Jl_cw+TMhhP3|j59kb~0?AUE|x0Ss-tmfzAOT0QVR`?W<3*|>APH5R0EG1^9 zzFsOC1I)Y3Wm5hAi+eUVr|B;SP^5&xK7XRc zNAW!&CZb+#)!^v{7wSQ2yiPwdUw`kd$)ZmGl1eVt_hfgl$2LnxDGyb3VV#}ZlfV*` z!IV9ZPUNaHCh{b_qxw5SL@6LlV&YY|nwoFdiYnXLU=L7QkRVbbt1BCT{QA z@;ZI!_@Z1i72^p(<5EfwE(mzQ)V%7EJK4tJ6|wpi3k@%@V#7ygXWR7Iag?|L*UM$p zmLfGufTwo&H9}3|OyZU8m=m~zz7pNazf%Wxma;iQFS?!Remcs)OK-9IPNt*3Fxzwn zl*wK$zRj@k(&`MW?~W)ZPF-v?3F%3vS@l#e@AHjxA?PS{9Q19h4=zqAxe=T;^Kj82 zsL`(6q9;^wk+$}rkzoYk{fNd>`m(&+#U`|D`S)R@P>h?T$LGzpi0_pLms%1j{G+kU2zGee4a$x`JV2&(>>Oj5!MTaYb8@POXegBT5lXrI+u9gvq(G( zG}=F`FxYZUf&8ScN)n;rX-}kY6px=)>Hsk<5;l)N-|jlZZa#7iK6@pQzMmZe!KgaF z^Ws_yF6-@jLB#NgW53z{MkT}*wL+G>+@f3FkU04P)ZXnf^VEb<$7BKj3x??{83tOo zn$a_&4J6?Lh0^^Z`2omots@kAzM$ys?bWf5dUbYIa2~RE4#|{l_9N&N6xhx-g_o+2 zg35+mvP&Nr2I+y|{mY>ypxFT)AR}UHDC9L8Y4hDz!^w$4JIzjb*{c#B`Gd!APACxR zVkGu*j%cwL$)uTLw3a15(ZiZje$Hvh6Iyc_a1(3Av}BI-1e$OL=|M zA(uQ{mB_vCE8C}$iVZEAK$~-3!S8TbyqS=HLlpB0SlJV0rbs{_JOLST5%ss}b_ zR^*2vwqZ)z>YdRK*abokxYQAr$Q0{GE^fg3Sjvw5P0lQ{)`^x2jWJp!Qn!+m5{7BV zD|!JZ>8WI3a?H=t`0L9ZBfR%oNO4CETWuv0^(9GQal(fQ`%$-u`%Kxhxz^C!B%j?N zt(d2ufw%~BRZYg$8_5$6w;_%*Q18j3lM)|1&l)A9tS!~M>VHn?rw7%$(Mg$ zCFhH1Nb$RM)O#^~C^7nrl{DI!12JlE9(ySaQ@>i_6`F1og20e?3M=MN-*CD1?TZV+5|_N@Bq#SR<_>Oe!UJzS zmjrFk>#3_CE8+gxAp39@)IxLIB)77zF^^Wyvhr-y*wQD4)_3E|xI9J6GTebNs_V0S zbOs%9PkIh+?vEXiQ7}Co6g`>epZSHhZdr)-=>4`8n$2X}^QE4I_M8^Pq7Dbl5^A`9!FV?cwtP84K{qqo z+d7DjxW7K2Mi8%O{LFPCon!KMlPvJJP*qC@;Z43GkqZEO{8;WIc{yREkQO%`Xwq~n zpA*xwWWD#|#(O$nppJfL7vrSe-1e7x#b@uLw+XG`a0sy$f@2_`0{2JoJ!Q$5C)?C8 zQm+xHmxY8O`u;+5CbuoyqjaI9yPAu^v9>3V>akS-zU@%}W6ON8c~og5WM7Oc>;60U zAxjl>FGYFlkc&rdg*9P7Or*cVqg;*;DqiYhmwz^Ka>QyV_2z0Ok;I_d>O|jmD`FD1 zlxi_DJ%ccU>;B?gl{abgquYk=r^zaI?3~7ZOQ|2T3PVgr&L88qK+9LbhItqql;`_L zK`Upy_%nY-9*QM>1TKHZ;#uwHNCb0doWXit!YuNxeh0x9*vi$~B9}w);5S~LH(H%P z)>u=BZQV49^D%2>x70eh1@nOydf)PNVbVzT=5!QHz#Y;!Z3CNkr~h<|+#moFiR zE5{?%F@cnX!L+kObg!=X*_<6ozU%)du;FRE&4CT3=E z+G*Ft<#{!!oR$lQN%Fn%v>^rZU^ZCWZ};ri5hcFuX7A7DN=y7*;0wr|H`zdin&$IE z`1JI$+d=2s8@RdTMgvnQzMTg7nC5?Pb@IWcWA2=tn>j-|f(KK({_Zo@eF=5Ip8Qty zduKymcaASxwN(td?|h;0ps?*yS5l30uo1_Q)#aH~1b4TYTL`Ezn^To;Ebjm}h z5)h4lqQ8K4L+DbaUJ*rR&l88)4aaYdp{Go0KhuVBvZXtkg<;Bgsb1hF74USixio~;ZgndOEoa--M2CP(QuXuDvK zE*@qf47#{TAP|Rb^7r|4-T(OJWVPz{v`b_M|HEs9u$-niVnHD-OQ9`7mm_aY#{{~1 zL7h_X5sJXv#!vNcWK<5HNXM>P3>GPtgSHT3`B>E?vWoV@N60*x!D-kO7q&Zst&r=k z>g8nc#9qgli%&+zCxU0jb?3uo&ZN}0m#&MW;tOJ<(I>OYtGgF4%XuT-mwtk_mVlYHUU}cp z;C5TZPAq0sBp>fIOh>$`Sh}YwF-uR_Tz)$^N-#vewvT& zJ_T|&DBAas-?;b$!;x8%$)C&A3A$;gxlK5gi_m^pAJAIFk-sNxm(Gd}Z4apO{mPd{ ziWPeC-l5IqWHnw*^~Y9=`&G+uKN$Fen=C2#k`BkgQ=Q@uKH5I5i;xw%f*A-zsDLfn z*Pc-p@J^VA0dTpNS+FnaC&4%T)k;K5!u9;;^S#LCB=pvz==pB#=34UFQfJ|l*bOPO zi`b!Ux}iWe#>~$SNgPeuo#d0A99aL#92eRA^_Bdm1)dcf9hcuPHDW1*EOZa}i$iHs z`#kFd*97+4F=y}8;$nMn^jLEwxQ(XGDq{Ntlx{X{@%vzm=H2q*6a6^q-YQ#J6%7v$ zAJ)9Tf%g}=-7hXI&67`ZtH@+o!ve?SJl-dU=qZ)3&L@$) zIUZ?o=EcDwG1SuABYym&Y!7#v;jn&3YzwWa&vO)(bP6uc=Yer;^#c-wib1AJ56_?NRoz!~~OjMv0SzB)bU^)+S zcbBATjhiD2M;IQO&zwHNwkAb`e`Wqc6>oJdIO$mkE))cR*zje@CXymi?;p47aSu^x zovC<0lc+4x_vgOrMQX*H?md%`K?ez274TdJ4;c&Cvj`L@<>3416{p3;Fo*ND^?E;M zy6KkpF4cXXK3A}d6VbIeVs)6~D*m>6`!}3=RZ(YhzuP$1N%EX2$4hSeE)_09=K-xv zWe(QTHzun$ABDwJc@)#ds#j|@GI3LP(rEN&Y1+HT6{@uPf^AM zAMVI_&OrOF*zB0UX|L&pmski>tEncubO0ASCGws3cq0vU34hxW_Y1w0i7*+!f(de; z5{tG?nXs+fDNQniFr-A)Iu&ucjgy2mw&b1gHQyZM@s9)y_XPDgFRLbyEVX)P+jbw} zk3bOSHA`OpRLjjUcsB3erbBW*i0R9lei|<>D|epVC-eF6X|}-(DE&PUuMOwzFx;AA zb03w~7F9&wbhCkp+}tkKOZ9nCDcXUQ)Yky6*ZP(M$8feg{b#%A;@r9aM52@0;5 z+#I(R0ndD}Pvg5H22zuxw@1@vJV%nhmqw7j!Y5S30@8myW5vZ!d|$EECeJ&gyY6n- zO`wL)?cbWT(o)@I0Me9@65=|T$Wd~Ax{oAgbr-*6roDO(s0&{n^Y{o3XMN(ZeR;G# z*ql1;xZJBk2g(rg{a6iX(bjTQl0Qy*1;FT3awG%UfI>hu!zb6+^z}5e#hOBcBO@PF zm=h0B;bD5C(r(KO3zL#3OdOQdXQlC=0f0$?&uQQN>ER@i6S&FcSp4&H!y8LDKp7>9 z4#;BE9qUdH8KfU|1SkNxvOA;8D;9yDTyDaUUa|kJy-yTDDzBk3AhU@|IF@?k1Ynuq zS_H1WatE%DKm1-88A+R>exs74u|MblOXf)D9)lP??*()Oag20C6j4*^YQ24_t#@s? zew*Q65}(7*R;H$Dy}K<8Z4@EqZ+CS+?&}r6ffyKyy8#6$IcE|eqiQR84be}ee6C9L z+dp1L{8u0osh5k3>+JQ{4Kh`#T?Zi}BlFsFaDxXB_!DHo2`m5|G`6-*T`ALT`r!8T zkSXFnYqQ)~gZswg)#nixS4aMOFbmPP$v}XIXVwF@!#<-*tv*`tL{pF{AX2VQ-_zH( z7{{V7_&I+nG{cL_xHlq61UMql!7auAK^K2SMk;t-Y>!~1Bqik{`x$5f7Q*{Cya4d9 zAZ~xQbdigLqiTAlSks3P53l|wm@M0cXviTX1UYgLCj?L{dz;qeLJ}wB@Hb8qh(tac za)zlkaQHHY+LOMvQ9Wq+fD+NhhYkIbnH3KeI!9Rj{MCfnor>-ntcdD)NPa^8!s?=x z+y6A-0sQ=50@^MpI*VA2S` zFBh1PScM{;p)h#Uc32UxK8T{EMPHv$5R9(=xct&26ENYw=SqiW2o-|uAo1hDJdV^b zx<6r4eg}g56>&v*#%#V`3);?oGtq63o+t#n{)I8zv(nZ}l+qjTj;ZKVbpKNR043*P z8*bJ_qt2q;>ERh81TS(h?RnU(%&mv~nll;k8I#ewJ0m}8a|%Z-6O(<>=;IUr@KP+S zf}T*SX4)OY!Pr&EhiY7sdwE|Spv@1cH6DlU8Jgur6_G-)hRmWyXuQ`dT1O+cZP+{j z=t}eNg?q%l%aXzQO6{=qz98>=^1~q&cFglGVBJI$im%oVjjz0LB{OD(bx#`{5|#>g zj|xq2oYMb59lOr%nSl#e&R=DIEVYQzFZV);H{-=B#|Und;A!3GMQNGshGDK@?IsYu zrF--e@_;V#!i-W_2Q{Z;R>^IbcAio~zabdw2szoD_&TxU8rO_D$K@{8aK~MJx$FlM z8k7pTr6jDu5rl~OLUX%3T}?K$^5L+9q+0`gSAq=*S)u1*6W1orS}m?`q5T$EdP`7} zMZ>*%<6Cye_qnZGj{$wo9a1WL`qnRJm{1VWQ%z`4h#@7m-m>{iR?FQHH-xP_2#C16 z0Z*i0hI6nC2dVSOA4V#9zGdaAkzDk>S%U-B*>u=QW)No39ASvL-cNZI5F4uX8{?TU z|7o!!qRgy$>$)Gv{V zV^{Hio~p$8V1ARqoH{9)^U(jTu)QR1P0<9Ci?1)1Qz-NJPvG-BkLab&z^rsUu^oS4 z_?h%MTc(|~#5&FIHc^RgPVgc6)!?RYovdHEC}8lD)U|6{*4{;U_4ES#EC__~wagZI zeQWH^M$D~s=4?Nlewr>Uq*pznoN=^P)AH`T0>&5N#!jEg&oMu*0Ap?V{)_8l$#2Pw z2$+KtXuGa)MU5m5mV(XG#YS3C!tTl#5;eJm7l9vo<8=80V!3o4}=XM?rzW@z?JbRywFa7A%L=~@IH zuI)s9>Cr2=^wlaz$G9)N*0`F}1`@LV~ zKKsI-XW#K1qyj2FbVmfm<=#fI!rj$5)X*2=zP5Ln9m*^`LPL&MpMMoWt)U0;q4kX~ zp{FGKsp~?GT@AohS3e&2+<`zv2HKOZUq>8@Rq;$$CocG0YTj9Sk-=)0ON7y1XyyGr z?88d=X?B;lF>=qSe^f&&+=gxX-*JFVF(bzKB!GIx+SNyvVc;&8vtud{G>vLfK8@K? z>7{myd|?0eNP*H*8JlKKLO2i^Z=nNgtgoVnef}p%x-j7T{MdNkHTEa#EL``4OmzZK zGf$pK&S=RAH@lw>ENPoeiAc20Dg?WmH3mv~?|a#ZH)9Ju(H>RV>Wb)pn-DLIABxz7 z0oq#EREsLHbd|lu*731)tTaYLy})L@?3YRPHV8mN;P4GnnCPIB3k{7ydsh$DrlZ(< zg-2wdEnOF_$y9OqNJfS~m+d5chub&Z-9wHJ8eHtsga1412`AkH`U-DR<(ZNxrzk0F z)Au7eE1Ss|p)e$34r)t}P!1bEls|BWyWHBgEUFs?wL_gL|t zdJEs%&*OcC4+Vi>rpNTWv9&XoSusK;ZH&D7*&Z)oEjWi!qCUxuQO)iOv?B?l)*eTU zakVv{U)rAj&IrmAi{7lghj7xO^Iub&@a7Ruyaa7hgATT5*2%`0K5+*YV}pK?v9Et} zwiSLHK&k(+NER`eRa1v5%y^wH>%le;QQo*6+W~81Jsc?j?UR3H5WQt{>h)#L105S5 zAEMO9XNydhe$krtVcY&$*NK1*!VFx+pduG54kjj_e|Rrptb)unCJ?CA0VB4kP5SU9 z*GQfC8B9G3V)i6RLh;{;2NQMWdtH+Y@In3HBeqLuiG-H{x49CT9Y=_$2EB_` z3^3~MUSthfVzvB%FzoOEHb%I#hMJ#bNrH?I{1Q%TXM2)Xw3!-B(5gcB;J*ZFw}be)c2R?me1#T04S8-EWM>KQO-Nd&!40H)fHIhA#n);(-dIl4_-618?dq>i;D+t=+TJSJq&%< zRCtd)e34|DK0>V~ke?MT_>KCy*uJw7jK2JUH==+~AaWYqVSsrnC#!z`kDom;aM!JWgOa0;G#XbLxB6K>L$% zFx%s%n)KTy!~N9cicQ_v5Lq6azkvTF;%8+HZ9nQwlQ+yC`aE+Zf&?63W00oo$j@87>= + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Java-base/maven-plugin-tools/src/src/site/xdoc/download.xml.vm b/Java-base/maven-plugin-tools/src/src/site/xdoc/download.xml.vm new file mode 100644 index 000000000..259ba700e --- /dev/null +++ b/Java-base/maven-plugin-tools/src/src/site/xdoc/download.xml.vm @@ -0,0 +1,126 @@ + + + + + + + Download ${project.name} Source + + +
    + +

    ${project.name} ${project.version} is distributed in source format. Use a source archive if you intend to build + ${project.name} yourself. Otherwise, simply use the ready-made binary artifacts from central repository.

    + +

    You will be prompted for a mirror - if the file is not found on yours, please be patient, as it may take 24 + hours to reach all mirrors.

    + +

    In order to guard against corrupted downloads/installations, it is highly recommended to + verify the signature + of the release bundles against the public KEYS used by the Apache Maven + developers.

    + +

    ${project.name} is distributed under the Apache License, version 2.0.

    + +

    We strongly encourage our users to configure a Maven repository mirror closer to their location, please read How to Use Mirrors for Repositories.

    + + + + +

    + [if-any logo] + + logo + + [end] + The currently selected mirror is + [preferred]. + If you encounter a problem with this mirror, + please select another mirror. + If all mirrors are failing, there are + backup + mirrors + (at the end of the mirrors list) that should be available. +

    + +
    + Other mirrors: + + +
    + +

    + You may also consult the + complete list of + mirrors. +

    + + + + + +

    This is the current stable version of ${project.name}.

    + + + + + + + + + + + + + + + + + + +
    LinkChecksumSignature
    ${project.name} ${project.version} (Source zip)maven/plugin-tools/${project.artifactId}-${project.version}-source-release.zipmaven/plugin-tools/${project.artifactId}-${project.version}-source-release.zip.sha512maven/plugin-tools/${project.artifactId}-${project.version}-source-release.zip.asc
    +
    + + + +

    Older non-recommended releases can be found on our archive site.

    + +
    +
    + +
    + diff --git a/Java-base/maven-plugin-tools/src/src/site/xdoc/index.xml b/Java-base/maven-plugin-tools/src/src/site/xdoc/index.xml new file mode 100644 index 000000000..af0d2963d --- /dev/null +++ b/Java-base/maven-plugin-tools/src/src/site/xdoc/index.xml @@ -0,0 +1,132 @@ + + + + + + + + Introduction + Vincent Siveton + Hervé Boutemy + + + + +
    + +

    The Maven Plugin Tools contains the necessary tools to generate rebarbative content like descriptor, + help and documentation. In addition, it provides tools to write Maven Plugins in scripting languages + like Ant or Beanshell.

    + +

    + + + maven-plugin-plugin + plugin-tools-api + plugin-tools-javadoc + plugin-tools-java + plugin-annotations + plugin-tools-annotations + plugin-tools-beanshell + maven-script-beanshell + plugin-tools-ant + maven-script-ant + plugin-tools-model + plugin-tools-generators + maven-script + maven-plugin-api + qdox + asm + Doxia + Beanshell + Ant + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ModuleOverview
    maven-plugin-pluginCreate a Maven plugin descriptor for any mojos found in the source tree, generate reports, create help goal.
    maven-plugin-tools-generatorsGenerators (XML descriptor, help, documentation), used by maven-plugin-plugin to generate content from descriptor extracted from sources.
    maven-plugin-tools-apiExtractor API, used by maven-plugin-plugin to extract Mojo information.
      maven-plugin-tools-javaExtractor for plugins written in Java annotated with Mojo Javadoc Tags.
        maven-plugin-tools-javadocProvides doclets to support Mojo Javadoc Tags in the Javadoc Tool.
      maven-plugin-tools-annotationsExtractor for plugins written in Java with Java annotations.
        maven-plugin-annotationsProvides the Java annotations to use in Mojos.
    maven-scriptMaven Script Mojo Support lets developer write Maven plugins/goals with scripting languages instead of compiled Java.
      maven-plugin-tools-beanshellExtractor for plugins written in Beanshell.
      maven-script-beanshellMaven Beanshell Mojo Support, ie write Maven plugins with Beanshell scripts.
      maven-plugin-tools-antExtractor for plugins written in Ant.
      maven-script-antMaven Ant Mojo Support, ie write Maven plugins with Ant script.
      maven-plugin-tools-modelPlugin Metadata Model for script-based plugins.
    + + + + + +
    + + + +
    diff --git a/Java-base/maven-plugin-tools/src/src/site/xdoc/plugin-tools-deps.odg b/Java-base/maven-plugin-tools/src/src/site/xdoc/plugin-tools-deps.odg new file mode 100644 index 0000000000000000000000000000000000000000..9d6bf478ddca446b2d5cd6a9fef9734354e5ca1f GIT binary patch literal 26872 zcmeEtRZu1{v*m}o4DK+%;O_43?(m_5ySuv&?(XjH4uiY9yF1+Z@7Ar_eb~2s+*Bo% z>ZJN1=}yv}a}=b(z|jBzXaGPs?x$D|7~LQ>008(;{U-ugn_HVWx!ai-*x6Z`8yPs6 z+uG2(*cj8<8aSFe(%IUX*cjUyIa{09IMJCp7}%Ma8#yZc9}17Om}&2L0f7HhtbYns z%$%(aZ4At<9O<3@r%PvNV;Zg?CyoG%1N(0Zf~16q5&!`5uM22`2L0Fa>o*Gn0K9FI zB7!PznU`Irak!GnWG8tfxz3<4q)L{3q><$-s*9EB=~w1mv@XAGkK0|Xp03`kOed$* zHa0eM-W_|6uB%qlA2*{{b-p#$@n<{cnHx4+cqitD4AE5;jhUK+KqbtgXY8+j08r9o z{z#Igp@qe2mI@FBg^qY$UGsi_aF&_lFc{=33-VoqrZU{}7*P3z$Apvt$hdHdK~qo6 zQepM;3;s7DeG8~rdWZqmhl;A|JYd78`WFaC4DO+O%rC}U4YxM*-ZrNi3siZCngCD%cV`akuUu7hjz7ckVHSY# z@^X*>k?mageU6zd@O`)3(HnA#!BmwR^$At=8K?|9co?o>b+gSsA9{_Zjemvc#N3CRq65dARzqWOk~kOsslO*zsYi@Q4>uL z9)=wDw&ZwrBM}`~6vuy4C228m)w237ViOQ@vo`qLOYvl%VdF&8ZejD?$EeUsc)5F; zOkG_YnbCB0VW+juFe886&23W^&L7re!VR6Q&;Vu78*Y{I4q_jUQO_0bpyc(OR%q+P z#&0?+`UZ{m(G>wQ-}AtuNcmmaXmZHcAqf#?Sn@$IDF=4FHnPi*s~MKrA7qNSglJh3S0rv&2lw z*jqTJulw@SiD6EBjzyYrcel>tH)UHlm&aMa=H=Kh26o2w;SNTP&&gRD{NsbRl}mba zC=?XiaSz1-^`>w_gvNx`W<%>cw$g@<-gy>}G&4r%1SNG44VW<&NCTAH>x~oz0F4K9 z0K0W4C`4SlqpM4Cfmz@jDEj4BvVB74hYP+d=eiwkrapM855vR*Do2fzti64b*1f{c z45kZ^oXZrHQB3@rzlMYgg*kW%xSE9t093G7i<;6QPRixNk+5SanPAKqRkpWBoiNr!q_B9i1MQWF;gyO*_`XBqKom z=W196ZXpd{w}f88DDLoV7m&G?MsNK10)z!c5)q`5FHLF{hYoEj7UVz*iNZn16#*hH z28P=9@j@4+fYgCoP}AKHzMl0%M-F_viN1zhuF;#Ed?MKZS23gRHzEPy4wZ;(zh8_{ zAbNEFJP(jQPz`Sy=nF+KgIB5qH>6}i9Y1~iOLC86Y91XsgU_TzQ(IVTzJXwWhl?I9 zvdD?62}7C+cfGd5u1&|MXWO7flj3Zb*hcDmA~;1GL~EcC5+B;8rNLg`va02wOgHb@ zZFod1OV0Ehwj6O^Buk;N4<7!=t(~Efi4wr2kgb(4WzaiJfZuvP#c!sWa`}`A6N-+I8F^XRKC;fN zPJL)^X#;@-g~k-!(B`~F@EX97x0xBVPnBB5kl_zKevC*#2xcy*oN1_}2!qroZ6c$x zGNfXr&RRE4v>ibq+fg;?69Z)gh~?i6g5ekE=Z+kBm&OFbC(#XBC4pUH(w5VF7;*MM zH;jirv>4J9XiOehrSP>0n%dg`w7#HrvZ}ziSqf)GRWvP(sf1u6&{u=8(fz zgKRFt^DCVY20f9iKjx_tQ0$2vGjMRMY;jsyTVrP-U102h)aqZ3*G_9NJ?_5l4Jr9~ z3oY5?;OU)c)AG(-<|n)1D~=MhIQrQH&T{^poa{5~UeK_(Hg~ z&J6rUm*PPy)~a&B%CluZN8o{T=aM-_h6c}V#f8F>2YH8D;S|_p;10!v8Yu@0z*jhbI#4TeH1R1t+E#8d5 zUq8)iered=D61ugFr8TR+b4H-^L1JHla8(8y|r|9I=nw+i5>3y}q4HQaXY-P?vda zhQ>)YlgP4Y<^0bgU zlgMtxpdU8Hq*5(mS^50?wZ=DIhScY~=e@v}vE}Ki<9f+L6|affQ?t~w)Nfe#>B5G) zewN<(&gv+XvX^gGe5oYASBxf&It8?*0VI|bTP~YVJh@k8DAm4n51h&E0lTGiI1gPo zE;S!SJ@#p&=M(7_wsZ+RxUgchcsUq^AZ)9!xKyFfkMCX$iOB+IXz#QrSg8ygeTU<0 zAG^17*qG_nCkhThPFe`T+2$?LkmBG?#YiJMy-u7TOOu2u(IcrBT_{=P0aZb>#rejQ zR0BKxwQ{G^ufI#R`Q1UM`*kxDw)-X@k@&5iuO3h2Kp?J+e@tdIGj!88CF^2P+uw z=lzwpRsvSDyog>K#uNFYRYROP_I{l@liaY*uC@r-k~OnXv|G$kO%j^v_*A$X~4U*41Ri`9|%Gobcyb7SMdql^FZRNi)@^>+GeG;{z z<0vj>r$MN_-c_)FJH!nNtXK{fm=@rxqmz`{zE~&C(dca1z>hv?(9D?Bt5G+WJfcb7 zkh41Z%f3P9$<|!k#1ooO`B&Xa_fv|NS|WYZW`fkPuW!uIVgBk?J%Y2#@|Q-kVb+%x zouGmYA39;zjc(31tu&SYZWd3*s{t(F{rAe#cBeaPGrHJ{%{EAFXxtE&(en=hx_cho zak7dr6$ekdJ7WiPI<4w@mhU!8VI#C!tR9{3&=jzvYcTqQ8Dri((*wo3Vy?NUnM4RL?U&bLc zj7TL{y#o=sakVvz%t6&Q(_DK{wL7_Ahg-1HK^+z`po8DNFk(7gPHj8EOhJ8+#JD-( zz_R=sfZw*TX^9QgQYda!ad?^D>sKxV>uPtD)4eb;!5B#RC-|-}A2{O}fd(}S2>c+3 z=nzc9HXR)uCY!h+^_nRlH2~}{gQvR4ZP$12nW#GMjcor}2dYbaA6^ayQEf_5F-d3e zA8*ZcrYi`%+MDE%-u@I$xm6e$U7iBTjaG8bkFttrzi%NqOF~I0gcdD8?`F{4NM6&H z`)>h!(3R|o0uT+cJ)dAI<^jViI)QlvFzN3@4(fJ(kF6@2NMPm`b+8*;e6a{XV7o`H`JX416K~u22?oAfa(*X zH3k2|fSU(*H-TXBhIM^mGODa~2p%nvTC!La(Vvga#3yy!HoC=UE;@?(o`xd~oaBmT zT=~Uj@%=ak3T7=_ zc&0hltUR6^c!<82jt;cJ)b)Di0#jpRMP=zydk3W%ik2;jCfK%;1q2un(Pu)8%K2$2 zh{3)9eVDm@vcICJ1lX8|P6ooFKi^K@cG4haeWUsn!&H$EZSsX0mW~yv zrwL0w;!v0~`ER;(MoS)e>>F?N%wpJgldHriq-0ME99CKvw`c9_Ga6G*~+QiP4>h zq3|?u=s@wYbnsxVs%lrLa3ru&P@4klzea~glD@a*v$KC}F}%i?fm>zS9W(&!Fq`#P z@%FR4)>nRqwBMcz?F~CDSff{Wt6;YO3XoP~;oXb%Kz}K-VDjRYcvm3zvrG*UPJvGX zHOKc?PO~yM_zCggk7Jybt`a7mFB)t%gTY|s?5v6mp4&1xq8x}IrKt_O4mMGC_IK>~ zMd`6lk0l87ovvja9~J_a#B0a@BP+SQ_vwY<7dsu;He}2!KtrDpRQ~;C&a0aE5gt-r z&Lt%ReYk%XO_MT-5%iEY-|S^k0!ermEA-r*1==gc?k&-BH+Uo-GEJ&z?>J{WGnE6x zGSTED1d*pIA0Il9w7?<>=Ubl&3k5&j5G$Q0h8RDr7(%@Q<`4MMG5_~2Qjcla<8I9@ z2h_PydnsRGd7<}nM+2d5`=@(Vx@1ZvTTC&`iT-N`UU-wSq*3>M6O1hCqt@(SD;IGk zz)G{TE0pPPNX(SxBegx6iN-gO8B(FG9{EiO#!PrJ7nygA2CR63k?(vTJ5!7Rn8TC?Nr_D77u%5f=FFz zr`PK>t1JT(W|MuP_NI9tH$u-{r`O$qwp_`5-8&tEGt?gY|3bWiq{_y2lbf;b6h0qm7=YtYPW{hy(ELRP8pppidcrKO!Q%LOgUr z{<1*f?47cd+qC(5RBw@GmbqAfL$5L6M48#PA8Gpi+fe9+56IWO(E2Xm>={l4v zPBoLbJ{zH_cRrsU==YsI9yvI}cYM5^H+$$>p5i1r|LGNxwB`lhu-z?PcSRXH7&W2- zEInkG`Rh$@WDO3g)J!8*>qJLSBkI{{jTe;%|6=F-Z5ObpVB^;5E;X{s^KMtlaMCSF zaLFG}YB8sge8=6zmxCI7W+zj*Y!D6Q@lhVt|JMV@=LdEkQ;pk>uxV%Gj}F!i9>3{?Te#O;^}@N4KQ zAjMi+R%1;EoM`u>9~2D~FonhiW5|Y8CLWp4@3*8dPhOLfM6pIoh5<#R2jq-Mb_pjU zxzpsbkz#2jN4wk4B!f*kx5DmGKym&ej6$=5^$21QN;{No181cg|A_gU3WrLHj@s5t1A9;ics1p$ z(INxoO1e_FrpT7C#bDld}`ELlObEaKsMs9 zw@S$uItnA)r!Fj_#!bu!6yH2X5Hv{VhX-(ieYqN9f=#fn{MOo9eNy%H3V?B5-1gd9 zW=2QGh9rs}1w*b5RcnV(+6t`IiDQ{{6^69wkR54i%%m#SVqV%Z+?Z&anZd=C1DVY; z1iP*GsC&PF40=WRwk0hZQ?Q%EBY<1j`?tE*qGK_hPYG=-aQ{ zQ-1-IUy=%xg;rm7zq)=-IPf+3Q$7u8FN?`#%3J+irlvWEpY;R2e89$mNLzLWf$=qA z)I2|kFI~|-M8_;kX)A=jdgaG${*>UUYdbjhT)sd28dENM5F_it$L2zZZg<_g-OAey zp7z9Bcrxp-FgAg6^MNql}zSUktg{i$qPi7{*# zuAIrdg8y+B*rSNHw#~bS4l~nSz9@v+2o^zKwit;rKaV?FG*@u!V|o8XZvQ775&l#< z?lPm4cy$A@hV}loX`!Qsx0$Jh_kN8CSgN)8G?oxpTUWhc$rckl`Sf#ycTLC6NN>o% zx#Uvh;KND(r6+h~2ej#UoiPMumq1W}KRjP*O#%U`yASnK_eVx_FrAH^S*l^}!QLO= zn~RyUc{OT~O-0ibprXKbnd436%?s(rL-00ayOTiRPYyOwWIxQN>bf-jQCi9LU6C^t^P@=b5a@>8$H?K6^H)Y${&`$3&i@iI@!KzA>W@AAk@^67I zngW616bc7XE5h-^06dy?(lf!_j+4vt&@TbjjKhylBh%lkC+DD@Q0XSHHwf@xo2Xd5 z(eL@wW!rCvS}_98APguh#aRI1e!G|JgI7uUnN!4qj+J>p9|wMYN7hC+9=4 zGFnM(=G+B2RM4uU4Y_!I(_aL(C1$L|CAHAbf`~tyLxxlZx$SgSG&BN0XGZ8~Hhbr7 zyvf=z7mk1|R1NzbbA#EVZxG(Xd@(57x|R8CFJ#d^_`Wy8jx{Rjcoq+8y* z9hdkPU{PqNzu6``Lkc^;9uV$7vmPmhU+%!3IF(5StA?B&H?EEE_7AJMi4zPL#xTDY z2)^`L8VQ^Z4Dcz}z-V}75j5NWIQmwqfDu!^i-QXC3<{b_C~dwj2vwaJydLh75)!HU8+~kAt60b%-&b;Q79Ybh^Rz z03p>YU2vFrCBO>PqG1_PoVFre8ARP1L+`Z%BaXMpK6dUuVzl>13{Q?i?v2=1BI2WfN zJZ^$xhas45U)&;ea>HVuB>zAk`V*PU#z#5&_07&<5?Mg{<5Xt+&XpK|fi4nI{Zx!K3jvLX+Wdz#EKf zb`YHL9?UITn*c%2c9Ar5^0FoiizqfN>&L?UvfbN^3hudBjt1D|rUf58*!ba7SU@(W zR0?SppXmm~&>E}va0r!P3Q8OrOfV3GR4`EkP8#bJ)j0zUwvc$B8m6eDPYF>F*-P+& zd*p{rEH!dtSv>^b03H2kYg&YxU?#$CKw^ktJ}4G*rxLG=%iF9cshv?}Cu_)S1 zkjc{c$*ii3yj*aMGATNDDqP_i)rJytlQlt9xubvT$T4V|n*$FkUECQ-kj3X)QICu0 zu)l^9jI`^u0A*K}yfu}db9>h6CBocZw$J$`#(6Or{^Y+oCOsz1B*9J~cxG#>uY0oS^=3xK;S|UG z9+j#Fxp{WgF#?d}|F&53_0*%|aZUJj^K9jU3-A_FZGXxDu7D}lX*s2cU9d$e)Ew?f zAHr^<9JN{6&kY46D=2dL#R4#*2%cx3~e3HqoFg0?0ORO@hr=n z7O=m>CZOKZOJYP!pjvFl!p4fG^;z}Y%cnmGv8YXfBkdSV%%Lkg`Z zyRfJnto^ILg#*)y?e=%y!CwXsLOvWWQAX*fTBWi56hu*vRyBo1-d;1kP7hj^S4Fz+ zrj}lvbF`MGm8B0~3bn?DZfEWvH|NtO7b2X^R!3GI52;EFs^F-&bqaK**Ox9YK0bz5 zkGrkVAkR^gp=4Vi(j!vUh7Q3=M%m#K8^$$w{ywu?KJNz?=-`oyH*8+@`Q+y&4Hh@3gSk*eu>CU|q zRa63vXDpfjbyMHd<7s(nV|Ri!Q9lz)WM8g8VL4g=$P7-yPyc$Dr=QNr$js?@#(Z`Q zoygeEY?0MH$vH_ndmTK}ayn?*IJ&eD#phzRc5GEG`~CQ|XUJA32H8)NEf70ka7xH& z-M~pQP?N-*L3|$V)~dud*6%ZjpZw}!cA~=Bq(+WMlAsJP&0MLBY6(7m>Ejzs{JVv8 z+$E);W?k4^DX;obJjHj6D!n29~B&Z*vT_4mL;Xi+T$OW7#83_em<0DQOHUznyT(tNaC&F%RqF;sh1UF1z;^A0LALzf} z+L3U~m|iTC=YaSE`P<y($x+U9F)gs5)d+gq z8TFWa{(@yFL`ryM8d}%tRxK}PXP@-E7Q>! zP~x()w+W1dlTi8%873X9Emq`!{)%v*N|G;P zvhDd)%|iBPmmh)NGbdwYEb=A%w{ftcfeqwOhY+BiN}oIi1leruQ{IzD{_~LV<6;$; z8%2936YD3Ri`mA4@8urfQ$v; zkY*-(1@O+h)rsk?CJUXhD`iBwg9O3_sbLdKoakA4jOXe$Z4Q_Ssl^dD6F`xhYbE{q z&zBsnmxn{;sI*x>`HX4`5rakon&`;BedOWi*jO%6IgN1ddIX9Vanr94+KAk#O#y6@ zUy_Vhf5F*H1Zb407om{HQZB@UCweL0sGau z^GiYoDLdbKqFlJRa+XqYig)B$eROR8(}|zC3n+GAw9xq$q``|)JVUcLbmf(>0e>}4 zl(;6_bm4`~qYq^t6$8Y=wpR);8lp%1djx4WHMbj~`Z3@_w|Zl;^6j)-HT<#};Kp0y z%RsIixOmhoTc}Kqu8OVbEP=L|je8Hcm%kI(-oPYFF(>{^9|y!D(W_Oc)xVa{A3CjA zMFbShle#eqq0ysd<6uhM0uo`whg9;s9`}LkUhz=3){S8IHwV&)p@B8(m=nQQ;p_o| z%T>=l1_&|Y9>loMHe#k*C=QlI5r7)Kfx;7w`WfpVfN{xc3re_75hc2D?O)uy|3YDerf*d6Jc0MGG^FA0wi{W-Xw|G z%)krVBiP*y{6n!J?v{SxXv%%KGav12wN32u?IBdppr)sRDQZH+c?*B7=x<0!NC$51 z^1sJ(V>6@JC^Z{z56rG+wc|>)6C;ho`Rc>R-tvJ@3E-tk4v7fO9caK+N+}(S`)cJ2 zd72a}I$O57AuZ*YD+9PP8`=$hbDVT7?h1DENY{&lmn`ak=nme~0~d8Cjtq_Gpnh%F zt3{DYPkm$0D+deDXlF=sq4A+(xL}d%lQIhrFbikKCTlqORK(!V_kE0G*w~3kj?bS zCvSIJS@q%&X=AS8dQtc)A0+12k$MHMw@(KIAK~l{(dBigEX&Qp9q43U8X$~AATI2O zaTdq7UH7E7yW1RZ0Xa0DFkGl+)@Q-z;l}n+!_aC=52m*64dej#M47;JA~nm79hCVn z2wJ$YwG9w3e{egGMi1&s8gX}s`gR8~Dn^bdlOAA}##GDkp<5VD6qlwXWxLADyZaUY z@U*rQ&R(XSQ(GN3kLq`5j3-z!PnM{RVpGIma5y!oa7{YEl(eAcW$k{k0I`w)4mqrn zhqbPQ%X^P#+9WVWdQiWKU*`@=Cyxn*;Lb${HjaN1LLQUl-l8)4-VX+@K%*83TP29M z&vCRj#O$o8-8z!R=M8x>F}Bg^em@wFT6_8<$QQ{I5V}q_;zDC{eh`Jk1?FE%-<5S0 z4Jl;cI&)2`f-H~535SZv$sqe#6)B<#00ZmBk8xNt%Qekpu_wyLz?2xW=9oHx?bRgj zdD|SdyC!*Iv;KE(0l|x)g}exWz??qlbdTqCE_V1UY`?CSnq%CM7ARR4a!AlmF!0sd zS#R$yk0bA$>&S64blMYIWNy6tmjjb#<+0m3nm+y}XvXQI{A62Xd6?L=FUBq+>QH7@I z#q@9d!IqN_QdRS~!3(y2tkBX`IZw$Ar+5Quy!J*}g%l_jc?39XS#e7Q(rZAK8N5&% z5vti~4oZ_2^CMP4Ml~LQM-R9YKUV1Gbu{jx11G{~koQKOSf3UndF5$$3knXaG)QFH z#34Q+4hwm1n%Qn?AdSL`C`_mO*G1YXikqF24!;`r6pfdMRyIsXL%EcZM5`K45S$FJZtfBM0=PaRt6E#SzO0k}+?-TQSVDd^c>X_oH0A4)syH`V| zG=_ts=#T*1r*HpG{Mu=GhNz@2r^EN@U|er+FnHoE-hpHpUkWQrYDJ2JXob_QZAD2n z_2n!%ATv|(C9k)9UEda6X|(DrQ7QvGGYd?3<(poZs4`LG)9HmGw1BX@mj5|o3O5$)a^l;#XO)ofXqVF{)sD$Qx_ z%I-I+_HH;_S73a{^|#jVkNE7FwGUc#qRs}c931vpSy${J3P$rUZAKdx@0DmsbkOEW6Ji& zR#~v+1V#>XLmD<0D+}{pU`##Vs;JKs>wWp|EUbQ$7Co@rs%3pW0ry|X6FfA8kY1RK zfmw<=4-P{$)X0lmX3SD|Jpae%c1eb4f3@yr?fPmg-DWtv^C|^x2x^}nIzsU-LjQD~$`o~QD5W2x8B>AL zwmj`Wzi{7bcVp8{!uSOey@S_EwA|0SfpdY&clqD~!?MZBAlAF3Jrv1Z5pyLeMoqp4 zv(l~g0MTX^$;|M$mL>0V34_S>X%I?{jGwLg@~0B8Il@;=&^rTiV*V~Hj8*UH_cx`Y z&G`Gpy)OGv43gJ{DQ&#%bCWGJkhJxxPZ0EGEX%9bm!kP5jTsr?Ip}QY<*urtIW2ON zmoD1gNnEIfU+X?3L~FX}?w6pDRYgs=b2pvkxg}j79QeC`&iBVL|JQ9SCI*Jv*LDGl zLF(US8ogwc&I@O9B{f^ciJgPR2lUr&ynl^v?`Spid($VC?c_P=}(3^kljt@ZUgT}L-bY#k$0G=Y4$-B`c7Vx%IkIXyVFcUBb~io)d5)^(AeLB1Y|)n21Lx?!Ra?Ad{xcZ+P&$d zI48HSSy6a7>l=wUGPvH8ma2;7P34Og1Gi)*mpkA5{l8_*u#aayoxApy^ekJ6qFsZN;T$l z1axsU6D+d-9Ewsg(f^13&|{qax|O2QLICNahD=tPdpc?uH;8-!+=Bw~Og5j0s%pmM z(-3A(&(m7jKVYjwKm?z)!>FMnOn(FZjQ?^-@)-Zyk}cfh9be5rDoo;Jaf*6!kAp$6 zUQLUbM&6Fk!|uE3bXLhJRCR*gj4=LRhyX2cf>5}^^0h&5lP0DkqF$q2PCI`USrg5V zKqS7;NZ^Nw?w_8oM^`t!A;QDW=9T1fIe(vFSid!u2m`E`)n}1fkP-?R1>?xg-5ZTD z9MdR(9bUJcE$1Bn3_ik=#oOS$u#@t10GzSZx6$qitRI)LsA?{!r-U5V#fCN8(bFaU zcTLV`M$1+^G`E*vT<+n`3HRx&q<&n^<9D{A<+7cRimVzU(c+F-482wg7_A7AB}dG^ zpsu>Qrl#lXP2EEEV4yVg$d=7GXT{fUJ?`!5-#c|;1ILYRaVO3VmJE5Ke_8mX3=h#c zqE6}W^LJm%ch2|ww$G>Kb+2`37GGm4mMobexcPKtlO-oVlwMDsw=C;|xWTRGGe)Og z&F0kUB)^NBlzvB&+Y1xV$;*3-EDxTzF1ZHsV23OFne#x*GGYSUC_=5Q@d+>jNSiD%8Lx-Ob*P6v8i{wXW{z88@AI zh9r`QcpoLGoMQ4xel}2mV1CjuKvPm?-^4tXGYOk`8#-cuImWD_n3T>2_ z$Sil9>sT@A*AF`vrE*G8dV4vxpQNfrTy~BT7#y|Rw%~Ztbf)ZtxMl^W&2*p-9KS6+ z4ux|~ftGFu;Qs1VkC&I1En9CET{gxh%o*P)FyivD)q0z6@M;_R<-eYq4xcT7fxWAz?e(Bg{zUyuU{WEG)si`J0b<){TcN0mBas3 zxNwwBc_t3GxW=kP-iq8VP@!sm)Tx`S(fB|ZTjl0OE4qXNXDh^@wyn)GULvSC+(VbQ zbIfKBqA&g!j7T|TccM(GsJN_7h^=N8j<3hn@vEA9B}K1CZPcnkjT>ehPTlsl2t{n{ z6|WjvI~<)4`AW`a2%pZBsX2l%M$3b>tt+IyW_Du_Gle6Cy~~3(c=k)e>GI9DsFJ`n zcYW^$Y-S2t=oHUF2tW72DOsy2M441N9#T5(cvb@)STzQ4T;V9iT$I8u|51F0F4$17 zLYCs%##>H2c0&Y%1li?5R~0%|TTFkbU6y$1LcI{ARF*t(SX?51)A^h2o1P>)0H%=s zVnD6Ieu`-i=21VQ*5SULo{47pK7go0NDtU5emIfHd{C>{CZm@`RX^<3X+@di>h_7z zF|Q^8+lhsDg83`_H!V)%vuIvwxZ@Q;vI+{W^w-u8O~@;Kk@%VNUfC@kG>@Ctk(`Z8 zAep3v#}nSK!z1UiBAJbC{&n0(HIb~TPe5ZotH+XWQhskgsKpoMKQ#AZVL?}v+dnD_BbK#+ z$M6(l78i^x{7SYIlicp!ruxxYb*-Vr_j@jf-mJ@`kPTAp-xs9a;+H;_Di>m&c zsb+<;DCH7M?DDczbDjPSQj3Wu+%DEa^fHj2L^?ViMpO+#K*w$0IT5{|pOMKQ1~lE> z?d$@VE+?g^RG@cT!m5rO>4Si13sEvrs)+xsfM2G_{% z#L~H-`qp$W)t(e$heHmH`qgVLb<-1GHuopX%##Eed$f5IBy0UGiP_&F_7jv2O9a*| zc19}+v2L5r)%7(%Xas)=*I7{`pF>`hu;ZFX_&i^9{gl^nnls zf@aUONPaRnX_B}GmKQrG88N^&F6&hw0;|WpR%d5X!ycRtBoZfv9GF!7uLNt?ix$q> z>JOeYBw^J>iZn`HgEPzAq=w7BN`V+>6}a4Zvct-Us|mb+h;liBb@(_qY#8OKHJY2v zxzn08YR#xc*`@#TvBC^^q855R`19(KOuUBlY_kI-HEF%iFl? zPhUr>foP<6*S$8CW;TuuRXR182o)9Do~*TTXqvo5(WE^Mj0B@w;^J}KI;Fx9T}n8Y z7IYcvL!H;7$*OhN{aVfz1~=8g?&mCXZ%(iVZ{NC^S=gB^1?Yf*+)Ft@|IE~@#d+miJ5t~w)JTC^3T1LQlZbod)Uu}!|IO$8L(tX>9*QM&&tN0i(Qu*Y@5WE*M=4) z23Mu-qUv$uIYf8i?j6o0NQ%v88lpL`t>0BElI%HFj676OV}*{X{N_(P-EO(3yRgWz z>A4g^w7}%K(62S1vKvFI_YL=6X2W4;aNLNmv{O%BA`SLl^HI@zgTgUnAQ)z68PI!0 z#0OLWsQ3uVATmxY|6ln3c0s;;J#&YZ$_LBl|3m4P6qOUH7Sa#+Up#SWXz2eYp8sd$ zf69Lo&rO^R=-jNWq7(aKG8oWApFd#_rk1d9|G;1{C}FBn%PvYKNNtJ^x+t~ildQ|k z_0%BzBt9(_G7R*->R6seiYReh7pdvjC{u;8%k-0=C~i|3LGjx53BtWm>7stvB}&WH zY3N2D?^A2#x>GVaZB-4}qA0hdrd4&Org4rslPi@JI%dI-8cuQ~S-eL1aH=kV&XOy6 zNgQ6o`!RKohtPpKzM6FIF%OSsD#1d`p%G*hMaD*|gF{t&FOl_Q>3Ye=Y`h-Fak4Xc z=?#Z#bQltTR`QRrnOBb4`uOiMBmJNA*2lchld|%bzt)RPK;Pxh3U)i)&y~E6&|a&T zt3zs(GPeRV7+=24@6XNYjTmrwK+Da?`<+#W>?pw`0_YRbszy8FhaBrexCoNAegt#}#)thN7zt5oaGj}=sl2G=e3)q4MYvYjk^%52m zPT6PbJo7^@B;I62Xr4y@nXyW8# zZe!~BAH&$x(seB7!0O%x&e}g2y1G>AUvdtaZ}uTADA&PCBxT6?l`h0FkfL4IZ2PTU z-WH4mnz)*FnTbneACG0EbP_teAJ2(n(lZni^tnRZDpBYNTp%wGG<5WjDnzgc^IP_8 z{5f54)L;B1cOd*X0*z@nbOw$OfBx+4N%tqLeG=eomI{)uQ1wVf5^(FH_4s*WA=TVn zFG8TVfqoPPv8Y5Dvp?~2_9v*}4~3)>WmgA2PEec!MXyp{$&c=w`|PEkZfBEnqMETj z{5i;XWL#;rdKy%nG|)+NZ|^QFkGxJ)>P*ci$oxC$)(=@#fTs^-gFkhi6?zqK8XXVC z-VK`9I)yr=)}IFFkWK5+_DkOp1c5$#B$yc!;lmxEC6(Q73_kbS{dw-&(~P|7SOWi5 z+E>6uwRL?D-62vU(kVzdASnn+cSuOr&^0ttBHb-RiL`_W(xsGyLw8AsbfeU~2kztN zz4!4x-}8RonjbT>&))05{%h@X)|`FLVQ+j|E@|cQuck$Qvxi)4!(p1s`?i+UtNHJr zJ9OjwYodNTwK&? z%@ss{Ax0E;-j893{*{hE=)iiT|-`n>4Ent7up(?A+f zTr{!TZ4&ezJ;DbV1q3kRJpiB)dAD4*Lz1uk&6|C6tTLNq_l+NGB4w+>}* zI*L&hzaPDaa^P`8+E%lC2Me)luQ!hK`knf@BGpOfkFY0+* z&=P9|lC$Je85Sh%X!^9t9lD;qdnJdfh(+P#XRb`Yai13B^>FN}xS-z~$%WQbwPyYmCffxVLcP7y@kx z302+I8(B>8&V64}kNHs5wWy6{w}6@1b(R(j`}`I6N7N5%`o3HeauKa`4g@6Ubd4D$ zfxD~uqPj%iN6Cn6tPS$aD_A_^?;49DbzW^FjLLYdZ+l}wbPi>r8EgLNQ~QbD3zKTT z$e>mf7SsIdgi*3AuE;6TA)UCFpb|;qAcaq#R#!<}qW1zRLfIlJzQ#6nlzx=Z{j_u2 zpJ*mvS59`*rdT)<3#sp@1${5R$$YR9%)gwU=WPj1_b^j@Fvyg708g`%ROCmyVVtI6 z9{d5T%qyK2W8Ze|F2if=syoPIi_wOVmp$cst{|uKok8J^f#(E|+0_WM<;|BLKCw$zwP-?a41n%wnTDV}YbA_3!DDBHtKX5nr>082nmH_&OG59#@as-;z zy7Uc#yKltBsVR#e+#iiX$xwrf6T*)=PYwii)s!eCK^`_^o2wNRs#@f(9!;?GN8KjI z1jWbC@pbIQ894SULNi&kSF{r_GS=_OnePsxOj~~xJ8s(;WoDKsP&eDn2{R~l^dc?6 z*RDt{^qOUg3QiZ5ZSmqKO>)Y&dFMP!{JFG5>uHX8eS?=Hsqyn1Y3~t-C%1+6KVIAl zTX8s~aIR%?xxY?hC zes@Q&0Gr~TnFpR_uiI%?NhuAmbOqe2O4ncTYB0KxGq~o&mj$6mk4|qNsP5&bw?p+^?qB32;B?^O3wYOL2J$UR5(;sH`xO7$tVHsDO8A@lZR@ zdm3UVMu@Vm&7q}ijNwo@pxj82Vi~yOXDAZri+y1@sD&Xew$0mNzP@Mq1U8Mw zdUgBB^*ELZtQ_I@zh^XWvgnZvr~cpw)riRPsSA^q9(ua+PD?)9YE*Vff7zOZ-tw3b zHzNZa{sHU>4^mud7}SM|dM&4Er)@DVaXH^#MN@A7X8piC3C_7UD5UE(q1 zlX>nl{dNPe99M<^l{ApF4XAF-v8Atp^m=o zq@Wz5V@@!ePXdI&Dn{n9D0wm3+?GHE!#)NzTJLjXK`c?+#t@zGfY0n*R%j)`7)V+Y zrQDMcqyC*1{z~H+hK#W;>;-Zh2lF}kghnNT*`C}r=S#zd(Pp^bMJ}sAJULFU;-g9b zgW+w|D65+_aSC^I#%#zu0;#Y;-?;Na`(zk8^GkAsLME}tZ`x^pHkrp)joG(U_IT$h zmtJiokEO=nY51O9AM3+%@~eOjqv}P;?gp2$sC&W7d2eG~(u3;_$kOt5V+h1bbY-Mn z4u9AtjuHE?>kXq=ciJcLI=)>{;ghx(CEj~Wl|eG5yPf)jAXI72OMI<>{1XjzilgJ* ze3si3&63TDjO+}tZ8y$fIK4hfh8&`L;RkZQhqS#bDe2x!DwDKr2Ga1sk5%8pnpa7- z@OfapK5v32N|#IOB&_!u11v-bIG3pF4??hnQJ%pf5I#xSVpsJN3A~STrF-ST%}Qq z)l3_eg?j>1=V5xCjAEW05s|%jHAR$6%f|b2aaN{1)E4?szS34nO=7!%dH0iso{P^^twNGIHG5{+WSUQ>w`qI7o7=7Gp|i0=XyANj zMnD?bW7nDp=6S>7h}O|Yp*^N^yMr+Zr5khaVwrIUd!lFo=6Qv%K6D^@h3@gA6CM_& z`3nwAiwA5WUXVz_UKOOMPlh_3`-3fL3TTHgUt?KX>r5_9NSvLFywXlWHDaSFVpx5_J1mVT2IDda&#O#NLzs~D z=!G+hlkMJ{LWH>nN{8V3KAUofYUNy^u!iGXFURJ(aX4R^c)Z=w!NXqUJR-(QJ zYlekG=bE*M`PaZql4?vT|n4k9>+dK{;-VSzov01f{aXC`__-b(VkVpfQ-pcs@Pn zZ>N{pTgzIwM>3&@9*sJ~`E=?%>JeF!XWD5vL%uL-``FW?hlPAnZOn&2x%2~C`1!$bJIhdoKqws0O2IU+H@)sjcqrI~=xj&x8+(``W0JGw^!kXq z(p`>D>hI^?*}A?g)f#tr^=~^`k5b@m)XrAl=G~~wV5^mmBk>Q%GU9H)a#at7_07f) zSl2WJ=}{8HDvf#h3tq>d@ArHsxR2aE%5EJbpU)syh@R48Db2n_c0XY;a|f_w2wHPsH-$#yA;`bG0wvsT0rr8t}v$YfkI^u7+4%-qsK1uN;-{T5d>Vie!4-){Ig@%5_4Q z*3q-7Ld_|}qWXY3w2k8AfiI86cYE}$!_b`^B)b9vzRYM_6Jb8Ps6v77-)aP2I=*xd zVw;u^h;*t!n(W6zK6cNGC zFAU7n4cwypTv}YxG*2n;i7&~X3F;k*R1q>ODDM;427Kw;=#O#ZPD4^04(hb6im>*w z++7^WU{b9=x4KhzZa4FOd_qG=qY`WQvh}$S?P4Hh!AN&~nR;mjaS<8&g%Z&jHDi_{ z!Q@GZMkilv?sBML6$)xOOS(tiiWd0dNI11}Ql{2}O1(JcBJ)@(*G~Q{qc6h{d#{t7 ztKB;}>fL*0yd!CmqEWR);dOL7Wqzr1E@ZD4Er|Ps+al2+@j+>wmV>73wJu%*MFj3M z_?D^<14iCvSiTb2ulJeSHj|g+itV){CRNDG6M1)Y#8!62jJhqdU`&B_4i&1 zW$sVD+GFPh(FDt)V>;5JD>{eg`ODP^jH`2J1&J6`6yVhONcZQt^UpaZ`?CFZbWlK` ztG|1|xwEpRiL(pT%!!km>(6rkUxlkrFqeQN_v7Es6A7XLFlaCVFwm2nu+Jb63P@RA zT>>bAKz_grTD+mk%K|mlF2n4^{4g$(xFbDz$ z!N4Fm7=*a4217s)2nYrN!66{Tb!#vT1c8BIFc2IDLR>3@;UEYc1cQU%a1i1e3yc6k z5Fi)=1i!L(1r1F1phky~+Jb-El3=D&T z;V>}bnikL+0tdt3U^pC%xMm3`Ll9sX0t`oh5!a*vCjiy}O@J3b1h5R40(3hveNIV2{yH|Gp?-%5+W@UA9_OLO# zzVf<7spm9Rv)B01KReZR5+j6;Q6P?Db>$tOC3V~}lg!!r3u$R_aUx2>^3C&5k*|n) zgF!tIgIH+7+cxS@wpqA9+ct82_{Ap-cHCX)`@{+Het)v?h`eI00t;GbQsNUF zvgdDJ-KX~~Z(5?5$ko`CJYtlbM!%!M5F3+76D#dh z_??Q3535f^5C4JeGS2MmmTT*bJIm4}!OB5x=^K((mB3f_W?5wmo#t4r?bxE^=suyT z_a)BugKIeCCLZYBpU~k|A9$(P!^j3gYm=zo?X^9#P}spJyBfa;w48hkp`_v_F#^XDNV%_y)XQB5@@cUMFI#M^r1Zy+reV= zw<-Aoeq_+D^?Q=oOcn3@Kc)Vm9t3mb5(x?-3zKD^E?6iK0odD3>rn zcdI7aLsOePUxoK$f+e^$Y)>zDd!@*miP6O-dlyW%9d--lhuDxW`kGZ*CY1MGBxYDv91AMc8$`YZ({`fAONNq4TDvTnf29R#k@^zs3E#Mcn)# zu{e2DN)%u6Z`3&c)9OeXr}<*7;P!HVwtiVIii-hStKfc{$f8#tI0Ga0*03CA!)o7T zGHHJHodaR>TaqZhY?M)}^IsHnEq=<8{A2)kBXhukSn}^L3hu4cs{4=|!hY)}7sm9r(m+1Tv6C$WV+4}hN^9p-(JQ4dKjIzO=*1OI>B=Rp z2oCo|<*XwpX>CMOnhowj< z2&LjDdlYgxX}_1L4u?P9VX54T?WFVUdG<6bwgG$5@Q8*SL!T?1mml-9J{Jr_h7jH` zktWZnPx$18uRITjvO=fLI@%%*lpAIG7EIT@S>lmD+4nE4Sa~M)P?ZA%7FLlL)dN{Z zRv$ls!&SnH99+>dJV|;>ceyP{Ix?U8qPKl?7aKxm3|E(7P`}|vRuj!&G(mwA7<5F- zVq+Y1C;4ner@cJ6WbHv2ukS5in>l~NID2;<7RN1c7b9h7&O*#>l^qSC5})k!Hv#Zf zl>j6oMpB{Vu#oBRicFXyWAe-Ds*PGEtavRqiQecihNWc*3qx8m2N`D7RUXVjCTom* z9=dJep-1gSurp>W>!KhiEA45t5+Cu?yba;rmdQ$rtbu<>p1(nPo6(ch^a-E31`n%N zE<1m}zp8}3;oLT9k+@VXe$EVO#HOJ{8NH`tkql#XakF|y89H%EGa3SS&LNKNVbUY5 z8F4S5FX~*YYizsExE7YP=A`FPqTaGkZiyS}QE)nBXHY?eL3Y=gJeq{2lwD z+ybld?AY>K7|d$kUWd_GPW}b+WT93T&P4QbRYa<*D>&0EcrqT6M0Kbs-7_514HpkB zExhb0u!H754EHZl@$x)RqDc9g8q_ksq;0jf@Rf(hC+XC~(f8CN&(YJ>o+3qfi2vb7 zDZGb${C6U@6(ojs*p!6~bsnASxy%iSU=-sm4^yB$2=p%@08NPj&+Ed@e&(cm0>)i8;p5_YGk({!^zQ9DF%TWwobh*jZB<{UlbUJcEPbo0NDBE3 z&d{OMoNdQ&rsO+^I?mu0+Zu8vwmMZo*fXk12Qxf(nj_LGg%qZQqF2zm^qCE)$cC@H z*bBu>{XXZZ!b+I4=2*wwj;m=M3v)I-_f%S}XIv}NBI5KiUAqe_mt?nDmN8q>XPDV! z2ohAsu`AW4v9opNuyY@q<`<1HI%9-YF($3tw!%I6NmYVvh~e4#bhHM%cH@zsblFSUthgY_pEB7vt7~asrA*W zQ@-psPC6IU8lu%BeYQvWBmK1{K6XXEI<`j;%?5SZzV(2jC7F#w5tn6CsH$El9hwrY z+G=iD>^Hjf@iOdamtuUs;5$W^5+&b|j%T8F54SL>AwrWW`Pru;&rAq3ida(ms9gxQ z3u+^cd&x$6Nsel>L^Ow2!%lUE`+t7bRe8;}jtCE%bRWNbT4~hps9l0wL9AACGUBPB zwHU9TV@DpjXFM|WYR|3UtCbUx>sv7H>Bd^c-HPFX_(QY|MVXPxrq6eT9LB#pk33Yy zL-Z8(j-)ZwP&%NAPDjZ00Pi-@s?YYfByvy_x^=qFQ z7bGm;QzhT>;WE3ocl)txDV&efbJ}@d=;RBs>N6JG`067~@kcC_Ehb_Yn?8%5r1iY9 z=0W-gQy3k(%WQQj^jxZ}arES)L)@NL?7jy0*~Dz@>osL^J13X!Q=#LUJF0I`R1nz%rr|GMo1j5+}_SLUu(EVzTO&J5h?&#%ZM+ioX1f+H+{Ocvr`rmCdR1X9NTCP#n<(YO_hN~d!|tH^ek8?O zbxgx@E5(^F^OPt(Gi&wqrKd}cYc^ofav;7&Tl$qYp=mh`=q#Y)O8&V%Y1 zW1$OBNFRRQ&hP_6>-sbfviKy~+bH;+d<NWA=BgKi~GfdhF=5^Rk>59@#G{iO7(-5)Er{3`bt{(DOK zl}rEV{h!vaw0lW^ traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-AntMojoWrapper_239/buggy.java b/Java/maven-plugin-tools-AntMojoWrapper_239/buggy.java new file mode 100644 index 000000000..345e98beb --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_239/buggy.java @@ -0,0 +1,345 @@ +package org.apache.maven.script.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DependencyResolutionRequiredException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.ContextEnabled; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.path.PathTranslator; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.PropertyHelper; +import org.apache.tools.ant.types.Path; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.zip.ZipUnArchiver; +import org.codehaus.plexus.component.MapOrientedComponent; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.component.factory.ant.AntComponentExecutionException; +import org.codehaus.plexus.component.factory.ant.AntScriptInvoker; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.logging.LogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + */ +public class AntMojoWrapper + extends AbstractMojo + implements ContextEnabled, MapOrientedComponent, LogEnabled +{ + + private Map pluginContext; + + private final AntScriptInvoker scriptInvoker; + + private Project antProject; + + private MavenProject mavenProject; + + private MojoExecution mojoExecution; + + private MavenSession session; + + private PathTranslator pathTranslator; + + private Logger logger; + + private transient List unconstructedParts = new ArrayList<>(); + + public AntMojoWrapper( AntScriptInvoker scriptInvoker ) + { + this.scriptInvoker = scriptInvoker; + } + + public void execute() + throws MojoExecutionException + { + if ( antProject == null ) + { + antProject = scriptInvoker.getProject(); + } + + Map allConfig = new HashMap<>(); + if ( pluginContext != null && !pluginContext.isEmpty() ) + { + allConfig.putAll( pluginContext ); + } + + @SuppressWarnings( "unchecked" ) + Map refs = scriptInvoker.getReferences(); + if ( refs != null ) + { + allConfig.putAll( refs ); + + for ( Map.Entry entry : refs.entrySet() ) + { + if ( entry.getKey().startsWith( PathTranslator.class.getName() ) ) + { + pathTranslator = entry.getValue(); + } + } + } + + mavenProject = (MavenProject) allConfig.get( "project" ); + + mojoExecution = (MojoExecution) allConfig.get( "mojoExecution" ); + + session = (MavenSession) allConfig.get( "session" ); + + unpackFileBasedResources(); + + addClasspathReferences(); + + if ( logger.isDebugEnabled() && !unconstructedParts.isEmpty() ) + { + StringBuilder buffer = new StringBuilder(); + + buffer.append( "The following standard Maven Ant-mojo support objects could not be created:\n\n" ); + + for ( String part : unconstructedParts ) + { + buffer.append( "\n- " ).append( part ); + } + + buffer.append( "\n\nMaven project, session, mojo-execution, or path-translation parameter " + + "information is " ); + buffer.append( "\nmissing from this mojo's plugin descriptor." ); + buffer.append( "\n\nPerhaps this Ant-based mojo depends on maven-script-ant < 2.1.0, " ); + buffer.append( "or used maven-plugin-tools-ant < 2.2 during release?\n\n" ); + + logger.debug( buffer.toString() ); + } + + try + { + scriptInvoker.invoke(); + } + catch ( AntComponentExecutionException e ) + { + throw new MojoExecutionException( "Failed to execute: " + e.getMessage(), e ); + } + + unconstructedParts.clear(); + } + + public void setPluginContext( Map pluginContext ) + { + this.pluginContext = pluginContext; + } + + public Map getPluginContext() + { + return pluginContext; + } + + public void addComponentRequirement( ComponentRequirement requirementDescriptor, Object requirementValue ) + throws ComponentConfigurationException + { + scriptInvoker.addComponentRequirement( requirementDescriptor, requirementValue ); + } + + public void setComponentConfiguration( Map componentConfiguration ) + throws ComponentConfigurationException + { + scriptInvoker.setComponentConfiguration( componentConfiguration ); + antProject = scriptInvoker.getProject(); + } + + private void unpackFileBasedResources() + throws MojoExecutionException + { + if ( mojoExecution == null || mavenProject == null ) + { + unconstructedParts.add( "Unpacked Ant build scripts (in Maven build directory)." ); + + return; + } + + // What we need to write out any resources in the plugin to the target directory of the + // mavenProject using the Ant-based plugin: + // + // 1. Need a reference to the plugin JAR itself + // 2. Need a reference to the ${basedir} of the mavenProject + + PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + + File pluginJar = pluginDescriptor.getPluginArtifact().getFile(); + + String resourcesPath = pluginDescriptor.getArtifactId(); + + File outputDirectory = new File( mavenProject.getBuild().getDirectory() ); + + try + { + UnArchiver ua = new ZipUnArchiver( pluginJar ); + + ua.extract( resourcesPath, outputDirectory ); + } + catch ( ArchiverException e ) + { + throw new MojoExecutionException( "Error extracting resources from your Ant-based plugin.", e ); + } + } + +private void addClasspathReferences() throws org.apache.maven.plugin.MojoExecutionException { + try { + if (((mavenProject != null) && (session != null)) && (pathTranslator != null)) { + org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator exprEvaluator = new org.apache.maven.plugin.PluginParameterExpressionEvaluator(session, mojoExecution, pathTranslator, logger, mavenProject, mavenProject.getProperties()); + org.apache.tools.ant.PropertyHelper propertyHelper = org.apache.tools.ant.PropertyHelper.getPropertyHelper(antProject); + propertyHelper.setNext(new org.apache.maven.script.ant.AntPropertyHelper(exprEvaluator, mavenProject.getArtifacts(), getLog())); + } else { + unconstructedParts.add("Maven parameter expression evaluator for Ant properties."); + } + @java.lang.SuppressWarnings("unchecked") + java.util.Map references = scriptInvoker.getReferences(); + { + // Compile classpath + org.apache.tools.ant.types.Path p = new org.apache.tools.ant.types.Path(antProject); + p.setPath(org.codehaus.plexus.util.StringUtils.join(/* NPEX_NULL_EXP */ + mavenProject.getCompileClasspathElements().iterator(), java.io.File.pathSeparator)); + /* maven.dependency.classpath it's deprecated as it's equal to maven.compile.classpath */ + references.put("maven.dependency.classpath", p); + antProject.addReference("maven.dependency.classpath", p); + references.put("maven.compile.classpath", p); + antProject.addReference("maven.compile.classpath", p); + // Runtime classpath + p = new org.apache.tools.ant.types.Path(antProject); + p.setPath(org.codehaus.plexus.util.StringUtils.join(mavenProject.getRuntimeClasspathElements().iterator(), java.io.File.pathSeparator)); + references.put("maven.runtime.classpath", p); + antProject.addReference("maven.runtime.classpath", p); + // Test classpath + p = new org.apache.tools.ant.types.Path(antProject); + p.setPath(org.codehaus.plexus.util.StringUtils.join(mavenProject.getTestClasspathElements().iterator(), java.io.File.pathSeparator)); + references.put("maven.test.classpath", p); + antProject.addReference("maven.test.classpath", p); + } + if (mojoExecution != null) { + // Plugin dependency classpath + org.apache.tools.ant.types.Path p = getPathFromArtifacts(mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifacts(), antProject); + references.put("maven.plugin.classpath", p); + antProject.addReference("maven.plugin.classpath", p); + } else { + unconstructedParts.add("Maven standard plugin-based classpath references."); + } + } catch (org.apache.maven.artifact.DependencyResolutionRequiredException e) { + throw new org.apache.maven.plugin.MojoExecutionException("Error creating classpath references for Ant-based plugin scripts.", e); + } +} + + public Path getPathFromArtifacts( Collection artifacts, Project antProject ) + throws DependencyResolutionRequiredException + { + List list = new ArrayList<>( artifacts.size() ); + + for ( Artifact a : artifacts ) + { + File file = a.getFile(); + + if ( file == null ) + { + throw new DependencyResolutionRequiredException( a ); + } + + list.add( file.getPath() ); + } + + Path p = new Path( antProject ); + + p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) ); + + return p; + } + + public Project getAntProject() + { + return antProject; + } + + public void setAntProject( Project antProject ) + { + this.antProject = antProject; + } + + public MavenProject getMavenProject() + { + return mavenProject; + } + + public void setMavenProject( MavenProject mavenProject ) + { + this.mavenProject = mavenProject; + } + + public MojoExecution getMojoExecution() + { + return mojoExecution; + } + + public void setMojoExecution( MojoExecution mojoExecution ) + { + this.mojoExecution = mojoExecution; + } + + public MavenSession getSession() + { + return session; + } + + public void setSession( MavenSession session ) + { + this.session = session; + } + + public PathTranslator getPathTranslator() + { + return pathTranslator; + } + + public void setPathTranslator( PathTranslator pathTranslator ) + { + this.pathTranslator = pathTranslator; + } + + public AntScriptInvoker getScriptInvoker() + { + return scriptInvoker; + } + + public void enableLogging( Logger logger ) + { + this.logger = logger; + } +} diff --git a/Java/maven-plugin-tools-AntMojoWrapper_239/metadata.json b/Java/maven-plugin-tools-AntMojoWrapper_239/metadata.json new file mode 100644 index 000000000..1ea43727c --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_239/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-AntMojoWrapper_239", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java", + "line": 232, + "npe_method": "addClasspathReferences", + "deref_field": "mavenProject", + "npe_class": "AntMojoWrapper", + "repo": "maven-plugin-tools", + "bug_id": "AntMojoWrapper_239" + } +} diff --git a/Java/maven-plugin-tools-AntMojoWrapper_239/npe.json b/Java/maven-plugin-tools-AntMojoWrapper_239/npe.json new file mode 100644 index 000000000..8fe416d85 --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_239/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java", + "line": 232, + "npe_method": "addClasspathReferences", + "deref_field": "mavenProject", + "npe_class": "AntMojoWrapper" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-AntMojoWrapper_279/Dockerfile b/Java/maven-plugin-tools-AntMojoWrapper_279/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_279/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-AntMojoWrapper_279/buggy.java b/Java/maven-plugin-tools-AntMojoWrapper_279/buggy.java new file mode 100644 index 000000000..aca6b739c --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_279/buggy.java @@ -0,0 +1,345 @@ +package org.apache.maven.script.ant; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DependencyResolutionRequiredException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.ContextEnabled; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.path.PathTranslator; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.PropertyHelper; +import org.apache.tools.ant.types.Path; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.zip.ZipUnArchiver; +import org.codehaus.plexus.component.MapOrientedComponent; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.component.factory.ant.AntComponentExecutionException; +import org.codehaus.plexus.component.factory.ant.AntScriptInvoker; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.logging.LogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + */ +public class AntMojoWrapper + extends AbstractMojo + implements ContextEnabled, MapOrientedComponent, LogEnabled +{ + + private Map pluginContext; + + private final AntScriptInvoker scriptInvoker; + + private Project antProject; + + private MavenProject mavenProject; + + private MojoExecution mojoExecution; + + private MavenSession session; + + private PathTranslator pathTranslator; + + private Logger logger; + + private transient List unconstructedParts = new ArrayList<>(); + + public AntMojoWrapper( AntScriptInvoker scriptInvoker ) + { + this.scriptInvoker = scriptInvoker; + } + + public void execute() + throws MojoExecutionException + { + if ( antProject == null ) + { + antProject = scriptInvoker.getProject(); + } + + Map allConfig = new HashMap<>(); + if ( pluginContext != null && !pluginContext.isEmpty() ) + { + allConfig.putAll( pluginContext ); + } + + @SuppressWarnings( "unchecked" ) + Map refs = scriptInvoker.getReferences(); + if ( refs != null ) + { + allConfig.putAll( refs ); + + for ( Map.Entry entry : refs.entrySet() ) + { + if ( entry.getKey().startsWith( PathTranslator.class.getName() ) ) + { + pathTranslator = entry.getValue(); + } + } + } + + mavenProject = (MavenProject) allConfig.get( "project" ); + + mojoExecution = (MojoExecution) allConfig.get( "mojoExecution" ); + + session = (MavenSession) allConfig.get( "session" ); + + unpackFileBasedResources(); + + addClasspathReferences(); + + if ( logger.isDebugEnabled() && !unconstructedParts.isEmpty() ) + { + StringBuilder buffer = new StringBuilder(); + + buffer.append( "The following standard Maven Ant-mojo support objects could not be created:\n\n" ); + + for ( String part : unconstructedParts ) + { + buffer.append( "\n- " ).append( part ); + } + + buffer.append( "\n\nMaven project, session, mojo-execution, or path-translation parameter " + + "information is " ); + buffer.append( "\nmissing from this mojo's plugin descriptor." ); + buffer.append( "\n\nPerhaps this Ant-based mojo depends on maven-script-ant < 2.1.0, " ); + buffer.append( "or used maven-plugin-tools-ant < 2.2 during release?\n\n" ); + + logger.debug( buffer.toString() ); + } + + try + { + scriptInvoker.invoke(); + } + catch ( AntComponentExecutionException e ) + { + throw new MojoExecutionException( "Failed to execute: " + e.getMessage(), e ); + } + + unconstructedParts.clear(); + } + + public void setPluginContext( Map pluginContext ) + { + this.pluginContext = pluginContext; + } + + public Map getPluginContext() + { + return pluginContext; + } + + public void addComponentRequirement( ComponentRequirement requirementDescriptor, Object requirementValue ) + throws ComponentConfigurationException + { + scriptInvoker.addComponentRequirement( requirementDescriptor, requirementValue ); + } + + public void setComponentConfiguration( Map componentConfiguration ) + throws ComponentConfigurationException + { + scriptInvoker.setComponentConfiguration( componentConfiguration ); + antProject = scriptInvoker.getProject(); + } + + private void unpackFileBasedResources() + throws MojoExecutionException + { + if ( mojoExecution == null || mavenProject == null ) + { + unconstructedParts.add( "Unpacked Ant build scripts (in Maven build directory)." ); + + return; + } + + // What we need to write out any resources in the plugin to the target directory of the + // mavenProject using the Ant-based plugin: + // + // 1. Need a reference to the plugin JAR itself + // 2. Need a reference to the ${basedir} of the mavenProject + + PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + + File pluginJar = pluginDescriptor.getPluginArtifact().getFile(); + + String resourcesPath = pluginDescriptor.getArtifactId(); + + File outputDirectory = new File( mavenProject.getBuild().getDirectory() ); + + try + { + UnArchiver ua = new ZipUnArchiver( pluginJar ); + + ua.extract( resourcesPath, outputDirectory ); + } + catch ( ArchiverException e ) + { + throw new MojoExecutionException( "Error extracting resources from your Ant-based plugin.", e ); + } + } + +private void addClasspathReferences() throws org.apache.maven.plugin.MojoExecutionException { + try { + if (((mavenProject != null) && (session != null)) && (pathTranslator != null)) { + org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator exprEvaluator = new org.apache.maven.plugin.PluginParameterExpressionEvaluator(session, mojoExecution, pathTranslator, logger, mavenProject, mavenProject.getProperties()); + org.apache.tools.ant.PropertyHelper propertyHelper = org.apache.tools.ant.PropertyHelper.getPropertyHelper(antProject); + propertyHelper.setNext(new org.apache.maven.script.ant.AntPropertyHelper(exprEvaluator, mavenProject.getArtifacts(), getLog())); + } else { + unconstructedParts.add("Maven parameter expression evaluator for Ant properties."); + } + @java.lang.SuppressWarnings("unchecked") + java.util.Map references = scriptInvoker.getReferences(); + if (mavenProject != null) { + // Compile classpath + org.apache.tools.ant.types.Path p = new org.apache.tools.ant.types.Path(antProject); + p.setPath(org.codehaus.plexus.util.StringUtils.join(mavenProject.getCompileClasspathElements().iterator(), java.io.File.pathSeparator)); + /* maven.dependency.classpath it's deprecated as it's equal to maven.compile.classpath */ + references.put("maven.dependency.classpath", p); + antProject.addReference("maven.dependency.classpath", p); + references.put("maven.compile.classpath", p); + antProject.addReference("maven.compile.classpath", p); + // Runtime classpath + p = new org.apache.tools.ant.types.Path(antProject); + p.setPath(org.codehaus.plexus.util.StringUtils.join(mavenProject.getRuntimeClasspathElements().iterator(), java.io.File.pathSeparator)); + references.put("maven.runtime.classpath", p); + antProject.addReference("maven.runtime.classpath", p); + // Test classpath + p = new org.apache.tools.ant.types.Path(antProject); + p.setPath(org.codehaus.plexus.util.StringUtils.join(mavenProject.getTestClasspathElements().iterator(), java.io.File.pathSeparator)); + references.put("maven.test.classpath", p); + antProject.addReference("maven.test.classpath", p); + } else { + unconstructedParts.add("Maven standard project-based classpath references."); + } + { + // Plugin dependency classpath + org.apache.tools.ant.types.Path p = getPathFromArtifacts(/* NPEX_NULL_EXP */ + mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifacts(), antProject); + references.put("maven.plugin.classpath", p); + antProject.addReference("maven.plugin.classpath", p); + } + } catch (org.apache.maven.artifact.DependencyResolutionRequiredException e) { + throw new org.apache.maven.plugin.MojoExecutionException("Error creating classpath references for Ant-based plugin scripts.", e); + } +} + + public Path getPathFromArtifacts( Collection artifacts, Project antProject ) + throws DependencyResolutionRequiredException + { + List list = new ArrayList<>( artifacts.size() ); + + for ( Artifact a : artifacts ) + { + File file = a.getFile(); + + if ( file == null ) + { + throw new DependencyResolutionRequiredException( a ); + } + + list.add( file.getPath() ); + } + + Path p = new Path( antProject ); + + p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) ); + + return p; + } + + public Project getAntProject() + { + return antProject; + } + + public void setAntProject( Project antProject ) + { + this.antProject = antProject; + } + + public MavenProject getMavenProject() + { + return mavenProject; + } + + public void setMavenProject( MavenProject mavenProject ) + { + this.mavenProject = mavenProject; + } + + public MojoExecution getMojoExecution() + { + return mojoExecution; + } + + public void setMojoExecution( MojoExecution mojoExecution ) + { + this.mojoExecution = mojoExecution; + } + + public MavenSession getSession() + { + return session; + } + + public void setSession( MavenSession session ) + { + this.session = session; + } + + public PathTranslator getPathTranslator() + { + return pathTranslator; + } + + public void setPathTranslator( PathTranslator pathTranslator ) + { + this.pathTranslator = pathTranslator; + } + + public AntScriptInvoker getScriptInvoker() + { + return scriptInvoker; + } + + public void enableLogging( Logger logger ) + { + this.logger = logger; + } +} diff --git a/Java/maven-plugin-tools-AntMojoWrapper_279/metadata.json b/Java/maven-plugin-tools-AntMojoWrapper_279/metadata.json new file mode 100644 index 000000000..5223c2537 --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_279/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-AntMojoWrapper_279", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java", + "line": 253, + "npe_method": "addClasspathReferences", + "deref_field": "mojoExecution", + "npe_class": "AntMojoWrapper", + "repo": "maven-plugin-tools", + "bug_id": "AntMojoWrapper_279" + } +} diff --git a/Java/maven-plugin-tools-AntMojoWrapper_279/npe.json b/Java/maven-plugin-tools-AntMojoWrapper_279/npe.json new file mode 100644 index 000000000..577376488 --- /dev/null +++ b/Java/maven-plugin-tools-AntMojoWrapper_279/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-script/maven-script-ant/src/main/java/org/apache/maven/script/ant/AntMojoWrapper.java", + "line": 253, + "npe_method": "addClasspathReferences", + "deref_field": "mojoExecution", + "npe_class": "AntMojoWrapper" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/Dockerfile b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/buggy.java b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/buggy.java new file mode 100644 index 000000000..cb96d53f7 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/buggy.java @@ -0,0 +1,312 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoClassVisitor; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.reflection.Reflector; +import org.codehaus.plexus.util.reflection.ReflectorException; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Type; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@org.codehaus.plexus.component.annotations.Component( role = MojoAnnotationsScanner.class ) +public class DefaultMojoAnnotationsScanner + extends AbstractLogEnabled + implements MojoAnnotationsScanner +{ + // classes with a dash must be ignored + private static final Pattern SCANNABLE_CLASS = Pattern.compile( "[^-]+\\.class" ); + + private Reflector reflector = new Reflector(); + + public Map scan( MojoAnnotationsScannerRequest request ) + throws ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + try + { + for ( Artifact dependency : request.getDependencies() ) + { + scan( mojoAnnotatedClasses, dependency.getFile(), request.getIncludePatterns(), dependency, true ); + } + + for ( File classDirectory : request.getClassesDirectories() ) + { + scan( mojoAnnotatedClasses, classDirectory, request.getIncludePatterns(), + request.getProject().getArtifact(), false ); + } + } + catch ( IOException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + + return mojoAnnotatedClasses; + } + + protected void scan( Map mojoAnnotatedClasses, File source, + List includePatterns, Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + if ( source == null || ! source.exists() ) + { + return; + } + + Map scanResult; + if ( source.isDirectory() ) + { + scanResult = scanDirectory( source, includePatterns, artifact, excludeMojo ); + } + else + { + scanResult = scanArchive( source, artifact, excludeMojo ); + } + + mojoAnnotatedClasses.putAll( scanResult ); + } + + /** + * @param archiveFile + * @param artifact + * @param excludeMojo for dependencies, we exclude Mojo annotations found + * @return annotated classes found + * @throws IOException + * @throws ExtractionException + */ + protected Map scanArchive( File archiveFile, Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + String zipEntryName = null; + try ( ZipInputStream archiveStream = new ZipInputStream( new FileInputStream( archiveFile ) ) ) + { + String archiveFilename = archiveFile.getAbsolutePath(); + for ( ZipEntry zipEntry = archiveStream.getNextEntry(); zipEntry != null; + zipEntry = archiveStream.getNextEntry() ) + { + zipEntryName = zipEntry.getName(); + if ( !SCANNABLE_CLASS.matcher( zipEntryName ).matches() ) + { + continue; + } + analyzeClassStream( mojoAnnotatedClasses, archiveStream, artifact, excludeMojo, archiveFilename, + zipEntry.getName() ); + } + } + catch ( IllegalArgumentException e ) + { + // In case of a class with newer specs an IllegalArgumentException can be thrown + getLogger().error( "Failed to analyze " + archiveFile.getAbsolutePath() + "!/" + zipEntryName ); + + throw e; + } + + return mojoAnnotatedClasses; + } + + /** + * @param classDirectory + * @param includePatterns + * @param artifact + * @param excludeMojo for dependencies, we exclude Mojo annotations found + * @return annotated classes found + * @throws IOException + * @throws ExtractionException + */ + protected Map scanDirectory( File classDirectory, List includePatterns, + Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir( classDirectory ); + scanner.addDefaultExcludes(); + if ( includePatterns != null ) + { + scanner.setIncludes( includePatterns.toArray( new String[includePatterns.size()] ) ); + } + scanner.scan(); + String[] classFiles = scanner.getIncludedFiles(); + String classDirname = classDirectory.getAbsolutePath(); + + for ( String classFile : classFiles ) + { + if ( !SCANNABLE_CLASS.matcher( classFile ).matches() ) + { + continue; + } + + try ( InputStream is = // + new BufferedInputStream( new FileInputStream( new File( classDirectory, classFile ) ) ) ) + { + analyzeClassStream( mojoAnnotatedClasses, is, artifact, excludeMojo, classDirname, classFile ); + } + } + return mojoAnnotatedClasses; + } + + private void analyzeClassStream( Map mojoAnnotatedClasses, InputStream is, + Artifact artifact, boolean excludeMojo, String source, String file ) + throws IOException, ExtractionException + { + MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() ); + + try + { + ClassReader rdr = new ClassReader( is ); + rdr.accept( mojoClassVisitor, ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG ); + } + catch ( ArrayIndexOutOfBoundsException aiooe ) + { + getLogger().warn( "Error analyzing class " + file + " in " + source + ": ignoring class", + getLogger().isDebugEnabled() ? aiooe : null ); + return; + } + catch ( IllegalArgumentException iae ) + { + if ( iae.getMessage() == null ) + { + getLogger().warn( "Error analyzing class " + file + " in " + source + ": ignoring class", + getLogger().isDebugEnabled() ? iae : null ); + return; + } + else + { + throw iae; + } + } + + analyzeVisitors( mojoClassVisitor ); + + MojoAnnotatedClass mojoAnnotatedClass = mojoClassVisitor.getMojoAnnotatedClass(); + + if ( excludeMojo ) + { + mojoAnnotatedClass.setMojo( null ); + } + + if ( mojoAnnotatedClass != null ) // see MPLUGIN-206 we can have intermediate classes without annotations + { + if ( getLogger().isDebugEnabled() && mojoAnnotatedClass.hasAnnotations() ) + { + getLogger().debug( "found MojoAnnotatedClass:" + mojoAnnotatedClass.getClassName() + ":" + + mojoAnnotatedClass ); + } + mojoAnnotatedClass.setArtifact( artifact ); + mojoAnnotatedClasses.put( mojoAnnotatedClass.getClassName(), mojoAnnotatedClass ); + } + } + + protected void populateAnnotationContent( Object content, MojoAnnotationVisitor mojoAnnotationVisitor ) + throws ReflectorException + { + for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() ) + { + reflector.invoke( content, entry.getKey(), new Object[] { entry.getValue() } ); + } + } + +protected void analyzeVisitors(org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoClassVisitor mojoClassVisitor) throws org.apache.maven.tools.plugin.extractor.ExtractionException { + final org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass mojoAnnotatedClass = mojoClassVisitor.getMojoAnnotatedClass(); + try { + // @Mojo annotation + org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitor(org.apache.maven.plugins.annotations.Mojo.class); + { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent mojoAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent(); + populateAnnotationContent(mojoAnnotationContent, /* NPEX_NULL_EXP */ + mojoAnnotationVisitor); + mojoAnnotatedClass.setMojo(mojoAnnotationContent); + } + // @Execute annotation + mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitor(org.apache.maven.plugins.annotations.Execute.class); + if (mojoAnnotationVisitor != null) { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent executeAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent(); + populateAnnotationContent(executeAnnotationContent, mojoAnnotationVisitor); + mojoAnnotatedClass.setExecute(executeAnnotationContent); + } + // @Parameter annotations + java.util.List mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation(org.apache.maven.plugins.annotations.Parameter.class); + for (org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors) { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent parameterAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent(mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName()); + if (mojoFieldVisitor.getMojoAnnotationVisitor() != null) { + populateAnnotationContent(parameterAnnotationContent, mojoFieldVisitor.getMojoAnnotationVisitor()); + } + mojoAnnotatedClass.getParameters().put(parameterAnnotationContent.getFieldName(), parameterAnnotationContent); + } + // @Component annotations + mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation(org.apache.maven.plugins.annotations.Component.class); + for (org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors) { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent componentAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent(mojoFieldVisitor.getFieldName()); + org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor annotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor(); + if (annotationVisitor != null) { + for (java.util.Map.Entry entry : annotationVisitor.getAnnotationValues().entrySet()) { + java.lang.String methodName = entry.getKey(); + if (org.codehaus.plexus.util.StringUtils.equals("role", methodName)) { + org.objectweb.asm.Type type = ((org.objectweb.asm.Type) (entry.getValue())); + componentAnnotationContent.setRoleClassName(type.getClassName()); + } else { + reflector.invoke(componentAnnotationContent, entry.getKey(), new java.lang.Object[]{ entry.getValue() }); + } + } + if (org.codehaus.plexus.util.StringUtils.isEmpty(componentAnnotationContent.getRoleClassName())) { + componentAnnotationContent.setRoleClassName(mojoFieldVisitor.getClassName()); + } + } + mojoAnnotatedClass.getComponents().put(componentAnnotationContent.getFieldName(), componentAnnotationContent); + } + } catch (org.codehaus.plexus.util.reflection.ReflectorException e) { + throw new org.apache.maven.tools.plugin.extractor.ExtractionException(e.getMessage(), e); + } +} +} diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/metadata.json b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/metadata.json new file mode 100644 index 000000000..bfa2a9f8a --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-DefaultMojoAnnotationsScanner_269", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java", + "line": 268, + "npe_method": "analyzeVisitors", + "deref_field": "mojoAnnotationVisitor", + "npe_class": "DefaultMojoAnnotationsScanner", + "repo": "maven-plugin-tools", + "bug_id": "DefaultMojoAnnotationsScanner_269" + } +} diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/npe.json b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/npe.json new file mode 100644 index 000000000..c65be4992 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_269/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java", + "line": 268, + "npe_method": "analyzeVisitors", + "deref_field": "mojoAnnotationVisitor", + "npe_class": "DefaultMojoAnnotationsScanner" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/Dockerfile b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/buggy.java b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/buggy.java new file mode 100644 index 000000000..38849cb0c --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/buggy.java @@ -0,0 +1,312 @@ +package org.apache.maven.tools.plugin.extractor.annotations.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoClassVisitor; +import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.reflection.Reflector; +import org.codehaus.plexus.util.reflection.ReflectorException; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Type; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +@org.codehaus.plexus.component.annotations.Component( role = MojoAnnotationsScanner.class ) +public class DefaultMojoAnnotationsScanner + extends AbstractLogEnabled + implements MojoAnnotationsScanner +{ + // classes with a dash must be ignored + private static final Pattern SCANNABLE_CLASS = Pattern.compile( "[^-]+\\.class" ); + + private Reflector reflector = new Reflector(); + + public Map scan( MojoAnnotationsScannerRequest request ) + throws ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + try + { + for ( Artifact dependency : request.getDependencies() ) + { + scan( mojoAnnotatedClasses, dependency.getFile(), request.getIncludePatterns(), dependency, true ); + } + + for ( File classDirectory : request.getClassesDirectories() ) + { + scan( mojoAnnotatedClasses, classDirectory, request.getIncludePatterns(), + request.getProject().getArtifact(), false ); + } + } + catch ( IOException e ) + { + throw new ExtractionException( e.getMessage(), e ); + } + + return mojoAnnotatedClasses; + } + + protected void scan( Map mojoAnnotatedClasses, File source, + List includePatterns, Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + if ( source == null || ! source.exists() ) + { + return; + } + + Map scanResult; + if ( source.isDirectory() ) + { + scanResult = scanDirectory( source, includePatterns, artifact, excludeMojo ); + } + else + { + scanResult = scanArchive( source, artifact, excludeMojo ); + } + + mojoAnnotatedClasses.putAll( scanResult ); + } + + /** + * @param archiveFile + * @param artifact + * @param excludeMojo for dependencies, we exclude Mojo annotations found + * @return annotated classes found + * @throws IOException + * @throws ExtractionException + */ + protected Map scanArchive( File archiveFile, Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + String zipEntryName = null; + try ( ZipInputStream archiveStream = new ZipInputStream( new FileInputStream( archiveFile ) ) ) + { + String archiveFilename = archiveFile.getAbsolutePath(); + for ( ZipEntry zipEntry = archiveStream.getNextEntry(); zipEntry != null; + zipEntry = archiveStream.getNextEntry() ) + { + zipEntryName = zipEntry.getName(); + if ( !SCANNABLE_CLASS.matcher( zipEntryName ).matches() ) + { + continue; + } + analyzeClassStream( mojoAnnotatedClasses, archiveStream, artifact, excludeMojo, archiveFilename, + zipEntry.getName() ); + } + } + catch ( IllegalArgumentException e ) + { + // In case of a class with newer specs an IllegalArgumentException can be thrown + getLogger().error( "Failed to analyze " + archiveFile.getAbsolutePath() + "!/" + zipEntryName ); + + throw e; + } + + return mojoAnnotatedClasses; + } + + /** + * @param classDirectory + * @param includePatterns + * @param artifact + * @param excludeMojo for dependencies, we exclude Mojo annotations found + * @return annotated classes found + * @throws IOException + * @throws ExtractionException + */ + protected Map scanDirectory( File classDirectory, List includePatterns, + Artifact artifact, boolean excludeMojo ) + throws IOException, ExtractionException + { + Map mojoAnnotatedClasses = new HashMap<>(); + + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir( classDirectory ); + scanner.addDefaultExcludes(); + if ( includePatterns != null ) + { + scanner.setIncludes( includePatterns.toArray( new String[includePatterns.size()] ) ); + } + scanner.scan(); + String[] classFiles = scanner.getIncludedFiles(); + String classDirname = classDirectory.getAbsolutePath(); + + for ( String classFile : classFiles ) + { + if ( !SCANNABLE_CLASS.matcher( classFile ).matches() ) + { + continue; + } + + try ( InputStream is = // + new BufferedInputStream( new FileInputStream( new File( classDirectory, classFile ) ) ) ) + { + analyzeClassStream( mojoAnnotatedClasses, is, artifact, excludeMojo, classDirname, classFile ); + } + } + return mojoAnnotatedClasses; + } + + private void analyzeClassStream( Map mojoAnnotatedClasses, InputStream is, + Artifact artifact, boolean excludeMojo, String source, String file ) + throws IOException, ExtractionException + { + MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() ); + + try + { + ClassReader rdr = new ClassReader( is ); + rdr.accept( mojoClassVisitor, ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG ); + } + catch ( ArrayIndexOutOfBoundsException aiooe ) + { + getLogger().warn( "Error analyzing class " + file + " in " + source + ": ignoring class", + getLogger().isDebugEnabled() ? aiooe : null ); + return; + } + catch ( IllegalArgumentException iae ) + { + if ( iae.getMessage() == null ) + { + getLogger().warn( "Error analyzing class " + file + " in " + source + ": ignoring class", + getLogger().isDebugEnabled() ? iae : null ); + return; + } + else + { + throw iae; + } + } + + analyzeVisitors( mojoClassVisitor ); + + MojoAnnotatedClass mojoAnnotatedClass = mojoClassVisitor.getMojoAnnotatedClass(); + + if ( excludeMojo ) + { + mojoAnnotatedClass.setMojo( null ); + } + + if ( mojoAnnotatedClass != null ) // see MPLUGIN-206 we can have intermediate classes without annotations + { + if ( getLogger().isDebugEnabled() && mojoAnnotatedClass.hasAnnotations() ) + { + getLogger().debug( "found MojoAnnotatedClass:" + mojoAnnotatedClass.getClassName() + ":" + + mojoAnnotatedClass ); + } + mojoAnnotatedClass.setArtifact( artifact ); + mojoAnnotatedClasses.put( mojoAnnotatedClass.getClassName(), mojoAnnotatedClass ); + } + } + + protected void populateAnnotationContent( Object content, MojoAnnotationVisitor mojoAnnotationVisitor ) + throws ReflectorException + { + for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() ) + { + reflector.invoke( content, entry.getKey(), new Object[] { entry.getValue() } ); + } + } + +protected void analyzeVisitors(org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoClassVisitor mojoClassVisitor) throws org.apache.maven.tools.plugin.extractor.ExtractionException { + final org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass mojoAnnotatedClass = mojoClassVisitor.getMojoAnnotatedClass(); + try { + // @Mojo annotation + org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitor(org.apache.maven.plugins.annotations.Mojo.class); + if (mojoAnnotationVisitor != null) { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent mojoAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent(); + populateAnnotationContent(mojoAnnotationContent, mojoAnnotationVisitor); + mojoAnnotatedClass.setMojo(mojoAnnotationContent); + } + // @Execute annotation + mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitor(org.apache.maven.plugins.annotations.Execute.class); + { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent executeAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent(); + populateAnnotationContent(executeAnnotationContent, /* NPEX_NULL_EXP */ + mojoAnnotationVisitor); + mojoAnnotatedClass.setExecute(executeAnnotationContent); + } + // @Parameter annotations + java.util.List mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation(org.apache.maven.plugins.annotations.Parameter.class); + for (org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors) { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent parameterAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent(mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName()); + if (mojoFieldVisitor.getMojoAnnotationVisitor() != null) { + populateAnnotationContent(parameterAnnotationContent, mojoFieldVisitor.getMojoAnnotationVisitor()); + } + mojoAnnotatedClass.getParameters().put(parameterAnnotationContent.getFieldName(), parameterAnnotationContent); + } + // @Component annotations + mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation(org.apache.maven.plugins.annotations.Component.class); + for (org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors) { + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent componentAnnotationContent = new org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent(mojoFieldVisitor.getFieldName()); + org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor annotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor(); + if (annotationVisitor != null) { + for (java.util.Map.Entry entry : annotationVisitor.getAnnotationValues().entrySet()) { + java.lang.String methodName = entry.getKey(); + if (org.codehaus.plexus.util.StringUtils.equals("role", methodName)) { + org.objectweb.asm.Type type = ((org.objectweb.asm.Type) (entry.getValue())); + componentAnnotationContent.setRoleClassName(type.getClassName()); + } else { + reflector.invoke(componentAnnotationContent, entry.getKey(), new java.lang.Object[]{ entry.getValue() }); + } + } + if (org.codehaus.plexus.util.StringUtils.isEmpty(componentAnnotationContent.getRoleClassName())) { + componentAnnotationContent.setRoleClassName(mojoFieldVisitor.getClassName()); + } + } + mojoAnnotatedClass.getComponents().put(componentAnnotationContent.getFieldName(), componentAnnotationContent); + } + } catch (org.codehaus.plexus.util.reflection.ReflectorException e) { + throw new org.apache.maven.tools.plugin.extractor.ExtractionException(e.getMessage(), e); + } +} +} diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/metadata.json b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/metadata.json new file mode 100644 index 000000000..380956510 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-DefaultMojoAnnotationsScanner_278", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java", + "line": 275, + "npe_method": "analyzeVisitors", + "deref_field": "mojoAnnotationVisitor", + "npe_class": "DefaultMojoAnnotationsScanner", + "repo": "maven-plugin-tools", + "bug_id": "DefaultMojoAnnotationsScanner_278" + } +} diff --git a/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/npe.json b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/npe.json new file mode 100644 index 000000000..127311822 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoAnnotationsScanner_278/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java", + "line": 275, + "npe_method": "analyzeVisitors", + "deref_field": "mojoAnnotationVisitor", + "npe_class": "DefaultMojoAnnotationsScanner" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_139/Dockerfile b/Java/maven-plugin-tools-DefaultMojoScanner_139/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_139/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_139/buggy.java b/Java/maven-plugin-tools-DefaultMojoScanner_139/buggy.java new file mode 100644 index 000000000..56d3944c8 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_139/buggy.java @@ -0,0 +1,149 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.codehaus.plexus.util.StringUtils; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author jdcasey + */ +public class DefaultMojoScanner + extends AbstractLogEnabled + implements MojoScanner +{ + + private Map mojoDescriptorExtractors; + + /** + * The names of the active extractors + */ + private Set activeExtractors; + + /** + * Default constructor + * + * @param extractors not null + */ + public DefaultMojoScanner( Map extractors ) + { + this.mojoDescriptorExtractors = extractors; + + this.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "standalone-scanner-logger" ) ); + } + + /** + * Empty constructor + */ + public DefaultMojoScanner() + { + // nop + } + + /** + * {@inheritDoc} + */ + public void populatePluginDescriptor( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Logger logger = getLogger(); + Set activeExtractorsInternal = getActiveExtractors(); + + logger.debug( "Using " + activeExtractorsInternal.size() + " mojo extractors." ); + + int numMojoDescriptors = 0; + + for ( String extractorId : activeExtractorsInternal ) + { + MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get( extractorId ); + + if ( extractor == null ) + { + throw new ExtractionException( "No mojo extractor with '" + extractorId + "' id." ); + } + + logger.debug( "Applying " + extractorId + " mojo extractor" ); + + List extractorDescriptors = extractor.execute( request ); + + logger.info( extractorId + " mojo extractor found " + extractorDescriptors.size() + + " mojo descriptor" + ( extractorDescriptors.size() > 1 ? "s" : "" ) + "." ); + numMojoDescriptors += extractorDescriptors.size(); + + for ( MojoDescriptor descriptor : extractorDescriptors ) + { + logger.debug( "Adding mojo: " + descriptor + " to plugin descriptor." ); + + descriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + request.getPluginDescriptor().addMojo( descriptor ); + } + } + + if ( numMojoDescriptors == 0 && !request.isSkipErrorNoDescriptorsFound() ) + { + throw new InvalidPluginDescriptorException( + "No mojo definitions were found for plugin: " + request.getPluginDescriptor().getPluginLookupKey() + + "." ); + } + } + + /** + * Gets the name of the active extractors. + * + * @return A Set containing the names of the active extractors. + */ + protected Set getActiveExtractors() + { + Set result = activeExtractors; + + if ( result == null ) + { + result = new HashSet<>( mojoDescriptorExtractors.keySet() ); + } + + return result; + } + +public void setActiveExtractors(java.util.Set extractors) { + { + this.activeExtractors = new java.util.HashSet<>(); + for (java.lang.String extractor : /* NPEX_NULL_EXP */ + extractors) { + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(extractor)) { + this.activeExtractors.add(extractor); + } + } + } +} + +} diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_139/metadata.json b/Java/maven-plugin-tools-DefaultMojoScanner_139/metadata.json new file mode 100644 index 000000000..de9548967 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_139/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-DefaultMojoScanner_139", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java", + "line": 141, + "npe_method": "setActiveExtractors", + "deref_field": "extractors", + "npe_class": "DefaultMojoScanner", + "repo": "maven-plugin-tools", + "bug_id": "DefaultMojoScanner_139" + } +} diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_139/npe.json b/Java/maven-plugin-tools-DefaultMojoScanner_139/npe.json new file mode 100644 index 000000000..98308c176 --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_139/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java", + "line": 141, + "npe_method": "setActiveExtractors", + "deref_field": "extractors", + "npe_class": "DefaultMojoScanner" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_89/Dockerfile b/Java/maven-plugin-tools-DefaultMojoScanner_89/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_89/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_89/buggy.java b/Java/maven-plugin-tools-DefaultMojoScanner_89/buggy.java new file mode 100644 index 000000000..a1485c61a --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_89/buggy.java @@ -0,0 +1,140 @@ +package org.apache.maven.tools.plugin.scanner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; +import org.codehaus.plexus.util.StringUtils; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author jdcasey + */ +public class DefaultMojoScanner + extends AbstractLogEnabled + implements MojoScanner +{ + + private Map mojoDescriptorExtractors; + + /** + * The names of the active extractors + */ + private Set activeExtractors; + + /** + * Default constructor + * + * @param extractors not null + */ + public DefaultMojoScanner( Map extractors ) + { + this.mojoDescriptorExtractors = extractors; + + this.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "standalone-scanner-logger" ) ); + } + + /** + * Empty constructor + */ + public DefaultMojoScanner() + { + // nop + } + + /** + * {@inheritDoc} + */ +/** + * {@inheritDoc } + */ +public void populatePluginDescriptor(org.apache.maven.tools.plugin.PluginToolsRequest request) throws org.apache.maven.tools.plugin.extractor.ExtractionException, org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.codehaus.plexus.logging.Logger logger = getLogger(); + java.util.Set activeExtractorsInternal = getActiveExtractors(); + logger.debug(("Using " + activeExtractorsInternal.size()) + " mojo extractors."); + int numMojoDescriptors = 0; + for (java.lang.String extractorId : activeExtractorsInternal) { + org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get(extractorId); + { + logger.debug(("Applying " + extractorId) + " mojo extractor"); + java.util.List extractorDescriptors = /* NPEX_NULL_EXP */ + extractor.execute(request); + logger.info(((((extractorId + " mojo extractor found ") + extractorDescriptors.size()) + " mojo descriptor") + (extractorDescriptors.size() > 1 ? "s" : "")) + "."); + numMojoDescriptors += extractorDescriptors.size(); + for (org.apache.maven.plugin.descriptor.MojoDescriptor descriptor : extractorDescriptors) { + logger.debug(("Adding mojo: " + descriptor) + " to plugin descriptor."); + descriptor.setPluginDescriptor(request.getPluginDescriptor()); + request.getPluginDescriptor().addMojo(descriptor); + } + } + } + if ((numMojoDescriptors == 0) && (!request.isSkipErrorNoDescriptorsFound())) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(("No mojo definitions were found for plugin: " + request.getPluginDescriptor().getPluginLookupKey()) + "."); + } +} + + /** + * Gets the name of the active extractors. + * + * @return A Set containing the names of the active extractors. + */ + protected Set getActiveExtractors() + { + Set result = activeExtractors; + + if ( result == null ) + { + result = new HashSet<>( mojoDescriptorExtractors.keySet() ); + } + + return result; + } + + public void setActiveExtractors( Set extractors ) + { + if ( extractors == null ) + { + this.activeExtractors = null; + } + else + { + this.activeExtractors = new HashSet<>(); + + for ( String extractor : extractors ) + { + if ( StringUtils.isNotEmpty( extractor ) ) + { + this.activeExtractors.add( extractor ); + } + } + } + } + +} diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_89/metadata.json b/Java/maven-plugin-tools-DefaultMojoScanner_89/metadata.json new file mode 100644 index 000000000..96d9db42b --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_89/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-DefaultMojoScanner_89", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java", + "line": 88, + "npe_method": "populatePluginDescriptor", + "deref_field": "extractor", + "npe_class": "DefaultMojoScanner", + "repo": "maven-plugin-tools", + "bug_id": "DefaultMojoScanner_89" + } +} diff --git a/Java/maven-plugin-tools-DefaultMojoScanner_89/npe.json b/Java/maven-plugin-tools-DefaultMojoScanner_89/npe.json new file mode 100644 index 000000000..53a8672dc --- /dev/null +++ b/Java/maven-plugin-tools-DefaultMojoScanner_89/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java", + "line": 88, + "npe_method": "populatePluginDescriptor", + "deref_field": "extractor", + "npe_class": "DefaultMojoScanner" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/buggy.java new file mode 100644 index 000000000..5d13d1b0d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + { + mojoDescriptor.setComponentConfigurator(/* NPEX_NULL_EXP */ + configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/metadata.json new file mode 100644 index 000000000..362db6742 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 141, + "npe_method": "createMojoDescriptor", + "deref_field": "configurator", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_133" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/npe.json new file mode 100644 index 000000000..a908f62ac --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_133/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 141, + "npe_method": "createMojoDescriptor", + "deref_field": "configurator", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/buggy.java new file mode 100644 index 000000000..e9d14ba53 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + { + java.lang.String executePhase = /* NPEX_NULL_EXP */ + execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/metadata.json new file mode 100644 index 000000000..253080c14 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 146, + "npe_method": "createMojoDescriptor", + "deref_field": "execute", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_140" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/npe.json new file mode 100644 index 000000000..ce142192b --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_140/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 146, + "npe_method": "createMojoDescriptor", + "deref_field": "execute", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/buggy.java new file mode 100644 index 000000000..0ee51f2fe --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + { + mojoDescriptor.setExecuteLifecycle(/* NPEX_NULL_EXP */ + lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/metadata.json new file mode 100644 index 000000000..d80277f1d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 157, + "npe_method": "createMojoDescriptor", + "deref_field": "lifecycle", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_159" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/npe.json new file mode 100644 index 000000000..dad27fa2f --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_159/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 157, + "npe_method": "createMojoDescriptor", + "deref_field": "lifecycle", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/buggy.java new file mode 100644 index 000000000..3a312e114 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + { + mojoDescriptor.setInstantiationStrategy(/* NPEX_NULL_EXP */ + tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/metadata.json new file mode 100644 index 000000000..8605053f8 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 174, + "npe_method": "createMojoDescriptor", + "deref_field": "tag", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_185" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/npe.json new file mode 100644 index 000000000..edbc4118a --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_185/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 174, + "npe_method": "createMojoDescriptor", + "deref_field": "tag", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/buggy.java new file mode 100644 index 000000000..2e7d48bb9 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + { + mojoDescriptor.setExecutionStrategy(/* NPEX_NULL_EXP */ + tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/metadata.json new file mode 100644 index 000000000..5b2ca0a3c --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 186, + "npe_method": "createMojoDescriptor", + "deref_field": "tag", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_204" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/npe.json new file mode 100644 index 000000000..43eee6529 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_204/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 186, + "npe_method": "createMojoDescriptor", + "deref_field": "tag", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/buggy.java new file mode 100644 index 000000000..2229aef19 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + { + mojoDescriptor.setPhase(/* NPEX_NULL_EXP */ + phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/metadata.json new file mode 100644 index 000000000..928f52d50 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 191, + "npe_method": "createMojoDescriptor", + "deref_field": "phase", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_211" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/npe.json new file mode 100644 index 000000000..171c828a2 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_211/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 191, + "npe_method": "createMojoDescriptor", + "deref_field": "phase", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/buggy.java new file mode 100644 index 000000000..26e9c2ed5 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + { + java.lang.String v = /* NPEX_NULL_EXP */ + requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/metadata.json new file mode 100644 index 000000000..a72da6cb7 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 196, + "npe_method": "createMojoDescriptor", + "deref_field": "requiresDependencyResolution", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_219" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/npe.json new file mode 100644 index 000000000..1669ed876 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_219/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 196, + "npe_method": "createMojoDescriptor", + "deref_field": "requiresDependencyResolution", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/buggy.java new file mode 100644 index 000000000..1bba38fae --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + { + java.lang.String v = /* NPEX_NULL_EXP */ + requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/metadata.json new file mode 100644 index 000000000..9175184b1 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 205, + "npe_method": "createMojoDescriptor", + "deref_field": "requiresDependencyCollection", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_234" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/npe.json new file mode 100644 index 000000000..4dc2518fb --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_234/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 205, + "npe_method": "createMojoDescriptor", + "deref_field": "requiresDependencyCollection", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/buggy.java new file mode 100644 index 000000000..07adc60ec --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + { + mojoDescriptor.setDeprecated(/* NPEX_NULL_EXP */ + deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (since != null) { + mojoDescriptor.setSince(since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/metadata.json new file mode 100644 index 000000000..5b28491b8 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 229, + "npe_method": "createMojoDescriptor", + "deref_field": "deprecated", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_273" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/npe.json new file mode 100644 index 000000000..e26fcf4b2 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_273/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 229, + "npe_method": "createMojoDescriptor", + "deref_field": "deprecated", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/buggy.java new file mode 100644 index 000000000..72b7988cf --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/buggy.java @@ -0,0 +1,604 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ +// ---------------------------------------------------------------------- +// Mojo descriptor creation from @tags +// ---------------------------------------------------------------------- +/** + * + * + * @param javaClass + * not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException + * if any + */ +protected org.apache.maven.plugin.descriptor.MojoDescriptor createMojoDescriptor(com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor mojoDescriptor = new org.apache.maven.tools.plugin.ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage("java"); + mojoDescriptor.setImplementation(javaClass.getFullyQualifiedName()); + mojoDescriptor.setDescription(javaClass.getComment()); + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + // Aggregator flag + com.thoughtworks.qdox.model.DocletTag aggregator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.AGGREGATOR); + if (aggregator != null) { + mojoDescriptor.setAggregator(true); + } + // Configurator hint + com.thoughtworks.qdox.model.DocletTag configurator = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.CONFIGURATOR); + if (configurator != null) { + mojoDescriptor.setComponentConfigurator(configurator.getValue()); + } + // Additional phase to execute first + com.thoughtworks.qdox.model.DocletTag execute = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE); + if (execute != null) { + java.lang.String executePhase = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_PHASE); + java.lang.String executeGoal = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_GOAL); + if ((executePhase == null) && (executeGoal == null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag requires either a 'phase' or 'goal' parameter"); + } else if ((executePhase != null) && (executeGoal != null)) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute tag can have only one of a 'phase' or 'goal' parameter"); + } + mojoDescriptor.setExecutePhase(executePhase); + mojoDescriptor.setExecuteGoal(executeGoal); + java.lang.String lifecycle = execute.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTE_LIFECYCLE); + if (lifecycle != null) { + mojoDescriptor.setExecuteLifecycle(lifecycle); + if (mojoDescriptor.getExecuteGoal() != null) { + throw new org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException(javaClass.getFullyQualifiedName() + ": @execute lifecycle requires a phase instead of a goal"); + } + } + } + // Goal name + com.thoughtworks.qdox.model.DocletTag goal = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.GOAL); + if (goal != null) { + mojoDescriptor.setGoal(goal.getValue()); + } + // inheritByDefault flag + boolean value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault()); + mojoDescriptor.setInheritedByDefault(value); + // instantiationStrategy + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.INSTANTIATION_STRATEGY); + if (tag != null) { + mojoDescriptor.setInstantiationStrategy(tag.getValue()); + } + // executionStrategy (and deprecated @attainAlways) + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY); + if (tag != null) { + getLogger().warn(((((("@" + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY) + " in ") + javaClass.getFullyQualifiedName()) + " is deprecated: please use '@") + org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY) + " always' instead."); + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.MULTI_PASS_EXEC_STRATEGY); + } else { + mojoDescriptor.setExecutionStrategy(org.apache.maven.plugin.descriptor.MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY); + } + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.EXECUTION_STATEGY); + if (tag != null) { + mojoDescriptor.setExecutionStrategy(tag.getValue()); + } + // Phase name + com.thoughtworks.qdox.model.DocletTag phase = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PHASE); + if (phase != null) { + mojoDescriptor.setPhase(phase.getValue()); + } + // Dependency resolution flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyResolution = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION); + if (requiresDependencyResolution != null) { + java.lang.String v = requiresDependencyResolution.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyResolutionRequired(v); + } + // Dependency collection flag + com.thoughtworks.qdox.model.DocletTag requiresDependencyCollection = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION); + if (requiresDependencyCollection != null) { + java.lang.String v = requiresDependencyCollection.getValue(); + if (org.codehaus.plexus.util.StringUtils.isEmpty(v)) { + v = "runtime"; + } + mojoDescriptor.setDependencyCollectionRequired(v); + } + // requiresDirectInvocation flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, mojoDescriptor.isDirectInvocationOnly()); + mojoDescriptor.setDirectInvocationOnly(value); + // Online flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired()); + mojoDescriptor.setOnlineRequired(value); + // Project flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired()); + mojoDescriptor.setProjectRequired(value); + // requiresReports flag + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports()); + mojoDescriptor.setRequiresReports(value); + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + // Deprecation hint + com.thoughtworks.qdox.model.DocletTag deprecated = javaClass.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecated != null) { + mojoDescriptor.setDeprecated(deprecated.getValue()); + } + // What version it was introduced in + com.thoughtworks.qdox.model.DocletTag since = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + { + mojoDescriptor.setSince(/* NPEX_NULL_EXP */ + since.getValue()); + } + // Thread-safe mojo + value = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.getBooleanTagValue(javaClass, org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe()); + mojoDescriptor.setThreadSafe(value); + extractParameters(mojoDescriptor, javaClass); + return mojoDescriptor; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/metadata.json new file mode 100644 index 000000000..c9899222e --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 234, + "npe_method": "createMojoDescriptor", + "deref_field": "since", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_280" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/npe.json new file mode 100644 index 000000000..1bb3fdd57 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_280/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 234, + "npe_method": "createMojoDescriptor", + "deref_field": "since", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/buggy.java new file mode 100644 index 000000000..9359028a4 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/buggy.java @@ -0,0 +1,664 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ +/** + * + * + * @param javaClass + * not null + * @param tagName + * not null + * @param defaultValue + * the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ +private static boolean getBooleanTagValue(com.thoughtworks.qdox.model.JavaClass javaClass, java.lang.String tagName, boolean defaultValue) { + com.thoughtworks.qdox.model.DocletTag tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(javaClass, tagName); + { + java.lang.String value = /* NPEX_NULL_EXP */ + tag.getValue(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(value)) { + defaultValue = java.lang.Boolean.valueOf(value).booleanValue(); + } + } + return defaultValue; +} + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/metadata.json new file mode 100644 index 000000000..5f3641a93 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 318, + "npe_method": "getBooleanTagValue", + "deref_field": "tag", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_306" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/npe.json new file mode 100644 index 000000000..17ecda5f8 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_306/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 318, + "npe_method": "getBooleanTagValue", + "deref_field": "tag", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/buggy.java new file mode 100644 index 000000000..b8bbf916f --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/buggy.java @@ -0,0 +1,660 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ +/** + * + * + * @param javaClass + * not null + * @param tagName + * not null + * @return docletTag instance + */ +private static com.thoughtworks.qdox.model.DocletTag findInClassHierarchy(com.thoughtworks.qdox.model.JavaClass javaClass, java.lang.String tagName) { + com.thoughtworks.qdox.model.DocletTag tag = javaClass.getTagByName(tagName); + if (tag == null) { + com.thoughtworks.qdox.model.JavaClass superClass = javaClass.getSuperJavaClass(); + { + tag = org.apache.maven.tools.plugin.extractor.javadoc.JavaJavadocMojoDescriptorExtractor.findInClassHierarchy(/* NPEX_NULL_EXP */ + superClass, tagName); + } + } + return tag; +} + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/metadata.json new file mode 100644 index 000000000..54e9b398a --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 367, + "npe_method": "findInClassHierarchy", + "deref_field": "superClass", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_360" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/npe.json new file mode 100644 index 000000000..b30ed16df --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_360/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 367, + "npe_method": "findInClassHierarchy", + "deref_field": "superClass", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/buggy.java new file mode 100644 index 000000000..8a404ccab --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/buggy.java @@ -0,0 +1,608 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param javaClass + * not null + * @throws InvalidPluginDescriptorException + * if any + */ +private void extractParameters(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + java.util.Map rawParams = extractFieldParameterTags(javaClass); + for (java.util.Map.Entry entry : rawParams.entrySet()) { + com.thoughtworks.qdox.model.JavaField field = entry.getValue(); + com.thoughtworks.qdox.model.JavaType type = field.getType(); + org.apache.maven.plugin.descriptor.Parameter pd = new org.apache.maven.plugin.descriptor.Parameter(); + pd.setName(entry.getKey()); + pd.setType(type.getFullyQualifiedName()); + pd.setDescription(field.getComment()); + com.thoughtworks.qdox.model.DocletTag deprecationTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + { + pd.setDeprecated(/* NPEX_NULL_EXP */ + deprecationTag.getValue()); + } + com.thoughtworks.qdox.model.DocletTag sinceTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (sinceTag != null) { + pd.setSince(sinceTag.getValue()); + } + com.thoughtworks.qdox.model.DocletTag componentTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT); + if (componentTag != null) { + // Component tag + java.lang.String role = componentTag.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT_ROLE); + if (role == null) { + role = field.getType().toString(); + } + java.lang.String roleHint = componentTag.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT_ROLEHINT); + if (roleHint == null) { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter("role-hint"); + } + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = org.apache.maven.tools.plugin.util.PluginUtils.MAVEN_COMPONENTS.containsValue(role); + if (!isDeprecated) { + // normal component + pd.setRequirement(new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn(((((("Deprecated @component Javadoc tag for '" + pd.getName()) + "' field in ") + javaClass.getFullyQualifiedName()) + ": replace with @Parameter( defaultValue = \"") + role) + "\", readonly = true )"); + pd.setDefaultValue(role); + pd.setRequired(true); + } + pd.setEditable(false); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } else { + // Parameter tag + com.thoughtworks.qdox.model.DocletTag parameter = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER); + pd.setRequired(field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRED) != null); + pd.setEditable(field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.READONLY) == null); + java.lang.String name = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_NAME); + if (!org.codehaus.plexus.util.StringUtils.isEmpty(name)) { + pd.setName(name); + } + java.lang.String alias = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_ALIAS); + if (!org.codehaus.plexus.util.StringUtils.isEmpty(alias)) { + pd.setAlias(alias); + } + java.lang.String expression = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_EXPRESSION); + java.lang.String property = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_PROPERTY); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && org.codehaus.plexus.util.StringUtils.isNotEmpty(property)) { + getLogger().error(((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ":"); + getLogger().error(" Cannot use both:"); + getLogger().error(" @parameter expression=\"${property}\""); + getLogger().error(" and"); + getLogger().error(" @parameter property=\"property\""); + getLogger().error(" Second syntax is preferred."); + throw new org.apache.maven.plugin.descriptor.InvalidParameterException((((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ": cannot") + " use both @parameter expression and property", null); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression)) { + getLogger().warn(((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ":"); + getLogger().warn(" The syntax"); + getLogger().warn(" @parameter expression=\"${property}\""); + getLogger().warn(" is deprecated, please use"); + getLogger().warn(" @parameter property=\"property\""); + getLogger().warn(" instead."); + } else if (org.codehaus.plexus.util.StringUtils.isNotEmpty(property)) { + expression = ("${" + property) + "}"; + } + pd.setExpression(expression); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + getLogger().warn(((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ":"); + getLogger().warn(" The syntax"); + getLogger().warn(" @parameter expression=\"${component.#}\""); + getLogger().warn(" is deprecated, please use"); + getLogger().warn(" @component role=\"\" roleHint=\"\""); + getLogger().warn(" instead."); + } + if ("${reports}".equals(pd.getExpression())) { + mojoDescriptor.setRequiresReports(true); + } + pd.setDefaultValue(parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE)); + pd.setImplementation(parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION)); + } + mojoDescriptor.addParameter(pd); + } +} + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/metadata.json new file mode 100644 index 000000000..73b05fae7 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 399, + "npe_method": "extractParameters", + "deref_field": "deprecationTag", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_399" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/npe.json new file mode 100644 index 000000000..836048d19 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_399/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 399, + "npe_method": "extractParameters", + "deref_field": "deprecationTag", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/buggy.java new file mode 100644 index 000000000..781a8e14f --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/buggy.java @@ -0,0 +1,608 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param javaClass + * not null + * @throws InvalidPluginDescriptorException + * if any + */ +private void extractParameters(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + java.util.Map rawParams = extractFieldParameterTags(javaClass); + for (java.util.Map.Entry entry : rawParams.entrySet()) { + com.thoughtworks.qdox.model.JavaField field = entry.getValue(); + com.thoughtworks.qdox.model.JavaType type = field.getType(); + org.apache.maven.plugin.descriptor.Parameter pd = new org.apache.maven.plugin.descriptor.Parameter(); + pd.setName(entry.getKey()); + pd.setType(type.getFullyQualifiedName()); + pd.setDescription(field.getComment()); + com.thoughtworks.qdox.model.DocletTag deprecationTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecationTag != null) { + pd.setDeprecated(deprecationTag.getValue()); + } + com.thoughtworks.qdox.model.DocletTag sinceTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + { + pd.setSince(/* NPEX_NULL_EXP */ + sinceTag.getValue()); + } + com.thoughtworks.qdox.model.DocletTag componentTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT); + if (componentTag != null) { + // Component tag + java.lang.String role = componentTag.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT_ROLE); + if (role == null) { + role = field.getType().toString(); + } + java.lang.String roleHint = componentTag.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT_ROLEHINT); + if (roleHint == null) { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter("role-hint"); + } + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = org.apache.maven.tools.plugin.util.PluginUtils.MAVEN_COMPONENTS.containsValue(role); + if (!isDeprecated) { + // normal component + pd.setRequirement(new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn(((((("Deprecated @component Javadoc tag for '" + pd.getName()) + "' field in ") + javaClass.getFullyQualifiedName()) + ": replace with @Parameter( defaultValue = \"") + role) + "\", readonly = true )"); + pd.setDefaultValue(role); + pd.setRequired(true); + } + pd.setEditable(false); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } else { + // Parameter tag + com.thoughtworks.qdox.model.DocletTag parameter = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER); + pd.setRequired(field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.REQUIRED) != null); + pd.setEditable(field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.READONLY) == null); + java.lang.String name = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_NAME); + if (!org.codehaus.plexus.util.StringUtils.isEmpty(name)) { + pd.setName(name); + } + java.lang.String alias = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_ALIAS); + if (!org.codehaus.plexus.util.StringUtils.isEmpty(alias)) { + pd.setAlias(alias); + } + java.lang.String expression = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_EXPRESSION); + java.lang.String property = parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_PROPERTY); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && org.codehaus.plexus.util.StringUtils.isNotEmpty(property)) { + getLogger().error(((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ":"); + getLogger().error(" Cannot use both:"); + getLogger().error(" @parameter expression=\"${property}\""); + getLogger().error(" and"); + getLogger().error(" @parameter property=\"property\""); + getLogger().error(" Second syntax is preferred."); + throw new org.apache.maven.plugin.descriptor.InvalidParameterException((((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ": cannot") + " use both @parameter expression and property", null); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression)) { + getLogger().warn(((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ":"); + getLogger().warn(" The syntax"); + getLogger().warn(" @parameter expression=\"${property}\""); + getLogger().warn(" is deprecated, please use"); + getLogger().warn(" @parameter property=\"property\""); + getLogger().warn(" instead."); + } else if (org.codehaus.plexus.util.StringUtils.isNotEmpty(property)) { + expression = ("${" + property) + "}"; + } + pd.setExpression(expression); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + getLogger().warn(((javaClass.getFullyQualifiedName() + "#") + field.getName()) + ":"); + getLogger().warn(" The syntax"); + getLogger().warn(" @parameter expression=\"${component.#}\""); + getLogger().warn(" is deprecated, please use"); + getLogger().warn(" @component role=\"\" roleHint=\"\""); + getLogger().warn(" instead."); + } + if ("${reports}".equals(pd.getExpression())) { + mojoDescriptor.setRequiresReports(true); + } + pd.setDefaultValue(parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE)); + pd.setImplementation(parameter.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION)); + } + mojoDescriptor.addParameter(pd); + } +} + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/metadata.json new file mode 100644 index 000000000..1ce046b0c --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 403, + "npe_method": "extractParameters", + "deref_field": "sinceTag", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_405" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/npe.json new file mode 100644 index 000000000..ea4c57867 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_405/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 403, + "npe_method": "extractParameters", + "deref_field": "sinceTag", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/buggy.java new file mode 100644 index 000000000..708c32b99 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/buggy.java @@ -0,0 +1,560 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param javaClass + * not null + * @throws InvalidPluginDescriptorException + * if any + */ +private void extractParameters(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, com.thoughtworks.qdox.model.JavaClass javaClass) throws org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + java.util.Map rawParams = extractFieldParameterTags(javaClass); + for (java.util.Map.Entry entry : rawParams.entrySet()) { + com.thoughtworks.qdox.model.JavaField field = entry.getValue(); + com.thoughtworks.qdox.model.JavaType type = field.getType(); + org.apache.maven.plugin.descriptor.Parameter pd = new org.apache.maven.plugin.descriptor.Parameter(); + pd.setName(entry.getKey()); + pd.setType(type.getFullyQualifiedName()); + pd.setDescription(field.getComment()); + com.thoughtworks.qdox.model.DocletTag deprecationTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.DEPRECATED); + if (deprecationTag != null) { + pd.setDeprecated(deprecationTag.getValue()); + } + com.thoughtworks.qdox.model.DocletTag sinceTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.SINCE); + if (sinceTag != null) { + pd.setSince(sinceTag.getValue()); + } + com.thoughtworks.qdox.model.DocletTag componentTag = field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT); + { + // Component tag + java.lang.String role = /* NPEX_NULL_EXP */ + componentTag.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT_ROLE); + if (role == null) { + role = field.getType().toString(); + } + java.lang.String roleHint = componentTag.getNamedParameter(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT_ROLEHINT); + if (roleHint == null) { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter("role-hint"); + } + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = org.apache.maven.tools.plugin.util.PluginUtils.MAVEN_COMPONENTS.containsValue(role); + if (!isDeprecated) { + // normal component + pd.setRequirement(new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn(((((("Deprecated @component Javadoc tag for '" + pd.getName()) + "' field in ") + javaClass.getFullyQualifiedName()) + ": replace with @Parameter( defaultValue = \"") + role) + "\", readonly = true )"); + pd.setDefaultValue(role); + pd.setRequired(true); + } + pd.setEditable(false); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + mojoDescriptor.addParameter(pd); + } +} + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/metadata.json new file mode 100644 index 000000000..a54bbb9f8 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 408, + "npe_method": "extractParameters", + "deref_field": "componentTag", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_412" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/npe.json new file mode 100644 index 000000000..489d7562d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_412/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 408, + "npe_method": "extractParameters", + "deref_field": "componentTag", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/buggy.java new file mode 100644 index 000000000..f712d0495 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/buggy.java @@ -0,0 +1,652 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ +/** + * extract fields that are either parameters or components. + * + * @param javaClass + * not null + * @return map with Mojo parameters names as keys + */ +private java.util.Map extractFieldParameterTags(com.thoughtworks.qdox.model.JavaClass javaClass) { + java.util.Map rawParams; + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + com.thoughtworks.qdox.model.JavaClass superClass = javaClass.getSuperJavaClass(); + { + rawParams = extractFieldParameterTags(/* NPEX_NULL_EXP */ + superClass); + } + for (com.thoughtworks.qdox.model.JavaField field : javaClass.getFields()) { + if ((field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.PARAMETER) != null) || (field.getTagByName(org.apache.maven.tools.plugin.extractor.javadoc.JavadocMojoAnnotation.COMPONENT) != null)) { + rawParams.put(field.getName(), field); + } + } + return rawParams; +} + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ + protected void validate( MojoDescriptor mojoDescriptor ) + throws InvalidParameterException + { + @SuppressWarnings( "unchecked" ) + List parameters = mojoDescriptor.getParameters(); + + if ( parameters != null ) + { + for ( int j = 0; j < parameters.size(); j++ ) + { + validateParameter( parameters.get( j ), j ); + } + } + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/metadata.json new file mode 100644 index 000000000..366df615d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 555, + "npe_method": "extractFieldParameterTags", + "deref_field": "superClass", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_549" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/npe.json new file mode 100644 index 000000000..eac37966b --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_549/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 555, + "npe_method": "extractFieldParameterTags", + "deref_field": "superClass", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/Dockerfile b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/buggy.java b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/buggy.java new file mode 100644 index 000000000..1323af834 --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/buggy.java @@ -0,0 +1,660 @@ +package org.apache.maven.tools.plugin.extractor.javadoc; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.descriptor.InvalidParameterException; +import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.extractor.ExtractionException; +import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.util.StringUtils; + +import com.thoughtworks.qdox.JavaProjectBuilder; +import com.thoughtworks.qdox.library.SortedClassLibraryBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaField; +import com.thoughtworks.qdox.model.JavaType; + +/** + *

    + * Extracts Mojo descriptors from Java sources. + *

    + * For more information about the usage tag, have a look to: + * + * http://maven.apache.org/developers/mojo-api-specification.html + * + * @see org.apache.maven.plugin.descriptor.MojoDescriptor + */ +@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" ) +public class JavaJavadocMojoDescriptorExtractor + extends AbstractLogEnabled + implements MojoDescriptorExtractor, JavadocMojoAnnotation +{ + /** + * @param parameter not null + * @param i positive number + * @throws InvalidParameterException if any + */ + protected void validateParameter( Parameter parameter, int i ) + throws InvalidParameterException + { + // TODO: remove when backward compatibility is no longer an issue. + String name = parameter.getName(); + + if ( name == null ) + { + throw new InvalidParameterException( "name", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String type = parameter.getType(); + + if ( type == null ) + { + throw new InvalidParameterException( "type", i ); + } + + // TODO: remove when backward compatibility is no longer an issue. + String description = parameter.getDescription(); + + if ( description == null ) + { + throw new InvalidParameterException( "description", i ); + } + } + + // ---------------------------------------------------------------------- + // Mojo descriptor creation from @tags + // ---------------------------------------------------------------------- + + /** + * @param javaClass not null + * @return a mojo descriptor + * @throws InvalidPluginDescriptorException if any + */ + protected MojoDescriptor createMojoDescriptor( JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); + mojoDescriptor.setLanguage( "java" ); + mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() ); + mojoDescriptor.setDescription( javaClass.getComment() ); + + // ---------------------------------------------------------------------- + // Mojo annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Aggregator flag + DocletTag aggregator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.AGGREGATOR ); + if ( aggregator != null ) + { + mojoDescriptor.setAggregator( true ); + } + + // Configurator hint + DocletTag configurator = findInClassHierarchy( javaClass, JavadocMojoAnnotation.CONFIGURATOR ); + if ( configurator != null ) + { + mojoDescriptor.setComponentConfigurator( configurator.getValue() ); + } + + // Additional phase to execute first + DocletTag execute = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTE ); + if ( execute != null ) + { + String executePhase = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_PHASE ); + String executeGoal = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_GOAL ); + + if ( executePhase == null && executeGoal == null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag requires either a 'phase' or 'goal' parameter" ); + } + else if ( executePhase != null && executeGoal != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute tag can have only one of a 'phase' or 'goal' parameter" ); + } + mojoDescriptor.setExecutePhase( executePhase ); + mojoDescriptor.setExecuteGoal( executeGoal ); + + String lifecycle = execute.getNamedParameter( JavadocMojoAnnotation.EXECUTE_LIFECYCLE ); + if ( lifecycle != null ) + { + mojoDescriptor.setExecuteLifecycle( lifecycle ); + if ( mojoDescriptor.getExecuteGoal() != null ) + { + throw new InvalidPluginDescriptorException( javaClass.getFullyQualifiedName() + + ": @execute lifecycle requires a phase instead of a goal" ); + } + } + } + + // Goal name + DocletTag goal = findInClassHierarchy( javaClass, JavadocMojoAnnotation.GOAL ); + if ( goal != null ) + { + mojoDescriptor.setGoal( goal.getValue() ); + } + + // inheritByDefault flag + boolean value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.INHERIT_BY_DEFAULT, + mojoDescriptor.isInheritedByDefault() ); + mojoDescriptor.setInheritedByDefault( value ); + + // instantiationStrategy + DocletTag tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.INSTANTIATION_STRATEGY ); + if ( tag != null ) + { + mojoDescriptor.setInstantiationStrategy( tag.getValue() ); + } + + // executionStrategy (and deprecated @attainAlways) + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY ); + if ( tag != null ) + { + getLogger().warn( "@" + JavadocMojoAnnotation.MULTI_EXECUTION_STRATEGY + " in " + + javaClass.getFullyQualifiedName() + " is deprecated: please use '@" + + JavadocMojoAnnotation.EXECUTION_STATEGY + " always' instead." ); + mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY ); + } + else + { + mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY ); + } + tag = findInClassHierarchy( javaClass, JavadocMojoAnnotation.EXECUTION_STATEGY ); + if ( tag != null ) + { + mojoDescriptor.setExecutionStrategy( tag.getValue() ); + } + + // Phase name + DocletTag phase = findInClassHierarchy( javaClass, JavadocMojoAnnotation.PHASE ); + if ( phase != null ) + { + mojoDescriptor.setPhase( phase.getValue() ); + } + + // Dependency resolution flag + DocletTag requiresDependencyResolution = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_RESOLUTION ); + if ( requiresDependencyResolution != null ) + { + String v = requiresDependencyResolution.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyResolutionRequired( v ); + } + + // Dependency collection flag + DocletTag requiresDependencyCollection = + findInClassHierarchy( javaClass, JavadocMojoAnnotation.REQUIRES_DEPENDENCY_COLLECTION ); + if ( requiresDependencyCollection != null ) + { + String v = requiresDependencyCollection.getValue(); + + if ( StringUtils.isEmpty( v ) ) + { + v = "runtime"; + } + + mojoDescriptor.setDependencyCollectionRequired( v ); + } + + // requiresDirectInvocation flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_DIRECT_INVOCATION, + mojoDescriptor.isDirectInvocationOnly() ); + mojoDescriptor.setDirectInvocationOnly( value ); + + // Online flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() ); + mojoDescriptor.setOnlineRequired( value ); + + // Project flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() ); + mojoDescriptor.setProjectRequired( value ); + + // requiresReports flag + value = + getBooleanTagValue( javaClass, JavadocMojoAnnotation.REQUIRES_REPORTS, mojoDescriptor.isRequiresReports() ); + mojoDescriptor.setRequiresReports( value ); + + // ---------------------------------------------------------------------- + // Javadoc annotations in alphabetical order + // ---------------------------------------------------------------------- + + // Deprecation hint + DocletTag deprecated = javaClass.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + if ( deprecated != null ) + { + mojoDescriptor.setDeprecated( deprecated.getValue() ); + } + + // What version it was introduced in + DocletTag since = findInClassHierarchy( javaClass, JavadocMojoAnnotation.SINCE ); + if ( since != null ) + { + mojoDescriptor.setSince( since.getValue() ); + } + + // Thread-safe mojo + + value = getBooleanTagValue( javaClass, JavadocMojoAnnotation.THREAD_SAFE, true, mojoDescriptor.isThreadSafe() ); + mojoDescriptor.setThreadSafe( value ); + + extractParameters( mojoDescriptor, javaClass ); + + return mojoDescriptor; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultValue the wanted default value + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + defaultValue = Boolean.valueOf( value ).booleanValue(); + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @param defaultForTag The wanted default value when only the tagname is present + * @param defaultValue the wanted default value when the tag is not specified + * @return the boolean value of the given tagName + * @see #findInClassHierarchy(JavaClass, String) + */ + private static boolean getBooleanTagValue( JavaClass javaClass, String tagName, boolean defaultForTag, + boolean defaultValue ) + { + DocletTag tag = findInClassHierarchy( javaClass, tagName ); + + if ( tag != null ) + { + String value = tag.getValue(); + + if ( StringUtils.isNotEmpty( value ) ) + { + return Boolean.valueOf( value ).booleanValue(); + } + else + { + return defaultForTag; + } + } + return defaultValue; + } + + /** + * @param javaClass not null + * @param tagName not null + * @return docletTag instance + */ + private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) + { + DocletTag tag = javaClass.getTagByName( tagName ); + + if ( tag == null ) + { + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + tag = findInClassHierarchy( superClass, tagName ); + } + } + + return tag; + } + + /** + * @param mojoDescriptor not null + * @param javaClass not null + * @throws InvalidPluginDescriptorException if any + */ + private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass ) + throws InvalidPluginDescriptorException + { + // --------------------------------------------------------------------------------- + // We're resolving class-level, ancestor-class-field, local-class-field order here. + // --------------------------------------------------------------------------------- + + Map rawParams = extractFieldParameterTags( javaClass ); + + for ( Map.Entry entry : rawParams.entrySet() ) + { + JavaField field = entry.getValue(); + + JavaType type = field.getType(); + + Parameter pd = new Parameter(); + + pd.setName( entry.getKey() ); + + pd.setType( type.getFullyQualifiedName() ); + + pd.setDescription( field.getComment() ); + + DocletTag deprecationTag = field.getTagByName( JavadocMojoAnnotation.DEPRECATED ); + + if ( deprecationTag != null ) + { + pd.setDeprecated( deprecationTag.getValue() ); + } + + DocletTag sinceTag = field.getTagByName( JavadocMojoAnnotation.SINCE ); + if ( sinceTag != null ) + { + pd.setSince( sinceTag.getValue() ); + } + + DocletTag componentTag = field.getTagByName( JavadocMojoAnnotation.COMPONENT ); + + if ( componentTag != null ) + { + // Component tag + String role = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLE ); + + if ( role == null ) + { + role = field.getType().toString(); + } + + String roleHint = componentTag.getNamedParameter( JavadocMojoAnnotation.COMPONENT_ROLEHINT ); + + if ( roleHint == null ) + { + // support alternate syntax for better compatibility with the Plexus CDC. + roleHint = componentTag.getNamedParameter( "role-hint" ); + } + + // recognize Maven-injected objects as components annotations instead of parameters + // Note: the expressions we are looking for, i.e. "${project}", are in the values of the Map, + // so the lookup mechanism is different here than in maven-plugin-tools-annotations + boolean isDeprecated = PluginUtils.MAVEN_COMPONENTS.containsValue( role ); + + if ( !isDeprecated ) + { + // normal component + pd.setRequirement( new Requirement( role, roleHint ) ); + } + else + { + // not a component but a Maven object to be transformed into an expression/property + getLogger().warn( "Deprecated @component Javadoc tag for '" + pd.getName() + "' field in " + + javaClass.getFullyQualifiedName() + + ": replace with @Parameter( defaultValue = \"" + role + + "\", readonly = true )" ); + pd.setDefaultValue( role ); + pd.setRequired( true ); + } + + pd.setEditable( false ); + /* TODO: or better like this? Need @component fields be editable for the user? + pd.setEditable( field.getTagByName( READONLY ) == null ); + */ + } + else + { + // Parameter tag + DocletTag parameter = field.getTagByName( JavadocMojoAnnotation.PARAMETER ); + + pd.setRequired( field.getTagByName( JavadocMojoAnnotation.REQUIRED ) != null ); + + pd.setEditable( field.getTagByName( JavadocMojoAnnotation.READONLY ) == null ); + + String name = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_NAME ); + + if ( !StringUtils.isEmpty( name ) ) + { + pd.setName( name ); + } + + String alias = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_ALIAS ); + + if ( !StringUtils.isEmpty( alias ) ) + { + pd.setAlias( alias ); + } + + String expression = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_EXPRESSION ); + String property = parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_PROPERTY ); + + if ( StringUtils.isNotEmpty( expression ) && StringUtils.isNotEmpty( property ) ) + { + getLogger().error( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().error( " Cannot use both:" ); + getLogger().error( " @parameter expression=\"${property}\"" ); + getLogger().error( " and" ); + getLogger().error( " @parameter property=\"property\"" ); + getLogger().error( " Second syntax is preferred." ); + throw new InvalidParameterException( javaClass.getFullyQualifiedName() + "#" + field.getName() + + ": cannot" + " use both @parameter expression and property", null ); + } + + if ( StringUtils.isNotEmpty( expression ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${property}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @parameter property=\"property\"" ); + getLogger().warn( " instead." ); + + } + else if ( StringUtils.isNotEmpty( property ) ) + { + expression = "${" + property + "}"; + } + + pd.setExpression( expression ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + getLogger().warn( javaClass.getFullyQualifiedName() + "#" + field.getName() + ":" ); + getLogger().warn( " The syntax" ); + getLogger().warn( " @parameter expression=\"${component.#}\"" ); + getLogger().warn( " is deprecated, please use" ); + getLogger().warn( " @component role=\"\" roleHint=\"\"" ); + getLogger().warn( " instead." ); + } + + if ( "${reports}".equals( pd.getExpression() ) ) + { + mojoDescriptor.setRequiresReports( true ); + } + + pd.setDefaultValue( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_DEFAULT_VALUE ) ); + + pd.setImplementation( parameter.getNamedParameter( JavadocMojoAnnotation.PARAMETER_IMPLEMENTATION ) ); + } + + mojoDescriptor.addParameter( pd ); + } + } + + /** + * extract fields that are either parameters or components. + * + * @param javaClass not null + * @return map with Mojo parameters names as keys + */ + private Map extractFieldParameterTags( JavaClass javaClass ) + { + Map rawParams; + + // we have to add the parent fields first, so that they will be overwritten by the local fields if + // that actually happens... + JavaClass superClass = javaClass.getSuperJavaClass(); + + if ( superClass != null ) + { + rawParams = extractFieldParameterTags( superClass ); + } + else + { + rawParams = new TreeMap(); + } + + for ( JavaField field : javaClass.getFields() ) + { + if ( field.getTagByName( JavadocMojoAnnotation.PARAMETER ) != null + || field.getTagByName( JavadocMojoAnnotation.COMPONENT ) != null ) + { + rawParams.put( field.getName(), field ); + } + } + return rawParams; + } + + /** {@inheritDoc} */ + public List execute( PluginToolsRequest request ) + throws ExtractionException, InvalidPluginDescriptorException + { + Collection javaClasses = discoverClasses( request ); + + List descriptors = new ArrayList<>(); + + for ( JavaClass javaClass : javaClasses ) + { + DocletTag tag = javaClass.getTagByName( GOAL ); + + if ( tag != null ) + { + MojoDescriptor mojoDescriptor = createMojoDescriptor( javaClass ); + mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() ); + + // Validate the descriptor as best we can before allowing it to be processed. + validate( mojoDescriptor ); + + descriptors.add( mojoDescriptor ); + } + } + + return descriptors; + } + + /** + * @param request The plugin request. + * @return an array of java class + */ + @SuppressWarnings( "unchecked" ) + protected Collection discoverClasses( final PluginToolsRequest request ) + { + JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder() ); + builder.setEncoding( request.getEncoding() ); + + // Build isolated Classloader with only the artifacts of the project (none of this plugin) + List urls = new ArrayList<>( request.getDependencies().size() ); + for ( Artifact artifact : request.getDependencies() ) + { + try + { + urls.add( artifact.getFile().toURI().toURL() ); + } + catch ( MalformedURLException e ) + { + // noop + } + } + builder.addClassLoader( new URLClassLoader( urls.toArray( new URL[0] ), ClassLoader.getSystemClassLoader() ) ); + + MavenProject project = request.getProject(); + + for ( String source : (List) project.getCompileSourceRoots() ) + { + builder.addSourceTree( new File( source ) ); + } + + // TODO be more dynamic + File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); + if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) ) + { + builder.addSourceTree( generatedPlugin ); + } + + return builder.getClasses(); + } + + /** + * @param mojoDescriptor not null + * @throws InvalidParameterException if any + */ +/** + * + * + * @param mojoDescriptor + * not null + * @throws InvalidParameterException + * if any + */ +protected void validate(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor) throws org.apache.maven.plugin.descriptor.InvalidParameterException { + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + { + for (int j = 0; j < /* NPEX_NULL_EXP */ + parameters.size(); j++) { + validateParameter(parameters.get(j), j); + } + } +} +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/metadata.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/metadata.json new file mode 100644 index 000000000..2a74d48fa --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 655, + "npe_method": "validate", + "deref_field": "parameters", + "npe_class": "JavaJavadocMojoDescriptorExtractor", + "repo": "maven-plugin-tools", + "bug_id": "JavaJavadocMojoDescriptorExtractor_648" + } +} diff --git a/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/npe.json b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/npe.json new file mode 100644 index 000000000..32a591b2d --- /dev/null +++ b/Java/maven-plugin-tools-JavaJavadocMojoDescriptorExtractor_648/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java", + "line": 655, + "npe_method": "validate", + "deref_field": "parameters", + "npe_class": "JavaJavadocMojoDescriptorExtractor" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_185/Dockerfile b/Java/maven-plugin-tools-ParameterAnnotationContent_185/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_185/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_185/buggy.java b/Java/maven-plugin-tools-ParameterAnnotationContent_185/buggy.java new file mode 100644 index 000000000..b7d7d9982 --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_185/buggy.java @@ -0,0 +1,199 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Parameter; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ParameterAnnotationContent + extends AnnotatedField + implements Parameter +{ + + private String name; + + private String alias; + + private String property; + + private String defaultValue; + + private boolean required = false; + + private boolean readonly = false; + + private String className; + + public ParameterAnnotationContent( String fieldName, String className ) + { + super( fieldName ); + this.className = className; + } + + public ParameterAnnotationContent( String fieldName, String alias, String property, String defaultValue, + boolean required, boolean readonly, String className ) + { + this( fieldName, className ); + this.alias = alias; + this.property = property; + this.defaultValue = defaultValue; + this.required = required; + this.readonly = readonly; + } + + public String name() + { + return name; + } + + public void name( String name ) + { + this.name = name; + } + + public String alias() + { + return alias; + } + + public void alias( String alias ) + { + this.alias = alias; + } + + public String property() + { + return property; + } + + public void property( String property ) + { + this.property = property; + } + + public String defaultValue() + { + return defaultValue; + } + + public void defaultValue( String defaultValue ) + { + this.defaultValue = defaultValue; + } + + public boolean required() + { + return required; + } + + public void required( boolean required ) + { + this.required = required; + } + + public boolean readonly() + { + return readonly; + } + + public void readonly( boolean readonly ) + { + this.readonly = readonly; + } + + public Class annotationType() + { + return null; + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( super.toString() ); + sb.append( "ParameterAnnotationContent" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", alias='" ).append( alias ).append( '\'' ); + sb.append( ", property='" ).append( property ).append( '\'' ); + sb.append( ", defaultValue='" ).append( defaultValue ).append( '\'' ); + sb.append( ", required=" ).append( required ); + sb.append( ", readonly=" ).append( readonly ); + sb.append( '}' ); + return sb.toString(); + } + + @Override +public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (!(o instanceof org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent)) { + return false; + } + org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent that = ((org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent) (o)); + if (readonly != that.readonly) { + return false; + } + if (required != that.required) { + return false; + } + if (getFieldName() != null ? !getFieldName().equals(that.getFieldName()) : that.getFieldName() != null) { + return false; + } + if (!/* NPEX_NULL_EXP */ + alias.equals(that.alias)) { + return false; + } + if (defaultValue != null ? !defaultValue.equals(that.defaultValue) : that.defaultValue != null) { + return false; + } + if (property != null ? !property.equals(that.property) : that.property != null) { + return false; + } + return true; +} + + @Override + public int hashCode() + { + int result = alias != null ? alias.hashCode() : 0; + result = 31 * result + ( getFieldName() != null ? getFieldName().hashCode() : 0 ); + result = 31 * result + ( property != null ? property.hashCode() : 0 ); + result = 31 * result + ( defaultValue != null ? defaultValue.hashCode() : 0 ); + result = 31 * result + ( required ? 1 : 0 ); + result = 31 * result + ( readonly ? 1 : 0 ); + return result; + } +} diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_185/metadata.json b/Java/maven-plugin-tools-ParameterAnnotationContent_185/metadata.json new file mode 100644 index 000000000..2e4b2b15d --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_185/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-ParameterAnnotationContent_185", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java", + "line": 176, + "npe_method": "equals", + "deref_field": "alias", + "npe_class": "ParameterAnnotationContent", + "repo": "maven-plugin-tools", + "bug_id": "ParameterAnnotationContent_185" + } +} diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_185/npe.json b/Java/maven-plugin-tools-ParameterAnnotationContent_185/npe.json new file mode 100644 index 000000000..0b90d6b3d --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_185/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java", + "line": 176, + "npe_method": "equals", + "deref_field": "alias", + "npe_class": "ParameterAnnotationContent" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_204/Dockerfile b/Java/maven-plugin-tools-ParameterAnnotationContent_204/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_204/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_204/buggy.java b/Java/maven-plugin-tools-ParameterAnnotationContent_204/buggy.java new file mode 100644 index 000000000..b621f2ec7 --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_204/buggy.java @@ -0,0 +1,212 @@ +package org.apache.maven.tools.plugin.extractor.annotations.datamodel; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugins.annotations.Parameter; + +import java.lang.annotation.Annotation; + +/** + * @author Olivier Lamy + * @since 3.0 + */ +public class ParameterAnnotationContent + extends AnnotatedField + implements Parameter +{ + + private String name; + + private String alias; + + private String property; + + private String defaultValue; + + private boolean required = false; + + private boolean readonly = false; + + private String className; + + public ParameterAnnotationContent( String fieldName, String className ) + { + super( fieldName ); + this.className = className; + } + + public ParameterAnnotationContent( String fieldName, String alias, String property, String defaultValue, + boolean required, boolean readonly, String className ) + { + this( fieldName, className ); + this.alias = alias; + this.property = property; + this.defaultValue = defaultValue; + this.required = required; + this.readonly = readonly; + } + + public String name() + { + return name; + } + + public void name( String name ) + { + this.name = name; + } + + public String alias() + { + return alias; + } + + public void alias( String alias ) + { + this.alias = alias; + } + + public String property() + { + return property; + } + + public void property( String property ) + { + this.property = property; + } + + public String defaultValue() + { + return defaultValue; + } + + public void defaultValue( String defaultValue ) + { + this.defaultValue = defaultValue; + } + + public boolean required() + { + return required; + } + + public void required( boolean required ) + { + this.required = required; + } + + public boolean readonly() + { + return readonly; + } + + public void readonly( boolean readonly ) + { + this.readonly = readonly; + } + + public Class annotationType() + { + return null; + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( super.toString() ); + sb.append( "ParameterAnnotationContent" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", alias='" ).append( alias ).append( '\'' ); + sb.append( ", property='" ).append( property ).append( '\'' ); + sb.append( ", defaultValue='" ).append( defaultValue ).append( '\'' ); + sb.append( ", required=" ).append( required ); + sb.append( ", readonly=" ).append( readonly ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( !( o instanceof ParameterAnnotationContent ) ) + { + return false; + } + + ParameterAnnotationContent that = (ParameterAnnotationContent) o; + + if ( readonly != that.readonly ) + { + return false; + } + if ( required != that.required ) + { + return false; + } + + if ( getFieldName() != null ? !getFieldName().equals( that.getFieldName() ) : that.getFieldName() != null ) + { + return false; + } + + if ( alias != null ? !alias.equals( that.alias ) : that.alias != null ) + { + return false; + } + if ( defaultValue != null ? !defaultValue.equals( that.defaultValue ) : that.defaultValue != null ) + { + return false; + } + if ( property != null ? !property.equals( that.property ) : that.property != null ) + { + return false; + } + + return true; + } + + @Override +public int hashCode() { + int result = /* NPEX_NULL_EXP */ + alias.hashCode(); + result = (31 * result) + (getFieldName() != null ? getFieldName().hashCode() : 0); + result = (31 * result) + (property != null ? property.hashCode() : 0); + result = (31 * result) + (defaultValue != null ? defaultValue.hashCode() : 0); + result = (31 * result) + (required ? 1 : 0); + result = (31 * result) + (readonly ? 1 : 0); + return result; +} +} diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_204/metadata.json b/Java/maven-plugin-tools-ParameterAnnotationContent_204/metadata.json new file mode 100644 index 000000000..4f2da71bd --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_204/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-ParameterAnnotationContent_204", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java", + "line": 204, + "npe_method": "hashCode", + "deref_field": "alias", + "npe_class": "ParameterAnnotationContent", + "repo": "maven-plugin-tools", + "bug_id": "ParameterAnnotationContent_204" + } +} diff --git a/Java/maven-plugin-tools-ParameterAnnotationContent_204/npe.json b/Java/maven-plugin-tools-ParameterAnnotationContent_204/npe.json new file mode 100644 index 000000000..89e68bd08 --- /dev/null +++ b/Java/maven-plugin-tools-ParameterAnnotationContent_204/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java", + "line": 204, + "npe_method": "hashCode", + "deref_field": "alias", + "npe_class": "ParameterAnnotationContent" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_155/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_155/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/buggy.java new file mode 100644 index 000000000..d34e3bb06 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/buggy.java @@ -0,0 +1,580 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + +public void writeDescriptor(java.io.File destinationFile, org.apache.maven.tools.plugin.PluginToolsRequest request, boolean helpDescriptor) throws java.io.IOException, org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException { + org.apache.maven.plugin.descriptor.PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + if (destinationFile.exists()) { + destinationFile.delete(); + } else if (!destinationFile.getParentFile().exists()) { + destinationFile.getParentFile().mkdirs(); + } + java.io.Writer writer = null; + try { + writer = new java.io.OutputStreamWriter(new java.io.FileOutputStream(destinationFile), java.nio.charset.StandardCharsets.UTF_8); + org.codehaus.plexus.util.xml.XMLWriter w = new org.codehaus.plexus.util.xml.PrettyPrintXMLWriter(writer, java.nio.charset.StandardCharsets.UTF_8.name(), null); + w.writeMarkup(("\n\n\n"); + w.startElement("plugin"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", pluginDescriptor.getName()); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", pluginDescriptor.getDescription(), helpDescriptor); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "groupId", pluginDescriptor.getGroupId()); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "artifactId", pluginDescriptor.getArtifactId()); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "version", pluginDescriptor.getVersion()); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "goalPrefix", pluginDescriptor.getGoalPrefix()); + if (!helpDescriptor) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "isolatedRealm", java.lang.String.valueOf(pluginDescriptor.isIsolatedRealm())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(pluginDescriptor.isInheritedByDefault())); + } + w.startElement("mojos"); + { + @java.lang.SuppressWarnings("unchecked") + java.util.List descriptors = /* NPEX_NULL_EXP */ + pluginDescriptor.getMojos(); + org.apache.maven.tools.plugin.util.PluginUtils.sortMojos(descriptors); + for (org.apache.maven.plugin.descriptor.MojoDescriptor descriptor : descriptors) { + processMojoDescriptor(descriptor, w, helpDescriptor); + } + } + w.endElement(); + if (!helpDescriptor) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.writeDependencies(w, pluginDescriptor); + } + w.endElement(); + writer.flush(); + } finally { + org.codehaus.plexus.util.IOUtil.close(writer); + } +} + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w, boolean helpDescriptor ) + { + w.startElement( "mojo" ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "goal" ); + w.writeText( mojoDescriptor.getGoal() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + String description = mojoDescriptor.getDescription(); + + if ( StringUtils.isNotEmpty( description ) ) + { + w.startElement( "description" ); + if ( helpDescriptor ) + { + w.writeText( GeneratorUtils.toText( mojoDescriptor.getDescription() ) ); + } + else + { + w.writeText( mojoDescriptor.getDescription() ); + } + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.isDependencyResolutionRequired() ) ) + { + GeneratorUtils.element( w, "requiresDependencyResolution", + mojoDescriptor.isDependencyResolutionRequired() ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresDirectInvocation", + String.valueOf( mojoDescriptor.isDirectInvocationOnly() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresProject", String.valueOf( mojoDescriptor.isProjectRequired() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresReports", String.valueOf( mojoDescriptor.isRequiresReports() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "aggregator", String.valueOf( mojoDescriptor.isAggregator() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "requiresOnline", String.valueOf( mojoDescriptor.isOnlineRequired() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + GeneratorUtils.element( w, "inheritedByDefault", String.valueOf( mojoDescriptor.isInheritedByDefault() ) ); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getPhase() ) ) + { + GeneratorUtils.element( w, "phase", mojoDescriptor.getPhase() ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) ) + { + GeneratorUtils.element( w, "executePhase", mojoDescriptor.getExecutePhase() ); + } + + if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteGoal() ) ) + { + GeneratorUtils.element( w, "executeGoal", mojoDescriptor.getExecuteGoal() ); + } + + if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteLifecycle() ) ) + { + GeneratorUtils.element( w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle() ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "implementation" ); + w.writeText( mojoDescriptor.getImplementation() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "language" ); + w.writeText( mojoDescriptor.getLanguage() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentConfigurator() ) ) + { + w.startElement( "configurator" ); + w.writeText( mojoDescriptor.getComponentConfigurator() ); + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( StringUtils.isNotEmpty( mojoDescriptor.getComponentComposer() ) ) + { + w.startElement( "composer" ); + w.writeText( mojoDescriptor.getComponentComposer() ); + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + w.startElement( "instantiationStrategy" ); + w.writeText( mojoDescriptor.getInstantiationStrategy() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement( "executionStrategy" ); + w.writeText( mojoDescriptor.getExecutionStrategy() ); + w.endElement(); + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( mojoDescriptor.getSince() != null ) + { + w.startElement( "since" ); + + if ( StringUtils.isEmpty( mojoDescriptor.getSince() ) ) + { + w.writeText( "No version given" ); + } + else + { + w.writeText( mojoDescriptor.getSince() ); + } + + w.endElement(); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + if ( mojoDescriptor.getDeprecated() != null ) + { + w.startElement( "deprecated" ); + + if ( StringUtils.isEmpty( mojoDescriptor.getDeprecated() ) ) + { + w.writeText( "No reason given" ); + } + else + { + w.writeText( mojoDescriptor.getDeprecated() ); + } + + w.endElement(); + } + + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + + if ( mojoDescriptor instanceof ExtendedMojoDescriptor ) + { + ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor; + if ( extendedMojoDescriptor.getDependencyCollectionRequired() != null ) + { + GeneratorUtils.element( w, "requiresDependencyCollection", + extendedMojoDescriptor.getDependencyCollectionRequired() ); + } + + GeneratorUtils.element( w, "threadSafe", String.valueOf( extendedMojoDescriptor.isThreadSafe() ) ); + } + + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + + @SuppressWarnings( "unchecked" ) List parameters = mojoDescriptor.getParameters(); + + w.startElement( "parameters" ); + + Map requirements = new LinkedHashMap<>(); + + Set configuration = new LinkedHashSet<>(); + + if ( parameters != null ) + { + if ( helpDescriptor ) + { + PluginUtils.sortMojoParameters( parameters ); + } + + for ( Parameter parameter : parameters ) + { + String expression = getExpression( parameter ); + + if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${component." ) ) + { + // treat it as a component...a requirement, in other words. + + // remove "component." plus expression delimiters + String role = expression.substring( "${component.".length(), expression.length() - 1 ); + + String roleHint = null; + + int posRoleHintSeparator = role.indexOf( '#' ); + if ( posRoleHintSeparator > 0 ) + { + roleHint = role.substring( posRoleHintSeparator + 1 ); + + role = role.substring( 0, posRoleHintSeparator ); + } + + // TODO: remove deprecated expression + requirements.put( parameter.getName(), new Requirement( role, roleHint ) ); + } + else if ( parameter.getRequirement() != null ) + { + requirements.put( parameter.getName(), parameter.getRequirement() ); + } + else if ( !helpDescriptor || parameter.isEditable() ) // don't show readonly parameters in help + { + // treat it as a normal parameter. + + w.startElement( "parameter" ); + + GeneratorUtils.element( w, "name", parameter.getName() ); + + if ( parameter.getAlias() != null ) + { + GeneratorUtils.element( w, "alias", parameter.getAlias() ); + } + + GeneratorUtils.element( w, "type", parameter.getType() ); + + if ( parameter.getSince() != null ) + { + w.startElement( "since" ); + + if ( StringUtils.isEmpty( parameter.getSince() ) ) + { + w.writeText( "No version given" ); + } + else + { + w.writeText( parameter.getSince() ); + } + + w.endElement(); + } + + if ( parameter.getDeprecated() != null ) + { + if ( StringUtils.isEmpty( parameter.getDeprecated() ) ) + { + GeneratorUtils.element( w, "deprecated", "No reason given" ); + } + else + { + GeneratorUtils.element( w, "deprecated", parameter.getDeprecated() ); + } + } + + if ( parameter.getImplementation() != null ) + { + GeneratorUtils.element( w, "implementation", parameter.getImplementation() ); + } + + GeneratorUtils.element( w, "required", Boolean.toString( parameter.isRequired() ) ); + + GeneratorUtils.element( w, "editable", Boolean.toString( parameter.isEditable() ) ); + + GeneratorUtils.element( w, "description", parameter.getDescription(), helpDescriptor ); + + if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) || StringUtils.isNotEmpty( + parameter.getExpression() ) ) + { + configuration.add( parameter ); + } + + w.endElement(); + } + + } + } + + w.endElement(); + + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + + if ( !configuration.isEmpty() ) + { + w.startElement( "configuration" ); + + for ( Parameter parameter : configuration ) + { + if ( helpDescriptor && !parameter.isEditable() ) + { + // don't show readonly parameters in help + continue; + } + + w.startElement( parameter.getName() ); + + String type = parameter.getType(); + if ( StringUtils.isNotEmpty( type ) ) + { + w.addAttribute( "implementation", type ); + } + + if ( parameter.getDefaultValue() != null ) + { + w.addAttribute( "default-value", parameter.getDefaultValue() ); + } + + if ( StringUtils.isNotEmpty( parameter.getExpression() ) ) + { + w.writeText( parameter.getExpression() ); + } + + w.endElement(); + } + + w.endElement(); + } + + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + + if ( !requirements.isEmpty() && !helpDescriptor ) + { + w.startElement( "requirements" ); + + for ( Map.Entry entry : requirements.entrySet() ) + { + String key = entry.getKey(); + Requirement requirement = entry.getValue(); + + w.startElement( "requirement" ); + + GeneratorUtils.element( w, "role", requirement.getRole() ); + + if ( StringUtils.isNotEmpty( requirement.getRoleHint() ) ) + { + GeneratorUtils.element( w, "role-hint", requirement.getRoleHint() ); + } + + GeneratorUtils.element( w, "field-name", key ); + + w.endElement(); + } + + w.endElement(); + } + + w.endElement(); + } + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_155/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/metadata.json new file mode 100644 index 000000000..5114dedb3 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_155", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 132, + "npe_method": "writeDescriptor", + "deref_field": "getMojos", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_155" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_155/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/npe.json new file mode 100644 index 000000000..07d6d22eb --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_155/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 132, + "npe_method": "writeDescriptor", + "deref_field": "getMojos", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_360/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_360/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/buggy.java new file mode 100644 index 000000000..a0ecd8171 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/buggy.java @@ -0,0 +1,476 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(/* NPEX_NULL_EXP */ + mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + if (parameters != null) { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_360/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/metadata.json new file mode 100644 index 000000000..8842cb28c --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_360", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 318, + "npe_method": "processMojoDescriptor", + "deref_field": "getSince", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_360" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_360/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/npe.json new file mode 100644 index 000000000..79cf271a3 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_360/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 318, + "npe_method": "processMojoDescriptor", + "deref_field": "getSince", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_380/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_380/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/buggy.java new file mode 100644 index 000000000..e7b49a344 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/buggy.java @@ -0,0 +1,476 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(/* NPEX_NULL_EXP */ + mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + if (parameters != null) { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_380/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/metadata.json new file mode 100644 index 000000000..8e6048ea0 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_380", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 330, + "npe_method": "processMojoDescriptor", + "deref_field": "getDeprecated", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_380" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_380/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/npe.json new file mode 100644 index 000000000..728bf14cd --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_380/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 330, + "npe_method": "processMojoDescriptor", + "deref_field": "getDeprecated", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_403/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_403/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/buggy.java new file mode 100644 index 000000000..f321f31cd --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", /* NPEX_NULL_EXP */ + extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + if (parameters != null) { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_403/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/metadata.json new file mode 100644 index 000000000..a459e5403 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_403", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 346, + "npe_method": "processMojoDescriptor", + "deref_field": "getDependencyCollectionRequired", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_403" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_403/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/npe.json new file mode 100644 index 000000000..8580116d4 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_403/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 346, + "npe_method": "processMojoDescriptor", + "deref_field": "getDependencyCollectionRequired", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_424/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_424/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/buggy.java new file mode 100644 index 000000000..b3099f36b --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(/* NPEX_NULL_EXP */ + parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_424/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/metadata.json new file mode 100644 index 000000000..1faf6d29f --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_424", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 360, + "npe_method": "processMojoDescriptor", + "deref_field": "parameters", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_424" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_424/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/npe.json new file mode 100644 index 000000000..8821f4f2a --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_424/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 360, + "npe_method": "processMojoDescriptor", + "deref_field": "parameters", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_455/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_455/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/buggy.java new file mode 100644 index 000000000..0463835a1 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/buggy.java @@ -0,0 +1,446 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else { + { + requirements.put(parameter.getName(), /* NPEX_NULL_EXP */ + parameter.getRequirement()); + } + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_455/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/metadata.json new file mode 100644 index 000000000..cb93bb660 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_455", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 378, + "npe_method": "processMojoDescriptor", + "deref_field": "getRequirement", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_455" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_455/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/npe.json new file mode 100644 index 000000000..c618a1245 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_455/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 378, + "npe_method": "processMojoDescriptor", + "deref_field": "getRequirement", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_467/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_467/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/buggy.java new file mode 100644 index 000000000..263d34d20 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", /* NPEX_NULL_EXP */ + parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_467/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/metadata.json new file mode 100644 index 000000000..25e28b0d3 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_467", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 384, + "npe_method": "processMojoDescriptor", + "deref_field": "getAlias", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_467" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_467/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/npe.json new file mode 100644 index 000000000..de74de0de --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_467/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 384, + "npe_method": "processMojoDescriptor", + "deref_field": "getAlias", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_474/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_474/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/buggy.java new file mode 100644 index 000000000..20e4a8854 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(/* NPEX_NULL_EXP */ + parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_474/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/metadata.json new file mode 100644 index 000000000..cff1ed389 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_474", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 389, + "npe_method": "processMojoDescriptor", + "deref_field": "getSince", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_474" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_474/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/npe.json new file mode 100644 index 000000000..5bbd78604 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_474/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 389, + "npe_method": "processMojoDescriptor", + "deref_field": "getSince", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_490/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_490/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/buggy.java new file mode 100644 index 000000000..db15154aa --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + { + if (org.codehaus.plexus.util.StringUtils.isEmpty(/* NPEX_NULL_EXP */ + parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_490/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/metadata.json new file mode 100644 index 000000000..3e51f28bb --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_490", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 397, + "npe_method": "processMojoDescriptor", + "deref_field": "getDeprecated", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_490" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_490/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/npe.json new file mode 100644 index 000000000..a71864b29 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_490/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 397, + "npe_method": "processMojoDescriptor", + "deref_field": "getDeprecated", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_502/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_502/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/buggy.java new file mode 100644 index 000000000..0c4265a96 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", /* NPEX_NULL_EXP */ + parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + if (parameter.getDefaultValue() != null) { + w.addAttribute("default-value", parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_502/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/metadata.json new file mode 100644 index 000000000..672ce0702 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_502", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 404, + "npe_method": "processMojoDescriptor", + "deref_field": "getImplementation", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_502" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_502/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/npe.json new file mode 100644 index 000000000..42b4cc29b --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_502/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 404, + "npe_method": "processMojoDescriptor", + "deref_field": "getImplementation", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_551/Dockerfile b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_551/buggy.java b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/buggy.java new file mode 100644 index 000000000..fab26278d --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/buggy.java @@ -0,0 +1,479 @@ +package org.apache.maven.tools.plugin.generator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.descriptor.Requirement; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; +import org.apache.maven.tools.plugin.PluginToolsRequest; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Generate a Maven Plugin Descriptor XML file and + * corresponding plugin-help.xml help content for {@link PluginHelpGenerator}. + * + */ +public class PluginDescriptorGenerator + implements Generator +{ + + private final Log log; + + public PluginDescriptorGenerator( Log log ) + { + this.log = log; + } + + /** + * {@inheritDoc} + */ + public void execute( File destinationDirectory, PluginToolsRequest request ) + throws GeneratorException + { + // eventually rewrite help mojo class to match actual package name + PluginHelpGenerator.rewriteHelpMojo( request, log ); + + try + { + // write complete plugin.xml descriptor + File f = new File( destinationDirectory, "plugin.xml" ); + writeDescriptor( f, request, false ); + + // write plugin-help.xml help-descriptor + MavenProject mavenProject = request.getProject(); + + f = new File( mavenProject.getBuild().getOutputDirectory(), + PluginHelpGenerator.getPluginHelpPath( mavenProject ) ); + + writeDescriptor( f, request, true ); + } + catch ( IOException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + catch ( DuplicateMojoDescriptorException e ) + { + throw new GeneratorException( e.getMessage(), e ); + } + } + + private String getVersion() + { + Package p = this.getClass().getPackage(); + String version = ( p == null ) ? null : p.getSpecificationVersion(); + return ( version == null ) ? "SNAPSHOT" : version; + } + + public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor ) + throws IOException, DuplicateMojoDescriptorException + { + PluginDescriptor pluginDescriptor = request.getPluginDescriptor(); + + if ( destinationFile.exists() ) + { + destinationFile.delete(); + } + else + { + if ( !destinationFile.getParentFile().exists() ) + { + destinationFile.getParentFile().mkdirs(); + } + } + + Writer writer = null; + try + { + writer = new OutputStreamWriter( new FileOutputStream( destinationFile ), UTF_8 ); + + XMLWriter w = new PrettyPrintXMLWriter( writer, UTF_8.name(), null ); + + w.writeMarkup( "\n\n\n" ); + + w.startElement( "plugin" ); + + GeneratorUtils.element( w, "name", pluginDescriptor.getName() ); + + GeneratorUtils.element( w, "description", pluginDescriptor.getDescription(), helpDescriptor ); + + GeneratorUtils.element( w, "groupId", pluginDescriptor.getGroupId() ); + + GeneratorUtils.element( w, "artifactId", pluginDescriptor.getArtifactId() ); + + GeneratorUtils.element( w, "version", pluginDescriptor.getVersion() ); + + GeneratorUtils.element( w, "goalPrefix", pluginDescriptor.getGoalPrefix() ); + + if ( !helpDescriptor ) + { + GeneratorUtils.element( w, "isolatedRealm", String.valueOf( pluginDescriptor.isIsolatedRealm() ) ); + + GeneratorUtils.element( w, "inheritedByDefault", + String.valueOf( pluginDescriptor.isInheritedByDefault() ) ); + } + + w.startElement( "mojos" ); + + if ( pluginDescriptor.getMojos() != null ) + { + @SuppressWarnings( "unchecked" ) List descriptors = pluginDescriptor.getMojos(); + + PluginUtils.sortMojos( descriptors ); + + for ( MojoDescriptor descriptor : descriptors ) + { + processMojoDescriptor( descriptor, w, helpDescriptor ); + } + } + + w.endElement(); + + if ( !helpDescriptor ) + { + GeneratorUtils.writeDependencies( w, pluginDescriptor ); + } + + w.endElement(); + + writer.flush(); + + } + finally + { + IOUtil.close( writer ); + } + } + + protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w ) + { + processMojoDescriptor( mojoDescriptor, w, false ); + } + + /** + * @param mojoDescriptor not null + * @param w not null + * @param helpDescriptor will clean html content from description fields + */ +/** + * + * + * @param mojoDescriptor + * not null + * @param w + * not null + * @param helpDescriptor + * will clean html content from description fields + */ +protected void processMojoDescriptor(org.apache.maven.plugin.descriptor.MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.XMLWriter w, boolean helpDescriptor) { + w.startElement("mojo"); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("goal"); + w.writeText(mojoDescriptor.getGoal()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + java.lang.String description = mojoDescriptor.getDescription(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(description)) { + w.startElement("description"); + if (helpDescriptor) { + w.writeText(org.apache.maven.tools.plugin.generator.GeneratorUtils.toText(mojoDescriptor.getDescription())); + } else { + w.writeText(mojoDescriptor.getDescription()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyResolution", mojoDescriptor.isDependencyResolutionRequired()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDirectInvocation", java.lang.String.valueOf(mojoDescriptor.isDirectInvocationOnly())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresProject", java.lang.String.valueOf(mojoDescriptor.isProjectRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresReports", java.lang.String.valueOf(mojoDescriptor.isRequiresReports())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "aggregator", java.lang.String.valueOf(mojoDescriptor.isAggregator())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresOnline", java.lang.String.valueOf(mojoDescriptor.isOnlineRequired())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "inheritedByDefault", java.lang.String.valueOf(mojoDescriptor.isInheritedByDefault())); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getPhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "phase", mojoDescriptor.getPhase()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecutePhase())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executePhase", mojoDescriptor.getExecutePhase()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteGoal())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeGoal", mojoDescriptor.getExecuteGoal()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getExecuteLifecycle())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle()); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("implementation"); + w.writeText(mojoDescriptor.getImplementation()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("language"); + w.writeText(mojoDescriptor.getLanguage()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentConfigurator())) { + w.startElement("configurator"); + w.writeText(mojoDescriptor.getComponentConfigurator()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) { + w.startElement("composer"); + w.writeText(mojoDescriptor.getComponentComposer()); + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + w.startElement("instantiationStrategy"); + w.writeText(mojoDescriptor.getInstantiationStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // Strategy for handling repeated reference to mojo in + // the calculated (decorated, resolved) execution stack + // ---------------------------------------------------------------------- + w.startElement("executionStrategy"); + w.writeText(mojoDescriptor.getExecutionStrategy()); + w.endElement(); + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(mojoDescriptor.getSince()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + if (mojoDescriptor.getDeprecated() != null) { + w.startElement("deprecated"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(mojoDescriptor.getDeprecated())) { + w.writeText("No reason given"); + } else { + w.writeText(mojoDescriptor.getDeprecated()); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Extended (3.0) descriptor + // ---------------------------------------------------------------------- + if (mojoDescriptor instanceof org.apache.maven.tools.plugin.ExtendedMojoDescriptor) { + org.apache.maven.tools.plugin.ExtendedMojoDescriptor extendedMojoDescriptor = ((org.apache.maven.tools.plugin.ExtendedMojoDescriptor) (mojoDescriptor)); + if (extendedMojoDescriptor.getDependencyCollectionRequired() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "requiresDependencyCollection", extendedMojoDescriptor.getDependencyCollectionRequired()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "threadSafe", java.lang.String.valueOf(extendedMojoDescriptor.isThreadSafe())); + } + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + @java.lang.SuppressWarnings("unchecked") + java.util.List parameters = mojoDescriptor.getParameters(); + w.startElement("parameters"); + java.util.Map requirements = new java.util.LinkedHashMap<>(); + java.util.Set configuration = new java.util.LinkedHashSet<>(); + if (parameters != null) { + if (helpDescriptor) { + org.apache.maven.tools.plugin.util.PluginUtils.sortMojoParameters(parameters); + } + for (org.apache.maven.plugin.descriptor.Parameter parameter : parameters) { + java.lang.String expression = getExpression(parameter); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(expression) && expression.startsWith("${component.")) { + // treat it as a component...a requirement, in other words. + // remove "component." plus expression delimiters + java.lang.String role = expression.substring("${component.".length(), expression.length() - 1); + java.lang.String roleHint = null; + int posRoleHintSeparator = role.indexOf('#'); + if (posRoleHintSeparator > 0) { + roleHint = role.substring(posRoleHintSeparator + 1); + role = role.substring(0, posRoleHintSeparator); + } + // TODO: remove deprecated expression + requirements.put(parameter.getName(), new org.apache.maven.plugin.descriptor.Requirement(role, roleHint)); + } else if (parameter.getRequirement() != null) { + requirements.put(parameter.getName(), parameter.getRequirement()); + } else // don't show readonly parameters in help + if ((!helpDescriptor) || parameter.isEditable()) { + // treat it as a normal parameter. + w.startElement("parameter"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "name", parameter.getName()); + if (parameter.getAlias() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "alias", parameter.getAlias()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "type", parameter.getType()); + if (parameter.getSince() != null) { + w.startElement("since"); + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getSince())) { + w.writeText("No version given"); + } else { + w.writeText(parameter.getSince()); + } + w.endElement(); + } + if (parameter.getDeprecated() != null) { + if (org.codehaus.plexus.util.StringUtils.isEmpty(parameter.getDeprecated())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", "No reason given"); + } else { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "deprecated", parameter.getDeprecated()); + } + } + if (parameter.getImplementation() != null) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "implementation", parameter.getImplementation()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "required", java.lang.Boolean.toString(parameter.isRequired())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "editable", java.lang.Boolean.toString(parameter.isEditable())); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "description", parameter.getDescription(), helpDescriptor); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getDefaultValue()) || org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + configuration.add(parameter); + } + w.endElement(); + } + } + } + w.endElement(); + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + if (!configuration.isEmpty()) { + w.startElement("configuration"); + for (org.apache.maven.plugin.descriptor.Parameter parameter : configuration) { + if (helpDescriptor && (!parameter.isEditable())) { + // don't show readonly parameters in help + continue; + } + w.startElement(parameter.getName()); + java.lang.String type = parameter.getType(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(type)) { + w.addAttribute("implementation", type); + } + { + w.addAttribute("default-value", /* NPEX_NULL_EXP */ + parameter.getDefaultValue()); + } + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(parameter.getExpression())) { + w.writeText(parameter.getExpression()); + } + w.endElement(); + } + w.endElement(); + } + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + if ((!requirements.isEmpty()) && (!helpDescriptor)) { + w.startElement("requirements"); + for (java.util.Map.Entry entry : requirements.entrySet()) { + java.lang.String key = entry.getKey(); + org.apache.maven.plugin.descriptor.Requirement requirement = entry.getValue(); + w.startElement("requirement"); + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role", requirement.getRole()); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(requirement.getRoleHint())) { + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "role-hint", requirement.getRoleHint()); + } + org.apache.maven.tools.plugin.generator.GeneratorUtils.element(w, "field-name", key); + w.endElement(); + } + w.endElement(); + } + w.endElement(); +} + + /** + * Get the expression value, eventually surrounding it with ${ }. + * + * @param parameter the parameter + * @return the expression value + */ + private String getExpression( Parameter parameter ) + { + String expression = parameter.getExpression(); + if ( StringUtils.isNotBlank( expression ) && !expression.contains( "${" ) ) + { + expression = "${" + expression.trim() + "}"; + parameter.setExpression( expression ); + } + return expression; + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_551/metadata.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/metadata.json new file mode 100644 index 000000000..8b4aaf0c3 --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginDescriptorGenerator_551", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 433, + "npe_method": "processMojoDescriptor", + "deref_field": "getDefaultValue", + "npe_class": "PluginDescriptorGenerator", + "repo": "maven-plugin-tools", + "bug_id": "PluginDescriptorGenerator_551" + } +} diff --git a/Java/maven-plugin-tools-PluginDescriptorGenerator_551/npe.json b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/npe.json new file mode 100644 index 000000000..a985ceb2f --- /dev/null +++ b/Java/maven-plugin-tools-PluginDescriptorGenerator_551/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java", + "line": 433, + "npe_method": "processMojoDescriptor", + "deref_field": "getDefaultValue", + "npe_class": "PluginDescriptorGenerator" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginMetadataParser_120/Dockerfile b/Java/maven-plugin-tools-PluginMetadataParser_120/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_120/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginMetadataParser_120/buggy.java b/Java/maven-plugin-tools-PluginMetadataParser_120/buggy.java new file mode 100644 index 000000000..377995763 --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_120/buggy.java @@ -0,0 +1,169 @@ +package org.apache.maven.tools.plugin.extractor.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.DuplicateParameterException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.tools.plugin.extractor.model.io.xpp3.PluginMetadataXpp3Reader; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Parser for plugin metadata. + */ +public class PluginMetadataParser +{ + /** + * Default implementation path which will be replaced in + * AbstractScriptedMojoDescriptorExtractor#extractMojoDescriptorsFromMetadata(Map, PluginDescriptor) + */ + public static final String IMPL_BASE_PLACEHOLDER = ""; + + /** + * @param metadataFile the metadata file to be parse + * @return a set of MojoDescriptor + * @throws PluginMetadataParseException if any + */ + public Set parseMojoDescriptors( File metadataFile ) + throws PluginMetadataParseException + { + Set descriptors = new HashSet<>(); + + try ( Reader reader = ReaderFactory.newXmlReader( metadataFile ) ) + { + + PluginMetadataXpp3Reader metadataReader = new PluginMetadataXpp3Reader(); + + PluginMetadata pluginMetadata = metadataReader.read( reader ); + + List mojos = pluginMetadata.getMojos(); + + if ( mojos != null ) + { + for ( Mojo mojo : mojos ) + { + MojoDescriptor descriptor = asDescriptor( metadataFile, mojo ); + + descriptors.add( descriptor ); + } + } + } + catch ( IOException | XmlPullParserException e ) + { + throw new PluginMetadataParseException( metadataFile, "Cannot parse plugin metadata from file.", e ); + } + + return descriptors; + } + + /** + * @param metadataFile not null + * @param mojo not null + * @return a mojo descriptor instance + * @throws PluginMetadataParseException if any + */ +/** + * + * + * @param metadataFile + * not null + * @param mojo + * not null + * @return a mojo descriptor instance + * @throws PluginMetadataParseException + * if any + */ +private org.apache.maven.plugin.descriptor.MojoDescriptor asDescriptor(java.io.File metadataFile, org.apache.maven.tools.plugin.extractor.model.Mojo mojo) throws org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException { + org.apache.maven.plugin.descriptor.MojoDescriptor descriptor = new org.apache.maven.plugin.descriptor.MojoDescriptor(); + if (mojo.getCall() != null) { + descriptor.setImplementation((org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser.IMPL_BASE_PLACEHOLDER + ":") + mojo.getCall()); + } else { + descriptor.setImplementation(org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser.IMPL_BASE_PLACEHOLDER); + } + descriptor.setGoal(mojo.getGoal()); + descriptor.setPhase(mojo.getPhase()); + descriptor.setDependencyResolutionRequired(mojo.getRequiresDependencyResolution()); + descriptor.setAggregator(mojo.isAggregator()); + descriptor.setInheritedByDefault(mojo.isInheritByDefault()); + descriptor.setDirectInvocationOnly(mojo.isRequiresDirectInvocation()); + descriptor.setOnlineRequired(mojo.isRequiresOnline()); + descriptor.setProjectRequired(mojo.isRequiresProject()); + descriptor.setRequiresReports(mojo.isRequiresReports()); + descriptor.setDescription(mojo.getDescription()); + descriptor.setDeprecated(mojo.getDeprecation()); + descriptor.setSince(mojo.getSince()); + org.apache.maven.tools.plugin.extractor.model.LifecycleExecution le = mojo.getExecution(); + { + descriptor.setExecuteLifecycle(/* NPEX_NULL_EXP */ + le.getLifecycle()); + descriptor.setExecutePhase(le.getPhase()); + descriptor.setExecuteGoal(le.getGoal()); + } + java.util.List parameters = mojo.getParameters(); + if ((parameters != null) && (!parameters.isEmpty())) { + for (org.apache.maven.tools.plugin.extractor.model.Parameter param : parameters) { + org.apache.maven.plugin.descriptor.Parameter dParam = new org.apache.maven.plugin.descriptor.Parameter(); + dParam.setAlias(param.getAlias()); + dParam.setDeprecated(param.getDeprecation()); + dParam.setDescription(param.getDescription()); + dParam.setEditable(!param.isReadonly()); + dParam.setExpression(param.getExpression()); + dParam.setDefaultValue(param.getDefaultValue()); + dParam.setSince(param.getSince()); + java.lang.String property = param.getProperty(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(property)) { + dParam.setName(property); + } else { + dParam.setName(param.getName()); + } + if (org.codehaus.plexus.util.StringUtils.isEmpty(dParam.getName())) { + throw new org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException(metadataFile, ("Mojo: \'" + mojo.getGoal()) + "\' has a parameter without either property or name attributes. Please specify one."); + } + dParam.setRequired(param.isRequired()); + dParam.setType(param.getType()); + try { + descriptor.addParameter(dParam); + } catch (org.apache.maven.plugin.descriptor.DuplicateParameterException e) { + throw new org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException(metadataFile, "Duplicate parameters detected for mojo: " + mojo.getGoal(), e); + } + } + } + java.util.List components = mojo.getComponents(); + if ((components != null) && (!components.isEmpty())) { + for (org.apache.maven.tools.plugin.extractor.model.Component component : components) { + org.codehaus.plexus.component.repository.ComponentRequirement cr = new org.codehaus.plexus.component.repository.ComponentRequirement(); + cr.setRole(component.getRole()); + cr.setRoleHint(component.getHint()); + descriptor.addRequirement(cr); + } + } + return descriptor; +} +} diff --git a/Java/maven-plugin-tools-PluginMetadataParser_120/metadata.json b/Java/maven-plugin-tools-PluginMetadataParser_120/metadata.json new file mode 100644 index 000000000..e0cf0309e --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_120/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginMetadataParser_120", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java", + "line": 125, + "npe_method": "asDescriptor", + "deref_field": "le", + "npe_class": "PluginMetadataParser", + "repo": "maven-plugin-tools", + "bug_id": "PluginMetadataParser_120" + } +} diff --git a/Java/maven-plugin-tools-PluginMetadataParser_120/npe.json b/Java/maven-plugin-tools-PluginMetadataParser_120/npe.json new file mode 100644 index 000000000..5e2f5ed3a --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_120/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java", + "line": 125, + "npe_method": "asDescriptor", + "deref_field": "le", + "npe_class": "PluginMetadataParser" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginMetadataParser_97/Dockerfile b/Java/maven-plugin-tools-PluginMetadataParser_97/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_97/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginMetadataParser_97/buggy.java b/Java/maven-plugin-tools-PluginMetadataParser_97/buggy.java new file mode 100644 index 000000000..880edac15 --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_97/buggy.java @@ -0,0 +1,167 @@ +package org.apache.maven.tools.plugin.extractor.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.descriptor.DuplicateParameterException; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.tools.plugin.extractor.model.io.xpp3.PluginMetadataXpp3Reader; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Parser for plugin metadata. + */ +public class PluginMetadataParser +{ + /** + * Default implementation path which will be replaced in + * AbstractScriptedMojoDescriptorExtractor#extractMojoDescriptorsFromMetadata(Map, PluginDescriptor) + */ + public static final String IMPL_BASE_PLACEHOLDER = ""; + + /** + * @param metadataFile the metadata file to be parse + * @return a set of MojoDescriptor + * @throws PluginMetadataParseException if any + */ + public Set parseMojoDescriptors( File metadataFile ) + throws PluginMetadataParseException + { + Set descriptors = new HashSet<>(); + + try ( Reader reader = ReaderFactory.newXmlReader( metadataFile ) ) + { + + PluginMetadataXpp3Reader metadataReader = new PluginMetadataXpp3Reader(); + + PluginMetadata pluginMetadata = metadataReader.read( reader ); + + List mojos = pluginMetadata.getMojos(); + + if ( mojos != null ) + { + for ( Mojo mojo : mojos ) + { + MojoDescriptor descriptor = asDescriptor( metadataFile, mojo ); + + descriptors.add( descriptor ); + } + } + } + catch ( IOException | XmlPullParserException e ) + { + throw new PluginMetadataParseException( metadataFile, "Cannot parse plugin metadata from file.", e ); + } + + return descriptors; + } + + /** + * @param metadataFile not null + * @param mojo not null + * @return a mojo descriptor instance + * @throws PluginMetadataParseException if any + */ +/** + * + * + * @param metadataFile + * not null + * @param mojo + * not null + * @return a mojo descriptor instance + * @throws PluginMetadataParseException + * if any + */ +private org.apache.maven.plugin.descriptor.MojoDescriptor asDescriptor(java.io.File metadataFile, org.apache.maven.tools.plugin.extractor.model.Mojo mojo) throws org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException { + org.apache.maven.plugin.descriptor.MojoDescriptor descriptor = new org.apache.maven.plugin.descriptor.MojoDescriptor(); + { + descriptor.setImplementation((org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser.IMPL_BASE_PLACEHOLDER + ":") + /* NPEX_NULL_EXP */ + mojo.getCall()); + } + descriptor.setGoal(mojo.getGoal()); + descriptor.setPhase(mojo.getPhase()); + descriptor.setDependencyResolutionRequired(mojo.getRequiresDependencyResolution()); + descriptor.setAggregator(mojo.isAggregator()); + descriptor.setInheritedByDefault(mojo.isInheritByDefault()); + descriptor.setDirectInvocationOnly(mojo.isRequiresDirectInvocation()); + descriptor.setOnlineRequired(mojo.isRequiresOnline()); + descriptor.setProjectRequired(mojo.isRequiresProject()); + descriptor.setRequiresReports(mojo.isRequiresReports()); + descriptor.setDescription(mojo.getDescription()); + descriptor.setDeprecated(mojo.getDeprecation()); + descriptor.setSince(mojo.getSince()); + org.apache.maven.tools.plugin.extractor.model.LifecycleExecution le = mojo.getExecution(); + if (le != null) { + descriptor.setExecuteLifecycle(le.getLifecycle()); + descriptor.setExecutePhase(le.getPhase()); + descriptor.setExecuteGoal(le.getGoal()); + } + java.util.List parameters = mojo.getParameters(); + if ((parameters != null) && (!parameters.isEmpty())) { + for (org.apache.maven.tools.plugin.extractor.model.Parameter param : parameters) { + org.apache.maven.plugin.descriptor.Parameter dParam = new org.apache.maven.plugin.descriptor.Parameter(); + dParam.setAlias(param.getAlias()); + dParam.setDeprecated(param.getDeprecation()); + dParam.setDescription(param.getDescription()); + dParam.setEditable(!param.isReadonly()); + dParam.setExpression(param.getExpression()); + dParam.setDefaultValue(param.getDefaultValue()); + dParam.setSince(param.getSince()); + java.lang.String property = param.getProperty(); + if (org.codehaus.plexus.util.StringUtils.isNotEmpty(property)) { + dParam.setName(property); + } else { + dParam.setName(param.getName()); + } + if (org.codehaus.plexus.util.StringUtils.isEmpty(dParam.getName())) { + throw new org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException(metadataFile, ("Mojo: \'" + mojo.getGoal()) + "\' has a parameter without either property or name attributes. Please specify one."); + } + dParam.setRequired(param.isRequired()); + dParam.setType(param.getType()); + try { + descriptor.addParameter(dParam); + } catch (org.apache.maven.plugin.descriptor.DuplicateParameterException e) { + throw new org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException(metadataFile, "Duplicate parameters detected for mojo: " + mojo.getGoal(), e); + } + } + } + java.util.List components = mojo.getComponents(); + if ((components != null) && (!components.isEmpty())) { + for (org.apache.maven.tools.plugin.extractor.model.Component component : components) { + org.codehaus.plexus.component.repository.ComponentRequirement cr = new org.codehaus.plexus.component.repository.ComponentRequirement(); + cr.setRole(component.getRole()); + cr.setRoleHint(component.getHint()); + descriptor.addRequirement(cr); + } + } + return descriptor; +} +} diff --git a/Java/maven-plugin-tools-PluginMetadataParser_97/metadata.json b/Java/maven-plugin-tools-PluginMetadataParser_97/metadata.json new file mode 100644 index 000000000..10803f95c --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_97/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginMetadataParser_97", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java", + "line": 107, + "npe_method": "asDescriptor", + "deref_field": "getCall", + "npe_class": "PluginMetadataParser", + "repo": "maven-plugin-tools", + "bug_id": "PluginMetadataParser_97" + } +} diff --git a/Java/maven-plugin-tools-PluginMetadataParser_97/npe.json b/Java/maven-plugin-tools-PluginMetadataParser_97/npe.json new file mode 100644 index 000000000..d9a3d45c8 --- /dev/null +++ b/Java/maven-plugin-tools-PluginMetadataParser_97/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-script/maven-plugin-tools-model/src/main/java/org/apache/maven/tools/plugin/extractor/model/PluginMetadataParser.java", + "line": 107, + "npe_method": "asDescriptor", + "deref_field": "getCall", + "npe_class": "PluginMetadataParser" +} \ No newline at end of file diff --git a/Java/maven-plugin-tools-PluginUtils_134/Dockerfile b/Java/maven-plugin-tools-PluginUtils_134/Dockerfile new file mode 100644 index 000000000..3bd4cd08d --- /dev/null +++ b/Java/maven-plugin-tools-PluginUtils_134/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-plugin-tools + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-plugin-tools-PluginUtils_134/buggy.java b/Java/maven-plugin-tools-PluginUtils_134/buggy.java new file mode 100644 index 000000000..3bab232c8 --- /dev/null +++ b/Java/maven-plugin-tools-PluginUtils_134/buggy.java @@ -0,0 +1,153 @@ +package org.apache.maven.tools.plugin.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; + +/** + * Convenience methods to play with Maven plugins. + * + * @author jdcasey + * + */ +public final class PluginUtils +{ + private PluginUtils() + { + // nop + } + + /** + * Expression associated with class types to recognize Maven objects (injected in fact as parameters by + * maven-core's PluginParameterExpressionEvaluator) like components ("real" components are injected by Plexus). + * + * @deprecated wrong approach (fake components), documented parameter default values instead to learn people how to + * discover them + */ + public static final Map MAVEN_COMPONENTS; + static + { + Map mavenComponents = new HashMap<>(); + + mavenComponents.put( "org.apache.maven.execution.MavenSession", "${session}" ); + mavenComponents.put( "org.apache.maven.project.MavenProject", "${project}" ); + mavenComponents.put( "org.apache.maven.plugin.MojoExecution", "${mojoExecution}" ); + mavenComponents.put( "org.apache.maven.plugin.descriptor.PluginDescriptor", "${plugin}" ); + mavenComponents.put( "org.apache.maven.settings.Settings", "${settings}" ); + + MAVEN_COMPONENTS = Collections.unmodifiableMap( mavenComponents ); + } + + /** + * @param basedir not null + * @param include not null + * @return list of included files with default SCM excluded files + */ + public static String[] findSources( String basedir, String include ) + { + return PluginUtils.findSources( basedir, include, null ); + } + + /** + * @param basedir not null + * @param include not null + * @param exclude could be null + * @return list of included files + */ + public static String[] findSources( String basedir, String include, String exclude ) + { + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir( basedir ); + scanner.setIncludes( new String[] { include } ); + if ( !StringUtils.isEmpty( exclude ) ) + { + scanner.setExcludes( new String[] { exclude, StringUtils.join( FileUtils.getDefaultExcludes(), "," ) } ); + } + else + { + scanner.setExcludes( FileUtils.getDefaultExcludes() ); + } + + scanner.scan(); + + return scanner.getIncludedFiles(); + } + + /** + * Sorts the specified mojo descriptors by goal name. + * + * @param mojoDescriptors The mojo descriptors to sort, may be null. + * @see MojoDescriptor#getGoal() + */ + public static void sortMojos( List mojoDescriptors ) + { + if ( mojoDescriptors != null ) + { + Collections.sort( mojoDescriptors, new Comparator() + { + /** {@inheritDoc} */ + public int compare( MojoDescriptor mojo0, MojoDescriptor mojo1 ) + { + return mojo0.getGoal().compareToIgnoreCase( mojo1.getGoal() ); + } + } ); + } + } + + /** + * Sorts the specified mojo parameters by name. + * + * @param parameters The mojo parameters to sort, may be null. + * @see Parameter#getName() + * @since 2.4.4 + */ +/** + * Sorts the specified mojo parameters by name. + * + * @param parameters + * The mojo parameters to sort, may be null. + * @see Parameter#getName() + * @since 2.4.4 + */ +public static void sortMojoParameters(java.util.List parameters) { + { + java.util.Collections.sort(/* NPEX_NULL_EXP */ + parameters, new java.util.Comparator() { + /** + * {@inheritDoc } + */ + public int compare(org.apache.maven.plugin.descriptor.Parameter parameter1, org.apache.maven.plugin.descriptor.Parameter parameter2) { + return parameter1.getName().compareToIgnoreCase(parameter2.getName()); + } + }); + } +} +} diff --git a/Java/maven-plugin-tools-PluginUtils_134/metadata.json b/Java/maven-plugin-tools-PluginUtils_134/metadata.json new file mode 100644 index 000000000..6580677bb --- /dev/null +++ b/Java/maven-plugin-tools-PluginUtils_134/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-plugin-tools-PluginUtils_134", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java", + "line": 143, + "npe_method": "sortMojoParameters", + "deref_field": "parameters", + "npe_class": "PluginUtils", + "repo": "maven-plugin-tools", + "bug_id": "PluginUtils_134" + } +} diff --git a/Java/maven-plugin-tools-PluginUtils_134/npe.json b/Java/maven-plugin-tools-PluginUtils_134/npe.json new file mode 100644 index 000000000..5575a9501 --- /dev/null +++ b/Java/maven-plugin-tools-PluginUtils_134/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java", + "line": 143, + "npe_method": "sortMojoParameters", + "deref_field": "parameters", + "npe_class": "PluginUtils" +} \ No newline at end of file