diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a81c847..e3af3a7 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,7 +5,6 @@ name: Java CI with Maven on: push: - branches: [ develop ] pull_request: branches: [ develop ] @@ -16,9 +15,13 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: Set up JDK + uses: actions/setup-java@v3 with: - java-version: 1.8 + java-version-file: .java-version + distribution: 'temurin' + cache: 'maven' + - name: Print Maven version + run: mvn --version - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B verify --file pom.xml -PintegrationTest diff --git a/.java-version b/.java-version new file mode 100644 index 0000000..b4de394 --- /dev/null +++ b/.java-version @@ -0,0 +1 @@ +11 diff --git a/README.md b/README.md index 1ed2c87..720524e 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,17 @@ You can use this Maven plugin to generate XML descriptors for FirstSpirit modules. -Make sure you use maven 3.1.x or newer when integrating this plugin into your workspace. +Make sure you use Maven 3.3 or newer when integrating this plugin into your workspace. + +**Attention:** Due to internal changes in Maven 3.8.8 or 3.9.0 and newer, incomplete module.xml files and +FirstSpirit modules may be created with the old `dependencyToXML` goal. Therefore, you should migrate to +plug-in version 2.0.0 and the new `prepare` goal as quickly as possible. # Getting started ## Maven Dependency [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.monday-consulting.maven.plugins/fsm-maven-plugin/badge.svg?style=flat)](http://mvnrepository.com/artifact/com.monday-consulting.maven.plugins/fsm-maven-plugin) -We published our plugin to the maven central repository. -You could include it into your workspace with the following maven dependency: +The FSM Maven plugin is published on Maven Central: ``` @@ -19,107 +22,47 @@ You could include it into your workspace with the following maven dependency: ``` +## Maven Goals + +As of version 2.0.0, the recommended Maven goal is `prepare`. + +- `prepare` +- `dependencyToXML` _(deprecated)_ +- `attachFSM` _(deprecated)_ + ## Plugin Configuration -* You have to configure the plugin with an prototype.xml, the config.xml and a target. -* Your plugin configuration should look like this: +Two things are important for the configuration of the plugin: +- `configXml` defines a list of modules for which dependencies are collected. These are then inserted into the prototype +`module.xml`. +- `prototypeXml` is the template for the `module.xml` to be generated. This is completed with all dependencies. + +Full examples can be found in the integration tests, e.g. [prepare-example](./src/it/prepare-example). ``` com.monday-consulting.maven.plugins fsm-maven-plugin - ${basedir}/target/extra-resources/prototype.module.xml ${basedir}/target/extra-resources/fsm-plugin.xml - ${basedir}/target/extra-resources/module.xml + ${basedir}/target/extra-resources/prototype.module.xml - dependencyToXML + prepare-module package - dependencyToXML + prepare ``` -## Prototype XML - -* This is your prototype FirstSpirit module descriptor which will be consumed by this plugin to generate your working module.xml -* In this file you have to configure your FirstSpirit module components (i.e. project and web components). -* Your prototype XML could look like this: - -``` - - Monday Webforms - ${project.version} - Monday Webforms Form Editor - Monday Consulting GmbH - - - - MONDAY_FORMEDITOR - Monday Webforms editor component - de.espirit.firstspirit.module.GadgetSpecification - - com.monday.webforms.editor.gom.GomFormEditor - com.monday.webforms.editor.gadgets.FormEditorSwingGadgetFactory - com.monday.webforms.editor.gadgets.FormValueEngineerFactory - - - - files/ - webforms-editor-resources - - - - - Monday Webforms Resources - Monday Webforms project resources - com.monday.webforms.admin.project.WebformsProjectApp - - files/ - webforms-admin-resources - - - - - Monday Webforms WebApp - Monday Webforms FIRSTspirit integration. - com.monday.webforms.admin.webapp.WebAppConfiguration - com.monday.webforms.admin.WebformsWebApp - web.xml - - webforms-admin-resources - - - webforms-webapp-resources - - - - - Monday Webforms Analytics Backend - Monday Webforms Analytics Backend FIRSTspirit integration. - com.monday.webforms.admin.analytics.backend.WebAppConfiguration - com.monday.webforms.admin.WebformsWebApp - external/backend/WEB-INF/web.xml - - webforms-admin-resources - - - webforms-backend-libs - - - - -``` - ## Config XML -* In your config.xml you have to configure which folder or artifact should be included in your module descriptor. -* Your config.xml could look like this: +Here you configure for which modules dependencies should be collected. The identifier from `dependencyTagValueInXml` +can then be used in the `module.xml` prototype. ``` @@ -130,9 +73,8 @@ You could include it into your workspace with the following maven dependency: - com.monday.webforms.firstspirit:webforms-webapp:war - lib/ - webforms-webapp-resources + org.example:example-webapp:war + example-webapp-resources module WEB-INF/web.xml @@ -145,368 +87,71 @@ You could include it into your workspace with the following maven dependency: - - com.monday.webforms.analytics:webforms-reporting-webapp:war:${monday.webforms.backend.version} - external/reporting/WEB-INF/lib/ - webforms-reporting-libs - module - - external/reporting/ - WEB-INF/web.xml - - ** - - - META-INF - WEB-INF/lib/ - - - ``` This example includes everything in the WEB-INF folder but excludes explicitly the folders WEB-INF/lib and WEB-INF/classes. -## Generated module XML +## Prototype XML -* A module.xml file generated by this plugin could look like this: +This is the prototype FirstSpirit module descriptor which will be consumed by this plugin to generate the working +`module.xml`. We recommend filtering this prototype beforehand with the Maven Resources plugin so that all variables +(e.g. `${project.version}`) are replaced. + +This is basically a `module.xml` with missing (web-)resources. Here, `identifier` is used +instead to refer to entries from the `configXml`. ``` - Monday Webforms - 5.5.0-SNAPSHOT - Monday Webforms Form Editor - Monday Consulting GmbH - - - MONDAY_FORMEDITOR - Monday Webforms editor component - de.espirit.firstspirit.module.GadgetSpecification - - com.monday.webforms.editor.gom.GomFormEditor - com.monday.webforms.editor.gadgets.FormEditorSwingGadgetFactory - com.monday.webforms.editor.gadgets.FormValueEngineerFactory - - - - files/ - lib/webforms-common-5.5.0-SNAPSHOT.jar - lib/webforms-shared-5.5.0-SNAPSHOT.jar - lib/commons-io-1.3.2.jar - lib/rhino-1.7.7.1.jar - lib/jPod-5.5.1.jar - lib/iscwt-5.5.jar - lib/isfreetype-5.5.jar - lib/isnativec-5.5.jar - lib/jai-core-1.1.3.jar - lib/jai-codec-1.1.3.jar - lib/isrt-4.10.jar - lib/jbig2-5.5.1.jar - lib/license4j-1.6.jar - lib/webforms-gui-5.5.0-SNAPSHOT.jar - lib/webforms-admin-5.5.0-SNAPSHOT.jar - lib/designgridlayout-1.1.jar - lib/swing-layout-1.0.2.jar - lib/monday-common-3.1.1.jar - lib/javax.mail-api-1.4.4.jar - lib/activation-1.1.1.jar - lib/jna-4.1.0.jar - lib/fs-access-5.2.181206.jar - lib/slf4j-api-1.6.4.jar - lib/gson-2.8.2.jar - lib/commons-lang3-3.7.jar - lib/rsyntaxtextarea-2.6.1.jar - lib/webforms-editor-5.5.0-SNAPSHOT.jar - - - - Monday Webforms WebApp - Monday Webforms FIRSTspirit integration. - com.monday.webforms.admin.webapp.WebAppConfiguration - com.monday.webforms.admin.WebformsWebApp - web.xml - - lib/webforms-gui-5.5.0-SNAPSHOT.jar - lib/rsyntaxtextarea-2.6.1.jar - lib/webforms-common-5.5.0-SNAPSHOT.jar - lib/webforms-shared-5.5.0-SNAPSHOT.jar - lib/commons-io-1.3.2.jar - lib/slf4j-api-1.6.4.jar - lib/rhino-1.7.7.1.jar - lib/gson-2.8.2.jar - lib/jPod-5.5.1.jar - lib/iscwt-5.5.jar - lib/isfreetype-5.5.jar - lib/isnativec-5.5.jar - lib/jna-4.1.0.jar - lib/jai-core-1.1.3.jar - lib/jai-codec-1.1.3.jar - lib/isrt-4.10.jar - lib/jbig2-5.5.1.jar - lib/monday-common-3.1.1.jar - lib/javax.mail-api-1.4.4.jar - lib/activation-1.1.1.jar - lib/fs-access-5.2.181206.jar - lib/license4j-1.6.jar - lib/designgridlayout-1.1.jar - lib/swing-layout-1.0.2.jar - lib/webforms-executables-5.5.0-SNAPSHOT.jar - lib/webforms-admin-5.5.0-SNAPSHOT.jar - - - lib/webforms-webapp-lib-5.5.0-SNAPSHOT.jar - lib/fs-access-5.2.181206.jar - lib/webforms-common-5.5.0-SNAPSHOT.jar - lib/jPod-5.5.1.jar - lib/iscwt-5.5.jar - lib/isfreetype-5.5.jar - lib/isnativec-5.5.jar - lib/jna-4.1.0.jar - lib/jai-core-1.1.3.jar - lib/jai-codec-1.1.3.jar - lib/isrt-4.10.jar - lib/jbig2-5.5.1.jar - lib/webforms-spring-5.5.0-SNAPSHOT.jar - lib/jcl-over-slf4j-1.6.4.jar - lib/webforms-shared-5.5.0-SNAPSHOT.jar - lib/webforms-executables-5.5.0-SNAPSHOT.jar - lib/monday-common-3.1.1.jar - lib/webforms-backend-api-client-2.2.2.jar - lib/webforms-backend-common-2.2.2.jar - lib/webforms-backend-api-model-2.2.2.jar - lib/annotations-13.0.jar - lib/jackson-core-2.8.11.jar - lib/jackson-databind-2.8.11.2.jar - lib/jackson-annotations-2.8.0.jar - lib/jai-imageio-core-1.3.1.jar - lib/commons-lang3-3.7.jar - lib/taglibs-standard-impl-1.2.5.jar - lib/commons-beanutils-1.9.3.jar - lib/commons-collections-3.2.2.jar - lib/commons-io-1.3.2.jar - lib/easystream-1.2.15.jar - lib/slf4j-api-1.6.4.jar - lib/slf4j-log4j12-1.6.4.jar - lib/log4j-1.2.17.jar - lib/javax.mail-api-1.4.4.jar - lib/activation-1.1.1.jar - lib/rhino-1.7.7.1.jar - lib/cglib-nodep-3.2.7.jar - lib/jcaptcha-2.0-alpha-1.jar - lib/filters-2.0.235.jar - lib/jcaptcha-api-2.0-alpha-1.jar - lib/spring-context-4.3.22.RELEASE.jar - lib/spring-aop-4.3.22.RELEASE.jar - lib/spring-expression-4.3.22.RELEASE.jar - lib/commons-fileupload-1.3.1.jar - lib/commons-validator-1.6.jar - lib/commons-digester-1.8.1.jar - lib/spring-web-4.3.22.RELEASE.jar - lib/spring-webmvc-4.3.22.RELEASE.jar - lib/spring-core-4.3.22.RELEASE.jar - lib/spring-context-support-4.3.22.RELEASE.jar - lib/license4j-1.6.jar - lib/poi-ooxml-3.17.jar - lib/poi-ooxml-schemas-3.17.jar - lib/xmlbeans-2.6.0.jar - lib/curvesapi-1.04.jar - lib/owasp-java-html-sanitizer-20180219.1.jar - lib/guava-11.0.2.jar - lib/poi-3.17.jar - lib/commons-codec-1.6.jar - lib/commons-collections4-4.1.jar - lib/spring-beans-4.3.22.RELEASE.jar - lib/javax.servlet.jsp.jstl-api-1.2.2.jar - lib/tika-core-1.17.jar - lib/gson-2.8.2.jar - lib/commonmark-0.12.1.jar - lib/commonmark-ext-gfm-tables-0.12.1.jar - lib/commonmark-ext-link-attributes-1.0.1.jar - lib/mapdb-1.0.6.jar - lib/freemarker-2.3.28.jar - lib/imgscalr-lib-4.2.jar - lib/httpclient-4.4.jar - lib/httpcore-4.4.jar - lib/commons-logging-1.1.3.jar - WEB-INF/webforms-analytics.properties - WEB-INF/webforms-mail.properties - WEB-INF/webforms-network.properties - WEB-INF/webforms-license.txt - WEB-INF/webforms-license.properties - WEB-INF/webforms-pdf.properties - WEB-INF/webforms-connection.properties - WEB-INF/templates/pageBreak.jsp - WEB-INF/templates/layout.jsp - WEB-INF/templates/error.jsp - WEB-INF/templates/checkBoxGroup.jsp - WEB-INF/templates/fileUpload.jsp - WEB-INF/templates/captcha.jsp - WEB-INF/templates/success.jsp - WEB-INF/templates/uploadSizeExceeded.jsp - WEB-INF/templates/exit.jsp - WEB-INF/templates/textArea.jsp - WEB-INF/templates/pdf.jsp - WEB-INF/templates/redirect.jsp - WEB-INF/templates/radioGroup.jsp - WEB-INF/templates/summary.jsp - WEB-INF/templates/condition.jsp - WEB-INF/templates/default.jsp - WEB-INF/templates/button.jsp - WEB-INF/templates/webform.jsp - WEB-INF/templates/passwordField.jsp - WEB-INF/templates/paragraph.jsp - WEB-INF/templates/hiddenField.jsp - WEB-INF/templates/methodNotSupported.jsp - WEB-INF/templates/inputField.jsp - WEB-INF/templates/optin.jsp - WEB-INF/templates/calculatedValue.jsp - WEB-INF/templates/comboBox.jsp - WEB-INF/templates/sessionExpired.jsp - WEB-INF/templates/invalidLicense.jsp - WEB-INF/webforms-excel.properties - WEB-INF/log4j.properties - WEB-INF/spring/webforms-views.xml - WEB-INF/spring/webforms-resourcebundle.xml - WEB-INF/spring/webforms-mail.xml - WEB-INF/spring/webforms-actions.xml - WEB-INF/spring/webforms-analytics.xml - WEB-INF/spring/webforms-network.xml - WEB-INF/spring/webforms-application.xml - WEB-INF/spring/webforms-services.xml - WEB-INF/spring/webforms-license.xml - WEB-INF/spring/webforms-connection.xml - WEB-INF/spring/webforms-controllers.xml - WEB-INF/spring/webforms-captcha.xml - - - - Monday Webforms Analytics Backend - 2.2.2 - Monday Webforms Analytics Backend FIRSTspirit integration. - com.monday.webforms.admin.analytics.backend.WebAppConfiguration - com.monday.webforms.admin.WebformsWebApp - external/backend/WEB-INF/web.xml - - lib/webforms-gui-5.5.0-SNAPSHOT.jar - lib/rsyntaxtextarea-2.6.1.jar - lib/webforms-common-5.5.0-SNAPSHOT.jar - lib/webforms-shared-5.5.0-SNAPSHOT.jar - lib/commons-io-1.3.2.jar - lib/slf4j-api-1.6.4.jar - lib/rhino-1.7.7.1.jar - lib/gson-2.8.2.jar - lib/jPod-5.5.1.jar - lib/iscwt-5.5.jar - lib/isfreetype-5.5.jar - lib/isnativec-5.5.jar - lib/jna-4.1.0.jar - lib/jai-core-1.1.3.jar - lib/jai-codec-1.1.3.jar - lib/isrt-4.10.jar - lib/jbig2-5.5.1.jar - lib/monday-common-3.1.1.jar - lib/javax.mail-api-1.4.4.jar - lib/activation-1.1.1.jar - lib/fs-access-5.2.181206.jar - lib/license4j-1.6.jar - lib/designgridlayout-1.1.jar - lib/swing-layout-1.0.2.jar - lib/webforms-executables-5.5.0-SNAPSHOT.jar - lib/webforms-admin-5.5.0-SNAPSHOT.jar - - - external/backend/WEB-INF/lib/webforms-backend-webapp-lib-2.2.2.jar - external/backend/WEB-INF/lib/webforms-backend-common-2.2.2.jar - external/backend/WEB-INF/lib/webforms-backend-api-model-2.2.2.jar - external/backend/WEB-INF/lib/jackson-annotations-2.8.0.jar - external/backend/WEB-INF/lib/monday-common-3.1.0.jar - external/backend/WEB-INF/lib/freemarker-2.3.28.jar - external/backend/WEB-INF/lib/commons-csv-1.5.jar - external/backend/WEB-INF/lib/commons-lang3-3.7.jar - external/backend/WEB-INF/lib/poi-3.17.jar - external/backend/WEB-INF/lib/commons-collections4-4.1.jar - external/backend/WEB-INF/lib/poi-ooxml-3.17.jar - external/backend/WEB-INF/lib/poi-ooxml-schemas-3.17.jar - external/backend/WEB-INF/lib/xmlbeans-2.6.0.jar - external/backend/WEB-INF/lib/stax-api-1.0.1.jar - external/backend/WEB-INF/lib/curvesapi-1.04.jar - external/backend/WEB-INF/lib/xbean-classloader-4.8.jar - external/backend/WEB-INF/lib/spring-boot-starter-amqp-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-messaging-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-rabbit-1.7.9.RELEASE.jar - external/backend/WEB-INF/lib/spring-amqp-1.7.9.RELEASE.jar - external/backend/WEB-INF/lib/spring-retry-1.2.2.RELEASE.jar - external/backend/WEB-INF/lib/http-client-1.1.1.RELEASE.jar - external/backend/WEB-INF/lib/httpclient-4.5.6.jar - external/backend/WEB-INF/lib/httpcore-4.4.10.jar - external/backend/WEB-INF/lib/amqp-client-4.0.3.jar - external/backend/WEB-INF/lib/spring-boot-starter-actuator-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-boot-actuator-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/persistence-api-1.0.2.jar - external/backend/WEB-INF/lib/commons-math3-3.6.1.jar - external/backend/WEB-INF/lib/gson-2.8.5.jar - external/backend/WEB-INF/lib/annotations-13.0.jar - external/backend/WEB-INF/lib/flyway-core-3.2.1.jar - external/backend/WEB-INF/lib/xstream-1.4.10.jar - external/backend/WEB-INF/lib/xmlpull-1.1.3.1.jar - external/backend/WEB-INF/lib/xpp3_min-1.1.4c.jar - external/backend/WEB-INF/lib/rxjava-1.3.8.jar - external/backend/WEB-INF/lib/spring-boot-legacy-1.1.0.RELEASE.jar - external/backend/WEB-INF/lib/spring-security-core-4.2.7.RELEASE.jar - external/backend/WEB-INF/lib/aopalliance-1.0.jar - external/backend/WEB-INF/lib/spring-aop-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-beans-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-context-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-core-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-expression-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-security-web-4.2.7.RELEASE.jar - external/backend/WEB-INF/lib/spring-web-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-security-config-4.2.7.RELEASE.jar - external/backend/WEB-INF/lib/spring-security-oauth2-2.0.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-webmvc-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/commons-codec-1.10.jar - external/backend/WEB-INF/lib/jackson-mapper-asl-1.9.13.jar - external/backend/WEB-INF/lib/jackson-core-asl-1.9.13.jar - external/backend/WEB-INF/lib/spring-security-aspects-4.2.7.RELEASE.jar - external/backend/WEB-INF/lib/slf4j-api-1.7.12.jar - external/backend/WEB-INF/lib/spring-boot-starter-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-boot-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-boot-autoconfigure-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/snakeyaml-1.17.jar - external/backend/WEB-INF/lib/spring-boot-starter-log4j2-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/log4j-slf4j-impl-2.7.jar - external/backend/WEB-INF/lib/log4j-api-2.7.jar - external/backend/WEB-INF/lib/log4j-core-2.7.jar - external/backend/WEB-INF/lib/jcl-over-slf4j-1.7.12.jar - external/backend/WEB-INF/lib/jul-to-slf4j-1.7.25.jar - external/backend/WEB-INF/lib/spring-boot-starter-web-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/hibernate-validator-5.3.6.Final.jar - external/backend/WEB-INF/lib/validation-api-1.1.0.Final.jar - external/backend/WEB-INF/lib/jboss-logging-3.3.2.Final.jar - external/backend/WEB-INF/lib/classmate-1.3.4.jar - external/backend/WEB-INF/lib/jackson-databind-2.8.11.2.jar - external/backend/WEB-INF/lib/jackson-core-2.8.11.jar - external/backend/WEB-INF/lib/spring-boot-starter-jdbc-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-jdbc-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-tx-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/spring-boot-starter-mail-1.5.15.RELEASE.jar - external/backend/WEB-INF/lib/spring-context-support-4.3.18.RELEASE.jar - external/backend/WEB-INF/lib/javax.mail-1.5.6.jar - external/backend/WEB-INF/lib/activation-1.1.jar - external/backend/WEB-INF/lib/commons-dbcp2-2.3.0.jar - external/backend/WEB-INF/lib/commons-pool2-2.4.3.jar - external/backend/WEB-INF/lib/commons-logging-1.2.jar - external/backend/WEB-INF/classes/log4j2.xml - external/backend/WEB-INF/classes/banner.txt - external/backend/WEB-INF/classes/application.properties - external/backend/WEB-INF/lib-migration/spring-security-oauth2-2.0.14.RELEASE.jar - external/backend/WEB-INF/lib-migration/spring-security-core-4.0.4.RELEASE.jar - external/backend/WEB-INF/webforms-backend.properties - external/backend/WEB-INF/spring/backend-custom-overrides.xml - external/backend/WEB-INF/spring/backend-authentication.xml - external/backend/WEB-INF/spring/backend-security.xml - - - + My FirstSpirit Module (I) + ${project.version} + A simple example for a prototype.module.xml + Monday Consulting GmbH + + + MY_PUBLIC_COMPONENT + A FirstSpirit Gadget + de.espirit.firstspirit.module.GadgetSpecification + + org.example.GomExampleEditor + org.example.gadgets.ExampleSwingGadgetFactory + org.example.gadgets.ExmplaeValueEngineerFactory + + + + files/ + my-gadget-dependencies + + + + Example WebApp + Monday Webforms FIRSTspirit integration. + org.example.webapp.WebAppConfiguration + org.example.ExanokeWebApp + web.xml + + example-webapp-config-resources + + + example-webapp-resources + + + ``` + +## Plugin output + +The plugin prepares the folder structure of a FirstSpirit module, which already contains the `module.xml` as well as +`module-isolated.xml` and all required dependencies: + +- `target/fsm-root` + - `META-INF` + - `module.xml` + - `module-isolated.xml` + - `lib` + - _all JARs referenced in the module descriptor_ + +Finally, to create the FSM archive, the Maven Assembly Plugin is required. With the help of an assembly descriptor, +additional files (configurations, customized `web.xml`, etc.) can be added to the module. You can find examples of +this in the integration tests: [prepare-example](./src/it/prepare-example). diff --git a/pom.xml b/pom.xml index 8c49753..95f2c39 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.monday-consulting.maven.plugins fsm-maven-plugin maven-plugin - 1.8.2 + 2.0.0 fsm-maven-plugin https://www.monday-consulting.com @@ -73,29 +73,29 @@ - 3.1.0 + 3.3.9 UTF-8 - 1.8 - 1.8 + 11 + 11 3.3.9 - 1.1.0 5.9.0 3.6.4 1.6.13 1.5 - 3.3.0 - 1.6 - 3.2.0 - 3.10.1 + 3.3.1 + 3.1.0 + 3.6.0 + 3.3.1 + 3.11.0 3.3.0 - 2.22.2 + 3.1.2 @@ -204,6 +204,18 @@ ${mavenVersion} provided + + org.apache.maven + maven-model + ${mavenVersion} + provided + + + org.apache.maven + maven-artifact + ${mavenVersion} + provided + org.apache.maven maven-plugin-api @@ -221,19 +233,9 @@ 2.3.6 - org.eclipse.aether - aether-api - ${eclipseAetherVersion} - - - org.eclipse.aether - aether-util - ${eclipseAetherVersion} - - - org.eclipse.aether - aether-impl - ${eclipseAetherVersion} + org.apache.maven.shared + maven-artifact-transfer + 0.13.1 net.lingala.zip4j @@ -253,6 +255,12 @@ ${junit.version} test + + org.mockito + mockito-core + 4.5.1 + test + @@ -305,7 +313,7 @@ org.apache.maven.plugins maven-invoker-plugin - 3.3.0 + ${maven.invoker.plugin} src/it ${project.build.directory}/it @@ -316,6 +324,13 @@ ${maven.home}/bin/mvnDebug --> + + + org.apache.groovy + groovy-xml + 4.0.13 + + integration-test diff --git a/src/it/dependency-conflict/fsm/plugin.xml b/src/it/d2xml-dependency-conflict/fsm/plugin.xml similarity index 100% rename from src/it/dependency-conflict/fsm/plugin.xml rename to src/it/d2xml-dependency-conflict/fsm/plugin.xml diff --git a/src/it/dependency-conflict/fsm/prototype.module.xml b/src/it/d2xml-dependency-conflict/fsm/prototype.module.xml similarity index 100% rename from src/it/dependency-conflict/fsm/prototype.module.xml rename to src/it/d2xml-dependency-conflict/fsm/prototype.module.xml diff --git a/src/it/dependency-conflict/pom.xml b/src/it/d2xml-dependency-conflict/pom.xml similarity index 100% rename from src/it/dependency-conflict/pom.xml rename to src/it/d2xml-dependency-conflict/pom.xml diff --git a/src/it/dependency-conflict/verify.groovy b/src/it/d2xml-dependency-conflict/verify.groovy similarity index 64% rename from src/it/dependency-conflict/verify.groovy rename to src/it/d2xml-dependency-conflict/verify.groovy index 4b690a3..807dfd0 100644 --- a/src/it/dependency-conflict/verify.groovy +++ b/src/it/d2xml-dependency-conflict/verify.groovy @@ -1,7 +1,9 @@ +import groovy.xml.XmlSlurper + def moduleXmlFile = new File(basedir, 'target/extra-resources/module.xml') -assert moduleXmlFile.exists() : "The module.xml descriptor was not created."; +assert moduleXmlFile.exists() : "The module.xml descriptor was not created" def doc = new XmlSlurper().parse(moduleXmlFile) -assert doc.version == "15.5.0" : "The module.xml version was not filtered." +assert doc.version == "15.5.0" : "The module.xml version was not filtered" // Verify resolved versions for guava @@ -12,16 +14,16 @@ static def getResource(doc, mode, scope, name) { } } -static def verifyResource(doc, mode, scope, version) { +static def verifyResource(doc, mode, scope, versionPattern) { def guava = "com.google.guava:guava" def resource = getResource(doc, mode, scope, guava) def resourceSize = resource.size() assert resourceSize == 1 def resourceVersion = resource.get(0).attributes().version - assert resourceVersion == version : "Guava version for " + mode + "-" + scope + " must be " + version + assert resourceVersion ==~ versionPattern: "Guava version for " + mode + "-" + scope + " must match " + versionPattern } -verifyResource(doc, "isolated", "module", "27.1-jre") -verifyResource(doc, "isolated", "server", "19.0.20150826") -verifyResource(doc, "legacy", "server", "31.1-jre") +verifyResource(doc, "isolated", "module", /27.1-jre/) +verifyResource(doc, "isolated", "server", /19.0.*/) +verifyResource(doc, "legacy", "server", /31.1-jre/) diff --git a/src/it/example/fsm/plugin.xml b/src/it/d2xml-example/fsm/plugin.xml similarity index 100% rename from src/it/example/fsm/plugin.xml rename to src/it/d2xml-example/fsm/plugin.xml diff --git a/src/it/example/fsm/prototype.module.xml b/src/it/d2xml-example/fsm/prototype.module.xml similarity index 100% rename from src/it/example/fsm/prototype.module.xml rename to src/it/d2xml-example/fsm/prototype.module.xml diff --git a/src/it/example/pom.xml b/src/it/d2xml-example/pom.xml similarity index 100% rename from src/it/example/pom.xml rename to src/it/d2xml-example/pom.xml diff --git a/src/it/example/verify.groovy b/src/it/d2xml-example/verify.groovy similarity index 93% rename from src/it/example/verify.groovy rename to src/it/d2xml-example/verify.groovy index c631c0f..22db268 100644 --- a/src/it/example/verify.groovy +++ b/src/it/d2xml-example/verify.groovy @@ -1,7 +1,9 @@ +import groovy.xml.XmlSlurper + def moduleXmlFile = new File(basedir, 'target/extra-resources/module.xml') -assert moduleXmlFile.exists() : "The module.xml descriptor was not created."; +assert moduleXmlFile.exists() : "The module.xml descriptor was not created" def doc = new XmlSlurper().parse(moduleXmlFile) -assert doc.version == 11 : "The module.xml version was not filtered." +assert doc.version == 11 : "The module.xml version was not filtered" // verify commons-math3 is under -> -> and has the correct version diff --git a/src/it/prepare-dependency-with-classifier/fsm/plugin.xml b/src/it/prepare-dependency-with-classifier/fsm/plugin.xml new file mode 100644 index 0000000..8269993 --- /dev/null +++ b/src/it/prepare-dependency-with-classifier/fsm/plugin.xml @@ -0,0 +1,12 @@ + + + + + + ${project.groupId}:${project.artifactId}:${project.version} + + + xmlresolver + + + diff --git a/src/it/prepare-dependency-with-classifier/fsm/prototype.module.xml b/src/it/prepare-dependency-with-classifier/fsm/prototype.module.xml new file mode 100644 index 0000000..392af89 --- /dev/null +++ b/src/it/prepare-dependency-with-classifier/fsm/prototype.module.xml @@ -0,0 +1,16 @@ + + + Monday XML Resovler + ${project.version} + + + + XML Resolver + ${project.version} + + + xmlresolver + + + + diff --git a/src/it/prepare-dependency-with-classifier/pom.xml b/src/it/prepare-dependency-with-classifier/pom.xml new file mode 100644 index 0000000..b2f1d4c --- /dev/null +++ b/src/it/prepare-dependency-with-classifier/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + com.monday-consulting.maven.plugins + dependency-with-classifier + 11 + pom + + + UTF-8 + 5.2.0 + + + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + + + org.xmlresolver + xmlresolver + data + ${xmlresolver.version} + + + + + + + fsm + true + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + + copy-resources + prepare-package + + copy-resources + + + ${basedir}/target/extra-resources + + + fsm + true + + + + + + + + + com.monday-consulting.maven.plugins + fsm-maven-plugin + @project.version@ + + ${basedir}/target/extra-resources/plugin.xml + ${basedir}/target/extra-resources/prototype.module.xml + + + + prepare-module + package + + prepare + + + + + + + diff --git a/src/it/prepare-dependency-with-classifier/verify.groovy b/src/it/prepare-dependency-with-classifier/verify.groovy new file mode 100644 index 0000000..80fd959 --- /dev/null +++ b/src/it/prepare-dependency-with-classifier/verify.groovy @@ -0,0 +1,24 @@ +import groovy.xml.XmlSlurper + +def fsmDir = new File(basedir, 'target/fsm-root') +assert fsmDir.exists() : "The FSM root directory was not created" + +def moduleXmlFile = new File(fsmDir, 'META-INF/module.xml') +assert moduleXmlFile.exists() : "The module.xml descriptor was not created" +def moduleIsolatedXmlFile = new File(fsmDir, 'META-INF/module-isolated.xml') +assert moduleIsolatedXmlFile.exists() : "The module-isolated.xml descriptor was not created" + +def doc = new XmlSlurper().parse(moduleXmlFile) +assert doc.version == 11 : "The module.xml version was not filtered" + +// verify commons-math3 is under -> -> and has the correct version +def resource = doc.components.'web-app'.'web-resources'.childNodes().find { it.attributes().name = "org.xmlresolver:xmlresolver" } +assert resource != null : "org.xmlresolver:xmlresolver (no classifier) resource must exist in module.xml" +def resourceWithClassifier = doc.components.'web-app'.'web-resources'.childNodes().find { it.attributes().name = "org.xmlresolver:xmlresolver:data" } +assert resourceWithClassifier != null : "org.xmlresolver:xmlresolver:data (with classifier) resource must exist in module.xml" + +// verify dependency has been copied to /lib/ +def libDir = new File(fsmDir, 'lib'); +assert libDir.exists() : "The lib directory was not created" +assert (new File(libDir, 'xmlresolver-5.2.0.jar').exists()) : "The resource lib 'xmlresolver-5.2.0.jar' was not copied to the lib/ directory" +assert (new File(libDir, 'xmlresolver-5.2.0-data.jar').exists()) : "The resource lib 'xmlresolver-5.2.0.jar-data' was not copied to the lib/ directory" diff --git a/src/it/prepare-example/fsm-assembly.xml b/src/it/prepare-example/fsm-assembly.xml new file mode 100644 index 0000000..36a57be --- /dev/null +++ b/src/it/prepare-example/fsm-assembly.xml @@ -0,0 +1,18 @@ + + + fsm + + zip + + false + + + + ${basedir}/target/fsm-root + / + + + + diff --git a/src/it/prepare-example/fsm/plugin.xml b/src/it/prepare-example/fsm/plugin.xml new file mode 100644 index 0000000..27fe480 --- /dev/null +++ b/src/it/prepare-example/fsm/plugin.xml @@ -0,0 +1,10 @@ + + + + + org.apache.commons:commons-math3:jar:${commons.math.version} + + math + + + diff --git a/src/it/prepare-example/fsm/prototype.module.xml b/src/it/prepare-example/fsm/prototype.module.xml new file mode 100644 index 0000000..bec796e --- /dev/null +++ b/src/it/prepare-example/fsm/prototype.module.xml @@ -0,0 +1,16 @@ + + + Monday Math + ${project.version} + + + + Math + ${project.version} + + + math + + + + diff --git a/src/it/prepare-example/pom.xml b/src/it/prepare-example/pom.xml new file mode 100644 index 0000000..bbef8de --- /dev/null +++ b/src/it/prepare-example/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + com.monday-consulting.maven.plugins + example + 11 + pom + + + UTF-8 + 3.6.1 + + + + + + fsm + true + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + + copy-resources + prepare-package + + copy-resources + + + ${basedir}/target/extra-resources + + + fsm + true + + + + + + + + + com.monday-consulting.maven.plugins + fsm-maven-plugin + @project.version@ + + ${basedir}/target/extra-resources/plugin.xml + ${basedir}/target/extra-resources/prototype.module.xml + + + + prepare-module + package + + prepare + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.6.0 + + + fsm-assembly.xml + + ${project.artifactId}-${project.version}.fsm + false + false + + + + make-assembly + package + + single + + + + + + + diff --git a/src/it/prepare-example/verify.groovy b/src/it/prepare-example/verify.groovy new file mode 100644 index 0000000..5d2c740 --- /dev/null +++ b/src/it/prepare-example/verify.groovy @@ -0,0 +1,24 @@ +import groovy.xml.XmlSlurper + +def fsmDir = new File(basedir, 'target/fsm-root') +assert fsmDir.exists() : "The FSM root directory was not created" + +def moduleXmlFile = new File(fsmDir, 'META-INF/module.xml') +assert moduleXmlFile.exists() : "The module.xml descriptor was not created" +def moduleIsolatedXmlFile = new File(fsmDir, 'META-INF/module-isolated.xml') +assert moduleIsolatedXmlFile.exists() : "The module-isolated.xml descriptor was not created" + +def doc = new XmlSlurper().parse(moduleXmlFile) +assert doc.version == 11 : "The module.xml version was not filtered" + +// verify commons-math3 is under -> -> and has the correct version +def resource = doc.components.'web-app'.'web-resources'.childNodes().find { it.attributes().name = "org.apache.commons:commons-math3" } +assert resource != null : "commons-math3 resource must exist in module.xml" +def resourceVersion = resource.attributes().version +assert resourceVersion == "3.6.1" : "commons-math3 version must be 3.6.1" + +// verify dependency has been copied to /lib/ +def libDir = new File(fsmDir, 'lib'); +assert libDir.exists() : "The lib directory was not created" +def resourceLib = new File(libDir, 'commons-math3-3.6.1.jar') +assert resourceLib.exists() : "The resource lib 'commons-math3-3.6.1.jar' was not copied to the lib/ directory" diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/AttachFSMMojo.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/AttachFSMMojo.java index 4f3d6c7..db9f91b 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/AttachFSMMojo.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/AttachFSMMojo.java @@ -16,12 +16,8 @@ limitations under the License. */ -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugins.annotations.*; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.MavenProjectHelper; - -import java.io.File; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; /** * This Mojo attaches the assembled FSM as a project artifact. @@ -29,36 +25,13 @@ * @author Oliver Degener * @since 1.6.0 */ +@SuppressWarnings("unused") @Mojo(name = "attachFSM", defaultPhase = LifecyclePhase.PACKAGE) -class AttachFSMMojo extends AbstractMojo { - - @Component - private MavenProjectHelper projectHelper; - - /** - * The filename of the assembled distribution file. - */ - @Parameter(property = "fsmFile", defaultValue = "${project.artifactId}-${project.version}.fsm.zip") - private String fsmFile; - - /** - * The artifact type, defaults to fsm. - */ - @Parameter(property = "type", defaultValue = "fsm") - private String type; - - @Parameter(defaultValue = "${project}", readonly = true, required = true) - private MavenProject project; +class AttachFSMMojo extends BaseFSMMojo { @Override public void execute() { - final String targetDir = project.getBuild().getDirectory(); - - String path = targetDir.concat(File.separator).concat(fsmFile); - File file = new File(path); - - getLog().info("Attaching '" + type + "' artifact: " + file.getAbsolutePath()); - projectHelper.attachArtifact(project, type, null, file); + attachFSM(); } } diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/BaseDependencyModuleMojo.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/BaseDependencyModuleMojo.java new file mode 100644 index 0000000..ef11dea --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/BaseDependencyModuleMojo.java @@ -0,0 +1,128 @@ +package com.monday_consulting.maven.plugins.fsm; + +import com.monday_consulting.maven.plugins.fsm.jaxb.FsmMavenPluginType; +import com.monday_consulting.maven.plugins.fsm.jaxb.ModuleType; +import com.monday_consulting.maven.plugins.fsm.maven.MavenCoordinate; +import com.monday_consulting.maven.plugins.fsm.util.Module; +import com.monday_consulting.maven.plugins.fsm.util.ModuleIdParser; +import com.monday_consulting.maven.plugins.fsm.util.resolver.IResolver; +import com.monday_consulting.maven.plugins.fsm.util.resolver.MavenGetArtifactsResolver; +import com.monday_consulting.maven.plugins.fsm.xml.FsmPluginConfigParser; +import com.monday_consulting.maven.plugins.fsm.xml.PrototypeXml; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; +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.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +abstract class BaseDependencyModuleMojo extends BaseFSMMojo { + + /** + * The xml containing the configuration for the plugin. + */ + @SuppressWarnings("unused") + @Parameter(defaultValue = "${configXml}") + private File configXml; + + /** + * The xml with the prototype for the target-xml. + */ + @SuppressWarnings("unused") + @Parameter(defaultValue = "${prototypeXml}") + private File prototypeXml; + + /** + * The Maven Session. + */ + @SuppressWarnings("unused") + @Parameter(defaultValue = "${session}", readonly = true, required = true) + private MavenSession session; + + /** + * The projects in the reactor. + */ + @Parameter(defaultValue = "${reactorProjects}", readonly = true) + protected List reactorProjects; + + /** + * The entry point towards a Maven version independent way of resolving + * artifacts (handles both Maven 3.0 Sonatype and Maven 3.1+ eclipse Aether + * implementations). + */ + @SuppressWarnings("unused") + @Component + private ArtifactResolver artifactResolver; + + @Component + @SuppressWarnings("unused") + private ProjectBuilder projectBuilder; + + /** + * Log Projects and their resolved dependencies via MavenProject.getArtifacts(). + * + * @param reactorProjects MavenProjects in the current reactor + */ + protected void checkReactor(final List reactorProjects) { + for (final MavenProject reactorProject : reactorProjects) { + final String msg = "Check resolved Artifacts for: " + + "\ngroudId: " + reactorProject.getGroupId() + + "\nartifactId: " + reactorProject.getArtifactId() + + "\nversion: " + reactorProject.getVersion(); + + getLog().debug(msg); + + if (reactorProject.getArtifacts() == null || reactorProject.getArtifacts().isEmpty()) { + getLog().debug("+ Dependencies not resolved or reactor project has no dependencies!"); + } else { + for (final Artifact artifact : reactorProject.getArtifacts()) { + if (getLog().isDebugEnabled()) { + getLog().debug(" + " + artifact.toString()); + } + } + } + } + } + + protected Map resolveModulesWithDependencies() throws MojoExecutionException, MojoFailureException { + final FsmMavenPluginType config = parseConfig(); + final IResolver resolver = new MavenGetArtifactsResolver(getLog(), session, artifactResolver, reactorProjects, projectBuilder, project); + final Map modules = new HashMap<>(); + for (final ModuleType moduleType : config.getModules().getModule()) { + if (modules.containsKey(moduleType.getDependencyTagValueInXml())) { + throw new MojoFailureException("Properties for Module: " + moduleType.getDependencyTagValueInXml() + + "defined twice\tFix to prevent unpredictable behaviour!\tPlease contact Responsible Developer, XSD has to be fixed!"); + } + + getLog().debug("Resolving module for dependency tag " + moduleType.getDependencyTagValueInXml()); + + List artifacts = ModuleIdParser.parseModuleTypeIds(moduleType); + List mavenProjects = resolver.resolveMavenProjects(artifacts); + + Module module = new Module(getLog(), moduleType, mavenProjects, config.getScopes().getScope()); + + modules.put(moduleType.getDependencyTagValueInXml(), module); + } + return modules; + } + + protected FsmMavenPluginType parseConfig() throws MojoExecutionException { + getLog().debug("Create config-xml-Object"); + FsmPluginConfigParser fsmPluginConfigParser = new FsmPluginConfigParser(getLog()); + return fsmPluginConfigParser.bindXmlConfigToPojo(configXml); + } + + protected PrototypeXml createPrototype() { + getLog().debug("Creating PrototypeXml-Object"); + return new PrototypeXml(getLog(), prototypeXml); + } + +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/BaseFSMMojo.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/BaseFSMMojo.java new file mode 100644 index 0000000..206601f --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/BaseFSMMojo.java @@ -0,0 +1,41 @@ +package com.monday_consulting.maven.plugins.fsm; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; + +import java.io.File; +import java.nio.file.Path; + +abstract class BaseFSMMojo extends AbstractMojo { + + @SuppressWarnings("unused") + @Parameter(defaultValue = "${project}", readonly = true, required = true) + protected MavenProject project; + + /** + * The filename of the assembled distribution file. + */ + @SuppressWarnings("unused") + @Parameter(property = "fsmFile", defaultValue = "${project.artifactId}-${project.version}.fsm.zip") + private String fsmFile; + + /** + * The artifact type, defaults to fsm. + */ + @SuppressWarnings("unused") + @Parameter(property = "type", defaultValue = "fsm") + private String type; + + @SuppressWarnings("unused") + @Component + private MavenProjectHelper projectHelper; + + void attachFSM() { + final File file = Path.of(project.getBuild().getDirectory()).resolve(fsmFile).toFile(); + getLog().info("Attaching '" + type + "' artifact: " + file.getAbsolutePath()); + projectHelper.attachArtifact(project, type, null, file); + } +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojo.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojo.java index 4dd442a..964247c 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojo.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojo.java @@ -16,44 +16,15 @@ limitations under the License. */ -import com.monday_consulting.maven.plugins.fsm.jaxb.FsmMavenPluginType; -import com.monday_consulting.maven.plugins.fsm.jaxb.ModuleType; -import com.monday_consulting.maven.plugins.fsm.jaxb.ScopesType; import com.monday_consulting.maven.plugins.fsm.util.Module; -import com.monday_consulting.maven.plugins.fsm.util.PrototypeXml; -import com.monday_consulting.maven.plugins.fsm.util.XmlValidationEventHandler; -import com.monday_consulting.maven.plugins.fsm.util.resolver.IResolver; -import com.monday_consulting.maven.plugins.fsm.util.resolver.MavenGetArtifactsResolver; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.AbstractMojo; +import com.monday_consulting.maven.plugins.fsm.xml.PrototypeXml; +import com.monday_consulting.maven.plugins.fsm.xml.ModuleXmlWriter; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.*; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuilder; -import org.codehaus.plexus.util.WriterFactory; -import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; -import org.codehaus.plexus.util.xml.XmlStreamWriter; -import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.codehaus.plexus.util.xml.Xpp3DomWriter; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.RepositorySystemSession; -import org.xml.sax.SAXException; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -74,50 +45,12 @@ * @author Kassim Hölting * @since 1.0.0 */ +@SuppressWarnings("unused") @Mojo(name = "dependencyToXML", defaultPhase = LifecyclePhase.PACKAGE, aggregator = true, requiresDependencyResolution = ResolutionScope.COMPILE) -class DependencyToXMLMojo extends AbstractMojo { - - /** - * The entry point to Aether, i.e. the component doing all the work. - */ - @Component - private RepositorySystem repoSystem; - - @Component - private ProjectBuilder projectBuilder; - - /** - * The current repository/network configuration of Maven. - */ - @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) - private RepositorySystemSession repoSession; - - /** - * The Maven-Project - */ - @Parameter(defaultValue = "${project}", readonly = true) - private MavenProject mavenProject; - - /** - * The projects in the reactor. - */ - @Parameter(defaultValue = "${reactorProjects}", readonly = true) - private List reactorProjects; - - /** - * The xml containing the configuration for the plugin. - */ - @Parameter(defaultValue = "${configXml}") - private File configXml; - - /** - * The xml with the prototype for the target-xml. - */ - @Parameter(defaultValue = "${prototypeXml}") - private File prototypeXml; +class DependencyToXMLMojo extends BaseDependencyModuleMojo { /** * The xml the module data write to. @@ -128,139 +61,23 @@ class DependencyToXMLMojo extends AbstractMojo { /** * {@inheritDoc} */ + @Override public void execute() throws MojoExecutionException, MojoFailureException { try { getLog().debug("*** Starting DependencyToXMLMojo"); checkReactor(reactorProjects); - getLog().debug("Create config-xml-Object"); - - final FsmMavenPluginType config = bindXmlConfigToPojo(configXml); - - getLog().debug("Creating PrototypeXml-Object"); - - PrototypeXml prototype = new PrototypeXml(getLog(), prototypeXml); - - if (getLog().isDebugEnabled()) { - getLog().debug("Getting target-file: " + targetXml.getAbsoluteFile()); - getLog().debug("Enhance created Modules"); - } - - final IResolver resolver = new MavenGetArtifactsResolver(getLog(), reactorProjects, repoSystem, repoSession, projectBuilder, mavenProject); - final Map modules = new HashMap<>(); - for (final ModuleType moduleType : config.getModules().getModule()) { - if (modules.containsKey(moduleType.getDependencyTagValueInXml())) { - throw new MojoFailureException("Properties for Module: " + moduleType.getDependencyTagValueInXml() + - "defined twice\tFix to prevent unpredictable behaviour!\tPlease contact Responsible Developer, XSD has to be fixed!"); - } - modules.put(moduleType.getDependencyTagValueInXml(), resolver.resolve(moduleType, config.getScopes().getScope())); - } - - getLog().debug("Enhance Prototype for TargetXml"); - + final PrototypeXml prototype = createPrototype(); + final Map modules = resolveModulesWithDependencies(); prototype.fillPrototypeDom(modules); - getLog().debug("Write TargetXml-File"); - - writeDomToTarget(targetXml, prototype.getPrototypeDom()); - - getLog().debug("Dependencies written to Module-XML:\n\t" + prototype.getPrototypeDom().toString()); + ModuleXmlWriter moduleXmlWriter = new ModuleXmlWriter(getLog()); + moduleXmlWriter.writeDomToTarget(targetXml, prototype.getPrototypeDom()); getLog().debug("*** DependencyToXMLMojo finished"); - } catch (XmlPullParserException | IOException e) { + } catch (IOException e) { throw new MojoExecutionException(e.getMessage(), e); } } - /** - * Log Projects and their resolved dependencies via MavenProject.getArtifacts(). - * - * @param reactorProjects MavenProjects in the current reactor - */ - private void checkReactor(final List reactorProjects) { - for (final MavenProject reactorProject : reactorProjects) { - final String msg = "Check resolved Artifacts for: " + - "\ngroudId: " + reactorProject.getGroupId() + - "\nartifactId: " + reactorProject.getArtifactId() + - "\nversion: " + reactorProject.getVersion(); - - getLog().debug(msg); - - if (reactorProject.getArtifacts() == null || reactorProject.getArtifacts().isEmpty()) { - getLog().debug("+ Dependencies not resolved or reactor project has no dependencies!"); - } else { - for (final Artifact artifact : reactorProject.getArtifacts()) { - if (getLog().isDebugEnabled()) { - getLog().debug(" + " + artifact.toString()); - } - } - } - } - } - - /** - * Validate a config-XML against the Plugin-XSD. - * Bind config-XML to generated POJOs. - * - * @param configXml The config-file to use - * @return WebformsMavenPluginType The corresponding Java-Object of the plugin-configuration. - * @throws MojoExecutionException in case of marshalling exception for the fsm-plugin.xsd. - */ - private FsmMavenPluginType bindXmlConfigToPojo(final File configXml) throws MojoExecutionException { - getLog().debug("*** Constructing ConfigXml-Object"); - - try { - final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - final Schema schema = sf.newSchema(getClass().getResource("/fsm-plugin.xsd")); - final StreamSource streamSource = new StreamSource(configXml); - final JAXBContext jaxbContext = JAXBContext.newInstance(FsmMavenPluginType.class); - final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema(schema); - unmarshaller.setEventHandler(new XmlValidationEventHandler(getLog())); - - final JAXBElement jaxbElement = unmarshaller.unmarshal(streamSource, FsmMavenPluginType.class); - FsmMavenPluginType config = jaxbElement.getValue(); - applyDefaultConfiguration(config); - return config; - } catch (SAXException e) { - throw new MojoExecutionException(e, "Error while parsing file with SAX", e.getMessage()); - } catch (JAXBException e) { - throw new MojoExecutionException(e, "Error while binding xml-file with JAXB", e.getMessage()); - } - } - - void applyDefaultConfiguration(FsmMavenPluginType config) { - if (config.getScopes() == null) { - ScopesType defaultScopesType = new ScopesType(); - List defaultScopes = defaultScopesType.getScope(); - defaultScopes.add("runtime"); - defaultScopes.add("compile"); - config.setScopes(defaultScopesType); - } - - for (ModuleType moduleType : config.getModules().getModule()) { - if (moduleType.getPrefix() == null) { - moduleType.setPrefix(""); - } - } - } - - /** - * Write a DOM-Tree to a target file. - * - * @param target File to write to. - * @param dom dom to write to file. - * @throws IOException in case of unexpected writer exceptions. - */ - private void writeDomToTarget(final File target, final Xpp3Dom dom) throws IOException { - getLog().info("Writing module descriptor: " + target.getAbsolutePath()); - - // ensure that the target directory exists - Files.createDirectories(target.toPath().getParent()); - - final XmlStreamWriter writer = WriterFactory.newXmlWriter(target); - final PrettyPrintXMLWriter pretty = new PrettyPrintXMLWriter(writer); - Xpp3DomWriter.write(pretty, dom); - writer.close(); - } } diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/PrepareMojo.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/PrepareMojo.java new file mode 100644 index 0000000..a717138 --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/PrepareMojo.java @@ -0,0 +1,73 @@ +package com.monday_consulting.maven.plugins.fsm; + +import com.monday_consulting.maven.plugins.fsm.assembly.DependencyAssembler; +import com.monday_consulting.maven.plugins.fsm.util.Module; +import com.monday_consulting.maven.plugins.fsm.xml.ModuleXmlWriter; +import com.monday_consulting.maven.plugins.fsm.xml.PrototypeXml; +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; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; + +@SuppressWarnings("unused") +@Mojo(name = "prepare", + defaultPhase = LifecyclePhase.PACKAGE, + aggregator = true, + requiresDependencyResolution = ResolutionScope.COMPILE) +class PrepareMojo extends BaseDependencyModuleMojo { + + /** + * Flag to control whether the FSM file should be attached as a project artifact. + */ + @Parameter(property = "attach", defaultValue = "true", required = true) + private boolean attach; + + /** + * The xml the module data write to. + */ + @Parameter(name = "fsm-root", defaultValue = "fsm-root") + private String fsmRoot; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + try { + getLog().debug("*** Starting PrepareMojo"); + checkReactor(reactorProjects); + + final PrototypeXml prototype = createPrototype(); + + final Map modules = resolveModulesWithDependencies(); + + getLog().debug("Enhance Prototype for TargetXml"); + + prototype.fillPrototypeDom(modules); + + Path fsmRootPath = Path.of(project.getBuild().getDirectory(), fsmRoot); + getLog().debug("FSM Root Directory is " + fsmRootPath); + Files.createDirectories(fsmRootPath); + + ModuleXmlWriter moduleXmlWriter = new ModuleXmlWriter(getLog()); + moduleXmlWriter.writeDomToTarget(fsmRootPath, prototype.getPrototypeDom()); + + getLog().debug("Copying dependencies to " + fsmRootPath); + new DependencyAssembler(getLog()).copyDependenciesForModuleAssembly(fsmRootPath, modules.values()); + getLog().debug("Module dependencies were successfully copied."); + + if (attach) { + attachFSM(); + } + + getLog().debug("*** PrepareMojo finished"); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/assembly/DependencyAssembler.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/assembly/DependencyAssembler.java new file mode 100644 index 0000000..90c49d1 --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/assembly/DependencyAssembler.java @@ -0,0 +1,45 @@ +package com.monday_consulting.maven.plugins.fsm.assembly; + +import com.monday_consulting.maven.plugins.fsm.util.Module; +import org.apache.maven.plugin.logging.Log; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Collection; +import java.util.List; + +public class DependencyAssembler { + + private final Log log; + + public DependencyAssembler(Log log) { + this.log = log; + } + + public void copyDependenciesForModuleAssembly(Path fsmRoot, Collection modules) throws IOException { + final Path libDir = fsmRoot.resolve(Module.LIB_PATH); + Files.createDirectories(libDir); + + modules.stream() + .map(Module::getDependencies).flatMap(List::stream) + .filter(artifact -> { + File artifactFile = artifact.getFile(); + if (artifactFile == null) { + log.warn("A dependency cannot be resolved and will be missing in the FSM: " + artifact); + return false; + } + return true; + }) + .forEach(artifact -> { + Path targetPath = libDir.resolve(artifact.getFile().getName()); + try { + Files.copy(artifact.getFile().toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException("Failed to copy artifact to FSM directory.", e); + } + }); + } +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/maven/MavenCoordinate.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/maven/MavenCoordinate.java new file mode 100644 index 0000000..3c9f250 --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/maven/MavenCoordinate.java @@ -0,0 +1,68 @@ +package com.monday_consulting.maven.plugins.fsm.maven; + +public class MavenCoordinate { + + private String groupId; + + private String artifactId; + + private String version; + + private String extension; + + private String classifier; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } + + public String getClassifier() { + return classifier; + } + + public void setClassifier(String classifier) { + this.classifier = classifier; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder().append(groupId).append(':') + .append(artifactId).append(':').append(getExtension()); + + if (classifier != null) { + sb.append(':').append(classifier); + } + + sb.append(':').append(version); + + return sb.toString(); + } +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ConflictResolver.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ConflictResolver.java index 919667f..305a808 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ConflictResolver.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ConflictResolver.java @@ -31,6 +31,8 @@ public List resolveVersionConflicts(List artifacts) { // first occurrence wins log.info("Resolving conflict for " + conflictId + " with first seen version " + artifact.getVersion()); resolvedConflicts.put(conflictId, artifact); + } else { + log.debug("Alternative version for " + conflictId + " is " + artifact.getVersion()); } } }); diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/Module.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/Module.java index 3222b1e..d5245ab 100755 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/Module.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/Module.java @@ -20,13 +20,11 @@ import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.exception.ZipException; import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.eclipse.aether.artifact.DefaultArtifact; import java.io.File; import java.io.IOException; @@ -46,86 +44,71 @@ public class Module { private static final String RESOURCE_TAG = "resource"; private static final String ROOT_TAG = "root"; + /** + * The lib path for JARs in the FSM. + */ + public static final String LIB_PATH = "lib/"; + private final Log log; private final ModuleType moduleType; - private final String prefix; private final List dependencyScopes; private final String dependencyTagValueInXml; private final Resource resource; - private final List artifacts = new ArrayList<>(); - - private List projects; + private final List dependencies; private final Map includesMap; private final Map excludesMap; + private final List projects; /** * @param log The logger. * @param moduleType The module component configuration. * @param scopes The dependency scopes that will be included (like compile, runtime). - * @throws MojoExecutionException in case of a general failures. */ - public Module(final Log log, final ModuleType moduleType, final List scopes) throws MojoExecutionException, - MojoFailureException { + public Module(final Log log, final ModuleType moduleType, final List mavenProjects, + final List scopes) throws MojoFailureException { this.log = log; this.moduleType = moduleType; - if (moduleType.getId() == null && moduleType.getIds() == null) { - throw new MojoExecutionException("Module construction failed: Missing module property ''."); - } - - if (moduleType.getId() != null) { - artifacts.add(parseID(moduleType.getId())); - } - - if (moduleType.getIds() != null) { - for (String id : moduleType.getIds().getId()) { - artifacts.add(parseID(id)); - } - } - - prefix = this.moduleType.getPrefix(); dependencyScopes = scopes; dependencyTagValueInXml = this.moduleType.getDependencyTagValueInXml(); resource = this.moduleType.getResource(); includesMap = getIncludesMap(); excludesMap = getExcludesMap(includesMap); - } - - private static DefaultArtifact parseID(String str) throws MojoExecutionException { - final String[] coords = str.split(":"); - if (coords.length < 3) { - throw new MojoExecutionException("Incomplete artifact ID specified: " + str); + if (moduleType.getPrefix() != null) { + if (LIB_PATH.equals(moduleType.getPrefix())) { + log.info("The module prefix 'lib/' equals the default convention and" + + " should be removed as the parameter is no longer considered."); + } else { + log.warn("The element in the module descriptor has been removed and has no effect." + + " All dependencies will be placed under '/lib' by convention."); + } } - return new DefaultArtifact(coords[0], coords[1], - coords.length > 4 ? coords[4] : null, coords[2], coords.length > 3 ? coords[3] : null); + this.projects = mavenProjects; + + this.dependencies = resolveDependencies(mavenProjects); + } + + public List getDependencies() { + return dependencies; } private Xpp3Dom getWebResourceTmpDom(final String name, final String dirPath) { final Xpp3Dom dom = new Xpp3Dom(RESOURCE_TAG); // fix windows paths to work with FirstSpirit module loader dom.setAttribute("target", "/" + dirPath.replace("\\", "/")); - final String value = getResource().getPrefix() != null ? getResource().getPrefix() + name : name; + final String value = resource.getPrefix() != null ? resource.getPrefix() + name : name; dom.setValue(value.replace("\\", "/")); return dom; } - /** - * Creates an XML dom for the resolved module artifacts. - * - * @throws MojoFailureException in case of plugin configuration problems. - */ - public Xpp3Dom getModuleDependencyDom() throws MojoFailureException { - log.info("Processing dependency tag '" + dependencyTagValueInXml + "'"); - final Xpp3Dom dom = new Xpp3Dom(ROOT_TAG); - final HashSet history = new HashSet<>(); - + protected List resolveDependencies(List projects) { final Set resolvedModuleArtifacts = new LinkedHashSet<>(); - for (final MavenProject mavenProject : getProjects()) { + for (final MavenProject mavenProject : projects) { log.info("Resolving dependencies for module " + mavenProject.getGroupId() + ":" + mavenProject.getArtifactId()); @@ -136,28 +119,45 @@ public Xpp3Dom getModuleDependencyDom() throws MojoFailureException { if (artifactType.equals("jar") || artifactType.equals("bundle")) { log.debug("Adding the project artifact itself: " + projectArtifact.getArtifactId() + - ", with absolute file: " + projectArtifact.getFile().getAbsoluteFile() + "; finalname: " + - mavenProject.getBuild().getFinalName()); + ", with file: " + projectArtifact.getFile() + "; finalname: " + + mavenProject.getBuild().getFinalName()); resolvedModuleArtifacts.add(projectArtifact); } - - if (artifactType.equals("war") || artifactType.equals("zip")) { - addArchiveFileIncludesToDom(dom, mavenProject, history); - } } List filteredModuleArtifacts = getFilteredModuleArtifacts(resolvedModuleArtifacts); ConflictResolver conflictResolver = new ConflictResolver(log, dependencyTagValueInXml); - List moduleArtifacts = conflictResolver.resolveVersionConflicts(filteredModuleArtifacts); + return conflictResolver.resolveVersionConflicts(filteredModuleArtifacts); + } - if (moduleArtifacts.isEmpty()) { + /** + * Creates an XML dom for the resolved module artifacts. + * + * @throws MojoFailureException in case of plugin configuration problems. + */ + public Xpp3Dom getModuleDependencyDom() throws MojoFailureException { + log.info("Processing dependency tag '" + dependencyTagValueInXml + "'"); + final Xpp3Dom dom = new Xpp3Dom(ROOT_TAG); + final HashSet history = new HashSet<>(); + + for (MavenProject project : projects) { + + final Artifact projectArtifact = project.getArtifact(); + final String artifactType = projectArtifact.getType(); + + if (artifactType.equals("war") || artifactType.equals("zip")) { + addArchiveFileIncludesToDom(dom, project, history); + } + } + + if (dependencies.isEmpty()) { log.warn("No artifacts found for dependency tag '" + dependencyTagValueInXml + "'. This is" + " most likely an error in the build configuration. Please make sure that all reactor projects" + " have been processed before running the FSM plugin and have not been modified after packaging."); } - addArtifactsToDom(dom, moduleArtifacts, history); + addArtifactsToDom(dom, dependencies, history); addIncludesToDom(dom, history); sortChildren(dom); return dom; @@ -193,7 +193,19 @@ private void sortChildren(Xpp3Dom src) { private void addArtifactsToDom(Xpp3Dom dom, List filteredModuleArtifacts, HashSet history) { for (final Artifact artifact : filteredModuleArtifacts) { - String value = getPrefix() + artifact.getFile().getName(); + final File artifactFile = artifact.getFile(); + + if (artifactFile == null) { + final String unresolvedArtifact = String.format("%s:%s:%s:%s", artifact.getGroupId(), + artifact.getArtifactId(), artifact.getType(), artifact.getVersion()); + final String errorMsg = "The required artifact " + unresolvedArtifact + " could not be" + + " resolved. Please ensure that all modules have been build or execute the plugin from the" + + " project root."; + log.error(errorMsg); + throw new RuntimeException(errorMsg); + } + + String value = LIB_PATH + artifactFile.getName(); if (!history.contains(value)) { history.add(value); @@ -206,7 +218,8 @@ private void addArtifactsToDom(Xpp3Dom dom, List filteredModuleArtifac if (moduleType.getFirstSpiritMode() != null && !moduleType.getFirstSpiritMode().isEmpty()) { tmpDom.setAttribute("mode", moduleType.getFirstSpiritMode().trim()); } - tmpDom.setAttribute("name", artifact.getGroupId() + ":" + artifact.getArtifactId()); + + tmpDom.setAttribute("name", formatArtifactName(artifact)); tmpDom.setAttribute("version", artifact.getBaseVersion()); tmpDom.setValue(value); @@ -215,6 +228,23 @@ private void addArtifactsToDom(Xpp3Dom dom, List filteredModuleArtifac } } + /** + * Constructs a formatted string representing the artifact details.
+ * Format: groupId:artifactId[:classifier] (classifier included if present). + * + * @param artifact Artifact object to be formatted. + * @return Formatted artifact details as a string. + */ + private static String formatArtifactName(Artifact artifact) { + String formattedName = artifact.getGroupId() + ":" + artifact.getArtifactId(); + + if (artifact.hasClassifier()) { + formattedName += ":" + artifact.getClassifier(); + } + + return formattedName; + } + private void addArchiveFileIncludesToDom(final Xpp3Dom dom, final MavenProject mavenProject, HashSet history) throws MojoFailureException { try { @@ -224,15 +254,13 @@ private void addArchiveFileIncludesToDom(final Xpp3Dom dom, final MavenProject m File targetDir = extractArtifactToTargetDir(mavenProject); - final Resource res = getResource(); + final Resource res = resource; if (res == null || res.getIncludes() == null || res.getIncludes().getInclude().isEmpty()) { // if there are no resources or includes then there are no files to handle return; } - if (res.getPrefix() == null || res.getPrefix().isEmpty()) { - log.warn("No defined. Prefix would be set to root."); - } + if (res.getWebXml() == null || res.getWebXml().isEmpty()) { throw new MojoFailureException("Module " + mavenProject.getArtifactId() + " from archive type " + mavenProject.getArtifact().getType() + " detected. No defined."); @@ -289,7 +317,7 @@ private void addIncludesToDom(Xpp3Dom dom, HashSet history) { tmpDom.setAttribute("mode", moduleType.getFirstSpiritMode().trim()); } - tmpDom.setValue(getPrefix() + includeType.getFileName()); + tmpDom.setValue(LIB_PATH + includeType.getFileName()); dom.addChild(tmpDom); } } @@ -358,14 +386,25 @@ private File extractArtifactToTargetDir(MavenProject mavenProject) throws IOExce File baseDir = new File(mavenProject.getBasedir() + targetFileDir); if (!baseDir.exists()) { - final File artifactFile = mavenProject.getArtifact().getFile(); + Artifact artifact = mavenProject.getArtifact(); + if (artifact == null || artifact.getFile() == null) { + final String unresolvedArtifact = String.format("%s:%s:%s:%s", mavenProject.getGroupId(), + mavenProject.getArtifactId(), mavenProject.getPackaging(), mavenProject.getVersion()); + final String errorMsg = "The required artifact " + unresolvedArtifact + " could not be" + + " resolved. Please ensure that all modules have been build or execute the plugin from the" + + " project root."; + log.error(errorMsg); + throw new RuntimeException(errorMsg); + } + + final File artifactFile = artifact.getFile(); try (final ZipFile fileToExtract = new ZipFile(artifactFile)) { if (!fileToExtract.isValidZipFile()) { - throw new ZipException("No valid ZIP file: " + mavenProject.getArtifact().getFile()); + throw new ZipException("No valid ZIP file: " + artifact.getFile()); } if (fileToExtract.isEncrypted()) { - throw new ZipException("The ZIP file is password encrypted: " + mavenProject.getArtifact().getFile()); + throw new ZipException("The ZIP file is password encrypted: " + artifact.getFile()); } baseDir = new File(mavenProject.getParent().getBasedir().getAbsolutePath() + targetFileDir); @@ -376,31 +415,4 @@ private File extractArtifactToTargetDir(MavenProject mavenProject) throws IOExce return baseDir; } - private String getPrefix() { - return prefix; - } - - public String getDependencyTagValueInXml() { - return dependencyTagValueInXml; - } - - private Resource getResource() { - return resource; - } - - private List getProjects() { - return projects; - } - - public void setProjects(List projects) { - this.projects = projects; - } - - public List getDependencyScopes() { - return dependencyScopes; - } - - public List getArtifacts() { - return artifacts; - } } diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ModuleIdParser.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ModuleIdParser.java new file mode 100644 index 0000000..2ce7375 --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/ModuleIdParser.java @@ -0,0 +1,54 @@ +package com.monday_consulting.maven.plugins.fsm.util; + +import com.monday_consulting.maven.plugins.fsm.jaxb.ModuleType; +import com.monday_consulting.maven.plugins.fsm.maven.MavenCoordinate; + +import java.util.ArrayList; +import java.util.List; + +public class ModuleIdParser { + + public static List parseModuleTypeIds(ModuleType moduleType) { + + final List artifacts = new ArrayList<>(); + + if (moduleType.getId() == null && moduleType.getIds() == null) { + throw new RuntimeException("ModuleType parsing failed: Missing module property '' or ''."); + } + + if (moduleType.getId() != null) { + artifacts.add(parseID(moduleType.getId())); + } + + if (moduleType.getIds() != null) { + for (String id : moduleType.getIds().getId()) { + artifacts.add(parseID(id)); + } + } + + return artifacts; + } + + private static MavenCoordinate parseID(String str) throws RuntimeException { + final String[] coords = str.split(":"); + + if (coords.length < 3) { + throw new RuntimeException("Incomplete artifact ID specified: " + str); + } + + final String groupId = coords[0]; + final String artifactId = coords[1]; + final String extension = coords[2]; + final String version = coords.length > 3 ? coords[3] : null; + final String classifier = coords.length > 4 ? coords[4] : null; + + MavenCoordinate coordinate = new MavenCoordinate(); + coordinate.setGroupId(groupId); + coordinate.setArtifactId(artifactId); + coordinate.setVersion(version); + coordinate.setClassifier(classifier); + coordinate.setExtension(extension); + return coordinate; + } + +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/IResolver.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/IResolver.java index b6d3a4c..5280540 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/IResolver.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/IResolver.java @@ -16,10 +16,8 @@ limitations under the License. */ -import com.monday_consulting.maven.plugins.fsm.jaxb.ModuleType; -import com.monday_consulting.maven.plugins.fsm.util.Module; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; +import com.monday_consulting.maven.plugins.fsm.maven.MavenCoordinate; +import org.apache.maven.project.MavenProject; import java.util.List; @@ -30,14 +28,14 @@ * @since 1.0.0 */ public interface IResolver { + /** - * Resolve the dependencies for a maven artifact. + * Resolve a MavenProject for every artifact. + * The MavenProject may be part of the reactor, part of the local workspace or a virtual project from a repository. * - * @param moduleType The module component configuration. - * @param scopes The dependency scopes that will be included. + * @param artifacts This list of artifacts represented as a coordinate * @return The module component. - * @throws MojoFailureException in case if no dependency for the configured module type could be found or could not be resolved. - * @throws MojoExecutionException in case of a general failures. */ - Module resolve(ModuleType moduleType, List scopes) throws MojoFailureException, MojoExecutionException; + List resolveMavenProjects(List artifacts); + } diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/MavenGetArtifactsResolver.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/MavenGetArtifactsResolver.java index e3a108f..7c9e674 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/MavenGetArtifactsResolver.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/util/resolver/MavenGetArtifactsResolver.java @@ -16,24 +16,23 @@ limitations under the License. */ -import com.monday_consulting.maven.plugins.fsm.jaxb.ModuleType; -import com.monday_consulting.maven.plugins.fsm.util.Module; +import com.monday_consulting.maven.plugins.fsm.maven.MavenCoordinate; import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.handler.DefaultArtifactHandler; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Build; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.*; -import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.RepositorySystemSession; -import org.eclipse.aether.artifact.DefaultArtifact; -import org.eclipse.aether.repository.LocalRepositoryManager; -import org.eclipse.aether.resolution.ArtifactRequest; -import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate; +import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver; +import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * Handles the resolution of an artifact within the maven reactor or repository. @@ -42,26 +41,20 @@ * @since 1.0.0 */ public class MavenGetArtifactsResolver implements IResolver { + private final Log log; + private final MavenSession session; + private final ArtifactResolver artifactResolver; private final List reactorProjects; - private final RepositorySystem repoSystem; - private final RepositorySystemSession repoSession; private final ProjectBuilder projectBuilder; private final MavenProject parentMavenProject; - /** - * @param log The logger. - * @param reactorProjects The projects within the reactor. - * @param repoSystem The maven repository system. - * @param repoSession The maven repository session. - * @param projectBuilder The maven project builder. - * @param parentMavenProject This maven project. - */ - public MavenGetArtifactsResolver(final Log log, final List reactorProjects, final RepositorySystem repoSystem, - final RepositorySystemSession repoSession, final ProjectBuilder projectBuilder, final MavenProject parentMavenProject) { - this.repoSystem = repoSystem; - this.repoSession = repoSession; + public MavenGetArtifactsResolver(final Log log, final MavenSession session, final ArtifactResolver artifactResolver, + final List reactorProjects, final ProjectBuilder projectBuilder, + final MavenProject parentMavenProject) { this.log = log; + this.session = session; + this.artifactResolver = artifactResolver; this.reactorProjects = reactorProjects; this.projectBuilder = projectBuilder; this.parentMavenProject = parentMavenProject; @@ -70,33 +63,35 @@ public MavenGetArtifactsResolver(final Log log, final List reactor /** * {@inheritDoc} */ - public Module resolve(final ModuleType moduleType, final List scopes) throws MojoFailureException, MojoExecutionException { - log.debug("Resolving module for dependency tag " + moduleType.getDependencyTagValueInXml()); - final Module module = new Module(log, moduleType, scopes); - List mavenProjects = getMavenProjects(module); - module.setProjects(mavenProjects); - return module; - } - - private List getMavenProjects(final Module module) throws MojoFailureException { + @Override + public List resolveMavenProjects(final List artifacts) { List mavenProjects = new ArrayList<>(); - for (final DefaultArtifact artifactInfo : module.getArtifacts()) { + for (final MavenCoordinate artifactInfo : artifacts) { + // Order: reactor project, local project, maven repository MavenProject mavenProject = getMavenProjectViaReactor(artifactInfo); - if (mavenProject != null) { mavenProjects.add(mavenProject); } else { - log.debug("Module " + artifactInfo.getGroupId() + ":" + artifactInfo.getArtifactId() - + " not found in reactor, trying to find it in the local repository."); - mavenProjects.add(getMavenProjectViaRepository(artifactInfo)); + mavenProject = getMavenProjectViaLocalWorkspace(artifactInfo); + if (mavenProject != null) { + mavenProjects.add(mavenProject); + } else { + // this succeeds or throws + mavenProjects.add(getMavenProjectViaRepository(artifactInfo)); + } } } - return mavenProjects; + return mavenProjects.stream().map(project -> { + project = project.clone(); + // without an artifact filter, artifact resolution may fail + project.setArtifactFilter((a) -> true); + return project; + }).collect(Collectors.toList()); } - private MavenProject getMavenProjectViaReactor(final DefaultArtifact artifact) { + private MavenProject getMavenProjectViaReactor(final MavenCoordinate artifact) { MavenProject mavenProject = null; boolean moduleInReactor = false; @@ -117,27 +112,75 @@ private MavenProject getMavenProjectViaReactor(final DefaultArtifact artifact) { return mavenProject; } - private MavenProject getMavenProjectViaRepository(final DefaultArtifact artifact) throws MojoFailureException { + private MavenProject getMavenProjectViaLocalWorkspace(final MavenCoordinate artifact) { + MavenProject rootProject = parentMavenProject.getParent(); + if (rootProject != null && rootProject.getGroupId().equals(artifact.getGroupId())) { + log.debug("Module " + artifact.getGroupId() + ":" + artifact.getArtifactId() + + " might exist locally."); + File localArtifactPom = rootProject.getBasedir().toPath() + .resolve(artifact.getArtifactId()).resolve("pom.xml") + .toFile(); + if (localArtifactPom.exists()) { + try { + MavenProject result = projectBuilder.build(localArtifactPom, buildingRequest()).getProject(); + if (result != null) { + Build build = result.getBuild(); + if (build != null) { + File artifactFile = new File(build.getDirectory()).toPath() + .resolve(build.getFinalName() + "." + result.getPackaging()).toFile(); + if (artifactFile.exists()) { + result.getArtifact().setFile(artifactFile); + log.info("Resolved " + artifact + " via local project " + localArtifactPom.getPath()); + return result; + } + } + } + } catch (ProjectBuildingException e) { + log.debug("Failed to build local project " + localArtifactPom + "."); + } + } + } + return null; + } + + private ProjectBuildingRequest buildingRequest() { + return new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()).setResolveDependencies(true); + } + + private Artifact coordinateToArtifact(MavenCoordinate artifactCoordinate) { + return coordinateToArtifact(artifactCoordinate, artifactCoordinate.getExtension()); + } + + private Artifact coordinateToArtifact(MavenCoordinate artifactCoordinate, String type) { + return new DefaultArtifact(artifactCoordinate.getGroupId(), artifactCoordinate.getArtifactId(), + artifactCoordinate.getVersion(), null, type, + artifactCoordinate.getClassifier(), new DefaultArtifactHandler(type)); + } + + private MavenProject getMavenProjectViaRepository(MavenCoordinate artifact) { + log.debug("Module " + artifact.getGroupId() + ":" + artifact.getArtifactId() + + " not found in reactor, trying to find it in the local repository."); try { - final ProjectBuildingRequest request = new DefaultProjectBuildingRequest() - .setResolveDependencies(true) - .setRemoteRepositories(parentMavenProject.getRemoteArtifactRepositories()) - .setRepositorySession(repoSession) - .setSystemProperties(System.getProperties()); + final ProjectBuildingRequest request = buildingRequest(); + request.setProject(null); - final LocalRepositoryManager localRepositoryManager = repoSession.getLocalRepositoryManager(); - final File repoBasedir = localRepositoryManager.getRepository().getBasedir(); + final ArtifactRepository localRepository = session.getLocalRepository(); + final File repoBasedir = new File(localRepository.getBasedir()); - // the module type artifact (war, jar, pom ...) + if ((artifact.getVersion() == null || artifact.getVersion().isEmpty()) + && parentMavenProject.getGroupId().equals(artifact.getGroupId())) { + log.info("Assuming project version " + parentMavenProject.getVersion() + + " for artifact " + artifact); + artifact.setVersion(parentMavenProject.getVersion()); + } - final String pathForLocalArtifact = localRepositoryManager.getPathForLocalArtifact(artifact); + final String pathForLocalArtifact = localRepository.pathOf(coordinateToArtifact(artifact)); final File moduleArtifactFile = new File(repoBasedir, pathForLocalArtifact); // the module pom artifact to build maven project - final DefaultArtifact pomArtifact = new DefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(), - artifact.getClassifier(), "pom", artifact.getVersion()); + final Artifact pomArtifact = coordinateToArtifact(artifact, "pom"); - final String localArtifactPath = localRepositoryManager.getPathForLocalArtifact(pomArtifact); + final String localArtifactPath = localRepository.pathOf(pomArtifact); final File projectFile = new File(repoBasedir, localArtifactPath); @@ -162,26 +205,30 @@ private MavenProject getMavenProjectViaRepository(final DefaultArtifact artifact result.getArtifact().setFile(moduleArtifactFile); result.setParent(parentMavenProject); } else { - throw new MojoFailureException("No dependency for " + artifact.getArtifactId() + " found in local or remote repository."); + throw new RuntimeException("No dependency for " + artifact.getArtifactId() + " found in local or remote repository."); } return result; } catch (ProjectBuildingException e) { - throw new MojoFailureException("No dependency for " + artifact.getArtifactId() + "found in local or remote repository.", e); + throw new RuntimeException("No dependency for " + artifact.getArtifactId() + " found in local or remote repository.", e); } } - private void resolveArtifact(final DefaultArtifact moduleArtifact) throws MojoFailureException { - log.info("Try to resolve artifact for " + moduleArtifact.getArtifactId() + " from remote repository..."); - final ArtifactRequest artifactRequest = new ArtifactRequest(); - artifactRequest.setArtifact(moduleArtifact); - artifactRequest.setRepositories(parentMavenProject.getRemoteProjectRepositories()); - + private void resolveArtifact(final MavenCoordinate mavenCoordinate) { + log.info("Try to resolve artifact for " + mavenCoordinate.getArtifactId() + " from remote repository..."); + + DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate(); + coordinate.setGroupId(mavenCoordinate.getGroupId()); + coordinate.setArtifactId(mavenCoordinate.getArtifactId()); + coordinate.setVersion(mavenCoordinate.getVersion()); + coordinate.setExtension(mavenCoordinate.getExtension()); + coordinate.setClassifier(mavenCoordinate.getClassifier()); + try { - repoSystem.resolveArtifact(repoSession, artifactRequest); - } catch (ArtifactResolutionException e1) { - throw new MojoFailureException("Could not resolve artifact " + moduleArtifact.getArtifactId() + ":" + - moduleArtifact.getExtension() + " for maven project.", e1); + artifactResolver.resolveArtifact(buildingRequest(), coordinate); + } catch (ArtifactResolverException e) { + log.error("Failed to resolve artifact " + coordinate + "."); + throw new RuntimeException(e); } } } diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/FsmPluginConfigParser.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/FsmPluginConfigParser.java new file mode 100644 index 0000000..f06ff07 --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/FsmPluginConfigParser.java @@ -0,0 +1,69 @@ +package com.monday_consulting.maven.plugins.fsm.xml; + +import com.monday_consulting.maven.plugins.fsm.jaxb.FsmMavenPluginType; +import com.monday_consulting.maven.plugins.fsm.jaxb.ScopesType; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.io.File; +import java.util.List; + +public class FsmPluginConfigParser { + + private final Log log; + + public FsmPluginConfigParser(Log log) { + this.log = log; + } + + /** + * Validate a config-XML against the Plugin-XSD. + * Bind config-XML to generated POJOs. + * + * @param configXml The config-file to use + * @return WebformsMavenPluginType The corresponding Java-Object of the plugin-configuration. + * @throws MojoExecutionException in case of marshalling exception for the fsm-plugin.xsd. + */ + public FsmMavenPluginType bindXmlConfigToPojo(final File configXml) throws MojoExecutionException { + log.debug("*** Constructing ConfigXml-Object"); + + try { + final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + final Schema schema = sf.newSchema(getClass().getResource("/fsm-plugin.xsd")); + final StreamSource streamSource = new StreamSource(configXml); + final JAXBContext jaxbContext = JAXBContext.newInstance(FsmMavenPluginType.class); + final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setSchema(schema); + unmarshaller.setEventHandler(new XmlValidationEventHandler(log)); + + final JAXBElement jaxbElement = unmarshaller.unmarshal(streamSource, FsmMavenPluginType.class); + FsmMavenPluginType config = jaxbElement.getValue(); + applyDefaultConfiguration(config); + return config; + } catch (SAXException e) { + throw new MojoExecutionException(e, "Error while parsing file with SAX", e.getMessage()); + } catch (JAXBException e) { + throw new MojoExecutionException(e, "Error while binding xml-file with JAXB", e.getMessage()); + } + } + + void applyDefaultConfiguration(FsmMavenPluginType config) { + if (config.getScopes() == null) { + ScopesType defaultScopesType = new ScopesType(); + List defaultScopes = defaultScopesType.getScope(); + defaultScopes.add("runtime"); + defaultScopes.add("compile"); + config.setScopes(defaultScopesType); + } + } + +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/ModuleXmlWriter.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/ModuleXmlWriter.java new file mode 100644 index 0000000..2029d11 --- /dev/null +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/ModuleXmlWriter.java @@ -0,0 +1,70 @@ +package com.monday_consulting.maven.plugins.fsm.xml; + +import org.apache.maven.plugin.logging.Log; +import org.codehaus.plexus.util.WriterFactory; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XmlStreamWriter; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomWriter; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class ModuleXmlWriter { + + private final Log log; + + public ModuleXmlWriter(Log log) { + this.log = log; + } + + /** + * Write a DOM-Tree to a target directory. + * This will create {@code ./META-INF/module.xml} and {@code ./META-INF/module-isolated.xml} + * + * @param target target directory to write to + * @param dom dom to write to file. + * @throws IOException in case of unexpected writer exceptions. + */ + public void writeDomToTarget(final Path target, final Xpp3Dom dom) throws IOException { + log.debug("Write TargetXml-File"); + + final Path metaInf = target.resolve("META-INF"); + // ensure that the target directory exists + Files.createDirectories(metaInf); + + final Path moduleXml = metaInf.resolve("module.xml"); + log.info("Writing module descriptor: " + moduleXml); + writeFile(moduleXml.toFile(), dom); + + final Path moduleIsolatedXml = metaInf.resolve("module-isolated.xml"); + log.info("Writing isolated module descriptor: " + moduleIsolatedXml); + Files.copy(moduleXml, moduleIsolatedXml); + + log.debug("Dependencies written to Module-XML:\n\t" + dom); + } + + /** + * Write a DOM-Tree to a target XML file. + * + * @param target File to write to. + * @param dom dom to write to file. + * @throws IOException in case of unexpected writer exceptions. + */ + public void writeDomToTarget(final File target, final Xpp3Dom dom) throws IOException { + log.info("Writing module descriptor: " + target.getAbsolutePath()); + + // ensure that the target directory exists + Files.createDirectories(target.toPath().getParent()); + writeFile(target, dom); + } + + private void writeFile(final File file, final Xpp3Dom dom) throws IOException { + final XmlStreamWriter writer = WriterFactory.newXmlWriter(file); + final PrettyPrintXMLWriter pretty = new PrettyPrintXMLWriter(writer); + Xpp3DomWriter.write(pretty, dom); + writer.close(); + } +} diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/PrototypeXml.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/PrototypeXml.java similarity index 91% rename from src/main/java/com/monday_consulting/maven/plugins/fsm/util/PrototypeXml.java rename to src/main/java/com/monday_consulting/maven/plugins/fsm/xml/PrototypeXml.java index 09a870c..df75479 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/PrototypeXml.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/PrototypeXml.java @@ -1,4 +1,4 @@ -package com.monday_consulting.maven.plugins.fsm.util; +package com.monday_consulting.maven.plugins.fsm.xml; /* Copyright 2016-2020 Monday Consulting GmbH @@ -16,6 +16,7 @@ limitations under the License. */ +import com.monday_consulting.maven.plugins.fsm.util.Module; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; @@ -41,10 +42,15 @@ public class PrototypeXml { private final List dependencyJointList; private Xpp3Dom prototypeDom; - public PrototypeXml(final Log log, final File prototypeXml) throws XmlPullParserException, IOException { + public PrototypeXml(final Log log, final File prototypeXml) { this.dependencyJointList = new ArrayList<>(); this.log = log; - this.prototypeDom = Xpp3DomBuilder.build(new XmlStreamReader(prototypeXml)); + + try { + this.prototypeDom = Xpp3DomBuilder.build(new XmlStreamReader(prototypeXml)); + } catch (XmlPullParserException | IOException e) { + throw new RuntimeException("Failed to parse Module prototype " + prototypeXml, e); + } if (log.isDebugEnabled()) { this.log.debug("Getting dependency-joints\nDependency-Joints to fill:"); @@ -52,7 +58,7 @@ public PrototypeXml(final Log log, final File prototypeXml) throws XmlPullParser for (final Xpp3Dom xpp3Dom : new Xpp3DomIterator(prototypeDom)) { if (xpp3Dom.getName().equals("dependencies")) { - if (xpp3Dom.getValue().equals("")) { + if (xpp3Dom.getValue().isEmpty()) { log.error("Prototype-Xml-Error:\nTried to retrieve dependency-joint, but because its value was empty, no connection to a module can be made."); } dependencyJointList.add(new DependencyJoint(xpp3Dom.getValue(), xpp3Dom)); @@ -69,6 +75,8 @@ public PrototypeXml(final Log log, final File prototypeXml) throws XmlPullParser * @throws MojoExecutionException in case of configuration problems. */ public void fillPrototypeDom(final Map moduleList) throws MojoExecutionException, MojoFailureException { + log.debug("Enhance Prototype for TargetXml"); + for (final DependencyJoint dJ : dependencyJointList) { Module moduleToInsert = moduleList.get(dJ.getDependencyTagValue()); diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/XmlValidationEventHandler.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/XmlValidationEventHandler.java similarity index 97% rename from src/main/java/com/monday_consulting/maven/plugins/fsm/util/XmlValidationEventHandler.java rename to src/main/java/com/monday_consulting/maven/plugins/fsm/xml/XmlValidationEventHandler.java index c7eae80..5598bf4 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/XmlValidationEventHandler.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/XmlValidationEventHandler.java @@ -1,4 +1,4 @@ -package com.monday_consulting.maven.plugins.fsm.util; +package com.monday_consulting.maven.plugins.fsm.xml; /* Copyright 2016-2020 Monday Consulting GmbH diff --git a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/Xpp3DomIterator.java b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/Xpp3DomIterator.java similarity index 98% rename from src/main/java/com/monday_consulting/maven/plugins/fsm/util/Xpp3DomIterator.java rename to src/main/java/com/monday_consulting/maven/plugins/fsm/xml/Xpp3DomIterator.java index eb67a90..1eb53d5 100644 --- a/src/main/java/com/monday_consulting/maven/plugins/fsm/util/Xpp3DomIterator.java +++ b/src/main/java/com/monday_consulting/maven/plugins/fsm/xml/Xpp3DomIterator.java @@ -1,4 +1,4 @@ -package com.monday_consulting.maven.plugins.fsm.util; +package com.monday_consulting.maven.plugins.fsm.xml; /* Copyright 2016-2020 Monday Consulting GmbH diff --git a/src/main/resources/fsm-plugin.xsd b/src/main/resources/fsm-plugin.xsd index 6c9c443..5f70e8b 100644 --- a/src/main/resources/fsm-plugin.xsd +++ b/src/main/resources/fsm-plugin.xsd @@ -42,7 +42,7 @@ - + diff --git a/src/test/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojoTest.java b/src/test/java/com/monday_consulting/maven/plugins/fsm/xml/FsmPluginConfigParserTest.java similarity index 73% rename from src/test/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojoTest.java rename to src/test/java/com/monday_consulting/maven/plugins/fsm/xml/FsmPluginConfigParserTest.java index bdf2b78..417b489 100644 --- a/src/test/java/com/monday_consulting/maven/plugins/fsm/DependencyToXMLMojoTest.java +++ b/src/test/java/com/monday_consulting/maven/plugins/fsm/xml/FsmPluginConfigParserTest.java @@ -1,15 +1,17 @@ -package com.monday_consulting.maven.plugins.fsm; +package com.monday_consulting.maven.plugins.fsm.xml; import com.monday_consulting.maven.plugins.fsm.jaxb.FsmMavenPluginType; import com.monday_consulting.maven.plugins.fsm.jaxb.ModuleType; import com.monday_consulting.maven.plugins.fsm.jaxb.ModulesType; +import org.apache.maven.plugin.logging.Log; import org.junit.jupiter.api.Test; import java.util.List; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; -class DependencyToXMLMojoTest { +class FsmPluginConfigParserTest { @Test void applyDefaultConfiguration() { @@ -20,15 +22,12 @@ void applyDefaultConfiguration() { config.setModules(modulesType); // apply default config - DependencyToXMLMojo mojo = new DependencyToXMLMojo(); - mojo.applyDefaultConfiguration(config); + FsmPluginConfigParser configParser = new FsmPluginConfigParser(mock(Log.class)); + configParser.applyDefaultConfiguration(config); // validate config final List defaultScopes = config.getScopes().getScope(); assertTrue(defaultScopes.contains("runtime"), "'runtime' should be a default scope"); assertTrue(defaultScopes.contains("compile"), "'compile' should be a default scope"); - - String prefix = config.getModules().getModule().get(0).getPrefix(); - assertEquals("", prefix, "Config should have an empty prefix"); } }