Skip to content

Commit 34bf0ec

Browse files
committed
Add support for symlinks in PlexusIoZipFileResourceCollection
1 parent f713c5d commit 34bf0ec

File tree

2 files changed

+95
-21
lines changed

2 files changed

+95
-21
lines changed

src/main/java/org/codehaus/plexus/archiver/zip/PlexusIoZipFileResourceCollection.java

+57-21
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
2020
import org.apache.commons.compress.archivers.zip.ZipFile;
21+
import org.codehaus.plexus.components.io.functions.SymlinkDestinationSupplier;
2122
import org.codehaus.plexus.components.io.resources.AbstractPlexusIoArchiveResourceCollection;
2223
import org.codehaus.plexus.components.io.resources.EncodingSupported;
2324
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
@@ -79,6 +80,59 @@ public URL getResource( String name )
7980
private static class ZipFileResourceIterator
8081
implements Iterator<PlexusIoResource>, Closeable
8182
{
83+
private class ZipFileResource
84+
extends PlexusIoURLResource
85+
{
86+
private ZipFileResource( ZipArchiveEntry entry )
87+
{
88+
super( entry.getName(), entry.getTime() == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : entry.getTime(),
89+
entry.isDirectory() ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize(),
90+
!entry.isDirectory(), entry.isDirectory(), true );
91+
}
92+
93+
public URL getURL()
94+
throws IOException
95+
{
96+
String spec = getName();
97+
if ( spec.startsWith( "/" ) )
98+
{
99+
// Code path for PLXCOMP-170. Note that urlClassloader does not seem to produce correct
100+
// urls for this. Which again means files loaded via this path cannot have file names
101+
// requiring url encoding
102+
spec = "./" + spec;
103+
return new URL( url, spec );
104+
}
105+
return urlClassLoader.getResource( spec );
106+
}
107+
}
108+
109+
private class ZipFileSymlinkResource
110+
extends ZipFileResource
111+
implements SymlinkDestinationSupplier
112+
{
113+
private final ZipArchiveEntry entry;
114+
115+
private ZipFileSymlinkResource( ZipArchiveEntry entry )
116+
{
117+
super( entry );
118+
119+
this.entry = entry;
120+
}
121+
122+
@Override
123+
public String getSymlinkDestination()
124+
throws IOException
125+
{
126+
return zipFile.getUnixSymlink( entry );
127+
}
128+
129+
@Override
130+
public boolean isSymbolicLink()
131+
{
132+
return true;
133+
}
134+
}
135+
82136
private final Enumeration<ZipArchiveEntry> en;
83137

84138
private final URL url;
@@ -103,28 +157,10 @@ public boolean hasNext()
103157
public PlexusIoResource next()
104158
{
105159
final ZipArchiveEntry entry = en.nextElement();
106-
long l = entry.getTime();
107-
final long lastModified = l == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : l;
108-
final boolean dir = entry.isDirectory();
109-
final long size = dir ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize();
110160

111-
return new PlexusIoURLResource( entry.getName(), lastModified, size, !dir, dir, true )
112-
{
113-
public URL getURL()
114-
throws IOException
115-
{
116-
String spec = getName();
117-
if ( spec.startsWith( "/" ) )
118-
{
119-
// Code path for PLXCOMP-170. Note that urlClassloader does not seem to produce correct
120-
// urls for this. Which again means files loaded via this path cannot have file names
121-
// requiring url encoding
122-
spec = "./" + spec;
123-
return new URL( url, spec );
124-
}
125-
return urlClassLoader.getResource( spec );
126-
}
127-
};
161+
return entry.isUnixSymlink()
162+
? new ZipFileSymlinkResource( entry )
163+
: new ZipFileResource( entry );
128164
}
129165

130166
public void remove()

src/test/java/org/codehaus/plexus/archiver/zip/PlexusIoZipFileResourceCollectionTest.java

+38
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
import org.apache.commons.io.IOUtils;
44
import org.codehaus.plexus.PlexusTestCase;
5+
import org.codehaus.plexus.components.io.functions.SymlinkDestinationSupplier;
56
import org.codehaus.plexus.components.io.resources.*;
67

78
import java.io.BufferedReader;
89
import java.io.File;
910
import java.io.InputStream;
1011
import java.io.InputStreamReader;
1112
import java.net.URL;
13+
import java.util.HashMap;
1214
import java.util.HashSet;
1315
import java.util.Iterator;
16+
import java.util.Map;
1417
import java.util.Set;
1518

1619
public class PlexusIoZipFileResourceCollectionTest
@@ -87,4 +90,39 @@ public void testFilesThatAreNotThere()
8790
}
8891
}
8992

93+
public void testSymlinkEntries()
94+
throws Exception
95+
{
96+
File testZip = new File( getBasedir(), "src/test/resources/symlinks/symlinks.zip" );
97+
Map<String, String> symLinks = new HashMap<String, String>();
98+
symLinks.put( "symDir", "targetDir/" );
99+
symLinks.put( "symLinkToDirOnTheOutside", "../dirOnTheOutside/" );
100+
symLinks.put( "symLinkToTheOutside", "../onTheOutside.txt" );
101+
symLinks.put( "symR", "fileR.txt" );
102+
symLinks.put( "symW", "fileW.txt" );
103+
symLinks.put( "symX", "fileX.txt" );
104+
PlexusIoZipFileResourceCollection
105+
prc = new PlexusIoZipFileResourceCollection();
106+
prc.setFile( testZip );
107+
final Iterator<PlexusIoResource> entries = prc.getEntries();
108+
while ( entries.hasNext() )
109+
{
110+
final PlexusIoResource next = entries.next();
111+
String symLinkTarget = symLinks.remove( next.getName() );
112+
if ( symLinkTarget != null )
113+
{
114+
assertTrue( next.getName() + " must be symlink", next.isSymbolicLink() );
115+
assertTrue( next instanceof SymlinkDestinationSupplier );
116+
assertEquals( symLinkTarget,
117+
( (SymlinkDestinationSupplier) next ).getSymlinkDestination() );
118+
}
119+
else
120+
{
121+
assertFalse( next.getName() + " must not be symlink", next.isSymbolicLink() );
122+
}
123+
}
124+
125+
assertTrue( symLinks.isEmpty() );
126+
}
127+
90128
}

0 commit comments

Comments
 (0)