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 2020/06/24 21:29:35 UTC

[maven] branch MNG-6946 created (now e6763e3)

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

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


      at e6763e3  [MNG-6946] Build/consumer incorrectly transforms name of artifactId

This branch includes the following new commits:

     new e6763e3  [MNG-6946] Build/consumer incorrectly transforms name of artifactId

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-6946] Build/consumer incorrectly transforms name of artifactId

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

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

commit e6763e3273c15c60a14f9ce01596ff6399ead7c0
Author: rfscholte <rf...@apache.org>
AuthorDate: Wed Jun 24 23:29:23 2020 +0200

    [MNG-6946] Build/consumer incorrectly transforms name of artifactId
---
 .../main/java/org/apache/maven/xml/Factories.java  |  42 +----
 .../xml/sax/filter/AbstractEventXMLFilter.java     |  43 ++++--
 .../maven/xml/sax/filter/CiFriendlyXMLFilter.java  | 170 ++++++++++++++++++++-
 .../maven/xml/sax/filter/ParentXMLFilter.java      |  10 +-
 .../xml/sax/filter/AbstractXMLFilterTests.java     |  66 +++++++-
 .../xml/sax/filter/CiFriendlyXMLFilterTest.java    |  67 ++++++++
 6 files changed, 329 insertions(+), 69 deletions(-)

diff --git a/maven-xml/src/main/java/org/apache/maven/xml/Factories.java b/maven-xml/src/main/java/org/apache/maven/xml/Factories.java
index eb2166a..8cccbc4 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/Factories.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/Factories.java
@@ -21,14 +21,13 @@ package org.apache.maven.xml;
 
 import javax.xml.XMLConstants;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 import javax.xml.transform.TransformerFactory;
 
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXNotRecognizedException;
 import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
 
 /**
  * Creates XML related factories with OWASP advices applied
@@ -56,46 +55,9 @@ public final class Factories
         return tf;
     }
     
-    public static SAXParserFactory newSAXParserFactory()
-    {
-        SAXParserFactory spf = SAXParserFactory.newInstance();
-
-        try
-        {
-            // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
-            // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
-   
-            // Using the SAXParserFactory's setFeature
-            spf.setFeature( "http://xml.org/sax/features/external-general-entities", false );
-            
-            // Xerces 2 only - http://xerces.apache.org/xerces-j/features.html#external-general-entities
-            spf.setFeature( "http://apache.org/xml/features/disallow-doctype-decl", true );
-        }
-        catch ( ParserConfigurationException e )
-        {
-            // Tried an unsupported feature.
-        }
-        catch ( SAXNotRecognizedException e )
-        {
-            // Tried an unknown feature.
-        }
-        catch ( SAXNotSupportedException e )
-        {
-            // Tried a feature known to the parser but unsupported.
-        }
-        return spf;
-    }
-    
-    public static SAXParser newSAXParser() throws ParserConfigurationException, SAXException
-    {
-        SAXParser saxParser = newSAXParserFactory().newSAXParser();
-        
-        return saxParser;
-    }
-    
     public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException
     {
-        XMLReader reader = newSAXParser().getXMLReader();
+        XMLReader reader = XMLReaderFactory.createXMLReader();
         
         try
         {
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractEventXMLFilter.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractEventXMLFilter.java
index d23bdec..8067125 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractEventXMLFilter.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractEventXMLFilter.java
@@ -20,6 +20,8 @@ package org.apache.maven.xml.sax.filter;
  */
 
 import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Queue;
 
 import org.apache.maven.xml.sax.SAXEvent;
@@ -44,7 +46,7 @@ abstract class AbstractEventXMLFilter extends AbstractSAXFilter
     
     // characters BEFORE startElement must get state of startingElement
     // this way removing based on state keeps correct formatting
-    private SAXEvent characters;
+    private List<SAXEvent> charactersSegments = new ArrayList<>();
     
     private boolean lockCharacters = false;
     
