1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.provider.tar;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.nio.file.Files;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.zip.GZIPInputStream;
27
28 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
29 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.commons.vfs2.Capability;
33 import org.apache.commons.vfs2.FileName;
34 import org.apache.commons.vfs2.FileObject;
35 import org.apache.commons.vfs2.FileSystemException;
36 import org.apache.commons.vfs2.FileSystemOptions;
37 import org.apache.commons.vfs2.Selectors;
38 import org.apache.commons.vfs2.VfsLog;
39 import org.apache.commons.vfs2.provider.AbstractFileName;
40 import org.apache.commons.vfs2.provider.AbstractFileSystem;
41 import org.apache.commons.vfs2.provider.UriParser;
42 import org.apache.commons.vfs2.provider.bzip2.Bzip2FileObject;
43
44
45
46
47 public class TarFileSystem extends AbstractFileSystem {
48 private static final Log LOG = LogFactory.getLog(TarFileSystem.class);
49
50 private final char[] ENC = {'!'};
51
52 private final File file;
53
54 private TarArchiveInputStream tarFile;
55
56
57
58
59 private final Map<FileName, FileObject> cache = new HashMap<>();
60
61 protected TarFileSystem(final AbstractFileName rootName, final FileObject parentLayer,
62 final FileSystemOptions fileSystemOptions) throws FileSystemException {
63 super(rootName, parentLayer, fileSystemOptions);
64
65
66 file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF);
67
68
69 if (!file.exists()) {
70
71 tarFile = null;
72 }
73
74
75 }
76
77
78
79
80 @Override
81 protected void addCapabilities(final Collection<Capability> caps) {
82 caps.addAll(TarFileProvider.capabilities);
83 }
84
85
86
87
88 @Override
89 protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
90
91 return new TarFileObject(name, null, this, false);
92 }
93
94 protected TarArchiveInputStream createTarFile(final File file) throws FileSystemException {
95 try {
96 if ("tgz".equalsIgnoreCase(getRootName().getScheme())) {
97 return new TarArchiveInputStream(new GZIPInputStream(Files.newInputStream(file.toPath())));
98 }
99 if ("tbz2".equalsIgnoreCase(getRootName().getScheme())) {
100 return new TarArchiveInputStream(
101 Bzip2FileObject.wrapInputStream(file.getAbsolutePath(), Files.newInputStream(file.toPath())));
102 }
103 return new TarArchiveInputStream(Files.newInputStream(file.toPath()));
104 } catch (final IOException ioe) {
105 throw new FileSystemException("vfs.provider.tar/open-tar-file.error", file, ioe);
106 }
107 }
108
109 protected TarFileObject createTarFileObject(final AbstractFileName name, final TarArchiveEntry entry) {
110 return new TarFileObject(name, entry, this, true);
111 }
112
113 @Override
114 protected void doCloseCommunicationLink() {
115
116 try {
117 if (tarFile != null) {
118 tarFile.close();
119 tarFile = null;
120 }
121 } catch (final IOException e) {
122
123 VfsLog.warn(getLogger(), LOG, "vfs.provider.tar/close-tar-file.error :" + file, e);
124 }
125 }
126
127
128
129
130 @Override
131 protected FileObject getFileFromCache(final FileName name) {
132 return cache.get(name);
133 }
134
135 public InputStream getInputStream(final TarArchiveEntry entry) throws FileSystemException {
136 resetTarFile();
137 try {
138 while (!tarFile.getNextEntry().equals(entry)) {
139 }
140 return tarFile;
141 } catch (final IOException e) {
142 throw new FileSystemException(e);
143 }
144 }
145
146 protected TarArchiveInputStream getTarFile() throws FileSystemException {
147 if (tarFile == null && this.file.exists()) {
148 recreateTarFile();
149 }
150
151 return tarFile;
152 }
153
154 @Override
155 public void init() throws FileSystemException {
156 super.init();
157
158
159 try {
160 TarArchiveEntry entry;
161 while ((entry = getTarFile().getNextTarEntry()) != null) {
162 final AbstractFileName/../../../org/apache/commons/vfs2/provider/AbstractFileName.html#AbstractFileName">AbstractFileName name = (AbstractFileName) getFileSystemManager().resolveName(getRootName(),
163 UriParser.encode(entry.getName(), ENC));
164
165
166 TarFileObject fileObj;
167 if (entry.isDirectory() && getFileFromCache(name) != null) {
168 fileObj = (TarFileObject) getFileFromCache(name);
169 fileObj.setTarEntry(entry);
170 continue;
171 }
172
173 fileObj = createTarFileObject(name, entry);
174 putFileToCache(fileObj);
175
176
177
178 TarFileObject parent = null;
179 for (AbstractFileName/../org/apache/commons/vfs2/provider/AbstractFileName.html#AbstractFileName">AbstractFileName parentName = (AbstractFileName) name
180 .getParent(); parentName != null; fileObj = parent, parentName = (AbstractFileName) parentName
181 .getParent()) {
182
183 parent = (TarFileObject) getFileFromCache(parentName);
184 if (parent == null) {
185 parent = createTarFileObject(parentName, null);
186 putFileToCache(parent);
187 }
188
189
190 parent.attachChild(fileObj.getName());
191 }
192 }
193 } catch (final IOException e) {
194 throw new FileSystemException(e);
195 } finally {
196 closeCommunicationLink();
197 }
198 }
199
200
201
202
203 @Override
204 protected void putFileToCache(final FileObject file) {
205 cache.put(file.getName(), file);
206 }
207
208
209
210
211
212
213 private void recreateTarFile() throws FileSystemException {
214 if (this.tarFile != null) {
215 try {
216 this.tarFile.close();
217 } catch (final IOException e) {
218 throw new FileSystemException("vfs.provider.tar/close-tar-file.error", file, e);
219 }
220 tarFile = null;
221 }
222 this.tarFile = createTarFile(this.file);
223 }
224
225
226
227
228 @Override
229 protected void removeFileFromCache(final FileName name) {
230 cache.remove(name);
231 }
232
233 protected void resetTarFile() throws FileSystemException {
234
235
236
237 if (this.file.exists()) {
238 recreateTarFile();
239 }
240 }
241 }