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