Skip to content

Commit e6b0c3a

Browse files
committed
Merge pull request #14 from plamentotev/symlinks-archived-file-set
Add support for symlinks in PlexusIoZipFileResourceCollection
2 parents b8b12c8 + 34bf0ec commit e6b0c3a

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;
@@ -86,6 +87,59 @@ public URL getResource( String name )
8687
private static class ZipFileResourceIterator
8788
implements Iterator<PlexusIoResource>, Closeable
8889
{
90+
private class ZipFileResource
91+
extends PlexusIoURLResource
92+
{
93+
private ZipFileResource( ZipArchiveEntry entry )
94+
{
95+
super( entry.getName(), entry.getTime() == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : entry.getTime(),
96+
entry.isDirectory() ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize(),
97+
!entry.isDirectory(), entry.isDirectory(), true );
98+
}
99+
100+
public URL getURL()
101+
throws IOException
102+
{
103+
String spec = getName();
104+
if ( spec.startsWith( "/" ) )
105+
{
106+
// Code path for PLXCOMP-170. Note that urlClassloader does not seem to produce correct
107+
// urls for this. Which again means files loaded via this path cannot have file names
108+
// requiring url encoding
109+
spec = "./" + spec;
110+
return new URL( url, spec );
111+
}
112+
return urlClassLoader.getResource( spec );
113+
}
114+
}
115+
116+
private class ZipFileSymlinkResource
117+
extends ZipFileResource
118+
implements SymlinkDestinationSupplier
119+
{
120+
private final ZipArchiveEntry entry;
121+
122+
private ZipFileSymlinkResource( ZipArchiveEntry entry )
123+
{
124+
super( entry );
125+
126+
this.entry = entry;
127+
}
128+
129+
@Override
130+
public String getSymlinkDestination()
131+
throws IOException
132+
{
133+
return zipFile.getUnixSymlink( entry );
134+
}
135+
136+
@Override
137+
public boolean isSymbolicLink()
138+
{
139+
return true;
140+
}
141+
}
142+
89143
private final Enumeration<ZipArchiveEntry> en;
90144

91145
private final URL url;
@@ -110,28 +164,10 @@ public boolean hasNext()
110164
public PlexusIoResource next()
111165
{
112166
final ZipArchiveEntry entry = en.nextElement();
113-
long l = entry.getTime();
114-
final long lastModified = l == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : l;
115-
final boolean dir = entry.isDirectory();
116-
final long size = dir ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize();
117167

118-
return new PlexusIoURLResource( entry.getName(), lastModified, size, !dir, dir, true )
119-
{
120-
public URL getURL()
121-
throws IOException
122-
{
123-
String spec = getName();
124-
if ( spec.startsWith( "/" ) )
125-
{
126-
// Code path for PLXCOMP-170. Note that urlClassloader does not seem to produce correct
127-
// urls for this. Which again means files loaded via this path cannot have file names
128-
// requiring url encoding
129-
spec = "./" + spec;
130-
return new URL( url, spec );
131-
}
132-
return urlClassLoader.getResource( spec );
133-
}
134-
};
168+
return entry.isUnixSymlink()
169+
? new ZipFileSymlinkResource( entry )
170+
: new ZipFileResource( entry );
135171
}
136172

137173
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)