1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codehaus.plexus.archiver.zip;
17
18 import java.io.Closeable;
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.net.URLClassLoader;
24 import java.nio.charset.Charset;
25 import java.nio.charset.StandardCharsets;
26 import java.util.Enumeration;
27 import java.util.Iterator;
28 import java.util.jar.JarFile;
29
30 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
31 import org.apache.commons.compress.archivers.zip.ZipFile;
32 import org.codehaus.plexus.components.io.functions.SymlinkDestinationSupplier;
33 import org.codehaus.plexus.components.io.resources.AbstractPlexusIoArchiveResourceCollection;
34 import org.codehaus.plexus.components.io.resources.EncodingSupported;
35 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
36 import org.codehaus.plexus.components.io.resources.PlexusIoURLResource;
37
38
39
40 public class PlexusIoZipFileResourceCollection extends AbstractPlexusIoArchiveResourceCollection
41 implements EncodingSupported {
42
43 private Charset charset = StandardCharsets.UTF_8;
44
45 public PlexusIoZipFileResourceCollection() {}
46
47 @Override
48 public boolean isConcurrentAccessSupported() {
49
50 return false;
51 }
52
53 @Override
54 protected Iterator<PlexusIoResource> getEntries() throws IOException {
55 final File f = getFile();
56 if (f == null) {
57 throw new IOException("The zip file has not been set.");
58 }
59 final URLClassLoader urlClassLoader =
60 new URLClassLoader(new URL[] {f.toURI().toURL()}, null) {
61
62 @Override
63 public URL getResource(String name) {
64 return findResource(name);
65 }
66 };
67
68 final URL url = new URL("jar:" + f.toURI().toURL() + "!/");
69 final JarFile jarFile = new JarFile(f);
70 final ZipFile zipFile = new ZipFile(f, charset != null ? charset.name() : "UTF8");
71 final Enumeration<ZipArchiveEntry> en = zipFile.getEntriesInPhysicalOrder();
72 return new ZipFileResourceIterator(en, url, jarFile, zipFile, urlClassLoader);
73 }
74
75 private static class ZipFileResourceIterator implements Iterator<PlexusIoResource>, Closeable {
76
77 private class ZipFileResource extends PlexusIoURLResource {
78 private final JarFile jarFile;
79
80 private ZipFileResource(JarFile jarFile, ZipArchiveEntry entry) {
81 super(
82 entry.getName(),
83 entry.getTime() == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : entry.getTime(),
84 entry.isDirectory() ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize(),
85 !entry.isDirectory(),
86 entry.isDirectory(),
87 true);
88
89 this.jarFile = jarFile;
90 }
91
92 @Override
93 public InputStream getContents() throws IOException {
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 return jarFile.getInputStream(jarFile.getEntry(getName()));
109 }
110
111 @Override
112 public URL getURL() throws IOException {
113 String spec = getName();
114 if (spec.startsWith("/")) {
115
116
117
118 spec = "./" + spec;
119 return new URL(url, spec);
120 }
121 return urlClassLoader.getResource(spec);
122 }
123 }
124
125 private class ZipFileSymlinkResource extends ZipFileResource implements SymlinkDestinationSupplier {
126
127 private final ZipArchiveEntry entry;
128
129 private ZipFileSymlinkResource(JarFile jarFile, ZipArchiveEntry entry) {
130 super(jarFile, entry);
131
132 this.entry = entry;
133 }
134
135 @Override
136 public String getSymlinkDestination() throws IOException {
137 return zipFile.getUnixSymlink(entry);
138 }
139
140 @Override
141 public boolean isSymbolicLink() {
142 return true;
143 }
144 }
145
146 private final Enumeration<ZipArchiveEntry> en;
147
148 private final URL url;
149
150 private final JarFile jarFile;
151
152 private final ZipFile zipFile;
153
154 private final URLClassLoader urlClassLoader;
155
156 public ZipFileResourceIterator(
157 Enumeration<ZipArchiveEntry> en,
158 URL url,
159 JarFile jarFile,
160 ZipFile zipFile,
161 URLClassLoader urlClassLoader) {
162 this.en = en;
163 this.url = url;
164 this.jarFile = jarFile;
165 this.zipFile = zipFile;
166 this.urlClassLoader = urlClassLoader;
167 }
168
169 @Override
170 public boolean hasNext() {
171 return en.hasMoreElements();
172 }
173
174 @Override
175 public PlexusIoResource next() {
176 final ZipArchiveEntry entry = en.nextElement();
177 return entry.isUnixSymlink()
178 ? new ZipFileSymlinkResource(jarFile, entry)
179 : new ZipFileResource(jarFile, entry);
180 }
181
182 @Override
183 public void remove() {
184 throw new UnsupportedOperationException("Removing isn't implemented.");
185 }
186
187 @Override
188 public void close() throws IOException {
189 try {
190 urlClassLoader.close();
191 } finally {
192 try {
193 zipFile.close();
194 } finally {
195 jarFile.close();
196 }
197 }
198 }
199 }
200
201 @Override
202 public void setEncoding(Charset charset) {
203 this.charset = charset;
204 }
205 }