Skip to content

Commit

Permalink
Fixing JT-173 (backport of modified PR provided by phax)
Browse files Browse the repository at this point in the history
The goal of this fix is to ensure that the order of files specified in included
configuration section is respected and used in plugin, no matter how plexus
returns them by DirectoryScanner since order is not consistent.

See issue codehaus-plexus/plexus-utils#70 in plexus-utils
  • Loading branch information
Laurent SCHOELENS committed Aug 9, 2023
1 parent 93f623a commit 30f349b
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 2 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -95,11 +98,93 @@ public static List<File> scanDirectoryForFiles(BuildContext buildContext, final

scanner.scan();

final List<File> files = new ArrayList<File>();
for (final String name : scanner.getIncludedFiles()) {
// Reorder files according to includes specific file ordering
List<String> orderedIncludedFiles = reorderFiles(scanner.getIncludedFiles(), includes);

final List<File> 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:<br>
* If the includes contain [a, b, c] and the resulting list should be in that order.<br>
* 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 <code>null</code>.
* @param includes
* The source includes in the correct order. May be <code>null</code> or empty.
* @return The ordered list of files, that tries to take the source order as good as possible
*/
protected static List<String> 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<String> resolvedFilesList = new ArrayList<>(Arrays.asList(resolvedFiles));
final List<String> 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<String> 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.<br>
* 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 <code>null</code>.
* @return The normalized pattern, never <code>null</code>.
*/
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;
}
}
@@ -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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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));
}
}

0 comments on commit 30f349b

Please sign in to comment.