diff --git a/maven-plugin/plugin-core/src/main/java/org/jvnet/jaxb/maven/util/IOUtils.java b/maven-plugin/plugin-core/src/main/java/org/jvnet/jaxb/maven/util/IOUtils.java index 5b5b70ea1..7716a4609 100644 --- a/maven-plugin/plugin-core/src/main/java/org/jvnet/jaxb/maven/util/IOUtils.java +++ b/maven-plugin/plugin-core/src/main/java/org/jvnet/jaxb/maven/util/IOUtils.java @@ -6,11 +6,14 @@ import java.net.URI; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.MatchPatterns; import org.codehaus.plexus.util.Scanner; +import org.codehaus.plexus.util.SelectorUtils; import org.jvnet.jaxb.maven.util.CollectionUtils.Function; import org.sonatype.plexus.build.incremental.BuildContext; import org.xml.sax.InputSource; @@ -95,11 +98,93 @@ public static List scanDirectoryForFiles(BuildContext buildContext, final scanner.scan(); - final List files = new ArrayList(); - for (final String name : scanner.getIncludedFiles()) { + // Reorder files according to includes specific file ordering + List orderedIncludedFiles = reorderFiles(scanner.getIncludedFiles(), includes); + + final List files = new ArrayList<>(); + for (final String name : orderedIncludedFiles) { files.add(new File(directory, name).getCanonicalFile()); } return files; } + + private static boolean isWildcard (final String s) { + return s.indexOf ('*') >= 0 || s.indexOf ('?') >= 0; + } + + /** + * Reorder the result of "scanner.getIncludedFile" so that the order of the + * source includes is maintained as good as possible. + * Examples:
+ * If the includes contain [a, b, c] and the resulting list should be in that order.
+ * If the includes contain [a, b*, c] the resulting list should be [a, matches-of(b*), c] + * + * @param resolvedFiles + * resolved files from scanner.getIncludedFiles. May not be null. + * @param includes + * The source includes in the correct order. May be null or empty. + * @return The ordered list of files, that tries to take the source order as good as possible + */ + protected static List reorderFiles(final String[] resolvedFiles, final String[] includes) { + if (includes == null || includes.length == 0) { + // return "as is" + return Arrays.asList(resolvedFiles); + } + + // copy of the initial list in order to avoid changes in resolvedFiles var + List resolvedFilesList = new ArrayList<>(Arrays.asList(resolvedFiles)); + final List ret = new ArrayList<>(resolvedFilesList.size()); + + // For each include + for (final String include : includes) { + // Create MatchPatterns from normalizePattern of the include (like it was done in DirectoryScanner) + MatchPatterns inc = MatchPatterns.from(normalizePattern(include)); + + // Find all matches in the resolved files list + final List matches = new ArrayList<>(); + for (final String resFile : resolvedFilesList) { + if (inc.matches(resFile, false)) { + matches.add(resFile); + } + } + + // Add all matches to the result list + ret.addAll(matches); + // Remove from the main list + resolvedFilesList.removeAll(matches); + } + + // Add all remaining resolved files in the order "as is" + ret.addAll(resolvedFilesList); + + return ret; + } + + /** + * Copy of Plexus-utils function (private) to normalize pattern of include.
+ * Normalizes the pattern, e.g. converts forward and backward slashes to the platform-specific file separator. + * + * @param pattern The pattern to normalize, must not be null. + * @return The normalized pattern, never null. + */ + private static String normalizePattern(String pattern) { + pattern = pattern.trim(); + + if (pattern.startsWith(SelectorUtils.REGEX_HANDLER_PREFIX)) { + if (File.separatorChar == '\\') { + pattern = org.codehaus.plexus.util.StringUtils.replace(pattern, "/", "\\\\"); + } else { + pattern = org.codehaus.plexus.util.StringUtils.replace(pattern, "\\\\", "/"); + } + } else { + pattern = pattern.replace(File.separatorChar == '/' ? '\\' : '/', File.separatorChar); + + if (pattern.endsWith(File.separator)) { + pattern += "**"; + } + } + + return pattern; + } } diff --git a/maven-plugin/plugin-core/src/test/java/org/jvnet/jaxb/maven/util/IOUtilsTests.java b/maven-plugin/plugin-core/src/test/java/org/jvnet/jaxb/maven/util/IOUtilsTests.java new file mode 100644 index 000000000..24cb39347 --- /dev/null +++ b/maven-plugin/plugin-core/src/test/java/org/jvnet/jaxb/maven/util/IOUtilsTests.java @@ -0,0 +1,129 @@ +package org.jvnet.jaxb.maven.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class IOUtilsTests { + + @Test + public void reorderFilesIncludesNull() { + String[] files = {"a.xsd", "c.xsd", "b.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, null); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + Assert.assertEquals(files[0], orderedFiles.get(0)); + Assert.assertEquals(files[1], orderedFiles.get(1)); + Assert.assertEquals(files[2], orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesEmpty() { + String[] files = {"a.xsd", "c.xsd", "b.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, new String[] {}); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + Assert.assertEquals(files[0], orderedFiles.get(0)); + Assert.assertEquals(files[1], orderedFiles.get(1)); + Assert.assertEquals(files[2], orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesNoWildcard() { + String[] files = {"a.xsd", "c.xsd", "b.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, new String[] { "b.xsd", "c.xsd", "a.xsd" }); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + Assert.assertEquals(files[2], orderedFiles.get(0)); + Assert.assertEquals(files[1], orderedFiles.get(1)); + Assert.assertEquals(files[0], orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesNoWildcardWithCommonSuffix() { + String[] files = {"a.xsd", "b.xsd", "service-ab.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, new String[] { "b.xsd", "a.xsd", "service-ab.xsd" }); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + Assert.assertEquals(files[1], orderedFiles.get(0)); + Assert.assertEquals(files[0], orderedFiles.get(1)); + Assert.assertEquals(files[2], orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesWithWildcardFirst() { + String[] files = {"a.xsd", "common/c1.xsd", "b.xsd", "common/c2.xsd", "common/a.xsd", "common/b.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, new String[] { "common/*.xsd", "a.xsd", "b.xsd" }); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + // we have all common/*.xsd files in same order + Assert.assertEquals(files[1], orderedFiles.get(0)); + Assert.assertEquals(files[3], orderedFiles.get(1)); + Assert.assertEquals(files[4], orderedFiles.get(2)); + Assert.assertEquals(files[5], orderedFiles.get(3)); + // and then a.xsd + Assert.assertEquals(files[0], orderedFiles.get(4)); + // and finally b.xsd + Assert.assertEquals(files[2], orderedFiles.get(5)); + } + + @Test + public void reorderFilesIncludesWithWildcardMiddle() { + String[] files = {"a.xsd", "common/c1.xsd", "b.xsd", "common/c2.xsd", "common/a.xsd", "common/b.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, new String[] { "a.xsd", "common/*.xsd", "b.xsd" }); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + + // we have a.xsd + Assert.assertEquals(files[0], orderedFiles.get(0)); + // and then all common/*.xsd files in same order + Assert.assertEquals(files[1], orderedFiles.get(1)); + Assert.assertEquals(files[3], orderedFiles.get(2)); + Assert.assertEquals(files[4], orderedFiles.get(3)); + Assert.assertEquals(files[5], orderedFiles.get(4)); + // and finally b.xsd + Assert.assertEquals(files[2], orderedFiles.get(5)); + } + + @Test + public void reorderFilesIncludesWithWildcardLast() { + String[] files = {"a.xsd", "common/c1.xsd", "b.xsd", "common/c2.xsd", "common/a.xsd", "common/b.xsd" }; + List orderedFiles = IOUtils.reorderFiles(files, new String[] { "a.xsd", "b.xsd", "common/*.xsd" }); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.length, orderedFiles.size()); + + // we have a.xsd + Assert.assertEquals(files[0], orderedFiles.get(0)); + // and then b.xsd + Assert.assertEquals(files[2], orderedFiles.get(1)); + // and finally all common/*.xsd files in same order + Assert.assertEquals(files[1], orderedFiles.get(2)); + Assert.assertEquals(files[3], orderedFiles.get(3)); + Assert.assertEquals(files[4], orderedFiles.get(4)); + Assert.assertEquals(files[5], orderedFiles.get(5)); + } +}