diff --git a/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java b/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java index 71dcc5f..e6f1a18 100644 --- a/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java +++ b/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java @@ -145,7 +145,7 @@ private void addResources(List result, String[] resources) thr String sourceDir = name.replace('\\', '/'); File f = new File(dir, sourceDir); - FileAttributes fattrs = new FileAttributes(f); + FileAttributes fattrs = new FileAttributes(f, isFollowingSymLinks()); PlexusIoResourceAttributes attrs = mergeAttributes(fattrs, fattrs.isDirectory()); String remappedName = getName(name); diff --git a/src/test/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollectionSymlinkTest.java b/src/test/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollectionSymlinkTest.java new file mode 100644 index 0000000..0c001e7 --- /dev/null +++ b/src/test/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollectionSymlinkTest.java @@ -0,0 +1,139 @@ +package org.codehaus.plexus.components.io.resources; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.codehaus.plexus.components.io.functions.SymlinkDestinationSupplier; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test for symlink handling in PlexusIoFileResourceCollection + */ +public class PlexusIoFileResourceCollectionSymlinkTest { + + @Test + @DisabledOnOs(OS.WINDOWS) + void testFollowSymlinksToFilesEnabled() throws Exception { + PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection(); + collection.setBaseDir(new File("src/test/resources/symlinks/src")); + collection.setIncludes(new String[] {"symR"}); + collection.setFollowingSymLinks(true); + + List resources = collectResources(collection); + assertEquals(1, resources.size()); + + PlexusIoResource resource = resources.get(0); + assertEquals("symR", resource.getName()); + // When following symlinks, the resource should NOT be detected as a symlink + assertFalse(resource.isSymbolicLink(), "Resource should not be a symlink when followSymlinks=true"); + assertTrue(resource.isFile(), "Resource should be a file"); + assertEquals(38, resource.getSize(), "Should have size of target file"); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void testFollowSymlinksToFilesDisabled() throws Exception { + PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection(); + collection.setBaseDir(new File("src/test/resources/symlinks/src")); + collection.setIncludes(new String[] {"symR"}); + collection.setFollowingSymLinks(false); + + List resources = collectResources(collection); + assertEquals(1, resources.size()); + + PlexusIoResource resource = resources.get(0); + assertEquals("symR", resource.getName()); + // When not following symlinks, the resource should be detected as a symlink + assertTrue(resource.isSymbolicLink(), "Resource should be a symlink when followSymlinks=false"); + assertTrue(resource instanceof SymlinkDestinationSupplier); + assertEquals("fileR.txt", ((SymlinkDestinationSupplier) resource).getSymlinkDestination()); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void testFollowSymlinksToDirsEnabled() throws Exception { + PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection(); + collection.setBaseDir(new File("src/test/resources/symlinks/src")); + collection.setIncludes(new String[] {"symDir/**"}); + collection.setFollowingSymLinks(true); + + List resources = collectResources(collection); + // Should include the symDir itself and files inside targetDir + assertTrue(resources.size() >= 1, "Should find resources when following directory symlinks"); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void testFollowSymlinksToDirsDisabled() throws Exception { + PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection(); + collection.setBaseDir(new File("src/test/resources/symlinks/src")); + collection.setIncludes(new String[] {"symDir/**"}); + collection.setFollowingSymLinks(false); + + List resources = collectResources(collection); + // When not following symlinks, DirectoryScanner won't traverse into symDir + // so we expect fewer resources than when following + PlexusIoFileResourceCollection followCollection = new PlexusIoFileResourceCollection(); + followCollection.setBaseDir(new File("src/test/resources/symlinks/src")); + followCollection.setIncludes(new String[] {"symDir/**"}); + followCollection.setFollowingSymLinks(true); + List followResources = collectResources(followCollection); + + assertTrue( + resources.size() < followResources.size(), + "Should have fewer resources when not following directory symlinks"); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void testMultipleSymlinksFollowEnabled() throws Exception { + PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection(); + collection.setBaseDir(new File("src/test/resources/symlinks/src")); + collection.setIncludes(new String[] {"symR", "symW", "symX"}); + collection.setFollowingSymLinks(true); + + List resources = collectResources(collection); + assertEquals(3, resources.size()); + + for (PlexusIoResource resource : resources) { + assertFalse( + resource.isSymbolicLink(), + "Resource " + resource.getName() + " should not be a symlink when followSymlinks=true"); + } + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void testMultipleSymlinksFollowDisabled() throws Exception { + PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection(); + collection.setBaseDir(new File("src/test/resources/symlinks/src")); + collection.setIncludes(new String[] {"symR", "symW", "symX"}); + collection.setFollowingSymLinks(false); + + List resources = collectResources(collection); + assertEquals(3, resources.size()); + + for (PlexusIoResource resource : resources) { + assertTrue( + resource.isSymbolicLink(), + "Resource " + resource.getName() + " should be a symlink when followSymlinks=false"); + } + } + + private List collectResources(PlexusIoFileResourceCollection collection) throws Exception { + List result = new ArrayList<>(); + Iterator resources = collection.getResources(); + while (resources.hasNext()) { + result.add(resources.next()); + } + return result; + } +}