1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.provider.tar;
18
19
20
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.commons.vfs.FileName;
25 import org.apache.commons.vfs.FileObject;
26 import org.apache.commons.vfs.FileSystem;
27 import org.apache.commons.vfs.FileSystemException;
28 import org.apache.commons.vfs.FileSystemOptions;
29 import org.apache.commons.vfs.Selectors;
30 import org.apache.commons.vfs.VfsLog;
31 import org.apache.commons.vfs.provider.AbstractFileSystem;
32 import org.apache.commons.vfs.provider.UriParser;
33 import org.apache.commons.vfs.provider.bzip2.Bzip2FileObject;
34
35 import java.io.File;
36 import java.io.FileInputStream;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.util.ArrayList;
40 import java.util.Collection;
41 import java.util.List;
42 import java.util.zip.GZIPInputStream;
43
44 /***
45 * A read-only file system for Tar files.
46 *
47 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
48 * @version $Revision: 484648 $ $Date: 2006-12-08 17:18:36 +0100 (Fr, 08 Dez 2006) $
49 */
50 public class TarFileSystem
51 extends AbstractFileSystem
52 implements FileSystem
53 {
54 private final static Log log = LogFactory.getLog(TarFileSystem.class);
55
56 private final File file;
57 private TarInputStream tarFile;
58
59 protected TarFileSystem(final FileName rootName,
60 final FileObject parentLayer,
61 final FileSystemOptions fileSystemOptions)
62 throws FileSystemException
63 {
64 super(rootName, parentLayer, fileSystemOptions);
65
66
67 file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF);
68
69
70 if (!file.exists())
71 {
72
73 tarFile = null;
74 return;
75 }
76
77
78 }
79
80 public void init() throws FileSystemException
81 {
82 super.init();
83
84
85 try
86 {
87 List strongRef = new ArrayList(100);
88 TarEntry entry;
89 while ((entry = getTarFile().getNextEntry()) != null)
90 {
91 FileName name = getFileSystemManager().resolveName(getRootName(), UriParser.encode(entry.getName()));
92
93
94 TarFileObject fileObj;
95 if (entry.isDirectory() && getFileFromCache(name) != null)
96 {
97 fileObj = (TarFileObject) getFileFromCache(name);
98 fileObj.setTarEntry(entry);
99 continue;
100 }
101
102 fileObj = createTarFileObject(name, entry);
103 putFileToCache(fileObj);
104 strongRef.add(fileObj);
105 fileObj.holdObject(strongRef);
106
107
108
109 TarFileObject parent = null;
110 for (FileName parentName = name.getParent();
111 parentName != null;
112 fileObj = parent, parentName = parentName.getParent())
113 {
114
115 parent = (TarFileObject) getFileFromCache(parentName);
116 if (parent == null)
117 {
118 parent = createTarFileObject(parentName, null);
119 putFileToCache(parent);
120 strongRef.add(parent);
121 parent.holdObject(strongRef);
122 }
123
124
125 parent.attachChild(fileObj.getName());
126 }
127 }
128 }
129 catch (IOException e)
130 {
131 throw new FileSystemException(e);
132 }
133 finally
134 {
135 closeCommunicationLink();
136 }
137 }
138
139 public InputStream getInputStream(TarEntry entry) throws FileSystemException
140 {
141 resetTarFile();
142 try
143 {
144 while (!tarFile.getNextEntry().equals(entry))
145 {
146 }
147 return tarFile;
148 }
149 catch (IOException e)
150 {
151 throw new FileSystemException(e);
152 }
153 }
154
155 protected void resetTarFile() throws FileSystemException
156 {
157
158
159
160 if (this.file.exists())
161 {
162 recreateTarFile();
163 }
164 }
165
166 private void recreateTarFile() throws FileSystemException
167 {
168 if (this.tarFile != null)
169 {
170 try
171 {
172 this.tarFile.close();
173 }
174 catch (IOException e)
175 {
176 throw new FileSystemException("vfs.provider.tar/close-tar-file.error", file, e);
177 }
178 tarFile = null;
179 }
180 TarInputStream tarFile = createTarFile(this.file);
181 this.tarFile = tarFile;
182 }
183
184 protected TarInputStream getTarFile() throws FileSystemException
185 {
186 if (tarFile == null && this.file.exists())
187 {
188 recreateTarFile();
189 }
190
191 return tarFile;
192 }
193
194 protected TarFileObject createTarFileObject(final FileName name,
195 final TarEntry entry) throws FileSystemException
196 {
197 return new TarFileObject(name, entry, this, true);
198 }
199
200 protected TarInputStream createTarFile(final File file) throws FileSystemException
201 {
202 try
203 {
204 if ("tgz".equalsIgnoreCase(getRootName().getScheme()))
205 {
206 return new TarInputStream(new GZIPInputStream(new FileInputStream(file)));
207 }
208 else if ("tbz2".equalsIgnoreCase(getRootName().getScheme()))
209 {
210 return new TarInputStream(Bzip2FileObject.wrapInputStream(file.getAbsolutePath(), new FileInputStream(file)));
211 }
212 return new TarInputStream(new FileInputStream(file));
213 }
214 catch (IOException ioe)
215 {
216 throw new FileSystemException("vfs.provider.tar/open-tar-file.error", file, ioe);
217 }
218 }
219
220 protected void doCloseCommunicationLink()
221 {
222
223 try
224 {
225 if (tarFile != null)
226 {
227 tarFile.close();
228 tarFile = null;
229 }
230 }
231 catch (final IOException e)
232 {
233
234 VfsLog.warn(getLogger(), log, "vfs.provider.tar/close-tar-file.error :" + file, e);
235 }
236 }
237
238 /***
239 * Returns the capabilities of this file system.
240 */
241 protected void addCapabilities(final Collection caps)
242 {
243 caps.addAll(TarFileProvider.capabilities);
244 }
245
246 /***
247 * Creates a file object.
248 */
249 protected FileObject createFile(final FileName name) throws FileSystemException
250 {
251
252 return new TarFileObject(name, null, this, false);
253 }
254
255 /***
256 * will be called after all file-objects closed their streams.
257 protected void notifyAllStreamsClosed()
258 {
259 closeCommunicationLink();
260 }
261 */
262 }