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..51126a4be 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 @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.Scanner; @@ -95,11 +96,74 @@ public static List scanDirectoryForFiles(BuildContext buildContext, final scanner.scan(); - final List files = new ArrayList(); + final List files = new ArrayList<>(); for (final String name : scanner.getIncludedFiles()) { files.add(new File(directory, name).getCanonicalFile()); } - return files; + return reorderFiles(files, directory, includes); + } + + 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. Source wildcard matches + * are postponed to the end.
+ * 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, c, + * matches-of(b*)] + * + * @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 List resolvedFiles, File directory, final String[] includes) { + if (includes == null || includes.length == 0) { + // return "as is" + return resolvedFiles; + } + + final List ret = new ArrayList<>(resolvedFiles.size()); + // copy of the initial list in order to avoid changes in resolvedFiles var + List resolvedFilesList = new ArrayList<>(resolvedFiles); + for (final String inc : includes) { + // Only deal with fixed files + if (!isWildcard(inc)) { + // Ensure to use the system path separator + final String sUnifiedInclude = inc.replace('\\', File.separatorChar).replace('/', File.separatorChar); + final File fileInclude = new File(directory, sUnifiedInclude); + + // Find all matches in the resolved files list + final List matches = new ArrayList<>(); + for (final File resFile : resolvedFilesList) { + if (resFile.getAbsolutePath().equals(fileInclude.getAbsolutePath())) { + matches.add(resFile); + } + } + + for (final File match : matches) { + // Add all matches to the result list + ret.add(match); + + // Remove from the main list + resolvedFilesList.remove(match); + } + } + } + + // Add all remaining resolved files in the order "as is" + ret.addAll(resolvedFilesList); + + return ret; } } 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..d40ddd1fb --- /dev/null +++ b/maven-plugin/plugin-core/src/test/java/org/jvnet/jaxb/maven/util/IOUtilsTests.java @@ -0,0 +1,107 @@ +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 { + + private File directory = new File("/"); + + @Test + public void reorderFilesIncludesNull() { + List files = new ArrayList<>(); + files.add(new File(directory, "a.xsd")); + files.add(new File(directory, "c.xsd")); + files.add(new File(directory, "b.xsd")); + List orderedFiles = IOUtils.reorderFiles(files, directory, null); + + Assert.assertNotNull("Ordered files list should not be null", + orderedFiles); + Assert.assertEquals("Ordered files list should contains all elements of initial list", + files.size(), orderedFiles.size()); + Assert.assertEquals(files.get(0), orderedFiles.get(0)); + Assert.assertEquals(files.get(1), orderedFiles.get(1)); + Assert.assertEquals(files.get(2), orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesEmpty() { + List files = new ArrayList<>(); + files.add(new File(directory, "a.xsd")); + files.add(new File(directory, "c.xsd")); + files.add(new File(directory, "b.xsd")); + List orderedFiles = IOUtils.reorderFiles(files, directory, 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.size(), orderedFiles.size()); + Assert.assertEquals(files.get(0), orderedFiles.get(0)); + Assert.assertEquals(files.get(1), orderedFiles.get(1)); + Assert.assertEquals(files.get(2), orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesNoWildcard() { + List files = new ArrayList<>(); + files.add(new File(directory, "a.xsd")); + files.add(new File(directory, "c.xsd")); + files.add(new File(directory, "b.xsd")); + List orderedFiles = IOUtils.reorderFiles(files, directory, 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.size(), orderedFiles.size()); + Assert.assertEquals(files.get(2), orderedFiles.get(0)); + Assert.assertEquals(files.get(1), orderedFiles.get(1)); + Assert.assertEquals(files.get(0), orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesNoWildcardWithCommonSuffix() { + List files = new ArrayList<>(); + files.add(new File(directory, "a.xsd")); + files.add(new File(directory, "b.xsd")); + files.add(new File(directory, "service-ab.xsd")); + List orderedFiles = IOUtils.reorderFiles(files, directory, 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.size(), orderedFiles.size()); + Assert.assertEquals(files.get(1), orderedFiles.get(0)); + Assert.assertEquals(files.get(0), orderedFiles.get(1)); + Assert.assertEquals(files.get(2), orderedFiles.get(2)); + } + + @Test + public void reorderFilesIncludesWithWildcard() { + List files = new ArrayList<>(); + files.add(new File(directory, "a.xsd")); + files.add(new File(directory, "common/c1.xsd")); + files.add(new File(directory, "b.xsd")); + files.add(new File(directory, "common/c2.xsd")); + files.add(new File(directory, "common/a.xsd")); + files.add(new File(directory, "common/b.xsd")); + List orderedFiles = IOUtils.reorderFiles(files, directory, 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.size(), orderedFiles.size()); + // a.xsd is the first file + Assert.assertEquals(files.get(0), orderedFiles.get(0)); + // b.xsd is the second file + Assert.assertEquals(files.get(2), orderedFiles.get(1)); + // and then we have all common/*.xsd files in same order + Assert.assertEquals(files.get(1), orderedFiles.get(2)); + Assert.assertEquals(files.get(3), orderedFiles.get(3)); + Assert.assertEquals(files.get(4), orderedFiles.get(4)); + Assert.assertEquals(files.get(5), orderedFiles.get(5)); + } +}