You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by eo...@apache.org on 2018/12/28 07:21:57 UTC

[maven-war-plugin] branch MWAR-371 created (now 5869cce)

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

eolivelli pushed a change to branch MWAR-371
in repository https://gitbox.apache.org/repos/asf/maven-war-plugin.git.


      at 5869cce  [MWAR-371] Overlays break first-win rule for web resource with target path ending with '/'

This branch includes the following new commits:

     new 5869cce  [MWAR-371] Overlays break first-win rule for web resource with target path ending with '/'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[maven-war-plugin] 01/01: [MWAR-371] Overlays break first-win rule for web resource with target path ending with '/'

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

eolivelli pushed a commit to branch MWAR-371
in repository https://gitbox.apache.org/repos/asf/maven-war-plugin.git

commit 5869cce047f6709964ac710d3333814548ff73c9
Author: Andre Tadeu de Carvalho <an...@gmail.com>
AuthorDate: Sun Dec 23 13:25:37 2018 -0200

    [MWAR-371] Overlays break first-win rule for web resource with target path ending with '/'
---
 src/it/MWAR-371/custom/pom.xml                     | 65 ++++++++++++++++
 src/it/MWAR-371/custom/src/main/custom/a1.txt      | 18 +++++
 src/it/MWAR-371/custom/src/main/custom/a2.txt      | 18 +++++
 src/it/MWAR-371/generic/pom.xml                    | 29 ++++++++
 src/it/MWAR-371/generic/src/main/webapp/x/a1.txt   | 18 +++++
 src/it/MWAR-371/generic/src/main/webapp/x/a2.txt   | 18 +++++
 src/it/MWAR-371/generic/src/main/webapp/x/a3.txt   | 18 +++++
 src/it/MWAR-371/pom.xml                            | 51 +++++++++++++
 src/it/MWAR-371/verify.groovy                      | 74 +++++++++++++++++++
 .../org/apache/maven/plugins/war/util/PathSet.java | 86 +++++++---------------
 .../apache/maven/plugins/war/util/PathSetTest.java | 70 ++++++++----------
 11 files changed, 366 insertions(+), 99 deletions(-)

