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/26 10:59:06 UTC

[maven] branch master updated: [MNG-6946] Build/consumer incorrectly transforms name of artifactId

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 76427d2  [MNG-6946] Build/consumer incorrectly transforms name of artifactId
76427d2 is described below

commit 76427d2320b5758f1a97fe81c61cdc6c5fff95b9
Author: rfscholte <rf...@apache.org>
AuthorDate: Fri Jun 26 12:58:50 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     | 31 +++++-----
 .../maven/xml/sax/filter/AbstractSAXFilter.java    | 14 +++++
 .../maven/xml/sax/filter/CiFriendlyXMLFilter.java  | 52 ++++++++++++++---
 .../maven/xml/sax/filter/ParentXMLFilter.java      | 10 ++--
 .../xml/sax/filter/ReactorDependencyXMLFilter.java | 18 ++++--
 .../xml/sax/filter/AbstractXMLFilterTests.java     | 66 ++++++++++++++++++++-
 .../xml/sax/filter/CiFriendlyXMLFilterTest.java    | 67 ++++++++++++++++++++++
 8 files changed, 224 insertions(+), 76 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..f5246b1 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
         {
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractSAXFilter.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractSAXFilter.java
index 89de519..454ae83 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractSAXFilter.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/AbstractSAXFilter.java
@@ -126,5 +126,19 @@ public class AbstractSAXFilter extends XMLFilterImpl implements LexicalHandler
             lexicalHandler.comment( ch, start, length );
         }
     }
+    
+    
+    protected static String nullSafeAppend( String originalValue, String charSegment )
+    {
+        if ( originalValue == null ) 
+        {
+            return charSegment;
+        }
+        else
+        {
+            return originalValue + charSegment;
+        }
+    }
+
 
 }
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..4375f18 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,10 +21,11 @@ package org.apache.maven.xml.sax.filter;
 
 import java.util.function.Function;
 
+import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
 /**
- * Resolves all ci-friendly properties occurrences
+ * Resolves all ci-friendly properties occurrences between version-tags
  * 
  * @author Robert Scholte
  * @since 3.7.0
@@ -34,6 +35,10 @@ class CiFriendlyXMLFilter
 {
     private Function<String, String> replaceChain = Function.identity();
     
+    private String characters; 
+    
+    private boolean parseVersion;
+    
     public CiFriendlyXMLFilter setChangelist( String changelist )
     {
         replaceChain = replaceChain.andThen( t -> t.replace( "${changelist}", changelist ) );
@@ -64,20 +69,49 @@ class CiFriendlyXMLFilter
     public void characters( char[] ch, int start, int length )
         throws SAXException
     {
-        String text = new String( ch, start, length );
-
-        // assuming this has the best performance
-        if ( text.contains( "${" ) )
+        if ( parseVersion )
         {
-            String newText = replaceChain.apply( text );
-            
-            super.characters( newText.toCharArray(), 0, newText.length() );
+            this.characters = nullSafeAppend( characters, new String( ch, start, length ) );
         }
         else
         {
             super.characters( ch, start, length );
         }
     }
+
+    @Override
+    public void startElement( String uri, String localName, String qName, Attributes atts )
+        throws SAXException
+    {
+        if ( !parseVersion && "version".equals( localName ) )
+        {
+            parseVersion = true;
+        }
+
+        super.startElement( uri, localName, qName, atts );
+    }
     
-    
+    @Override
+    public void endElement( String uri, String localName, String qName )
+        throws SAXException
+    {
+        if ( parseVersion )
+        {
+            // assuming this has the best performance
+            if ( characters != null && characters.contains( "${" ) )
+            {
+                char[] ch = replaceChain.apply( characters ).toCharArray();
+                super.characters( ch, 0, ch.length );
+            }
+            else
+            {
+                char[] ch = characters.toCharArray();
+                super.characters( ch, 0, ch.length );
+            }
+            characters = null;
+            parseVersion = false;
+        }
+
+        super.endElement( uri, localName, qName );
+    }
 }
\ 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/main/java/org/apache/maven/xml/sax/filter/ReactorDependencyXMLFilter.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ReactorDependencyXMLFilter.java
index 38f8fb8..080adc7 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ReactorDependencyXMLFilter.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ReactorDependencyXMLFilter.java
@@ -39,7 +39,7 @@ public class ReactorDependencyXMLFilter extends AbstractEventXMLFilter
     private String state;
     
     // whiteSpace after <dependency>, to be used to position <version>
-    private String dependencyWhitespace = "";
+    private String dependencyWhitespace;
 
     private boolean hasVersion;
 
@@ -79,16 +79,17 @@ public class ReactorDependencyXMLFilter extends AbstractEventXMLFilter
         if ( parsingDependency )
         {
             final String eventState = state;
+            String value = new String( ch, start, length );
             switch ( eventState )
             {
                 case "dependency":
-                    dependencyWhitespace = new String( ch, start, length );
+                    dependencyWhitespace = nullSafeAppend( dependencyWhitespace, value );
                     break;
                 case "groupId":
-                    groupId = new String( ch, start, length );
+                    groupId = nullSafeAppend( groupId, value );
                     break;
                 case "artifactId":
-                    artifactId = new String( ch, start, length );
+                    artifactId = nullSafeAppend( artifactId, value );
                     break;
                 default:
                     break;
@@ -115,8 +116,12 @@ public class ReactorDependencyXMLFilter extends AbstractEventXMLFilter
                         {
                             try ( Includer i = super.include() )
                             {
-                                super.characters( dependencyWhitespace.toCharArray(), 0,
-                                                  dependencyWhitespace.length() );
+                                if ( dependencyWhitespace != null )
+                                {
+                                    super.characters( dependencyWhitespace.toCharArray(), 0,
+                                                      dependencyWhitespace.length() );
+
+                                }
                                 String versionQName = SAXEventUtils.renameQName( qName, "version" );
                                 
                                 super.startElement( uri, "version", versionQName, null );
@@ -131,6 +136,7 @@ public class ReactorDependencyXMLFilter extends AbstractEventXMLFilter
                     
                     // reset
                     hasVersion = false;
+                    dependencyWhitespace = null;
                     groupId = null;
                     artifactId = null;
                     
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..f01f268 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();
     }
+    
+    /**
+     * From {@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 relevant wherever XML permits arbitrary characters, such as 
+     * attribute values,processing instruction data, and comments as well as in data reported from this method. It's 
+     * also generally relevant whenever Java code manipulates 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 );
+    }
+}