@@ -82,18 +84,20 @@ abstract class AbstractEventXMLFilter extends AbstractSAXFilter
         if ( isParsing() )
         {
             final String eventState = getState();
-            final SAXEvent charactersEvent = characters;
             
-            if ( !lockCharacters && charactersEvent != null )
+            if ( !lockCharacters )
             {
-                saxEvents.add( () -> 
+                charactersSegments.stream().forEach( e -> 
                 {
-                    if ( acceptEvent( eventState ) )
+                    saxEvents.add( () -> 
                     {
-                        charactersEvent.execute();
-                    }
+                        if ( acceptEvent( eventState ) )
+                        {
+                            e.execute();
+                        }
+                    } );
                 } );
-                characters = null;
+                charactersSegments.clear();
             }
 
             saxEvents.add( () -> 
@@ -126,18 +130,17 @@ abstract class AbstractEventXMLFilter extends AbstractSAXFilter
     protected final void executeEvents() throws SAXException
     {
         final String eventState = getState();
-        final SAXEvent charactersEvent = characters;
-        if ( charactersEvent != null )
+        charactersSegments.stream().forEach( e -> 
         {
             saxEvents.add( () -> 
             {
                 if ( acceptEvent( eventState ) )
                 {
-                    charactersEvent.execute();
+                    e.execute();
                 }
             } );
-            characters = null;
-        }
+        } );
+        charactersSegments.clear();
         
         // not with streams due to checked SAXException
         while ( !saxEvents.isEmpty() )
@@ -204,7 +207,7 @@ abstract class AbstractEventXMLFilter extends AbstractSAXFilter
         }
         else if ( isParsing() )
         {
-            this.characters = getEventFactory().characters( ch, start, length );
+            this.charactersSegments.add( getEventFactory().characters( ch, start, length ) );
         }
         else
         {
@@ -275,6 +278,18 @@ abstract class AbstractEventXMLFilter extends AbstractSAXFilter
         processEvent( getEventFactory().comment( ch, start, length ) );
     }
     
+    protected static String nullSafeAppend( String parentWhitespace, String charSegment )
+    {
+        if ( parentWhitespace == null ) 
+        {
+            return charSegment;
+        }
+        else
+        {
+            return parentWhitespace + charSegment;
+        }
+    }
+    
     /**
      * AutoCloseable with a close method that doesn't throw an exception
      * 
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java
index a13e4d4..c2d48db 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java
@@ -21,6 +21,7 @@ package org.apache.maven.xml.sax.filter;
 
 import java.util.function.Function;
 
+import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
 /**
@@ -30,10 +31,26 @@ import org.xml.sax.SAXException;
  * @since 3.7.0
  */
 class CiFriendlyXMLFilter
-    extends AbstractSAXFilter
+    extends AbstractEventXMLFilter
 {
     private Function<String, String> replaceChain = Function.identity();
     
+    private String characters; 
+    
+    private boolean parsing = false;
+
+    @Override
+    protected boolean isParsing()
+    {
+        return parsing;
+    }
+
+    @Override
+    protected String getState()
+    {
+        return null;
+    }
+    
     public CiFriendlyXMLFilter setChangelist( String changelist )
     {
         replaceChain = replaceChain.andThen( t -> t.replace( "${changelist}", changelist ) );
@@ -64,20 +81,157 @@ class CiFriendlyXMLFilter
     public void characters( char[] ch, int start, int length )
         throws SAXException
     {
-        String text = new String( ch, start, length );
+        this.parsing = true;
+        this.characters = nullSafeAppend( characters, new String( ch, start, length ) );
+    }
+
+    @Override
+    public void comment( char[] ch, int start, int length )
+        throws SAXException
+    {
+        parseCharacters();
+        super.comment( ch, start, length );
+    }
+
+    @Override
+    public void endElement( String uri, String localName, String qName )
+        throws SAXException
+    {
+        parseCharacters();
+        super.endElement( uri, localName, qName );
+    }
+    
+    @Override
+    public void endCDATA()
+        throws SAXException
+    {
+        parseCharacters();
+        super.endCDATA();
+    }
+
+    @Override
+    public void endDocument()
+        throws SAXException
+    {
+        parseCharacters();
+        super.endDocument();
+    }
+
+    @Override
+    public void endDTD()
+        throws SAXException
+    {
+        parseCharacters();
+        super.endDTD();
+    }
+    
+    @Override
+    public void endEntity( String name )
+        throws SAXException
+    {
+        parseCharacters();
+        super.endEntity( name );
+    }
+    
+    @Override
+    public void endPrefixMapping( String prefix )
+        throws SAXException
+    {
+        parseCharacters();
+        super.endPrefixMapping( prefix );
+    }
 
+    @Override
+    public void skippedEntity( String name )
+        throws SAXException
+    {
+        parseCharacters();
+        super.skippedEntity( name );
+    }
+    
+    @Override
+    public void startCDATA()
+        throws SAXException
+    {
+        parseCharacters();
+        super.startCDATA();
+    }
+    
+    @Override
+    public void ignorableWhitespace( char[] ch, int start, int length )
+        throws SAXException
+    {
+        parseCharacters();
+        super.ignorableWhitespace( ch, start, length );
+    }
+    
+    @Override
+    public void processingInstruction( String target, String data )
+        throws SAXException
+    {
+        parseCharacters();
+        super.processingInstruction( target, data );
+    }
+    
+    @Override
+    public void startDocument()
+        throws SAXException
+    {
+        parseCharacters();
+        super.startDocument();
+    }
+    
+    @Override
+    public void startDTD( String name, String publicId, String systemId )
+        throws SAXException
+    {
+        parseCharacters();
+        super.startDTD( name, publicId, systemId );
+    }
+    
+    @Override
+    public void startElement( String uri, String localName, String qName, Attributes atts )
+        throws SAXException
+    {
+        parseCharacters();
+        super.startElement( uri, localName, qName, atts );
+    }
+    
+    @Override
+    public void startEntity( String name )
+        throws SAXException
+    {
+        parseCharacters();
+        super.startEntity( name );
+    }
+    
+    @Override
+    public void startPrefixMapping( String prefix, String uri )
+        throws SAXException
+    {
+        parseCharacters();
+        super.startPrefixMapping( prefix, uri );
+    }
+    
+    private void parseCharacters() throws SAXException
+    {
+        this.parsing = false;
+        if ( characters == null )
+        {
+            return;
+        }
         // assuming this has the best performance
-        if ( text.contains( "${" ) )
+        if ( characters.contains( "${" ) )
         {
-            String newText = replaceChain.apply( text );
-            
-            super.characters( newText.toCharArray(), 0, newText.length() );
+            char[] ch = replaceChain.apply( characters ).toCharArray();
+            super.characters( ch, 0, ch.length );
         }
         else
         {
-            super.characters( ch, start, length );
+            char[] ch = characters.toCharArray();
+            super.characters( ch, 0, ch.length );
         }
+        characters = null;
     }
     
-    
 }
\ No newline at end of file
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ParentXMLFilter.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ParentXMLFilter.java
index df43ec1..8296e74 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ParentXMLFilter.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ParentXMLFilter.java
@@ -120,19 +120,21 @@ class ParentXMLFilter
         {
             final String eventState = state;
             
+            final String charSegment =  new String( ch, start, length );
+            
             switch ( eventState )
             {
                 case "parent":
-                    parentWhitespace = new String( ch, start, length );
+                    parentWhitespace = nullSafeAppend( parentWhitespace, charSegment );
                     break;
                 case "relativePath":
-                    relativePath = new String( ch, start, length );
+                    relativePath = nullSafeAppend( relativePath, charSegment );
                     break;
                 case "groupId":
-                    groupId = new String( ch, start, length );
+                    groupId = nullSafeAppend( groupId, charSegment );
                     break;
                 case "artifactId":
-                    artifactId = new String( ch, start, length );
+                    artifactId = nullSafeAppend( artifactId, charSegment );
                     break;
                 default:
                     break;
diff --git a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/AbstractXMLFilterTests.java b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/AbstractXMLFilterTests.java
index 4fa3b0d..3725e15 100644
--- a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/AbstractXMLFilterTests.java
+++ b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/AbstractXMLFilterTests.java
@@ -23,6 +23,7 @@ import java.io.Reader;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.net.ContentHandler;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
@@ -35,10 +36,10 @@ import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 
 import org.apache.maven.xml.Factories;
-import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
 
 public abstract class AbstractXMLFilterTests
 {
@@ -55,7 +56,10 @@ public abstract class AbstractXMLFilterTests
         {
             XMLReader r = Factories.newXMLReader();
             
-            filter.setParent( r );
+            AbstractSAXFilter perChar = new PerCharXMLFilter();
+            perChar.setParent( r );
+            
+            filter.setParent( perChar );
             filter.setFeature( "http://xml.org/sax/features/namespaces", true );
         }
     }
@@ -86,6 +90,9 @@ public abstract class AbstractXMLFilterTests
         throws TransformerException, SAXException, ParserConfigurationException
     {
         setParent( filter );
+
+        filter = new PerCharXMLFilter( filter );
+
         return transform( new StringReader( input ), filter );
     }
 
@@ -107,7 +114,7 @@ public abstract class AbstractXMLFilterTests
         }
         transformerHandler.setResult( result );
         Transformer transformer = transformerFactory.newTransformer();
-
+        
         SAXSource transformSource = new SAXSource( filter, new InputSource( input ) );
 
         SAXResult transformResult = new SAXResult( transformerHandler );
@@ -116,4 +123,57 @@ public abstract class AbstractXMLFilterTests
 
         return writer.toString();
     }
+    
+    /**
+     * Form {@link ContentHandler}
+     * <q>Your code should not assume that algorithms using char-at-a-time idioms will be working in characterunits; 
+     * in some cases they will split characters. This is relevantwherever XML permits arbitrary characters, such as 
+     * attribute values,processing instruction data, and comments as well as in data reportedfrom this method. It's 
+     * also generally relevant whenever Java codemanipulates internationalized text; the issue isn't unique to XML.</q>
+     *  
+     * @author Robert Scholte
+     */
+    class PerCharXMLFilter
+        extends AbstractSAXFilter
+    {
+        public PerCharXMLFilter()
+        {
+            super();
+        }
+        
+        public <T extends XMLReader & LexicalHandler> PerCharXMLFilter( T parent )
+        {
+            super( parent );
+        }
+
+        @Override
+        public void characters( char[] ch, int start, int length )
+            throws SAXException
+        {
+            for ( int i = 0; i < length; i++ )
+            {
+                super.characters( ch, start + i, 1 );
+            }
+        }
+        
+        @Override
+        public void comment( char[] ch, int start, int length )
+            throws SAXException
+        {
+            for ( int i = 0; i < length; i++ )
+            {
+                super.comment( ch, start + i, 1 );
+            }
+        }
+        
+        @Override
+        public void ignorableWhitespace( char[] ch, int start, int length )
+            throws SAXException
+        {
+            for ( int i = 0; i < length; i++ )
+            {
+                super.ignorableWhitespace( ch, start + i, 1 );
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java
new file mode 100644
index 0000000..e93c720
--- /dev/null
+++ b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java
@@ -0,0 +1,67 @@
+package org.apache.maven.xml.sax.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.junit.Assert.assertEquals;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+public class CiFriendlyXMLFilterTest extends AbstractXMLFilterTests
+{
+    private CiFriendlyXMLFilter filter;
+    
+    @Before
+    public void setUp()
+    {
+        filter = new CiFriendlyXMLFilter();
+        filter.setChangelist( "CHANGELIST" );
+    }
+    
+    @Override
+    protected AbstractSAXFilter getFilter()
+        throws TransformerException, SAXException, ParserConfigurationException
+    {
+        return filter;
+    }
+
+    @Test
+    public void changelist() throws Exception
+    {
+        String input = "<project>"
+            + "  <groupId>GROUPID</groupId>"
+            + "  <artifactId>ARTIFACTID</artifactId>"
+            +   "<version>${changelist}</version>"
+            + "</project>";
+        String expected = "<project>"
+                        + "  <groupId>GROUPID</groupId>"
+                        + "  <artifactId>ARTIFACTID</artifactId>"
+                        +   "<version>CHANGELIST</version>"
+                        + "</project>";
+
+        String actual = transform( input );
+
+        assertEquals( expected, actual );
+    }
+}