diff --git a/src/it/MWAR-371/custom/pom.xml b/src/it/MWAR-371/custom/pom.xml
new file mode 100644
index 0000000..b2aa197
--- /dev/null
+++ b/src/it/MWAR-371/custom/pom.xml
@@ -0,0 +1,65 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>mwar371</groupId>
+		<artifactId>mwar371</artifactId>
+		<version>1.0-SNAPSHOT</version>
+	</parent>
+	<artifactId>custom</artifactId>
+	<packaging>war</packaging>
+	<dependencies>
+		<dependency>
+			<groupId>mwar371</groupId>
+			<artifactId>generic</artifactId>
+			<version>1.0-SNAPSHOT</version>
+			<type>war</type>
+		</dependency>
+	</dependencies>
+	<build>
+
+		<plugins>
+			<plugin>
+				<artifactId>maven-war-plugin</artifactId>
+				<configuration>
+					<webResources>
+						<webResource>
+							<directory>src/main/custom</directory>
+							<includes>
+								<include>a1.txt</include>
+							</includes>
+							<targetPath>x/</targetPath>
+						</webResource>
+						<webResource>
+							<directory>src/main/custom</directory>
+							<includes>
+								<include>a2.txt</include>
+							</includes>
+							<targetPath>x</targetPath>
+						</webResource>
+					</webResources>
+				</configuration>
+			</plugin>
+		</plugins>
+
+	</build>
+</project>
\ No newline at end of file
diff --git a/src/it/MWAR-371/custom/src/main/custom/a1.txt b/src/it/MWAR-371/custom/src/main/custom/a1.txt
new file mode 100644
index 0000000..7fe810a
--- /dev/null
+++ b/src/it/MWAR-371/custom/src/main/custom/a1.txt
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+i'm custom
\ No newline at end of file
diff --git a/src/it/MWAR-371/custom/src/main/custom/a2.txt b/src/it/MWAR-371/custom/src/main/custom/a2.txt
new file mode 100644
index 0000000..7fe810a
--- /dev/null
+++ b/src/it/MWAR-371/custom/src/main/custom/a2.txt
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+i'm custom
\ No newline at end of file
diff --git a/src/it/MWAR-371/generic/pom.xml b/src/it/MWAR-371/generic/pom.xml
new file mode 100644
index 0000000..beeef48
--- /dev/null
+++ b/src/it/MWAR-371/generic/pom.xml
@@ -0,0 +1,29 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>mwar371</groupId>
+    <artifactId>mwar371</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>generic</artifactId>
+  <packaging>war</packaging>
+</project>
\ No newline at end of file
diff --git a/src/it/MWAR-371/generic/src/main/webapp/x/a1.txt b/src/it/MWAR-371/generic/src/main/webapp/x/a1.txt
new file mode 100644
index 0000000..fc4dee1
--- /dev/null
+++ b/src/it/MWAR-371/generic/src/main/webapp/x/a1.txt
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+I'm generic
\ No newline at end of file
diff --git a/src/it/MWAR-371/generic/src/main/webapp/x/a2.txt b/src/it/MWAR-371/generic/src/main/webapp/x/a2.txt
new file mode 100644
index 0000000..fc4dee1
--- /dev/null
+++ b/src/it/MWAR-371/generic/src/main/webapp/x/a2.txt
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+I'm generic
\ No newline at end of file
diff --git a/src/it/MWAR-371/generic/src/main/webapp/x/a3.txt b/src/it/MWAR-371/generic/src/main/webapp/x/a3.txt
new file mode 100644
index 0000000..fc4dee1
--- /dev/null
+++ b/src/it/MWAR-371/generic/src/main/webapp/x/a3.txt
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+I'm generic
\ No newline at end of file
diff --git a/src/it/MWAR-371/pom.xml b/src/it/MWAR-371/pom.xml
new file mode 100644
index 0000000..1f72884
--- /dev/null
+++ b/src/it/MWAR-371/pom.xml
@@ -0,0 +1,51 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>mwar371</groupId>
+	<artifactId>mwar371</artifactId>
+	<version>1.0-SNAPSHOT</version>
+	<packaging>pom</packaging>
+  <name>Maven Integration Test :: MWAR-371</name> 
+  <description>MWAR-371 integration test</description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  	
+	<modules>
+		<module>generic</module>
+		<module>custom</module>
+	</modules>
+	<build>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<artifactId>maven-war-plugin</artifactId>
+					<version>@project.version@</version>
+					<configuration>
+						<failOnMissingWebXml>false</failOnMissingWebXml>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
+</project>
\ No newline at end of file
diff --git a/src/it/MWAR-371/verify.groovy b/src/it/MWAR-371/verify.groovy
new file mode 100644
index 0000000..e66bcd5
--- /dev/null
+++ b/src/it/MWAR-371/verify.groovy
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+boolean checkFile( String fileName, String artifact, String module )
+{
+    def customA1 = new File( basedir, "${artifact}/target/${artifact}-1.0-SNAPSHOT/x/${fileName}" )
+    if ( ! customA1.exists() )
+    {
+        System.err.println( "${artifact}/target/${artifact}-1.0-SNAPSHOT/x/${fileName} does not exist." )
+        return false
+    }
+    if ( ! customA1.text.contains( module ) )
+    {
+        System.err.println( "${artifact}/target/${artifact}-1.0-SNAPSHOT/x/${fileName} is not ${module}." )
+        return false
+    }
+    return true
+}
+
+boolean checkFile( String fileName, String module )
+{
+    return checkFile( fileName, module, module )
+}
+
+try {
+    if ( ! checkFile( "a1.txt", "custom" ) )
+    {
+        return false
+    }
+    if ( ! checkFile( "a2.txt", "custom" ) )
+    {
+        return false
+    }
+    if ( ! checkFile( "a3.txt", "custom", "generic" ) )
+    {
+        return false
+    }
+    if ( ! checkFile( "a1.txt", "generic" ) )
+    {
+        return false
+    }
+    if ( ! checkFile( "a2.txt", "generic" ) )
+    {
+        return false
+    }
+    if ( ! checkFile( "a3.txt", "generic" ) )
+    {
+        return false
+    }
+}
+catch ( Throwable e )
+{
+    e.printStackTrace()
+    return false
+}
+
+return true
+
diff --git a/src/main/java/org/apache/maven/plugins/war/util/PathSet.java b/src/main/java/org/apache/maven/plugins/war/util/PathSet.java
index ebf5469..4fdf7e6 100644
--- a/src/main/java/org/apache/maven/plugins/war/util/PathSet.java
+++ b/src/main/java/org/apache/maven/plugins/war/util/PathSet.java
@@ -20,7 +20,6 @@ package org.apache.maven.plugins.war.util;
  */
 
 import org.codehaus.plexus.util.DirectoryScanner;
