[ARCHETYPE-637] Fix PomUtils pretty-print issue on Java 9+

As of Java 9, the Transformer class's pretty-print feature doesn't define the actual format. Therefore, whitespace-only nodes will be outputted as well. This has been discussed in this [JDK bug ticket](https://bugs.openjdk.java.net/browse/JDK-8262285?attachmentViewMode=list). Also, [Java 9's release note](https://www.oracle.com/java/technologies/javase/9-notes.html) has explained this in the xml/jaxp section.

If we want our pretty-print method to always generate the same format under various Java versions, we need to provide a stylesheet file.

ref:

   https://bugs.openjdk.java.net/browse/JDK-8262285?attachmentViewMode=list

   https://www.baeldung.com/java-pretty-print-xml#pretty-printing-xml-with-the-transformer-class

Co-authored-by: Moderne <team@moderne.io>

---

https://issues.apache.org/jira/browse/ARCHETYPE-637
diff --git a/archetype-common/src/main/java/org/apache/maven/archetype/common/util/PomUtils.java b/archetype-common/src/main/java/org/apache/maven/archetype/common/util/PomUtils.java
index caea494..a1b0b6f 100644
--- a/archetype-common/src/main/java/org/apache/maven/archetype/common/util/PomUtils.java
+++ b/archetype-common/src/main/java/org/apache/maven/archetype/common/util/PomUtils.java
@@ -38,6 +38,8 @@
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.InputStream;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.Writer;
@@ -127,14 +129,17 @@
             tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "" );
 
             tf.setAttribute( "indent-number", 2 );
-            Transformer tr = tf.newTransformer();
-            tr.setOutputProperty( OutputKeys.INDENT, "yes" );
-            tr.setOutputProperty( OutputKeys.METHOD, "xml" );
-            tr.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
-            tr.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2" );
-            document.getDomConfig().setParameter( "infoset", Boolean.TRUE );
-            document.getDocumentElement().normalize();
-            tr.transform( new DOMSource( document ), new StreamResult( fileWriter ) );
+            try ( InputStream xsl = PomUtils.class.getResourceAsStream( "/prettyprint.xsl" ) ) 
+            {
+                final Transformer tr = tf.newTransformer( new StreamSource( xsl ) );
+                tr.setOutputProperty( OutputKeys.INDENT, "yes" );
+                tr.setOutputProperty( OutputKeys.METHOD, "xml" );
+                tr.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
+                tr.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2" );
+                document.getDomConfig().setParameter( "infoset", Boolean.TRUE );
+                document.getDocumentElement().normalize();
+                tr.transform( new DOMSource( document ), new StreamResult( fileWriter ) );
+            }
             return true;
         }
         else
diff --git a/archetype-common/src/main/resources/prettyprint.xsl b/archetype-common/src/main/resources/prettyprint.xsl
new file mode 100644
index 0000000..b365960
--- /dev/null
+++ b/archetype-common/src/main/resources/prettyprint.xsl
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:strip-space elements="*"/>
+    <xsl:output method="xml" encoding="UTF-8"/>
+
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()"/>
+        </xsl:copy>
+    </xsl:template>
+
+</xsl:stylesheet>
diff --git a/archetype-common/src/test/java/org/apache/maven/archetype/common/TestPomManager.java b/archetype-common/src/test/java/org/apache/maven/archetype/common/TestPomManager.java
new file mode 100644
index 0000000..c2fe362
--- /dev/null
+++ b/archetype-common/src/test/java/org/apache/maven/archetype/common/TestPomManager.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.archetype.common;
+
+import java.io.File;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestPomManager {
+
+  //ref: https://www.baeldung.com/java-pretty-print-xml
+  //https://bugs.openjdk.java.net/browse/JDK-8262285?attachmentViewMode=list
+  @Test
+  public void testAddModule() throws Exception {
+    PomManager pomManager = new DefaultPomManager();
+
+    URL pom = getClass().getResource("/projects/generate-9/pom.xml.sample");
+    File pomFileSrc = new File(pom.toURI());
+    File pomFile = new File(pomFileSrc.getAbsolutePath() + "-copied.xml");
+    FileUtils.copyFile(pomFileSrc, pomFile);
+    final int moduleNumber = 4;
+    for (int i = 0; i < moduleNumber; i++ ) {
+      pomManager.addModule(pomFile, "test" + i);
+    }
+    String fileText = FileUtils.readFileToString( pomFile, "UTF-8" );
+    Pattern pattern = Pattern.compile("(^[ ]+[\\r\\n]+){"+moduleNumber + "}", Pattern.MULTILINE);
+    Matcher matcher = pattern.matcher(fileText);
+    Assert.assertFalse(matcher.find());
+  }
+
+}