You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2019/05/14 19:26:18 UTC

[maven] branch MNG-6656 created (now 65a5a1b)

This is an automated email from the ASF dual-hosted git repository.

rfscholte pushed a change to branch MNG-6656
in repository https://gitbox.apache.org/repos/asf/maven.git.


      at 65a5a1b  [MNG-6656] Introduce base for build/consumer pom

This branch includes the following new commits:

     new 65a5a1b  [MNG-6656] Introduce base for build/consumer pom

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[maven] 01/01: [MNG-6656] Introduce base for build/consumer pom

Posted by rf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rfscholte pushed a commit to branch MNG-6656
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 65a5a1bbaaf205fa2614d0725291a4bbc63f9633
Author: rfscholte <rf...@apache.org>
AuthorDate: Tue May 14 21:26:07 2019 +0200

    [MNG-6656] Introduce base for build/consumer pom
---
 maven-core/pom.xml                                 |   5 +
 .../DefaultRepositorySystemSessionFactory.java     | 107 +++++++++++++++--
 .../apache/maven/xml/filter/BuildPomXMLFilter.java |  44 +++++++
 .../maven/xml/filter/ConsumerPomXMLFilter.java     |  73 ++++++++++++
 .../apache/maven/xml/filter/FastForwardFilter.java | 128 +++++++++++++++++++++
 .../apache/maven/xml/filter/ModulesXMLFilter.java  | 102 ++++++++++++++++
 .../maven/xml/filter/RelativePathXMLFilter.java    |  98 ++++++++++++++++
 .../maven/xml/filter/AbstractXMLFilterTests.java   |  80 +++++++++++++
 .../maven/xml/filter/ConsumerPomXMLFilterTest.java |  64 +++++++++++
 .../maven/xml/filter/ModulesXMLFilterTest.java     |  62 ++++++++++
 .../xml/filter/RelativePathXMLFilterTest.java      |  61 ++++++++++
 pom.xml                                            |   8 +-
 12 files changed, 823 insertions(+), 9 deletions(-)

diff --git a/maven-core/pom.xml b/maven-core/pom.xml
index be31a3e..e467851 100644
--- a/maven-core/pom.xml
+++ b/maven-core/pom.xml
@@ -136,6 +136,11 @@ under the License.
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.xmlunit</groupId>
+      <artifactId>xmlunit-assertj</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
index 248a3b6..792b085 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
@@ -19,6 +19,27 @@ package org.apache.maven.internal.aether;
  * under the License.
  */
 
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+
 import org.apache.maven.RepositoryUtils;
 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
 import org.apache.maven.bridge.MavenRepositorySystem;
@@ -32,32 +53,31 @@ import org.apache.maven.settings.building.SettingsProblem;
 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
 import org.apache.maven.settings.crypto.SettingsDecrypter;
 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
+import org.apache.maven.xml.filter.ConsumerPomXMLFilter;
 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 import org.eclipse.aether.ConfigurationProperties;
 import org.eclipse.aether.DefaultRepositorySystemSession;
 import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.repository.LocalRepository;
 import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
 import org.eclipse.aether.repository.RepositoryPolicy;
 import org.eclipse.aether.repository.WorkspaceReader;
 import org.eclipse.aether.resolution.ResolutionErrorPolicy;
 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