-import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
 import java.util.Collection;
@@ -42,25 +41,31 @@ import java.util.Set;
 public class PathSet
     implements Iterable<String>
 {
-
+    private static final String SEPARATOR = "/";
+    private static final char SEPARATOR_CHAR = SEPARATOR.charAt( 0 );
     /**
      * Set of normalized paths
      */
-    private Set<String> pathsSet = new LinkedHashSet<String>();
+    private Set<String> pathsSet = new LinkedHashSet<>();
 
-    /**
-     * The method normalizes the path.
-     * <ul>
-     * <li>changes directory separator to unix's separator(/)</li>
-     * <li>deletes all trailing slashes</li>
-     * </ul>
-     *
-     * @param path to normalization
-     * @return normalized path
-     */
-    protected String normalizeFilePath( String path )
+    static String normalizeSubPath( String path )
     {
-        return normalizeFilePathStatic( path );
+        if ( path.isEmpty() )
+        {
+            return path;
+        }
+        String cleanPath = path.replaceAll( "[\\\\]+", SEPARATOR )
+                .replaceAll( "[/]+" , SEPARATOR );
+        cleanPath = cleanPath.charAt( 0 ) == SEPARATOR_CHAR ? cleanPath.substring( 1 ) : cleanPath;
+        if ( cleanPath.isEmpty() )
+        {
+            return cleanPath;
+        }
+        if ( cleanPath.charAt( cleanPath.length() - 1 ) == SEPARATOR_CHAR )
+        {
+            return cleanPath.substring( 0, cleanPath.length() - 1 );
+        }
+        return cleanPath;
     }
 
     /*-------------------- Business interface ------------------------------*/
@@ -100,7 +105,7 @@ public class PathSet
      */
     public void add( String path )
     {
-        pathsSet.add( normalizeFilePath( path ) );
+        pathsSet.add( normalizeSubPath( path ) );
     }
 
     /**
@@ -113,7 +118,7 @@ public class PathSet
     {
         for ( String val : paths )
         {
-            add( prefix + val );
+            add( prefix + SEPARATOR +  val );
         }
     }
 
@@ -127,7 +132,7 @@ public class PathSet
     {
         for ( String val : paths )
         {
-            add( prefix + val );
+            add( prefix + SEPARATOR + val );
         }
     }
 
@@ -141,7 +146,7 @@ public class PathSet
     {
         for ( String path : paths )
         {
-            add( prefix + path );
+            add( prefix + SEPARATOR + path );
         }
     }
 
@@ -183,7 +188,7 @@ public class PathSet
      */
     public boolean contains( String path )
     {
-        return pathsSet.contains( normalizeFilePath( path ) );
+        return pathsSet.contains( normalizeSubPath( path ) );
     }
 
     /**
@@ -194,9 +199,7 @@ public class PathSet
      */
     boolean remove( String path )
     {
-        final String normalizedPath = normalizeFilePath( path );
-        return pathsSet.remove( normalizedPath );
-
+        return pathsSet.remove( normalizeSubPath( path ) );
     }
 
     /**
@@ -226,10 +229,10 @@ public class PathSet
      */
     public void addPrefix( String prefix )
     {
-        final Set<String> newSet = new HashSet<String>();
+        final Set<String> newSet = new HashSet<>();
         for ( String path : pathsSet )
         {
-            newSet.add( normalizeFilePath( prefix + path ) );
+            newSet.add( normalizeSubPath( prefix + path ) );
         }
         pathsSet = newSet;
     }
@@ -258,37 +261,4 @@ public class PathSet
         addAll( scanner.getIncludedFiles(), prefix );
     }
 
