[Git][java-team/plexus-utils2][upstream] 2 commits: New upstream version 3.2.0
Emmanuel Bourg
gitlab at salsa.debian.org
Fri Jul 12 08:14:23 BST 2019
Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / plexus-utils2
Commits:
4e033ff2 by Emmanuel Bourg at 2019-07-12T06:08:26Z
New upstream version 3.2.0
- - - - -
553fd973 by Emmanuel Bourg at 2019-07-12T06:08:41Z
New upstream version 3.2.1
- - - - -
16 changed files:
- .travis.yml
- pom.xml
- src/main/java/org/codehaus/plexus/util/MatchPattern.java
- src/main/java/org/codehaus/plexus/util/NioFiles.java
- src/main/java/org/codehaus/plexus/util/StringUtils.java
- src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java
- src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java
- src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java
- src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java
- src/test/java/org/codehaus/plexus/util/DirectoryScannerTest.java
- src/test/java/org/codehaus/plexus/util/MatchPatternTest.java
- src/test/java/org/codehaus/plexus/util/xml/Xpp3DomBuilderTest.java
- + src/test/java/org/codehaus/plexus/util/xml/Xpp3DomPerfTest.java
- src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java
- src/test/java/org/codehaus/plexus/util/xml/Xpp3DomUtilsTest.java
- src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java
Changes:
=====================================
.travis.yml
=====================================
@@ -1,7 +1,9 @@
language: java
jdk:
- openjdk7
- - oraclejdk8
+ - openjdk8
+ - openjdk11
+# - openjdk12 add once code is requires Java 7
# No need for preliminary install step.
install: true
=====================================
pom.xml
=====================================
@@ -22,11 +22,11 @@ limitations under the License.
<parent>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus</artifactId>
- <version>4.0</version>
+ <version>5.1</version>
</parent>
<artifactId>plexus-utils</artifactId>
- <version>3.1.1</version>
+ <version>3.2.1</version>
<name>Plexus Common Utilities</name>
<description>A collection of various utility classes to ease working with strings, files, command lines, XML and
@@ -37,7 +37,7 @@ limitations under the License.
<connection>scm:git:git at github.com:codehaus-plexus/plexus-utils.git</connection>
<developerConnection>scm:git:git at github.com:codehaus-plexus/plexus-utils.git</developerConnection>
<url>http://github.com/codehaus-plexus/plexus-utils</url>
- <tag>plexus-utils-3.1.1</tag>
+ <tag>plexus-utils-3.2.1</tag>
</scm>
<issueManagement>
<system>github</system>
@@ -50,10 +50,6 @@ limitations under the License.
</site>
</distributionManagement>
- <properties>
- <javaVersion>6</javaVersion>
- </properties>
-
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
@@ -61,7 +57,20 @@ limitations under the License.
<version>1.1</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-core</artifactId>
+ <version>1.21</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-generator-annprocess</artifactId>
+ <version>1.21</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+
<build>
<pluginManagement>
<plugins>
@@ -114,7 +123,6 @@ limitations under the License.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
- <version>1.1.1</version>
<executions>
<execution>
<id>enforce-java</id>
@@ -133,6 +141,7 @@ limitations under the License.
</plugin>
</plugins>
</build>
+
<profiles>
<profile>
<!-- See https://github.com/codehaus-plexus/plexus-utils/pull/27 -->
=====================================
src/main/java/org/codehaus/plexus/util/MatchPattern.java
=====================================
@@ -94,7 +94,7 @@ public boolean matchPatternStart( String str, boolean isCaseSensitive )
}
else
{
- String altStr = source.replace( '\\', '/' );
+ String altStr = str.replace( '\\', '/' );
return SelectorUtils.matchAntPathPatternStart( this, str, File.separator, isCaseSensitive )
|| SelectorUtils.matchAntPathPatternStart( this, altStr, "/", isCaseSensitive );
=====================================
src/main/java/org/codehaus/plexus/util/NioFiles.java
=====================================
@@ -138,7 +138,7 @@ public static File copy( File source, File target )
throws IOException
{
Path copy = Files.copy( source.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING,
- StandardCopyOption.COPY_ATTRIBUTES, LinkOption.NOFOLLOW_LINKS );
+ StandardCopyOption.COPY_ATTRIBUTES );
return copy.toFile();
}
=====================================
src/main/java/org/codehaus/plexus/util/StringUtils.java
=====================================
@@ -57,6 +57,7 @@
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.StringTokenizer;
/**
@@ -258,10 +259,12 @@ public static boolean isNotBlank( String str )
* @param str1 the first string
* @param str2 the second string
* @return <code>true</code> if the Strings are equal, case sensitive, or both <code>null</code>
+ * @see Objects#equals(Object, Object)
*/
+ @Deprecated
public static boolean equals( String str1, String str2 )
{
- return ( str1 == null ? str2 == null : str1.equals( str2 ) );
+ return Objects.equals( str1, str2 );
}
/**
@@ -2038,7 +2041,9 @@ public static boolean isNumericSpace( String str )
*
* @param obj the Object to check
* @return the passed in Object's toString, or blank if it was <code>null</code>
+ * @see Objects#toString(Object, String)
*/
+ @Deprecated
public static String defaultString( Object obj )
{
return defaultString( obj, "" );
@@ -2053,10 +2058,12 @@ public static String defaultString( Object obj )
* @param obj the Object to check
* @param defaultString the default String to return if str is <code>null</code>
* @return the passed in string, or the default if it was <code>null</code>
+ * @see Objects#toString(Object, String)
*/
+ @Deprecated
public static String defaultString( Object obj, String defaultString )
{
- return ( obj == null ) ? defaultString : obj.toString();
+ return Objects.toString( obj, defaultString );
}
// Reversing
=====================================
src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java
=====================================
@@ -23,9 +23,11 @@
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
/**
@@ -44,10 +46,13 @@
protected final List<Xpp3Dom> childList;
- protected final Map<String, Xpp3Dom> childMap;
-
protected Xpp3Dom parent;
+ /**
+ * @since 3.2.0
+ */
+ protected Object inputLocation;
+
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final Xpp3Dom[] EMPTY_DOM_ARRAY = new Xpp3Dom[0];
@@ -83,7 +88,15 @@ public Xpp3Dom( String name )
{
this.name = name;
childList = new ArrayList<Xpp3Dom>();
- childMap = new HashMap<String, Xpp3Dom>();
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public Xpp3Dom( String name, Object inputLocation )
+ {
+ this( name );
+ this.inputLocation = inputLocation;
}
/**
@@ -100,11 +113,11 @@ public Xpp3Dom( Xpp3Dom src )
public Xpp3Dom( Xpp3Dom src, String name )
{
this.name = name;
+ this.inputLocation = src.inputLocation;
int childCount = src.getChildCount();
childList = new ArrayList<Xpp3Dom>( childCount );
- childMap = new HashMap<String, Xpp3Dom>( childCount << 1 );
setValue( src.getValue() );
@@ -155,13 +168,13 @@ public void setValue( String value )
}
else
{
- return (String[]) attributes.keySet().toArray( new String[attributes.size()] );
+ return attributes.keySet().toArray( EMPTY_STRING_ARRAY );
}
}
public String getAttribute( String name )
{
- return ( null != attributes ) ? (String) attributes.get( name ) : null;
+ return ( null != attributes ) ? attributes.get( name ) : null;
}
/**
@@ -194,19 +207,30 @@ public void setAttribute( String name, String value )
public Xpp3Dom getChild( int i )
{
- return (Xpp3Dom) childList.get( i );
+ return childList.get( i );
}
public Xpp3Dom getChild( String name )
{
- return (Xpp3Dom) childMap.get( name );
+ if ( name != null )
+ {
+ ListIterator<Xpp3Dom> it = childList.listIterator( childList.size() );
+ while ( it.hasPrevious() )
+ {
+ Xpp3Dom child = it.previous();
+ if ( name.equals( child.getName() ) )
+ {
+ return child;
+ }
+ }
+ }
+ return null;
}
public void addChild( Xpp3Dom xpp3Dom )
{
xpp3Dom.setParent( this );
childList.add( xpp3Dom );
- childMap.put( xpp3Dom.getName(), xpp3Dom );
}
public Xpp3Dom[] getChildren()
@@ -217,31 +241,45 @@ public void addChild( Xpp3Dom xpp3Dom )
}
else
{
- return (Xpp3Dom[]) childList.toArray( new Xpp3Dom[childList.size()] );
+ return childList.toArray( EMPTY_DOM_ARRAY );
}
}
public Xpp3Dom[] getChildren( String name )
+ {
+ return getChildrenAsList( name ).toArray( EMPTY_DOM_ARRAY );
+ }
+
+ private List<Xpp3Dom> getChildrenAsList( String name )
{
if ( null == childList )
{
- return EMPTY_DOM_ARRAY;
+ return Collections.emptyList();
}
else
{
- ArrayList<Xpp3Dom> children = new ArrayList<Xpp3Dom>();
- int size = childList.size();
+ ArrayList<Xpp3Dom> children = null;
- for ( Xpp3Dom aChildList : childList )
+ for ( Xpp3Dom configuration : childList )
{
- Xpp3Dom configuration = (Xpp3Dom) aChildList;
if ( name.equals( configuration.getName() ) )
{
+ if ( children == null )
+ {
+ children = new ArrayList<Xpp3Dom>();
+ }
children.add( configuration );
}
}
- return (Xpp3Dom[]) children.toArray( new Xpp3Dom[children.size()] );
+ if ( children != null )
+ {
+ return children;
+ }
+ else
+ {
+ return Collections.emptyList();
+ }
}
}
@@ -258,7 +296,6 @@ public int getChildCount()
public void removeChild( int i )
{
Xpp3Dom child = getChild( i );
- childMap.values().remove( child );
childList.remove( i );
// In case of any dangling references
child.setParent( null );
@@ -278,6 +315,26 @@ public void setParent( Xpp3Dom parent )
this.parent = parent;
}
+ // ----------------------------------------------------------------------
+ // Input location handling
+ // ----------------------------------------------------------------------
+
+ /**
+ * @since 3.2.0
+ */
+ public Object getInputLocation()
+ {
+ return inputLocation;
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public void setInputLocation( Object inputLocation )
+ {
+ this.inputLocation = inputLocation;
+ }
+
// ----------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------
@@ -296,23 +353,41 @@ public void writeToSerializer( String namespace, XmlSerializer serializer )
}
/**
- * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm. The
- * algorithm is as follows: 1. if the recessive DOM is null, there is nothing to do...return. 2. Determine whether
- * the dominant node will suppress the recessive one (flag=mergeSelf). A. retrieve the 'combine.self' attribute on
- * the dominant node, and try to match against 'override'... if it matches 'override', then set mergeSelf ==
- * false...the dominant node suppresses the recessive one completely. B. otherwise, use the default value for
- * mergeSelf, which is true...this is the same as specifying 'combine.self' == 'merge' as an attribute of the
- * dominant root node. 3. If mergeSelf == true A. if the dominant root node's value is empty, set it to the
- * recessive root node's value B. For each attribute in the recessive root node which is not set in the dominant
- * root node, set it. C. Determine whether children from the recessive DOM will be merged or appended to the
- * dominant DOM as siblings (flag=mergeChildren). i. if childMergeOverride is set (non-null), use that value
- * (true/false) ii. retrieve the 'combine.children' attribute on the dominant node, and try to match against
- * 'append'...if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
- * siblings of the dominant children. iii. otherwise, use the default value for mergeChildren, which is true...this
- * is the same as specifying 'combine.children' == 'merge' as an attribute on the dominant root node. D. Iterate
- * through the recessive children, and: i. if mergeChildren == true and there is a corresponding dominant child
- * (matched by element name), merge the two. ii. otherwise, add the recessive child as a new child on the dominant
- * root node.
+ * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.<p>
+ * The algorithm is as follows:
+ * <ol>
+ * <li> if the recessive DOM is null, there is nothing to do... return.</li>
+ * <li> Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
+ * <ol type="A">
+ * <li> retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
+ * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one
+ * completely.</li>
+ * <li> otherwise, use the default value for mergeSelf, which is true...this is the same as specifying
+ * 'combine.self' == 'merge' as an attribute of the dominant root node.</li>
+ * </ol></li>
+ * <li> If mergeSelf == true
+ * <ol type="A">
+ * <li> if the dominant root node's value is empty, set it to the recessive root node's value</li>
+ * <li> For each attribute in the recessive root node which is not set in the dominant root node, set it.</li>
+ * <li> Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as
+ * siblings (flag=mergeChildren).
+ * <ol type="i">
+ * <li> if childMergeOverride is set (non-null), use that value (true/false)</li>
+ * <li> retrieve the 'combine.children' attribute on the dominant node, and try to match against
+ * 'append'...</li>
+ * <li> if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
+ * siblings of the dominant children.</li>
+ * <li> otherwise, use the default value for mergeChildren, which is true...this is the same as specifying
+ * 'combine.children' == 'merge' as an attribute on the dominant root node.</li>
+ * </ol></li>
+ * <li> Iterate through the recessive children, and:
+ * <ol type="i">
+ * <li> if mergeChildren == true and there is a corresponding dominant child (matched by element name),
+ * merge the two.</li>
+ * <li> otherwise, add the recessive child as a new child on the dominant root node.</li>
+ * </ol></li>
+ * </ol></li>
+ * </ol>
*/
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
{
@@ -333,17 +408,20 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
if ( mergeSelf )
{
- if ( isEmpty( dominant.getValue() ) )
+ if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) )
{
dominant.setValue( recessive.getValue() );
+ dominant.setInputLocation( recessive.getInputLocation() );
}
- String[] recessiveAttrs = recessive.getAttributeNames();
- for ( String attr : recessiveAttrs )
+ if ( recessive.attributes != null )
{
- if ( isEmpty( dominant.getAttribute( attr ) ) )
+ for ( String attr : recessive.attributes.keySet() )
{
- dominant.setAttribute( attr, recessive.getAttribute( attr ) );
+ if ( isEmpty( dominant.getAttribute( attr ) ) )
+ {
+ dominant.setAttribute( attr, recessive.getAttribute( attr ) );
+ }
}
}
@@ -387,12 +465,16 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
{
Map<String, Iterator<Xpp3Dom>> commonChildren = new HashMap<String, Iterator<Xpp3Dom>>();
- for ( String childName : recessive.childMap.keySet() )
+ for ( Xpp3Dom recChild : recessive.childList )
{
- Xpp3Dom[] dominantChildren = dominant.getChildren( childName );
- if ( dominantChildren.length > 0 )
+ if ( commonChildren.containsKey( recChild.name ) )
+ {
+ continue;
+ }
+ List<Xpp3Dom> dominantChildren = dominant.getChildrenAsList( recChild.name );
+ if ( dominantChildren.size() > 0 )
{
- commonChildren.put( childName, Arrays.asList( dominantChildren ).iterator() );
+ commonChildren.put( recChild.name, dominantChildren.iterator() );
}
}
=====================================
src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java
=====================================
@@ -37,7 +37,16 @@
public static Xpp3Dom build( Reader reader )
throws XmlPullParserException, IOException
{
- return build( reader, DEFAULT_TRIM );
+ return build( reader, null );
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder )
+ throws XmlPullParserException, IOException
+ {
+ return build( reader, DEFAULT_TRIM, locationBuilder );
}
public static Xpp3Dom build( InputStream is, String encoding )
@@ -68,13 +77,22 @@ public static Xpp3Dom build( InputStream is, String encoding, boolean trim )
public static Xpp3Dom build( Reader reader, boolean trim )
throws XmlPullParserException, IOException
+ {
+ return build( reader, trim, null );
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder )
+ throws XmlPullParserException, IOException
{
try
{
final XmlPullParser parser = new MXParser();
parser.setInput( reader );
- final Xpp3Dom xpp3Dom = build( parser, trim );
+ final Xpp3Dom xpp3Dom = build( parser, trim, locationBuilder );
reader.close();
reader = null;
@@ -94,6 +112,15 @@ public static Xpp3Dom build( XmlPullParser parser )
public static Xpp3Dom build( XmlPullParser parser, boolean trim )
throws XmlPullParserException, IOException
+ {
+ return build( parser, trim, null );
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder )
+ throws XmlPullParserException, IOException
{
List<Xpp3Dom> elements = new ArrayList<Xpp3Dom>();
@@ -113,6 +140,11 @@ public static Xpp3Dom build( XmlPullParser parser, boolean trim )
Xpp3Dom childConfiguration = new Xpp3Dom( rawName );
+ if ( locationBuilder != null )
+ {
+ childConfiguration.setInputLocation( locationBuilder.toInputLocation( parser ) );
+ }
+
int depth = elements.size();
if ( depth > 0 )
@@ -194,4 +226,14 @@ else if ( eventType == XmlPullParser.END_TAG )
throw new IllegalStateException( "End of document found before returning to 0 depth" );
}
+
+ /**
+ * Input location builder interface, to be implemented to choose how to store data.
+ *
+ * @since 3.2.0
+ */
+ public static interface InputLocationBuilder
+ {
+ Object toInputLocation( XmlPullParser parser );
+ }
}
=====================================
src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java
=====================================
@@ -19,6 +19,10 @@
import org.codehaus.plexus.util.xml.pull.XmlSerializer;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
/** @author Jason van Zyl */
public class Xpp3DomUtils
@@ -71,24 +75,43 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
}
/**
- * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm. The
- * algorithm is as follows: 1. if the recessive DOM is null, there is nothing to do...return. 2. Determine whether
- * the dominant node will suppress the recessive one (flag=mergeSelf). A. retrieve the 'combine.self' attribute on
- * the dominant node, and try to match against 'override'... if it matches 'override', then set mergeSelf ==
- * false...the dominant node suppresses the recessive one completely. B. otherwise, use the default value for
- * mergeSelf, which is true...this is the same as specifying 'combine.self' == 'merge' as an attribute of the
- * dominant root node. 3. If mergeSelf == true A. if the dominant root node's value is empty, set it to the
- * recessive root node's value B. For each attribute in the recessive root node which is not set in the dominant
- * root node, set it. C. Determine whether children from the recessive DOM will be merged or appended to the
- * dominant DOM as siblings (flag=mergeChildren). i. if childMergeOverride is set (non-null), use that value
- * (true/false) ii. retrieve the 'combine.children' attribute on the dominant node, and try to match against
- * 'append'...if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
- * siblings of the dominant children. iii. otherwise, use the default value for mergeChildren, which is true...this
- * is the same as specifying 'combine.children' == 'merge' as an attribute on the dominant root node. D. Iterate
- * through the recessive children, and: i. if 'combine.id' is set and there is a corresponding dominant child
- * (matched by value of 'combine.id'), merge the two. ii. if mergeChildren == true and there is a corresponding
- * dominant child (matched by element name), merge the two. iii. otherwise, add the recessive child as a new child
- * on the dominant root node.
+ * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.<p>
+ * The algorithm is as follows:
+ * <ol>
+ * <li> if the recessive DOM is null, there is nothing to do... return.</li>
+ * <li> Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
+ * <ol type="A">
+ * <li> retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
+ * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one
+ * completely.</li>
+ * <li> otherwise, use the default value for mergeSelf, which is true...this is the same as specifying
+ * 'combine.self' == 'merge' as an attribute of the dominant root node.</li>
+ * </ol></li>
+ * <li> If mergeSelf == true
+ * <ol type="A">
+ * <li> if the dominant root node's value is empty, set it to the recessive root node's value</li>
+ * <li> For each attribute in the recessive root node which is not set in the dominant root node, set it.</li>
+ * <li> Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as
+ * siblings (flag=mergeChildren).
+ * <ol type="i">
+ * <li> if childMergeOverride is set (non-null), use that value (true/false)</li>
+ * <li> retrieve the 'combine.children' attribute on the dominant node, and try to match against
+ * 'append'...</li>
+ * <li> if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
+ * siblings of the dominant children.</li>
+ * <li> otherwise, use the default value for mergeChildren, which is true...this is the same as specifying
+ * 'combine.children' == 'merge' as an attribute on the dominant root node.</li>
+ * </ol></li>
+ * <li> Iterate through the recessive children, and:
+ * <ol type="i">
+ * <li> if 'combine.id' is set and there is a corresponding dominant child (matched by value of 'combine.id'),
+ * merge the two.</li>
+ * <li> if mergeChildren == true and there is a corresponding dominant child (matched by element name),
+ * merge the two.</li>
+ * <li> otherwise, add the recessive child as a new child on the dominant root node.</li>
+ * </ol></li>
+ * </ol></li>
+ * </ol>
*/
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
{
@@ -109,9 +132,10 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
if ( mergeSelf )
{
- if ( isEmpty( dominant.getValue() ) )
+ if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) )
{
dominant.setValue( recessive.getValue() );
+ dominant.setInputLocation( recessive.getInputLocation() );
}
String[] recessiveAttrs = recessive.getAttributeNames();
=====================================
src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java
=====================================
@@ -2664,13 +2664,16 @@ else if ( ch == '\t' || ch == '\n' || ch == '\r' )
entityRefName = null;
posStart = pos;
char ch = more();
- StringBuilder sb = new StringBuilder();
if ( ch == '#' )
{
// parse character reference
+
char charRef = 0;
ch = more();
- if ( ch == 'x' )
+ StringBuilder sb = new StringBuilder();
+ boolean isHex = ( ch == 'x' );
+
+ if ( isHex )
{
// encoded in hex
while ( true )
@@ -2710,6 +2713,7 @@ else if ( ch >= 'A' && ch <= 'F' )
if ( ch >= '0' && ch <= '9' )
{
charRef = (char) ( charRef * 10 + ( ch - '0' ) );
+ sb.append( ch );
}
else if ( ch == ';' )
{
@@ -2724,20 +2728,19 @@ else if ( ch >= 'A' && ch <= 'F' )
}
}
posEnd = pos - 1;
- if ( sb.length() > 0 )
+ try
{
- char[] tmp = toChars( Integer.parseInt( sb.toString(), 16 ) );
- charRefOneCharBuf = tmp;
- if ( tokenize )
- {
- text = newString( charRefOneCharBuf, 0, charRefOneCharBuf.length );
- }
- return charRefOneCharBuf;
+ charRefOneCharBuf = toChars( Integer.parseInt( sb.toString(), isHex ? 16 : 10 ) );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ throw new XmlPullParserException( "character reference (with " + ( isHex ? "hex" : "decimal" )
+ + " value " + sb.toString() + ") is invalid", this, null );
}
- charRefOneCharBuf[0] = charRef;
+
if ( tokenize )
{
- text = newString( charRefOneCharBuf, 0, 1 );
+ text = newString( charRefOneCharBuf, 0, charRefOneCharBuf.length );
}
return charRefOneCharBuf;
}
@@ -3014,6 +3017,7 @@ protected boolean parsePI()
try
{
+ boolean seenPITarget = false;
boolean seenQ = false;
char ch = more();
if ( isS( ch ) )
@@ -3028,6 +3032,11 @@ protected boolean parsePI()
if ( ch == '?' )
{
+ if ( !seenPITarget )
+ {
+ throw new XmlPullParserException( "processing instruction PITarget name not found", this,
+ null );
+ }
seenQ = true;
}
else if ( ch == '>' )
@@ -3036,7 +3045,12 @@ else if ( ch == '>' )
{
break; // found end sequence!!!!
}
- seenQ = false;
+
+ if ( !seenPITarget )
+ {
+ throw new XmlPullParserException( "processing instruction PITarget name not found", this,
+ null );
+ }
}
else
{
@@ -3075,6 +3089,7 @@ else if ( ch == '>' )
}
}
}
+
seenQ = false;
}
if ( normalizeIgnorableWS )
@@ -3124,6 +3139,7 @@ else if ( ch == '\n' )
normalizedCR = false;
}
}
+ seenPITarget = true;
ch = more();
}
}
@@ -3689,31 +3705,57 @@ else if ( expand )
StringBuilder expectedTagStack = new StringBuilder();
if ( depth > 0 )
{
- // final char[] cbuf = elRawName[depth];
- // final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
- expectedTagStack.append( " - expected end tag" );
- if ( depth > 1 )
- {
- expectedTagStack.append( "s" ); // more than one end tag
- }
- expectedTagStack.append( " " );
- for ( int i = depth; i > 0; i-- )
+ if ( elRawName == null || elRawName[depth] == null )
{
- String tagName = new String( elRawName[i], 0, elRawNameEnd[i] );
- expectedTagStack.append( "</" ).append( tagName ).append( '>' );
+ String tagName = new String( buf, posStart + 1, pos - posStart - 1 );
+ expectedTagStack.append( " - expected the opening tag <" ).append( tagName ).append( "...>" );
}
- expectedTagStack.append( " to close" );
- for ( int i = depth; i > 0; i-- )
+ else
{
- if ( i != depth )
+ // final char[] cbuf = elRawName[depth];
+ // final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
+ expectedTagStack.append( " - expected end tag" );
+ if ( depth > 1 )
{
- expectedTagStack.append( " and" ); // more than one end tag
+ expectedTagStack.append( "s" ); // more than one end tag
}
- String tagName = new String( elRawName[i], 0, elRawNameEnd[i] );
- expectedTagStack.append( " start tag <" ).append( tagName ).append( ">" );
- expectedTagStack.append( " from line " ).append( elRawNameLine[i] );
+ expectedTagStack.append( " " );
+
+ for ( int i = depth; i > 0; i-- )
+ {
+ if ( elRawName == null || elRawName[i] == null )
+ {
+ String tagName = new String( buf, posStart + 1, pos - posStart - 1 );
+ expectedTagStack.append( " - expected the opening tag <" ).append( tagName ).append( "...>" );
+ }
+ else
+ {
+ String tagName = new String( elRawName[i], 0, elRawNameEnd[i] );
+ expectedTagStack.append( "</" ).append( tagName ).append( '>' );
+ }
+ }
+ expectedTagStack.append( " to close" );
+ for ( int i = depth; i > 0; i-- )
+ {
+ if ( i != depth )
+ {
+ expectedTagStack.append( " and" ); // more than one end tag
+ }
+ if ( elRawName == null || elRawName[i] == null )
+ {
+ String tagName = new String( buf, posStart + 1, pos - posStart - 1 );
+ expectedTagStack.append( " start tag <" ).append( tagName ).append( ">" );
+ expectedTagStack.append( " from line " ).append( elRawNameLine[i] );
+ }
+ else
+ {
+ String tagName = new String( elRawName[i], 0, elRawNameEnd[i] );
+ expectedTagStack.append( " start tag <" ).append( tagName ).append( ">" );
+ expectedTagStack.append( " from line " ).append( elRawNameLine[i] );
+ }
+ }
+ expectedTagStack.append( ", parser stopped on" );
}
- expectedTagStack.append( ", parser stopped on" );
}
throw new EOFException( "no more data available" + expectedTagStack.toString()
+ getPositionDescription() );
@@ -3996,15 +4038,21 @@ private static boolean isHighSurrogate( char ch )
return ( MIN_HIGH_SURROGATE <= ch && MAX_HIGH_SURROGATE >= ch );
}
- private static final int MIN_CODE_POINT = 0x000000;
-
private static final int MAX_CODE_POINT = 0x10FFFF;
private static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
+ /**
+ * Check if the provided parameter is a valid Char, according to: {@link https://www.w3.org/TR/REC-xml/#NT-Char}
+ *
+ * @param codePoint the numeric value to check
+ * @return true if it is a valid numeric character reference. False otherwise.
+ */
private static boolean isValidCodePoint( int codePoint )
{
- return ( MIN_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint );
+ // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ return codePoint == 0x9 || codePoint == 0xA || codePoint == 0xD || ( 0x20 <= codePoint && codePoint <= 0xD7FF )
+ || ( 0xE000 <= codePoint && codePoint <= 0xFFFD ) || ( 0x10000 <= codePoint && codePoint <= 0x10FFFF );
}
private static boolean isSupplementaryCodePoint( int codePoint )
=====================================
src/test/java/org/codehaus/plexus/util/DirectoryScannerTest.java
=====================================
@@ -31,8 +31,11 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
@@ -50,6 +53,19 @@
private static String testDir = getTestDirectory().getPath();
+ @Before
+ public void setUp()
+ {
+ try
+ {
+ FileUtils.deleteDirectory( testDir );
+ }
+ catch ( IOException e )
+ {
+ fail( "Could not delete directory " + testDir );
+ }
+ }
+
@Test
public void testCrossPlatformIncludesString()
throws IOException, URISyntaxException
@@ -477,6 +493,75 @@ public void testRegexWithSlashInsideCharacterClass()
assertInclusionsAndExclusions( ds.getIncludedFiles(), excludedPaths, includedPaths );
}
+ /**
+ * Test that the directory scanning does not enter into not matching directories.
+ *
+ * @see <a href="https://github.com/codehaus-plexus/plexus-utils/issues/63">Issue #63</a>
+ * @throws IOException if occurs an I/O error.
+ */
+ @Test
+ public void testDoNotScanUnnecesaryDirectories()
+ throws IOException
+ {
+ createTestDirectories();
+
+ // create additional directories 'anotherDir1', 'anotherDir2' and 'anotherDir3' with a 'file1.dat' file
+ FileUtils.mkdir( testDir + File.separator + "directoryTest" + File.separator + "testDir123" + File.separator
+ + "anotherDir1" );
+ FileUtils.mkdir( testDir + File.separator + "directoryTest" + File.separator + "test_dir_123" + File.separator
+ + "anotherDir2" );
+ FileUtils.mkdir( testDir + File.separator + "directoryTest" + File.separator + "test-dir-123" + File.separator
+ + "anotherDir3" );
+
+ this.createFile( new File( testDir + File.separator + "directoryTest" + File.separator + "testDir123"
+ + File.separator + "anotherDir1" + File.separator + "file1.dat" ), 0 );
+ this.createFile( new File( testDir + File.separator + "directoryTest" + File.separator + "test_dir_123"
+ + File.separator + "anotherDir2" + File.separator + "file1.dat" ), 0 );
+ this.createFile( new File( testDir + File.separator + "directoryTest" + File.separator + "test-dir-123"
+ + File.separator + "anotherDir3" + File.separator + "file1.dat" ), 0 );
+
+ String[] excludedPaths = {
+ "directoryTest" + File.separator + "testDir123" + File.separator + "anotherDir1" + File.separator
+ + "file1.dat",
+ "directoryTest" + File.separator + "test_dir_123" + File.separator + "anotherDir2" + File.separator
+ + "file1.dat",
+ "directoryTest" + File.separator + "test-dir-123" + File.separator + "anotherDir3" + File.separator
+ + "file1.dat"
+ };
+
+ String[] includedPaths = {
+ "directoryTest" + File.separator + "testDir123" + File.separator + "file1.dat",
+ "directoryTest" + File.separator + "test_dir_123" + File.separator + "file1.dat",
+ "directoryTest" + File.separator + "test-dir-123" + File.separator + "file1.dat"
+ };
+
+ final Set<String> scannedDirSet = new HashSet<String>();
+
+ DirectoryScanner ds = new DirectoryScanner()
+ {
+ @Override
+ protected void scandir( File dir, String vpath, boolean fast )
+ {
+ scannedDirSet.add( dir.getName() );
+ super.scandir( dir, vpath, fast );
+ }
+
+ };
+
+ // one '*' matches only ONE directory level
+ String[] includes = { "directoryTest" + File.separator + "*" + File.separator + "file1.dat" };
+ ds.setIncludes( includes );
+ ds.setBasedir( new File( testDir ) );
+ ds.scan();
+
+ assertInclusionsAndExclusions( ds.getIncludedFiles(), excludedPaths, includedPaths );
+
+ Set<String> expectedScannedDirSet =
+ new HashSet<String>( Arrays.asList( "io", "directoryTest", "testDir123", "test_dir_123", "test-dir-123" ) );
+
+ assertEquals( expectedScannedDirSet, scannedDirSet );
+ }
+
@Test
public void testIsSymbolicLink()
throws IOException
=====================================
src/test/java/org/codehaus/plexus/util/MatchPatternTest.java
=====================================
@@ -16,6 +16,7 @@
* limitations under the License.
*/
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -32,4 +33,23 @@ public void testMatchPath()
MatchPattern mp = MatchPattern.fromString( "ABC*" );
assertTrue( mp.matchPath( "ABCD", true ) );
}
+
+ /**
+ * @see <a href="https://github.com/codehaus-plexus/plexus-utils/issues/63">Issue #63</a>
+ */
+ @Test
+ public void testMatchPatternStart()
+ {
+ MatchPattern mp = MatchPattern.fromString( "ABC*" );
+
+ assertTrue( mp.matchPatternStart( "ABCD", true ) );
+ assertFalse( mp.matchPatternStart( "AbCD", true ) );
+
+ assertTrue( mp.matchPatternStart( "ABCD", false ) );
+ assertTrue( mp.matchPatternStart( "AbCD", false ) );
+
+ assertFalse( mp.matchPatternStart( "XXXX", true ) );
+ assertFalse( mp.matchPatternStart( "XXXX", false ) );
+ }
+
}
=====================================
src/test/java/org/codehaus/plexus/util/xml/Xpp3DomBuilderTest.java
=====================================
@@ -175,6 +175,35 @@ public void testEscapingInAttributes()
assertEquals( "Compare stringified DOMs", newString, s );
}
+ @Test
+ public void testInputLocationTracking()
+ throws IOException, XmlPullParserException
+ {
+ Xpp3DomBuilder.InputLocationBuilder ilb = new Xpp3DomBuilder.InputLocationBuilder() {
+ public Object toInputLocation( XmlPullParser parser )
+ {
+ return parser.getLineNumber(); // store only line number as a simple Integer
+ }
+
+ };
+ Xpp3Dom dom = Xpp3DomBuilder.build( new StringReader( createDomString() ), true, ilb );
+ Xpp3Dom expectedDom = createExpectedDom();
+ assertEquals( "root input location", expectedDom.getInputLocation(), dom.getInputLocation() );
+ for( int i = 0; i < dom.getChildCount(); i++ )
+ {
+ Xpp3Dom elt = dom.getChild( i );
+ Xpp3Dom expectedElt = expectedDom.getChild( i );
+ assertEquals( elt.getName() + " input location", expectedElt.getInputLocation(), elt.getInputLocation() );
+
+ if ( "el2".equals( elt.getName() ) )
+ {
+ Xpp3Dom el3 = elt.getChild( 0 );
+ Xpp3Dom expectedEl3 = expectedElt.getChild( 0 );
+ assertEquals( el3.getName() + " input location", expectedEl3.getInputLocation(), el3.getInputLocation() );
+ }
+ }
+ }
+
private static String getAttributeEncodedString()
{
StringBuilder domString = new StringBuilder();
@@ -237,23 +266,33 @@ private static String createDomString()
private static Xpp3Dom createExpectedDom()
{
+ int line = 1;
Xpp3Dom expectedDom = new Xpp3Dom( "root" );
+ expectedDom.setInputLocation( line );
Xpp3Dom el1 = new Xpp3Dom( "el1" );
+ el1.setInputLocation( ++line );
el1.setValue( "element1" );
expectedDom.addChild( el1 );
+ ++line; // newline trimmed in Xpp3Dom but not in source
Xpp3Dom el2 = new Xpp3Dom( "el2" );
+ el2.setInputLocation( ++line );
el2.setAttribute( "att2", "attribute2\nnextline" );
expectedDom.addChild( el2 );
Xpp3Dom el3 = new Xpp3Dom( "el3" );
+ el3.setInputLocation( ++line );
el3.setAttribute( "att3", "attribute3" );
el3.setValue( "element3" );
el2.addChild( el3 );
+ ++line;
Xpp3Dom el4 = new Xpp3Dom( "el4" );
+ el4.setInputLocation( ++line );
el4.setValue( "" );
expectedDom.addChild( el4 );
Xpp3Dom el5 = new Xpp3Dom( "el5" );
+ el5.setInputLocation( ++line );
expectedDom.addChild( el5 );
Xpp3Dom el6 = new Xpp3Dom( "el6" );
+ el6.setInputLocation( ++line );
el6.setAttribute( "xml:space", "preserve" );
el6.setValue( " do not trim " );
expectedDom.addChild( el6 );
=====================================
src/test/java/org/codehaus/plexus/util/xml/Xpp3DomPerfTest.java
=====================================
@@ -0,0 +1,80 @@
+package org.codehaus.plexus.util.xml;
+
+/*
+ * Copyright The Codehaus Foundation.
+ *
+ * Licensed 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.IOException;
+import java.io.StringReader;
+import java.util.concurrent.TimeUnit;
+
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+ at BenchmarkMode(Mode.Throughput)
+ at OutputTimeUnit(TimeUnit.MILLISECONDS)
+ at Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
+public class Xpp3DomPerfTest
+{
+ @State(Scope.Benchmark)
+ static public class AdditionState {
+ Xpp3Dom dom1;
+ Xpp3Dom dom2;
+
+ @Setup(Level.Iteration)
+ public void setUp() throws IOException, XmlPullParserException {
+ String testDom = "<configuration><items thing='blah'><item>one</item><item>two</item></items></configuration>";
+ dom1 = Xpp3DomBuilder.build( new StringReader( testDom ) );
+ dom2 = new Xpp3Dom( dom1 );
+ }
+ }
+
+
+ @Benchmark
+ public Xpp3Dom benchmarkClone(AdditionState state)
+ {
+ return new Xpp3Dom( state.dom1 );
+ }
+
+ @Benchmark
+ public void benchmarkMerge(AdditionState state)
+ {
+ Xpp3Dom.mergeXpp3Dom( state.dom1, state.dom2 );
+ }
+
+ public static void main( String... args )
+ throws RunnerException
+ {
+ Options opts = new OptionsBuilder()
+ .measurementIterations( 3 )
+ .measurementTime( TimeValue.milliseconds( 3000 ) )
+ .forks( 1 )
+ .build();
+ new Runner( opts ).run();
+ }
+}
=====================================
src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java
=====================================
@@ -27,6 +27,7 @@
import java.io.StringReader;
import java.util.HashMap;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.Test;
@@ -38,17 +39,21 @@ public void testShouldPerformAppendAtFirstSubElementLevel()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
+ t1.setInputLocation( "t1top" );
Xpp3Dom t1s1 = new Xpp3Dom( "topsub1" );
t1s1.setValue( "t1s1Value" );
+ t1s1.setInputLocation( "t1s1" );
t1.addChild( t1s1 );
// create the recessive DOM
Xpp3Dom t2 = new Xpp3Dom( "top" );
+ t2.setInputLocation( "t2top" );
Xpp3Dom t2s1 = new Xpp3Dom( "topsub1" );
t2s1.setValue( "t2s1Value" );
+ t2s1.setInputLocation( "t2s1" );
t2.addChild( t2s1 );
@@ -56,6 +61,12 @@ public void testShouldPerformAppendAtFirstSubElementLevel()
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
assertEquals( 2, result.getChildren( "topsub1" ).length );
+ assertEquals( "t2s1Value", result.getChildren( "topsub1" )[0].getValue() );
+ assertEquals( "t1s1Value", result.getChildren( "topsub1" )[1].getValue() );
+
+ assertEquals( "t1top", result.getInputLocation() );
+ assertEquals( "t2s1", result.getChildren( "topsub1" )[0].getInputLocation() );
+ assertEquals( "t1s1", result.getChildren( "topsub1" )[1].getInputLocation() );
}
@Test
@@ -64,17 +75,21 @@ public void testShouldOverrideAppendAndDeepMerge()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
+ t1.setInputLocation( "t1top" );
Xpp3Dom t1s1 = new Xpp3Dom( "topsub1" );
t1s1.setValue( "t1s1Value" );
+ t1s1.setInputLocation( "t1s1" );
t1.addChild( t1s1 );
// create the recessive DOM
Xpp3Dom t2 = new Xpp3Dom( "top" );
+ t2.setInputLocation( "t2top" );
Xpp3Dom t2s1 = new Xpp3Dom( "topsub1" );
t2s1.setValue( "t2s1Value" );
+ t2s1.setInputLocation( "t2s1" );
t2.addChild( t2s1 );
@@ -82,6 +97,10 @@ public void testShouldOverrideAppendAndDeepMerge()
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2, Boolean.TRUE );
assertEquals( 1, result.getChildren( "topsub1" ).length );
+ assertEquals( "t1s1Value", result.getChildren( "topsub1" )[0].getValue() );
+
+ assertEquals( "t1top", result.getInputLocation() );
+ assertEquals( "t1s1", result.getChildren( "topsub1" )[0].getInputLocation() );
}
@Test
@@ -90,6 +109,7 @@ public void testShouldPerformSelfOverrideAtTopLevel()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( "attr", "value" );
+ t1.setInputLocation( "t1top" );
t1.setAttribute( Xpp3Dom.SELF_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.SELF_COMBINATION_OVERRIDE );
@@ -97,12 +117,14 @@ public void testShouldPerformSelfOverrideAtTopLevel()
Xpp3Dom t2 = new Xpp3Dom( "top" );
t2.setAttribute( "attr2", "value2" );
t2.setValue( "t2Value" );
+ t2.setInputLocation( "t2top" );
// merge and check results.
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
assertEquals( 2, result.getAttributeNames().length );
assertNull( result.getValue() );
+ assertEquals( "t1top", result.getInputLocation() );
}
@Test
@@ -111,11 +133,13 @@ public void testShouldMergeValuesAtTopLevelByDefault()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( "attr", "value" );
+ t1.setInputLocation( "t1top" );
// create the recessive DOM
Xpp3Dom t2 = new Xpp3Dom( "top" );
t2.setAttribute( "attr2", "value2" );
t2.setValue( "t2Value" );
+ t2.setInputLocation( "t2top" );
// merge and check results.
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
@@ -124,6 +148,7 @@ public void testShouldMergeValuesAtTopLevelByDefault()
assertEquals( 2, result.getAttributeNames().length );
assertEquals( result.getValue(), t2.getValue() );
+ assertEquals( "t2top", result.getInputLocation() );
}
@Test
@@ -213,10 +238,12 @@ public void testShouldOverwritePluginConfigurationSubItemsByDefault()
throws XmlPullParserException, IOException
{
String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
- Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
+ Xpp3Dom parentConfig =
+ Xpp3DomBuilder.build( new StringReader( parentConfigStr ), new FixedInputLocationBuilder( "parent" ) );
String childConfigStr = "<configuration><items><item>three</item></items></configuration>";
- Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
+ Xpp3Dom childConfig =
+ Xpp3DomBuilder.build( new StringReader( childConfigStr ), new FixedInputLocationBuilder( "child" ) );
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
Xpp3Dom items = result.getChild( "items" );
@@ -225,6 +252,7 @@ public void testShouldOverwritePluginConfigurationSubItemsByDefault()
Xpp3Dom item = items.getChild( 0 );
assertEquals( "three", item.getValue() );
+ assertEquals( "child", item.getInputLocation() );
}
@Test
@@ -232,11 +260,13 @@ public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
throws XmlPullParserException, IOException
{
String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
- Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
+ Xpp3Dom parentConfig =
+ Xpp3DomBuilder.build( new StringReader( parentConfigStr ), new FixedInputLocationBuilder( "parent" ) );
String childConfigStr =
"<configuration><items combine.children=\"append\"><item>three</item></items></configuration>";
- Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
+ Xpp3Dom childConfig =
+ Xpp3DomBuilder.build( new StringReader( childConfigStr ), new FixedInputLocationBuilder( "child" ) );
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
Xpp3Dom items = result.getChild( "items" );
@@ -246,8 +276,11 @@ public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
Xpp3Dom[] item = items.getChildren();
assertEquals( "one", item[0].getValue() );
+ assertEquals( "parent", item[0].getInputLocation() );
assertEquals( "two", item[1].getValue() );
+ assertEquals( "parent", item[1].getInputLocation() );
assertEquals( "three", item[2].getValue() );
+ assertEquals( "child", item[2].getInputLocation() );
}
@Test
@@ -295,4 +328,20 @@ public void testDupeChildren()
assertNotNull( dom );
assertEquals( "y", dom.getChild( "foo" ).getValue() );
}
+
+ private static class FixedInputLocationBuilder
+ implements Xpp3DomBuilder.InputLocationBuilder
+ {
+ private final Object location;
+
+ public FixedInputLocationBuilder( Object location )
+ {
+ this.location = location;
+ }
+
+ public Object toInputLocation( XmlPullParser parser )
+ {
+ return location;
+ }
+ }
}
=====================================
src/test/java/org/codehaus/plexus/util/xml/Xpp3DomUtilsTest.java
=====================================
@@ -20,6 +20,7 @@
import java.io.StringReader;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.Test;
public class Xpp3DomUtilsTest
@@ -34,17 +35,44 @@ public void testCombineId()
String rhs = "<props>" + "<property combine.id='RHS-ONLY'><name>RHS-ONLY</name><value>RHS</value></property>"
+ "<property combine.id='TOOVERWRITE'><name>TOOVERWRITE</name><value>RHS</value></property>" + "</props>";
- Xpp3Dom leftDom = Xpp3DomBuilder.build( new StringReader( lhs ) );
- Xpp3Dom rightDom = Xpp3DomBuilder.build( new StringReader( rhs ) );
+ Xpp3Dom leftDom = Xpp3DomBuilder.build( new StringReader( lhs ), new FixedInputLocationBuilder( "left" ) );
+ Xpp3Dom rightDom = Xpp3DomBuilder.build( new StringReader( rhs ), new FixedInputLocationBuilder( "right" ) );
Xpp3Dom mergeResult = Xpp3DomUtils.mergeXpp3Dom( leftDom, rightDom, true );
assertEquals( 3, mergeResult.getChildren( "property" ).length );
- assertEquals( "LHS-ONLY", mergeResult.getChildren( "property" )[0].getChild( "name" ).getValue() );
- assertEquals( "LHS", mergeResult.getChildren( "property" )[0].getChild( "value" ).getValue() );
+ Xpp3Dom p0 = mergeResult.getChildren( "property" )[0];
+ assertEquals( "LHS-ONLY", p0.getChild( "name" ).getValue() );
+ assertEquals( "left", p0.getChild( "name" ).getInputLocation() );
+ assertEquals( "LHS", p0.getChild( "value" ).getValue() );
+ assertEquals( "left", p0.getChild( "value" ).getInputLocation() );
+
+ Xpp3Dom p1 = mergeResult.getChildren( "property" )[1];
assertEquals( "TOOVERWRITE", mergeResult.getChildren( "property" )[1].getChild( "name" ).getValue() );
+ assertEquals( "left", p1.getChild( "name" ).getInputLocation() );
assertEquals( "LHS", mergeResult.getChildren( "property" )[1].getChild( "value" ).getValue() );
+ assertEquals( "left", p1.getChild( "value" ).getInputLocation() );
+
+ Xpp3Dom p2 = mergeResult.getChildren( "property" )[2];
assertEquals( "RHS-ONLY", mergeResult.getChildren( "property" )[2].getChild( "name" ).getValue() );
+ assertEquals( "right", p2.getChild( "name" ).getInputLocation() );
assertEquals( "RHS", mergeResult.getChildren( "property" )[2].getChild( "value" ).getValue() );
+ assertEquals( "right", p2.getChild( "value" ).getInputLocation() );
+ }
+
+ private static class FixedInputLocationBuilder
+ implements Xpp3DomBuilder.InputLocationBuilder
+ {
+ private final Object location;
+
+ public FixedInputLocationBuilder( Object location )
+ {
+ this.location = location;
+ }
+
+ public Object toInputLocation( XmlPullParser parser )
+ {
+ return location;
+ }
}
}
=====================================
src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java
=====================================
@@ -17,7 +17,10 @@
*/
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.io.EOFException;
import java.io.IOException;
import java.io.StringReader;
@@ -156,6 +159,133 @@ public void testUnicodeEntities()
assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
}
+ @Test
+ public void testInvalidCharacterReferenceHexa()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+ String input = "<root>�</root>";
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ fail( "Should fail since � is an illegal character reference" );
+ }
+ catch ( XmlPullParserException e )
+ {
+ assertTrue( e.getMessage().contains( "character reference (with hex value 110000) is invalid" ) );
+ }
+ }
+
+ @Test
+ public void testValidCharacterReferenceHexa()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+ String input = "<root>	

 Ȁ퟿ᄁ�𐀀􏿽</root>";
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0x9, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0xA, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0xD, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0x20, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0x200, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0xD7FF, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0xE000, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0xFFA2, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0xFFFD, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0x10000, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0x10FFFD, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 0x10FFFF, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
+ }
+ catch ( XmlPullParserException e )
+ {
+ fail( "Should success since the input represents all legal character references" );
+ }
+ }
+
+ @Test
+ public void testInvalidCharacterReferenceDecimal()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+ String input = "<root></root>";
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ fail( "Should fail since is an illegal character reference" );
+ }
+ catch ( XmlPullParserException e )
+ {
+ assertTrue( e.getMessage().contains( "character reference (with decimal value 1114112) is invalid" ) );
+ }
+ }
+
+ @Test
+ public void testValidCharacterReferenceDecimal()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+ String input =
+ "<root>
Ȁᄁ�𐀀</root>";
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 9, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 10, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 13, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 32, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 512, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 55295, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 57344, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 65442, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 65533, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 65536, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 1114109, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.ENTITY_REF, parser.nextToken() );
+ assertEquals( 1114111, parser.getText().codePointAt( 0 ) );
+ assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
+ }
+ catch ( XmlPullParserException e )
+ {
+ fail( "Should success since the input represents all legal character references" );
+ }
+ }
+
@Test
public void testProcessingInstruction()
throws Exception
@@ -171,6 +301,31 @@ public void testProcessingInstruction()
assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
}
+ @Test
+ public void testProcessingInstructionsContainingXml()
+ throws Exception
+ {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
+ sb.append( "<project>\n" );
+ sb.append( " <?pi\n" );
+ sb.append( " <tag>\n" );
+ sb.append( " </tag>\n" );
+ sb.append( " ?>\n" );
+ sb.append( "</project>" );
+
+ MXParser parser = new MXParser();
+ parser.setInput( new StringReader( sb.toString() ) );
+
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.nextToken() );
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.TEXT, parser.nextToken() ); // whitespace
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.nextToken() );
+ assertEquals( XmlPullParser.TEXT, parser.nextToken() ); // whitespace
+ assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
+ }
+
@Test
public void testSubsequentProcessingInstructionShort()
throws Exception
@@ -235,4 +390,243 @@ public void testSubsequentProcessingInstructionMoreThan8k()
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.nextToken() );
assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
}
+
+ public void testMalformedProcessingInstructionAfterTag()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+
+ String input = "<project /><?>";
+
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.END_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
+
+ fail( "Should fail since it has an invalid Processing Instruction" );
+ }
+ catch ( XmlPullParserException ex )
+ {
+ assertTrue( ex.getMessage().contains( "processing instruction PITarget name not found" ) );
+ }
+ }
+
+ public void testMalformedProcessingInstructionBeforeTag()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+
+ String input = "<?><project />";
+
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
+
+ assertEquals( XmlPullParser.START_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.END_TAG, parser.next() );
+
+ fail( "Should fail since it has invalid PI" );
+ }
+ catch ( XmlPullParserException ex )
+ {
+ assertTrue( ex.getMessage().contains( "processing instruction PITarget name not found" ) );
+ }
+ }
+
+ public void testMalformedProcessingInstructionSpaceBeforeName()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+
+ StringBuilder sb = new StringBuilder();
+ sb.append( "<? shouldhavenospace>" );
+ sb.append( "<project />" );
+
+ parser.setInput( new StringReader( sb.toString() ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
+
+ assertEquals( XmlPullParser.START_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.END_TAG, parser.next() );
+
+ fail( "Should fail since it has invalid PI" );
+ }
+ catch ( XmlPullParserException ex )
+ {
+ assertTrue( ex.getMessage().contains( "processing instruction PITarget must be exactly after <? and not white space character" ) );
+ }
+ }
+
+ public void testMalformedProcessingInstructionNoClosingQuestionMark()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+
+ StringBuilder sb = new StringBuilder();
+ sb.append( "<?shouldhavenospace>" );
+ sb.append( "<project />" );
+
+ parser.setInput( new StringReader( sb.toString() ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
+
+ assertEquals( XmlPullParser.START_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.END_TAG, parser.next() );
+
+ fail( "Should fail since it has invalid PI" );
+ }
+ catch ( XmlPullParserException ex )
+ {
+ assertTrue( ex.getMessage().contains( "processing instruction started on line 1 and column 2 was not closed" ) );
+ }
+ }
+
+ public void testSubsequentMalformedProcessingInstructionNoClosingQuestionMark()
+ throws Exception
+ {
+ MXParser parser = new MXParser();
+
+ StringBuilder sb = new StringBuilder();
+ sb.append( "<project />" );
+ sb.append( "<?shouldhavenospace>" );
+
+ parser.setInput( new StringReader( sb.toString() ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.END_TAG, parser.next() );
+
+ assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
+
+ fail( "Should fail since it has invalid PI" );
+ }
+ catch ( XmlPullParserException ex )
+ {
+ assertTrue( ex.getMessage().contains( "processing instruction started on line 1 and column 13 was not closed" ) );
+ }
+ }
+
+ public void testMalformedXMLRootElement()
+ throws Exception
+ {
+ String input = "<Y";
+
+ MXParser parser = new MXParser();
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+
+ fail( "Should throw EOFException" );
+ }
+ catch ( EOFException e )
+ {
+ assertTrue( e.getMessage().contains( "no more data available - expected the opening tag <Y...>" ) );
+ }
+ }
+
+ public void testMalformedXMLRootElement2()
+ throws Exception
+ {
+ String input = "<hello";
+
+ MXParser parser = new MXParser();
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+
+ fail( "Should throw EOFException" );
+ }
+ catch ( EOFException e )
+ {
+ assertTrue( e.getMessage().contains( "no more data available - expected the opening tag <hello...>" ) );
+ }
+ }
+
+ public void testMalformedXMLRootElement3()
+ throws Exception
+ {
+ String input = "<hello><how";
+
+ MXParser parser = new MXParser();
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+
+ fail( "Should throw EOFException" );
+ }
+ catch ( EOFException e )
+ {
+ assertTrue( e.getMessage().contains( "no more data available - expected the opening tag <how...>" ) );
+ }
+ }
+
+ public void testMalformedXMLRootElement4()
+ throws Exception
+ {
+ String input = "<hello>some text<how";
+
+ MXParser parser = new MXParser();
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.TEXT, parser.nextToken() );
+ assertEquals( "some text", parser.getText() );
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+
+ fail( "Should throw EOFException" );
+ }
+ catch ( EOFException e )
+ {
+ assertTrue( e.getMessage().contains( "no more data available - expected the opening tag <how...>" ) );
+ }
+ }
+
+ public void testMalformedXMLRootElement5()
+ throws Exception
+ {
+ String input = "<hello>some text</hello";
+
+ MXParser parser = new MXParser();
+ parser.setInput( new StringReader( input ) );
+
+ try
+ {
+ assertEquals( XmlPullParser.START_TAG, parser.nextToken() );
+ assertEquals( XmlPullParser.TEXT, parser.nextToken() );
+ assertEquals( "some text", parser.getText() );
+ assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
+
+ fail( "Should throw EOFException" );
+ }
+ catch ( EOFException e )
+ {
+ assertTrue( e.getMessage().contains( "no more data available - expected end tag </hello> to close start tag <hello>" ) );
+ }
+ }
+
}
View it on GitLab: https://salsa.debian.org/java-team/plexus-utils2/compare/6ee425b87545d0e4d508ab22c427ce70bbe28bbb...553fd9735a0e01f32fcf9930387493ffbfe5a64f
--
View it on GitLab: https://salsa.debian.org/java-team/plexus-utils2/compare/6ee425b87545d0e4d508ab22c427ce70bbe28bbb...553fd9735a0e01f32fcf9930387493ffbfe5a64f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20190712/579a4ce7/attachment.html>
More information about the pkg-java-commits
mailing list