+import org.eclipse.aether.transform.FileTransformer;
+import org.eclipse.aether.transform.FileTransformerManager;
+import org.eclipse.aether.transform.TransformException;
 import org.eclipse.aether.util.repository.AuthenticationBuilder;
 import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
 import org.eclipse.aether.util.repository.DefaultMirrorSelector;
 import org.eclipse.aether.util.repository.DefaultProxySelector;
 import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy;
 import org.eclipse.sisu.Nullable;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
 /**
  * @since 3.3.0
@@ -238,9 +258,80 @@ public class DefaultRepositorySystemSessionFactory
         mavenRepositorySystem.injectProxy( session, request.getPluginArtifactRepositories() );
         mavenRepositorySystem.injectAuthentication( session, request.getPluginArtifactRepositories() );
 
+        if ( Boolean.getBoolean( "maven.experimental.buildconsumer" ) )
+        {
+            session.setFileTransformerManager( newFileTransformerManager() );
+        }
         return session;
     }
 
+    private FileTransformerManager newFileTransformerManager()
+    {
+        return new FileTransformerManager()
+        {
+            @Override
+            public Collection<FileTransformer> getTransformersForArtifact( Artifact artifact )
+            {
+                Collection<FileTransformer> transformers = new ArrayList<>();
+                if ( "pom".equals( artifact.getExtension() ) )
+                {
+                    final TransformerFactory transformerFactory = TransformerFactory.newInstance();
+
+                    transformers.add( new FileTransformer()
+                    {
+                        @Override
+                        public InputStream transformData( File file )
+                            throws IOException, TransformException
+                        {
+                            try
+                            {
+                                final PipedOutputStream pipedOutputStream  = new PipedOutputStream();
+                                final PipedInputStream pipedInputStream  = new PipedInputStream( pipedOutputStream );
+                                
+                                final SAXSource transformSource =
+                                                new SAXSource( new ConsumerPomXMLFilter(), 
+                                                               new InputSource( new FileReader( file ) ) );
+                                
+                                final StreamResult result = new StreamResult( pipedOutputStream );
+                                
+                                final Runnable runnable = new Runnable()
+                                {
+                                    @Override
+                                    public void run()
+                                    {
+                                        try ( PipedOutputStream out = pipedOutputStream )
+                                        {
+                                            transformerFactory.newTransformer().transform( transformSource, result );
+                                        }
+                                        catch ( TransformerException | IOException e )
+                                        {
+                                            throw new RuntimeException( e );
+                                        }
+                                    }
+                                };
+
+                                new Thread( runnable ).start();
+
+                                return pipedInputStream;
+                            }
+                            catch ( SAXException | ParserConfigurationException  e )
+                            {
+                                throw new TransformException( e );
+                            }
+                        }
+
+                        @Override
+                        public Artifact transformArtifact( Artifact artifact )
+                        {
+                            return artifact;
+                        }
+                    } );
+                }
+                return Collections.unmodifiableCollection( transformers );
+            }
+        };
+    }
+    
     private String getUserAgent()
     {
         return "Apache-Maven/" + getMavenVersion() + " (Java " + System.getProperty( "java.version" ) + "; "
diff --git a/maven-core/src/main/java/org/apache/maven/xml/filter/BuildPomXMLFilter.java b/maven-core/src/main/java/org/apache/maven/xml/filter/BuildPomXMLFilter.java
new file mode 100644
index 0000000..60f0c49
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/xml/filter/BuildPomXMLFilter.java
@@ -0,0 +1,44 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * Filter to adjust pom on filesystem before being processed for effective pom.
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+public class BuildPomXMLFilter extends XMLFilterImpl
+{
+    public BuildPomXMLFilter()
+    {
+        super();
+    }
+
+    public BuildPomXMLFilter( XMLReader parent )
+    {
+        super( parent );
+    }
+
+    
+}
diff --git a/maven-core/src/main/java/org/apache/maven/xml/filter/ConsumerPomXMLFilter.java b/maven-core/src/main/java/org/apache/maven/xml/filter/ConsumerPomXMLFilter.java
new file mode 100644
index 0000000..8709b9c
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/xml/filter/ConsumerPomXMLFilter.java
@@ -0,0 +1,73 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.XMLReader;
+
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * XML Filter to transform pom.xml to consumer pom.
+ * This often means stripping of build-specific information.
+ * 
+ * This filter is used at 2 locations:
+ * - {@link org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory} when publishing pom files.
+ * - TODO ???Class when a reactor module is used as dependency. This ensures consistency of dependency handling
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+public class ConsumerPomXMLFilter extends XMLFilterImpl
+{
+    private final XMLFilter rootFilter;
+
+    public ConsumerPomXMLFilter() throws SAXException, ParserConfigurationException
+    {
+        this( SAXParserFactory.newInstance().newSAXParser().getXMLReader() );
+    }
+
+    public ConsumerPomXMLFilter( XMLReader parent )
+    {
+        rootFilter = new BuildPomXMLFilter( parent );
+        
+        // Ensure that xs:any elements aren't touched by next filters
+        XMLFilter filter = new FastForwardFilter( rootFilter );
+        
+        // Strip modules
+        filter = new ModulesXMLFilter( filter );
+        // Adjust relativePath
+        filter = new RelativePathXMLFilter( filter );
+        
+        // maybe more to follow
+        
+        super.setParent( filter );
+    }
+    
+    @Override
+    public void setParent( XMLReader parent )
+    {
+        rootFilter.setParent( parent );
+    }
+}
diff --git a/maven-core/src/main/java/org/apache/maven/xml/filter/FastForwardFilter.java b/maven-core/src/main/java/org/apache/maven/xml/filter/FastForwardFilter.java
new file mode 100644
index 0000000..df68167
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/xml/filter/FastForwardFilter.java
@@ -0,0 +1,128 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * This filter will skip all following filters and write directly to the output.
+ * Should be used in case of a DOM that should not be effected by other filters, even though the elements match 
+ * 
+ * @author Robert Scholte
+ * @since 4.0.0
+ */
+class FastForwardFilter extends XMLFilterImpl
+{
+    /**
+     * DOM elements of pom
+     * 
+     * <ul>
+     *  <li>execution.configuration</li>
+     *  <li>plugin.configuration</li>
+     *  <li>plugin.goals</li>
+     *  <li>profile.reports</li>
+     *  <li>project.reports</li>
+     *  <li>reportSet.configuration</li>
+     * <ul>
+     */
+    private final Deque<String> state = new ArrayDeque<>();
+    
+    private int domDepth = 0;
+    
+    private ContentHandler originalHandler;
+    
+    FastForwardFilter()
+    {
+        super();
+    }
+
+    FastForwardFilter( XMLReader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    public void startElement( String uri, String localName, String qName, Attributes atts )
+        throws SAXException
+    {
+        super.startElement( uri, localName, qName, atts );
+        if ( domDepth > 0 )
+        {
+            domDepth++;
+        }
+        else
+        {
+            final String key = state.peek() + '.' + localName;
+            switch ( key )
+            {
+                case "execution.configuration":
+                case "plugin.configuration":
+                case "plugin.goals":
+                case "profile.reports":
+                case "project.reports":
+                case "reportSet.configuration":
+                    domDepth++;
+
+                    originalHandler = getContentHandler();
+
+                    ContentHandler outputContentHandler = getContentHandler();
+                    while ( outputContentHandler instanceof XMLFilter )
+                    {
+                        outputContentHandler = ( (XMLFilter) outputContentHandler ).getContentHandler();
+                    }
+                    setContentHandler( outputContentHandler );
+                    break;
+                default:
+                    break;
+            }
+            state.push( localName );
+        }
+    }
+    
+    @Override
+    public void endElement( String uri, String localName, String qName )
+        throws SAXException
+    {
+        if ( domDepth > 0 )
+        {
+            domDepth--;
+            
+            if ( domDepth == 0 )
+            {
+                setContentHandler( originalHandler );
+            }
+        }
+        else
+        {
+            state.pop();
+        }
+        super.endElement( uri, localName, qName );
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/maven-core/src/main/java/org/apache/maven/xml/filter/ModulesXMLFilter.java b/maven-core/src/main/java/org/apache/maven/xml/filter/ModulesXMLFilter.java
new file mode 100644
index 0000000..9e7b6fd
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/xml/filter/ModulesXMLFilter.java
@@ -0,0 +1,102 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * Remove all modules, this is just buildtime information
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+class ModulesXMLFilter
+    extends XMLFilterImpl
+{
+    /**
+     * Using 3 to also remove whitespace-block after closing tag
+     * -1 none
+     *  1 started
+     *  2 ended
+     */
+    int modulesStatus = -1;
+    
+    ModulesXMLFilter()
+    {
+        super();
+    }
+
+    ModulesXMLFilter( XMLReader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    public void startElement( String uri, String localName, String qName, Attributes atts )
+        throws SAXException
+    {
+        if ( modulesStatus == -1 && "modules".equals( localName ) )
+        {
+            modulesStatus = 1;
+        }
+        else if ( modulesStatus == 2 )
+        {
+            modulesStatus = -1;
+        }
+
+        if ( modulesStatus != 1 )
+        {
+            super.startElement( uri, localName, qName, atts );
+        }
+    }
+
+    @Override
+    public void endElement( String uri, String localName, String qName )
+        throws SAXException
+    {
+        if ( modulesStatus == 1 && "modules".equals( localName ) )
+        {
+            modulesStatus = 2;
+        }
+        else if ( modulesStatus == 2 )
+        {
+            modulesStatus = -1;
+        }
+        
+        if ( modulesStatus == -1 )
+        {
+            super.endElement( uri, localName, qName );
+        }
+    }
+
+    @Override
+    public void characters( char[] ch, int start, int length )
+        throws SAXException
+    {
+        if ( modulesStatus == -1 )
+        {
+            super.characters( ch, start, length );
+        }
+    }
+
+}
diff --git a/maven-core/src/main/java/org/apache/maven/xml/filter/RelativePathXMLFilter.java b/maven-core/src/main/java/org/apache/maven/xml/filter/RelativePathXMLFilter.java
new file mode 100644
index 0000000..8548ddd
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/xml/filter/RelativePathXMLFilter.java
@@ -0,0 +1,98 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * Remove content from relativePath
+ * 
+ * TODO fix indentation of closing parent tag
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+class RelativePathXMLFilter
+    extends XMLFilterImpl
+{
+    /**
+     * Using 3 to also remove whitespace-block after closing tag
+     * -1 none
+     *  1 started
+     *  2 ended
+     */
+    int relativePathStatus = -1;
+    
+    RelativePathXMLFilter()
+    {
+        super();
+    }
+
+    RelativePathXMLFilter( XMLReader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    public void startElement( String uri, String localName, String qName, Attributes atts )
+        throws SAXException
+    {
+        if ( relativePathStatus == -1 && "relativePath".equals( localName ) )
+        {
+            relativePathStatus = 1;
+        }
+        else if ( relativePathStatus == 2 )
+        {
+            relativePathStatus = -1;
+        }
+
+        super.startElement( uri, localName, qName, atts );
+    }
+
+    @Override
+    public void endElement( String uri, String localName, String qName )
+        throws SAXException
+    {
+        if ( relativePathStatus == 1 && "relativePath".equals( localName ) )
+        {
+            relativePathStatus = 2;
+        }
+        else if ( relativePathStatus == 2 )
+        {
+            relativePathStatus = -1;
+        }
+        
+        super.endElement( uri, localName, qName );
+    }
+
+    @Override
+    public void characters( char[] ch, int start, int length )
+        throws SAXException
+    {
+        if ( relativePathStatus != 1 )
+        {
+            super.characters( ch, start, length );
+        }
+    }
+
+}
diff --git a/maven-core/src/test/java/org/apache/maven/xml/filter/AbstractXMLFilterTests.java b/maven-core/src/test/java/org/apache/maven/xml/filter/AbstractXMLFilterTests.java
new file mode 100644
index 0000000..69fc33b
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/xml/filter/AbstractXMLFilterTests.java
@@ -0,0 +1,80 @@
+package org.apache.maven.xml.filter;
+
+import java.io.Reader;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public class AbstractXMLFilterTests
+{
+
+    public AbstractXMLFilterTests()
+    {
+        super();
+    }
+
+    protected String transform( String input, XMLFilter filter )
+        throws TransformerException, SAXException
+    {
+        return transform( new StringReader( input ), filter );
+    }
+    
+    protected String transform( Reader input, XMLFilter filter )
+        throws TransformerException, SAXException
+    {
+        XMLReader reader = XMLReaderFactory.createXMLReader();
+
+        XMLFilter parent = filter;
+        while ( parent.getParent() instanceof XMLFilter )
+        {
+            parent = (XMLFilter) parent.getParent();
+        }
+        parent.setParent( reader );
+
+        Writer writer = new StringWriter();
+        StreamResult result = new StreamResult( writer );
+
+        TransformerFactory transformerFactory = TransformerFactory.newInstance();
+        Transformer transformer = transformerFactory.newTransformer();
+        transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" );
+
+        SAXSource transformSource = new SAXSource( filter, new InputSource( input ) );
+
+        transformer.transform( transformSource, result );
+
+        return writer.toString();
+    }
+}
\ No newline at end of file
diff --git a/maven-core/src/test/java/org/apache/maven/xml/filter/ConsumerPomXMLFilterTest.java b/maven-core/src/test/java/org/apache/maven/xml/filter/ConsumerPomXMLFilterTest.java
new file mode 100644
index 0000000..b3d44db
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/xml/filter/ConsumerPomXMLFilterTest.java
@@ -0,0 +1,64 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import static org.xmlunit.assertj.XmlAssert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
+{
+    private ConsumerPomXMLFilter filter;
+    
+    @Before
+    public void setup() throws Exception {
+        filter = new ConsumerPomXMLFilter();
+    }
+    
+    @Test
+    public void testAllFilters() throws Exception {
+        String input = "<project>\n"
+                     + "  <parent>\n"
+                     + "    <groupId>GROUPID</groupId>\n"
+                     + "    <artifactId>PARENT</artifactId>\n"
+                     + "    <version>VERSION</version>\n"
+                     + "    <relativePath>../pom.xml</relativePath>\n"
+                     + "  </parent>\n"
+                     + "  <artifactId>PROJECT</artifactId>\n"
+                     + "  <modules>\n"
+                     + "    <module>ab</module>\n"
+                     + "    <module>../cd</module>\n"
+                     + "  </modules>\n"
+                     + "</project>";
+        String expected = "<project>\n"
+                        + "  <parent>\n"
+                        + "    <groupId>GROUPID</groupId>\n"
+                        + "    <artifactId>PARENT</artifactId>\n"
+                        + "    <version>VERSION</version>\n"
+                        + "    <relativePath/>\n"
+                        + "  </parent>\n"
+                        + "  <artifactId>PROJECT</artifactId>\n"
+                        + "</project>";
+        String actual = transform( input, filter );
+        assertThat( actual ).and( expected ).ignoreWhitespace().areIdentical();
+    }
+
+}
diff --git a/maven-core/src/test/java/org/apache/maven/xml/filter/ModulesXMLFilterTest.java b/maven-core/src/test/java/org/apache/maven/xml/filter/ModulesXMLFilterTest.java
new file mode 100644
index 0000000..353f174
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/xml/filter/ModulesXMLFilterTest.java
@@ -0,0 +1,62 @@
+package org.apache.maven.xml.filter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import static org.xmlunit.assertj.XmlAssert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ModulesXMLFilterTest extends AbstractXMLFilterTests {
+
+	private ModulesXMLFilter filter;
+	
+	@Before
+	public void setup() {
+		filter = new ModulesXMLFilter();
+	}
+	
+	@Test
+	public void testEmptyModules() throws Exception {
+		String input = "<project><modules/></project>";
+        String expected = "<project/>";
+        String actual = transform( input, filter );
+        assertThat( actual ).and( expected ).areIdentical();
+	}
+
+	@Test
+	public void testSetOfModules() throws Exception {
+		String input = "<project><modules>"
+				+ "<module>ab</module>"
+				+ "<module>../cd</module>"
+				+ "</modules></project>";
+		String expected = "<project/>";
+		String actual = transform( input, filter );
+		assertThat( actual ).and( expected ).areIdentical();
+	}
+	
+	@Test
+    public void testNoModules() throws Exception {
+        String input = "<project><name>NAME</name></project>";
+        String expected = input;
+        String actual = transform( input, filter );
+        assertThat( actual ).and( expected ).areIdentical();
+    }
+}
diff --git a/maven-core/src/test/java/org/apache/maven/xml/filter/RelativePathXMLFilterTest.java b/maven-core/src/test/java/org/apache/maven/xml/filter/RelativePathXMLFilterTest.java
new file mode 100644
index 0000000..298197d
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/xml/filter/RelativePathXMLFilterTest.java
@@ -0,0 +1,61 @@
+package org.apache.maven.xml.filter;
+
+import static org.xmlunit.assertj.XmlAssert.assertThat;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class RelativePathXMLFilterTest extends AbstractXMLFilterTests
+{
+    private RelativePathXMLFilter filter;
+    
+    @Before
+    public void setup() {
+        filter = new RelativePathXMLFilter();
+    }
+    
+    @Test
+    public void testRelativePath() throws Exception
+    {
+        String input = "<project>\n"
+                        + "  <parent>\n"
+                        + "    <groupId>GROUPID</groupId>\n"
+                        + "    <artifactId>PARENT</artifactId>\n"
+                        + "    <version>VERSION</version>\n"
+                        + "    <relativePath>../pom.xml</relativePath>\n"
+                        + "  </parent>\n"
+                        + "  <artifactId>PROJECT</artifactId>\n"
+                        + "</project>";
+           String expected = "<project>\n"
+                           + "  <parent>\n"
+                           + "    <groupId>GROUPID</groupId>\n"
+                           + "    <artifactId>PARENT</artifactId>\n"
+                           + "    <version>VERSION</version>\n"
+                           + "    <relativePath/>\n"
+                           + "  </parent>\n"
+                           + "  <artifactId>PROJECT</artifactId>\n"
+                           + "</project>";
+           String actual = transform( input, filter );
+           assertThat( actual ).and( expected ).areIdentical();
+    }
+
+}
diff --git a/pom.xml b/pom.xml
index cb9dae5..640e57c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,7 +66,7 @@ under the License.
     <jxpathVersion>1.3</jxpathVersion>
     <resolverVersion>1.3.3</resolverVersion>
     <slf4jVersion>1.7.25</slf4jVersion>
-    <xmlunitVersion>2.2.1</xmlunitVersion>
+    <xmlunitVersion>2.6.2</xmlunitVersion>
     <maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
     <!-- Control the name of the distribution and information output by mvn -->
     <distributionId>apache-maven</distributionId>
@@ -407,6 +407,12 @@ under the License.
       </dependency>
       <dependency>
         <groupId>org.xmlunit</groupId>
+        <artifactId>xmlunit-assertj</artifactId>
+        <version>${xmlunitVersion}</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.xmlunit</groupId>
         <artifactId>xmlunit-core</artifactId>
         <version>${xmlunitVersion}</version>
         <scope>test</scope>