-    /*-------------------- Universal static mathods ------------------------*/
-    /**
-     * The method normalizes the path.
-     * 
-     * <ul>
-     * <li>changes directory separator to unix's separator(/)</li>
-     * <li>deletes all trailing slashes</li>
-     * </ul>
-     *
-     * @param path to normalization
-     * @return normalized path
-     */
-    public static String normalizeFilePathStatic( String path )
-    {
-        return trimTrailingSlashes( StringUtils.replace( path, '\\', '/' ) );
-    }
-
-    /**
-     * The method deletes all trailing slashes from the given string
-     *
-     * @param str a string
-     * @return trimed string
-     */
-    public static String trimTrailingSlashes( String str )
-    {
-        int i;
-        for ( i = 0; i < str.length() && str.charAt( i ) == '/'; i++ )
-        {
-            // just calculate i
-        }
-        return str.substring( i );
-    }
-
 }
diff --git a/src/test/java/org/apache/maven/plugins/war/util/PathSetTest.java b/src/test/java/org/apache/maven/plugins/war/util/PathSetTest.java
index f644ed9..33f1011 100644
--- a/src/test/java/org/apache/maven/plugins/war/util/PathSetTest.java
+++ b/src/test/java/org/apache/maven/plugins/war/util/PathSetTest.java
@@ -26,6 +26,7 @@ import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
@@ -37,45 +38,31 @@ public class PathSetTest
     /* --------------- Normalization tests --------------*/
 
     /**
-     * Test method for 'org.apache.maven.plugin.war.PathSet.normalizeFilePathStatic(String)'
+     * Test method for 'org.apache.maven.plugin.war.PathSet.normalizeSubPath(String)'
      */
