[MNG-7360] Fix xml transformation to ensure proper context (#744)

This commit is contained in:
Guillaume Nodet 2022-06-28 08:43:10 +02:00 committed by GitHub
parent 7dbbcc23a9
commit 90c084dcf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 37 deletions

View File

@ -53,7 +53,9 @@ public class BuildToRawPomXMLFilterFactory
public final XmlPullParser get( XmlPullParser orgParser, Path projectFile ) public final XmlPullParser get( XmlPullParser orgParser, Path projectFile )
{ {
XmlPullParser parser = orgParser; // Ensure that xs:any elements aren't touched by next filters
XmlPullParser parser = orgParser instanceof FastForwardFilter
? orgParser : new FastForwardFilter( orgParser );
if ( getDependencyKeyToVersionMapper() != null ) if ( getDependencyKeyToVersionMapper() != null )
{ {

View File

@ -28,8 +28,9 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* This filter will skip all following filters and write directly to the output. * This filter will bypass 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. * Should be used in case of a DOM that should not be effected by other filters,
* even though the elements match.
* *
* @author Robert Scholte * @author Robert Scholte
* @author Guillaume Nodet * @author Guillaume Nodet
@ -59,7 +60,22 @@ class FastForwardFilter extends BufferingParser
} }
@Override @Override
protected boolean accept() throws XmlPullParserException, IOException public int next() throws XmlPullParserException, IOException
{
int event = super.next();
filter();
return event;
}
@Override
public int nextToken() throws XmlPullParserException, IOException
{
int event = super.nextToken();
filter();
return event;
}
protected void filter() throws XmlPullParserException, IOException
{ {
if ( xmlPullParser.getEventType() == START_TAG ) if ( xmlPullParser.getEventType() == START_TAG )
{ {
@ -70,7 +86,7 @@ class FastForwardFilter extends BufferingParser
} }
else else
{ {
final String key = state.peek() + '/' + localName; final String key = state.peekLast() + '/' + localName;
switch ( key ) switch ( key )
{ {
case "execution/configuration": case "execution/configuration":
@ -79,8 +95,11 @@ class FastForwardFilter extends BufferingParser
case "profile/reports": case "profile/reports":
case "project/reports": case "project/reports":
case "reportSet/configuration": case "reportSet/configuration":
if ( domDepth == 0 )
{
bypass( true );
}
domDepth++; domDepth++;
disable();
break; break;
default: default:
break; break;
@ -90,14 +109,20 @@ class FastForwardFilter extends BufferingParser
} }
else if ( xmlPullParser.getEventType() == END_TAG ) else if ( xmlPullParser.getEventType() == END_TAG )
{ {
domDepth--; if ( domDepth > 0 )
if ( domDepth == 0 )
{ {
enable(); if ( --domDepth == 0 )
{
bypass( false );
}
} }
state.pop(); state.removeLast();
} }
return true;
} }
@Override
public void bypass( boolean bypass )
{
this.bypass = bypass;
}
} }

View File

@ -39,13 +39,12 @@ public class RawToConsumerPomXMLFilterFactory
public final XmlPullParser get( XmlPullParser orgParser, Path projectPath ) public final XmlPullParser get( XmlPullParser orgParser, Path projectPath )
{ {
XmlPullParser parser = orgParser; // Ensure that xs:any elements aren't touched by next filters
XmlPullParser parser = orgParser instanceof FastForwardFilter
? orgParser : new FastForwardFilter( orgParser );
parser = buildPomXMLFilterFactory.get( parser, projectPath ); parser = buildPomXMLFilterFactory.get( parser, projectPath );
// Ensure that xs:any elements aren't touched by next filters
parser = new FastForwardFilter( parser );
// Strip modules // Strip modules
parser = new ModulesXMLFilter( parser ); parser = new ModulesXMLFilter( parser );
// Adjust relativePath // Adjust relativePath

View File

@ -41,7 +41,7 @@ public class BufferingParser implements XmlPullParser
protected XmlPullParser xmlPullParser; protected XmlPullParser xmlPullParser;
protected Deque<Event> events; protected Deque<Event> events;
protected Event current; protected Event current;
protected boolean disabled; protected boolean bypass;
@SuppressWarnings( "checkstyle:VisibilityModifier" ) @SuppressWarnings( "checkstyle:VisibilityModifier" )
public static class Event public static class Event
@ -404,7 +404,7 @@ public class BufferingParser implements XmlPullParser
throw new XmlPullParserException( "already reached end of XML input", this, null ); throw new XmlPullParserException( "already reached end of XML input", this, null );
} }
int currentEvent = xmlPullParser.next(); int currentEvent = xmlPullParser.next();
if ( disabled || accept() ) if ( bypass() || accept() )
{ {
return currentEvent; return currentEvent;
} }
@ -430,7 +430,7 @@ public class BufferingParser implements XmlPullParser
throw new XmlPullParserException( "already reached end of XML input", this, null ); throw new XmlPullParserException( "already reached end of XML input", this, null );
} }
int currentEvent = xmlPullParser.nextToken(); int currentEvent = xmlPullParser.nextToken();
if ( accept() ) if ( bypass() || accept() )
{ {
return currentEvent; return currentEvent;
} }
@ -531,22 +531,20 @@ public class BufferingParser implements XmlPullParser
return true; return true;
} }
protected void enable() public void bypass( boolean bypass )
{ {
disabled = false; if ( bypass && events != null && !events.isEmpty() )
}
protected void disable()
{
if ( events != null && !events.isEmpty() )
{ {
throw new IllegalStateException( "Can not disable filter while processing" ); throw new IllegalStateException( "Can not disable filter while processing" );
} }
disabled = true; this.bypass = bypass;
if ( xmlPullParser instanceof BufferingParser ) }
{
( ( BufferingParser ) xmlPullParser ).disable(); public boolean bypass()
} {
return bypass
|| ( xmlPullParser instanceof BufferingParser
&& ( (BufferingParser) xmlPullParser ).bypass() );
} }
protected static String nullSafeAppend( String originalValue, String charSegment ) protected static String nullSafeAppend( String originalValue, String charSegment )

