Skip to content
Commits on Source (7)
language: java
jdk:
- openjdk7
- oraclejdk8
- openjdk8
- openjdk11
# - openjdk12 add once code is requires Java 7
# No need for preliminary install step.
install: true
......
plexus-utils2 (3.2.1-1) unstable; urgency=medium
* Team upload.
* New upstream release
- Refreshed the patches
- Disabled the performance tests
* Standards-Version updated to 4.4.0
-- Emmanuel Bourg <ebourg@apache.org> Fri, 12 Jul 2019 08:51:10 +0200
plexus-utils2 (3.1.1-1) unstable; urgency=medium
* New upstream release
......
......@@ -11,7 +11,7 @@ Build-Depends:
libmaven-javadoc-plugin-java,
libmaven-plugin-testing-java,
maven-debian-helper
Standards-Version: 4.3.0
Standards-Version: 4.4.0
Vcs-Git: https://salsa.debian.org/java-team/plexus-utils2.git
Vcs-Browser: https://salsa.debian.org/java-team/plexus-utils2
Homepage: http://codehaus-plexus.github.io/plexus-utils/
......
......@@ -17,3 +17,4 @@
org.apache.maven.plugins maven-enforcer-plugin * * * *
org.apache.maven.plugins maven-release-plugin * * * *
org.apache.maven.plugins maven-scm-publish-plugin * * * *
org.openjdk.jmh * * * * *
......@@ -3,16 +3,16 @@ Author: Emmanuel Bourg <ebourg@apache.org>
Forwarded: not-needed
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,12 @@
<version>1.1</version>
@@ -69,6 +69,12 @@
<version>1.21</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.2</version>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<pluginManagement>
......@@ -3,7 +3,7 @@ Author: Emmanuel Bourg <ebourg@apache.org>
Forwarded: no
--- a/pom.xml
+++ b/pom.xml
@@ -62,6 +62,12 @@
@@ -70,6 +70,12 @@
<scope>test</scope>
</dependency>
<dependency>
......@@ -15,4 +15,4 @@ Forwarded: no
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<version>4.12</version>
Description: Follow symlink when copying files with NIO
Author: Michael Simacek <msimacek@redhat.com>
Forwarded: https://github.com/codehaus-plexus/plexus-utils/issues/45
--- a/src/main/java/org/codehaus/plexus/util/NioFiles.java
+++ b/src/main/java/org/codehaus/plexus/util/NioFiles.java
@@ -138,7 +138,7 @@
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();
}
Description: Disables the performance tests
Author: Emmanuel Bourg <ebourg@apache.org>
Forwarded: not-needed
--- a/pom.xml
+++ b/pom.xml
@@ -95,6 +95,14 @@
</pluginManagement>
<plugins>
<plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <testExcludes>
+ <testExclude>**/*PerfTest*</testExclude>
+ </testExcludes>
+ </configuration>
+ </plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-publish-plugin</artifactId>
<configuration>
01-add-junit-dependency.patch
02-propertyutils-compatibility.patch
03-maven-plugin-testing-compatibility.patch
05-fix-nio-file-copy.patch
06-ignore-jmh-benchmarks.patch
......@@ -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@github.com:codehaus-plexus/plexus-utils.git</connection>
<developerConnection>scm:git:git@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 -->
......
......@@ -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 );
......
......@@ -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();
}
......
......@@ -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
......
......@@ -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 @@ public class Xpp3Dom
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 String[] getAttributeNames()
}
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 Xpp3Dom[] getChildren()
}
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,19 +408,22 @@ 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 )
{
for ( String attr : recessive.attributes.keySet() )
{
if ( isEmpty( dominant.getAttribute( attr ) ) )
{
dominant.setAttribute( attr, recessive.getAttribute( attr ) );
}
}
}
if ( recessive.getChildCount() > 0 )
{
......@@ -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() );
}
}
......
......@@ -37,7 +37,16 @@ public class Xpp3DomBuilder
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 );
}
}
......@@ -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();
......
......@@ -2664,13 +2664,16 @@ protected char[] parseEntityRef()
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 )
{
char[] tmp = toChars( Integer.parseInt( sb.toString(), 16 ) );
charRefOneCharBuf = tmp;
if ( tokenize )
try
{
text = newString( charRefOneCharBuf, 0, charRefOneCharBuf.length );
charRefOneCharBuf = toChars( Integer.parseInt( sb.toString(), isHex ? 16 : 10 ) );
}
return charRefOneCharBuf;
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();
}
}
......@@ -3688,6 +3704,13 @@ else if ( expand )
{
StringBuilder expectedTagStack = new StringBuilder();
if ( depth > 0 )
{
if ( elRawName == null || elRawName[depth] == null )
{
String tagName = new String( buf, posStart + 1, pos - posStart - 1 );
expectedTagStack.append( " - expected the opening tag <" ).append( tagName ).append( "...>" );
}
else
{
// final char[] cbuf = elRawName[depth];
// final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
......@@ -3697,11 +3720,20 @@ else if ( expand )
expectedTagStack.append( "s" ); // more than one end tag
}
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-- )
{
......@@ -3709,12 +3741,22 @@ else if ( expand )
{
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" );
}
}
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 )
......
......@@ -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 @@ public class DirectoryScannerTest
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
......
......@@ -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 ) );
}
}
......@@ -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 );
......