-    public void testNormalizeFilePathStatic()
+    public void testNormalizeSubPath()
     {
-        assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "" ) );
-        assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "/" ) );
-        assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "////" ) );
-        assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "\\" ) );
-        assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "\\\\\\\\" ) );
-
-        assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "abc" ) );
-        assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "/abc" ) );
-        assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "////abc" ) );
-        assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "\\abc" ) );
-        assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "\\\\\\\\abc" ) );
-
-        assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "abc/def\\xyz\\" ) );
-        assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "/abc/def/xyz/" ) );
-        assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "////abc/def/xyz/" ) );
-        assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "\\abc/def/xyz/" ) );
-        assertEquals( "Normalized path error", "abc/def/xyz/",
-                      PathSet.normalizeFilePathStatic( "\\\\\\\\abc/def/xyz/" ) );
-    }
-
-    /**
-     * Test method for 'org.apache.maven.plugin.war.PathSet.trimTrailingSlashes(String)'
-     */
-    public void testTrimTrailingSlashes()
-    {
-        assertEquals( "Trimed path error", "", PathSet.trimTrailingSlashes( "" ) );
-        assertEquals( "Trimed path error", "", PathSet.trimTrailingSlashes( "/" ) );
-        assertEquals( "Trimed path error", "", PathSet.trimTrailingSlashes( "//" ) );
-        assertEquals( "Trimed path error", "\\", PathSet.trimTrailingSlashes( "\\" ) );
-        assertEquals( "Trimed path error", "abc/def\\xyz\\", PathSet.trimTrailingSlashes( "abc/def\\xyz\\" ) );
-        assertEquals( "Trimed path error", "abc/def/xyz/", PathSet.trimTrailingSlashes( "/abc/def/xyz/" ) );
-        assertEquals( "Trimed path error", "abc/def/xyz/", PathSet.trimTrailingSlashes( "////abc/def/xyz/" ) );
-        assertEquals( "Trimed path error", "\\abc/def/xyz\\", PathSet.trimTrailingSlashes( "\\abc/def/xyz\\" ) );
-        assertEquals( "Trimed path error", "\\\\\\\\abc/def/xyz",
-                      PathSet.trimTrailingSlashes( "\\\\\\\\abc/def/xyz" ) );
+        assertEquals( "Normalized path error", "", PathSet.normalizeSubPath( "" ) );
+        assertEquals( "Normalized path error", "", PathSet.normalizeSubPath( "/" ) );
+        assertEquals( "Normalized path error", "", PathSet.normalizeSubPath( "////" ) );
+        assertEquals( "Normalized path error", "", PathSet.normalizeSubPath( "\\" ) );
+        assertEquals( "Normalized path error", "", PathSet.normalizeSubPath( "\\\\\\\\" ) );
+
+        assertEquals( "Normalized path error", "abc", PathSet.normalizeSubPath( "abc" ) );
+        assertEquals( "Normalized path error", "abc", PathSet.normalizeSubPath( "/abc" ) );
+        assertEquals( "Normalized path error", "abc", PathSet.normalizeSubPath( "////abc" ) );
+        assertEquals( "Normalized path error", "abc", PathSet.normalizeSubPath( "\\abc" ) );
+        assertEquals( "Normalized path error", "abc", PathSet.normalizeSubPath( "\\\\\\\\abc" ) );
+
+        assertEquals( "Normalized path error", "abc/def/xyz", PathSet.normalizeSubPath( "abc/def\\xyz\\" ) );
+        assertEquals( "Normalized path error", "abc/def/xyz", PathSet.normalizeSubPath( "/abc/def/xyz/" ) );
+        assertEquals( "Normalized path error", "abc/def/xyz", PathSet.normalizeSubPath( "////abc/def/xyz/" ) );
+        assertEquals( "Normalized path error", "abc/def/xyz", PathSet.normalizeSubPath( "\\abc/def/xyz/" ) );
+        assertEquals( "Normalized path error", "abc/def/xyz",
+                PathSet.normalizeSubPath( "\\\\\\\\abc/def/xyz/" ) );
+        // MWAR-371
+        assertEquals( "Normalized path error", "abc/def/ghi",
+                PathSet.normalizeSubPath( "///abc/////def////ghi//" ) );
     }
 
     /* -------------- Operations tests ------------------*/
@@ -115,9 +102,8 @@ public class PathSetTest
         assertEquals( "Unexpected PathSet size", ps.size(), 2 );
 
         int i = 0;
-        for (String p1 : ps) {
+        for (String pathstr : ps) {
             i++;
-            String pathstr = p1;
             assertTrue(ps.contains(pathstr));
             assertTrue(ps.contains("/" + pathstr));
             assertTrue(ps.contains("/" + StringUtils.replace(pathstr, '/', '\\')));
@@ -128,9 +114,8 @@ public class PathSetTest
 
         ps.addPrefix( "/ab/c/" );
         i = 0;
-        for (String p : ps) {
+        for (String pathstr : ps) {
             i++;
-            String pathstr = p;
             assertTrue(pathstr.startsWith("ab/c/"));
             assertFalse(pathstr.startsWith("ab/c//"));
             assertTrue(ps.contains(pathstr));
@@ -208,6 +193,9 @@ public class PathSetTest
             assertTrue(ps2.contains("/" + str));
         }
 
+        PathSet ps3 = new PathSet();
+        ps3.addAll(new String[]{ "a/b/c" }, "d");
+        assertTrue( "Unexpected PathSet path", ps3.contains( "d/a/b/c" ) );
     }
 
     /**