View File

@ -33,7 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParentXMLFilterTest public class ParentXMLFilterTest
extends AbstractXMLFilterTests extends AbstractXMLFilterTests
{ {
private Function<XmlPullParser, ParentXMLFilter> filterCreator; private Function<XmlPullParser, XmlPullParser> filterCreator;
@BeforeEach @BeforeEach
void reset() { void reset() {
@ -41,22 +41,93 @@ public class ParentXMLFilterTest
} }
@Override @Override
protected ParentXMLFilter getFilter( XmlPullParser parser ) protected XmlPullParser getFilter( XmlPullParser parser )
{ {
Function<XmlPullParser, ParentXMLFilter> filterCreator = Function<XmlPullParser, XmlPullParser> filterCreator =
(this.filterCreator != null ? this.filterCreator : this::createFilter); (this.filterCreator != null ? this.filterCreator : this::createFilter);
return filterCreator.apply(parser); return filterCreator.apply(parser);
} }
protected ParentXMLFilter createFilter( XmlPullParser parser ) { protected XmlPullParser createFilter( XmlPullParser parser ) {
return createFilter( parser, return createFilter( parser,
x -> Optional.of(new RelativeProject("GROUPID", "ARTIFACTID", "1.0.0")), x -> Optional.of(new RelativeProject("GROUPID", "ARTIFACTID", "1.0.0")),
Paths.get( "pom.xml").toAbsolutePath() ); Paths.get( "pom.xml").toAbsolutePath() );
} }
protected ParentXMLFilter createFilter( XmlPullParser parser, Function<Path, Optional<RelativeProject>> pathMapper, Path projectPath ) { protected XmlPullParser createFilter( XmlPullParser parser, Function<Path, Optional<RelativeProject>> pathMapper, Path projectPath ) {
ParentXMLFilter filter = new ParentXMLFilter( parser, pathMapper, projectPath ); return new ParentXMLFilter( new FastForwardFilter( parser ), pathMapper, projectPath );
return filter; }
@Test
public void testWithFastForward()
throws Exception
{
String input = "<project>"
+ "<build>"
+ "<plugins>"
+ "<plugin>"
+ "<configuration>"
+ "<parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "</parent>"
+ "</configuration>"
+ "</plugin>"
+ "</plugins>"
+ "</build>"
+ "</project>";
String expected = input;
String actual = transform( input );
assertEquals( expected, actual );
}
@Test
public void testWithFastForwardAfterByPass()
throws Exception
{
String input = "<project>"
+ "<build>"
+ "<plugins>"
+ "<plugin>"
+ "<configuration>"
+ "<parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "</parent>"
+ "</configuration>"
+ "</plugin>"
+ "</plugins>"
+ "</build>"
+ "<parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "</parent>"
+ "</project>";
String expected = "<project>"
+ "<build>"
+ "<plugins>"
+ "<plugin>"
+ "<configuration>"
+ "<parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "</parent>"
+ "</configuration>"
+ "</plugin>"
+ "</plugins>"
+ "</build>"
+ "<parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<version>1.0.0</version>"
+ "</parent>"
+ "</project>";
String actual = transform( input );
assertEquals( expected, actual );
} }
@Test @Test