Skip to content

Commit fcee0af

Browse files
quipsy-kargplamentotev
authored andcommitted
Parameter fileMapper for unpack path rewriting
The new parameter `fileMapper` (default: null) can be set to an implementation of the `org.codehaus.plexus.components.io.filemappers.FileMapper` interface to rewrite the target path of each unpacked file. This is useful in case prefixes of target files names within the target directory shall be added (using `PrefixFileMapper`), changed or omitted (using `RegExpFileMapper`). Signed-off-by: Markus KARG <[email protected]> Closes #100
1 parent 5da37a1 commit fcee0af

File tree

5 files changed

+155
-10
lines changed

5 files changed

+155
-10
lines changed

src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java

+25-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.List;
2828
import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
2929
import org.codehaus.plexus.components.io.attributes.SymlinkUtils;
30+
import org.codehaus.plexus.components.io.filemappers.FileMapper;
3031
import org.codehaus.plexus.components.io.fileselectors.FileSelector;
3132
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
3233
import org.codehaus.plexus.logging.AbstractLogEnabled;
@@ -51,6 +52,8 @@ public abstract class AbstractUnArchiver
5152

5253
private boolean overwrite = true;
5354

55+
private FileMapper[] fileMappers;
56+
5457
private List finalizers;
5558

5659
private FileSelector[] fileSelectors;
@@ -125,6 +128,18 @@ public void setOverwrite( final boolean b )
125128
overwrite = b;
126129
}
127130

131+
@Override
132+
public FileMapper[] getFileMappers()
133+
{
134+
return fileMappers;
135+
}
136+
137+
@Override
138+
public void setFileMappers( final FileMapper[] fileMappers )
139+
{
140+
this.fileMappers = fileMappers;
141+
}
142+
128143
@Override
129144
public final void extract()
130145
throws ArchiverException
@@ -301,10 +316,18 @@ public void setIgnorePermissions( final boolean ignorePermissions )
301316
}
302317

