-
Notifications
You must be signed in to change notification settings - Fork 36
/
ArchiverCompressorDecorator.java
144 lines (122 loc) · 5.24 KB
/
ArchiverCompressorDecorator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* Copyright 2013 Thomas Rausch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rauschig.jarchivelib;
import static org.rauschig.jarchivelib.CommonsStreamFactory.createArchiveInputStream;
import static org.rauschig.jarchivelib.CommonsStreamFactory.createCompressorInputStream;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.compressors.CompressorException;
/**
* Decorates an {@link Archiver} with a {@link Compressor}, s.t. it is able to compress the archives it generates and
* decompress the archives it extracts.
*/
class ArchiverCompressorDecorator implements Archiver {
private CommonsArchiver archiver;
private CommonsCompressor compressor;
/**
* Decorates the given Archiver with the given Compressor.
*
* @param archiver the archiver to decorate
* @param compressor the compressor used for compression
*/
ArchiverCompressorDecorator(CommonsArchiver archiver, CommonsCompressor compressor) {
this.archiver = archiver;
this.compressor = compressor;
}
@Override
public File create(String archive, File destination, File source) throws IOException {
return create(archive, destination, IOUtils.filesContainedIn(source));
}
@Override
public File create(String archive, File destination, File... sources) throws IOException {
IOUtils.requireDirectory(destination);
File temp = File.createTempFile(destination.getName(), archiver.getFilenameExtension(), destination);
File destinationArchive = null;
try {
temp = archiver.create(temp.getName(), temp.getParentFile(), sources);
destinationArchive = new File(destination, getArchiveFileName(archive));
compressor.compress(temp, destinationArchive);
} finally {
temp.delete();
}
return destinationArchive;
}
@Override
public void extract(File archive, File destination) throws IOException {
IOUtils.requireDirectory(destination);
/*
* The decompressor has to map F-N-F to I-A-E in some cases to preserve compatibility,
* and we don't want that here.
*/
if (!archive.exists()) {
throw new FileNotFoundException(String.format("Archive %s does not exist.", archive.getAbsolutePath()));
}
InputStream archiveStream = null;
try {
archiveStream = new BufferedInputStream(new FileInputStream(archive));
archiver.extract(compressor.decompressingStream(archiveStream), destination);
} catch (FileNotFoundException e) {
// Java throws F-N-F for no access, and callers expect I-A-E for that.
throw new IllegalArgumentException(String.format("Access control or other error opening %s", archive.getAbsolutePath()), e);
} finally {
IOUtils.closeQuietly(archiveStream);
}
}
@Override
public void extract(InputStream archive, File destination) throws IOException {
IOUtils.requireDirectory(destination);
archiver.extract(compressor.decompressingStream(archive), destination);
}
@Override
public ArchiveStream stream(File archive) throws IOException {
try {
return new CommonsArchiveStream(createArchiveInputStream(archiver, createCompressorInputStream(archive)));
} catch (ArchiveException e) {
throw new IOException(e);
} catch (CompressorException e) {
throw new IOException(e);
}
}
@Override
public String getFilenameExtension() {
return archiver.getFilenameExtension() + compressor.getFilenameExtension();
}
/**
* Returns a file name from the given archive name. The file extension suffix will be appended according to what is
* already present.
* <br>
* E.g. if the compressor uses the file extension "gz", the archiver "tar", and passed argument is "archive.tar",
* the returned value will be "archive.tar.gz".
*
* @param archive the existing archive file name
* @return the normalized archive file name including the correct file name extension
*/
private String getArchiveFileName(String archive) {
String fileExtension = getFilenameExtension();
if (archive.endsWith(fileExtension)) {
return archive;
} else if (archive.endsWith(archiver.getFilenameExtension())) {
return archive + compressor.getFilenameExtension();
} else {
return archive + fileExtension;
}
}
}