303318
protected void extractFile( final File srcF, final File dir, final InputStream compressedInputStream,
304-
final String entryName, final Date entryDate, final boolean isDirectory,
305-
final Integer mode, String symlinkDestination )
319+
String entryName, final Date entryDate, final boolean isDirectory,
320+
final Integer mode, String symlinkDestination, final FileMapper[] fileMappers )
306321
throws IOException, ArchiverException
307322
{
323+
if ( fileMappers != null )
324+
{
325+
for ( final FileMapper fileMapper : fileMappers )
326+
{
327+
entryName = fileMapper.getMappedFileName( entryName );
328+
}
329+
}
330+
308331
// Hmm. Symlinks re-evaluate back to the original file here. Unsure if this is a good thing...
309332
final File f = FileUtils.resolveFile( dir, entryName );
310333

src/main/java/org/codehaus/plexus/archiver/UnArchiver.java

+20
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.codehaus.plexus.archiver;
1818

1919
import java.io.File;
20+
import org.codehaus.plexus.components.io.filemappers.FileMapper;
2021
import org.codehaus.plexus.components.io.fileselectors.FileSelector;
2122

2223
public interface UnArchiver
@@ -72,6 +73,25 @@ void extract( String path, File outputDirectory )
7273
*/
7374
void setOverwrite( boolean b );
7475

76+
/**
77+
* Get chain of components which rewrite the target path of each unpacked file.
78+
*
79+
* @return {@link FileMapper}s to be used for rewriting each target path, or {@code null} if no rewriting shall happen.
80+
*
81+
* @since 3.7.0
82+
*/
83+
FileMapper[] getFileMappers();
84+
85+
/***
86+
* Sets chain of components to be used for rewriting target path of each unpacked file.
87+
*
88+
* @param fileMappers {@link FileMapper} to be used for rewriting each target path, or {@code null} if no
89+
* rewriting shall happen.
90+
*
91+
* @since 3.7.0
92+
*/
93+
void setFileMappers( FileMapper[] fileMappers );
94+
7595
/**
7696
* Sets a set of {@link FileSelector} instances, which may be used to select the files to extract from the archive.
7797
* If file selectors are present, then a file is only extracted, if it is confirmed by all file selectors.

src/main/java/org/codehaus/plexus/archiver/tar/TarUnArchiver.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.codehaus.plexus.archiver.AbstractUnArchiver;
3030
import org.codehaus.plexus.archiver.ArchiverException;
3131
import org.codehaus.plexus.archiver.util.Streams;
32+
import org.codehaus.plexus.components.io.filemappers.FileMapper;
3233
import org.codehaus.plexus.util.IOUtil;
3334
import org.iq80.snappy.SnappyInputStream;
3435

@@ -84,16 +85,16 @@ public void setEncoding( String encoding )
8485
protected void execute()
8586
throws ArchiverException
8687
{
87-
execute( getSourceFile(), getDestDirectory() );
88+
execute( getSourceFile(), getDestDirectory(), getFileMappers() );
8889
}
8990

9091
@Override
9192
protected void execute( String path, File outputDirectory )
9293
{
93-
execute( new File( path ), getDestDirectory() );
94+
execute( new File( path ), getDestDirectory(), getFileMappers() );
9495
}
9596

96-
protected void execute( File sourceFile, File destDirectory )
97+
protected void execute( File sourceFile, File destDirectory, FileMapper[] fileMappers )
9798
throws ArchiverException
9899
{
99100
TarArchiveInputStream tis = null;
@@ -111,7 +112,7 @@ protected void execute( File sourceFile, File destDirectory )
111112
{
112113
final String symlinkDestination = te.isSymbolicLink() ? te.getLinkName() : null;
113114
extractFile( sourceFile, destDirectory, tis, te.getName(), te.getModTime(), te.isDirectory(),
114-
te.getMode() != 0 ? te.getMode() : null, symlinkDestination );
115+
te.getMode() != 0 ? te.getMode() : null, symlinkDestination, fileMappers );
115116

116117
}
117118
}

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.commons.compress.utils.IOUtils;
3131
import org.codehaus.plexus.archiver.AbstractUnArchiver;
3232
import org.codehaus.plexus.archiver.ArchiverException;
33+
import org.codehaus.plexus.components.io.filemappers.FileMapper;
3334
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
3435

3536
/**
@@ -178,7 +179,7 @@ protected void execute()
178179
extractFileIfIncluded( getSourceFile(), getDestDirectory(), in, fileInfo.getName(),
179180
new Date( ze.getTime() ), ze.isDirectory(),
180181
ze.getUnixMode() != 0 ? ze.getUnixMode() : null,
181-
resolveSymlink( zf, ze ) );
182+
resolveSymlink( zf, ze ), getFileMappers() );
182183

183184
in.close();
184185
in = null;
@@ -216,10 +217,10 @@ private String resolveSymlink( ZipFile zf, ZipArchiveEntry ze )
216217

217218
private void extractFileIfIncluded( final File sourceFile, final File destDirectory, final InputStream inputStream,
218219
final String name, final Date time, final boolean isDirectory,
219-
final Integer mode, String symlinkDestination )
220+
final Integer mode, String symlinkDestination, final FileMapper[] fileMappers )
220221
throws IOException, ArchiverException
221222
{
222-
extractFile( sourceFile, destDirectory, inputStream, name, time, isDirectory, mode, symlinkDestination );
223+
extractFile( sourceFile, destDirectory, inputStream, name, time, isDirectory, mode, symlinkDestination, fileMappers );
223224
}
224225

225226
@Override
@@ -250,7 +251,7 @@ protected void execute( final String path, final File outputDirectory )
250251
extractFileIfIncluded( getSourceFile(), outputDirectory, in,
251252
ze.getName(), new Date( ze.getTime() ), ze.isDirectory(),
252253
ze.getUnixMode() != 0 ? ze.getUnixMode() : null,
253-
resolveSymlink( zipFile, ze ) );
254+
resolveSymlink( zipFile, ze ), getFileMappers() );
254255

255256
in.close();
256257
in = null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
*
3+
* Copyright 2018 The Apache Software Foundation
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.codehaus.plexus.archiver;
18+
19+
import java.io.File;
20+
import java.io.IOException;
21+
import java.nio.file.Files;
22+
23+
import org.codehaus.plexus.components.io.filemappers.FileMapper;
24+
import org.junit.After;
25+
import org.junit.Before;
26+
import org.junit.Rule;
27+
import org.junit.Test;
28+
import org.junit.rules.ExpectedException;
29+
30+
/**
31+
* Unit test for {@link AbstractUnArchiver}
32+
*
33+
* @author <a href="mailto:[email protected]">Markus KARG</a>
34+
*/
35+
public class AbstractUnArchiverTest
36+
{
37+
@Rule
38+
public ExpectedException thrown = ExpectedException.none();
39+
40+
private AbstractUnArchiver abstractUnArchiver;
41+
42+
@Before
43+
public void setUp()
44+
{
45+
this.abstractUnArchiver = new AbstractUnArchiver()
46+
{
47+
@Override
48+
protected void execute( final String path, final File outputDirectory )
49+
throws ArchiverException
50+
{
51+
// unused
52+
}
53+
54+
@Override
55+
protected void execute()
56+
throws ArchiverException
57+
{
58+
// unused
59+
}
60+
};
61+
}
62+
63+
@After
64+
public void tearDown()
65+
{
66+
this.abstractUnArchiver = null;
67+
}
68+
69+
@Test
70+
public void shouldThrowExceptionBecauseRewrittenPathIsOutOfDirectory()
71+
throws ArchiverException, IOException
72+
{
73+
// given
74+
this.thrown.expectMessage( "Entry is outside of the target directory (../PREFIX/ENTRYNAME.SUFFIX)" );
75+
final File targetFolder = Files.createTempDirectory( null ).toFile();
76+
final FileMapper[] fileMappers = new FileMapper[] { new FileMapper()
77+
{
78+
@Override
79+
public String getMappedFileName( String pName )
80+
{
81+
return "../PREFIX/" + pName;
82+
}
83+
}, new FileMapper()
84+
{
85+
@Override
86+
public String getMappedFileName( String pName )
87+
{
88+
return pName + ".SUFFIX";
89+
}
90+
} };
91+
92+
// when
93+
this.abstractUnArchiver.extractFile( null, targetFolder, null, "ENTRYNAME", null, false, null, null,
94+
fileMappers );
95+
96+
// then
97+
// ArchiverException is thrown providing the rewritten path
98+
}
99+
100+
}

0 commit comments

Comments
 (0)