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
41
42
43
44 public class PlexusIoJarFileResourceCollectionWithSignatureVerification
45 extends AbstractPlexusIoArchiveResourceCollection implements EncodingSupported {
46
47 private Charset charset = StandardCharsets.UTF_8;
48
49 public PlexusIoJarFileResourceCollectionWithSignatureVerification() {}
50
51 @Override
52 public boolean isConcurrentAccessSupported() {
53
54 return false;
55 }
56
57 @Override
58 protected Iterator<PlexusIoResource> getEntries() throws IOException {
59 final File f = getFile();
60 if (f == null) {
61 throw new IOException("The zip file has not been set.");
62 }
63 final URLClassLoader urlClassLoader =
64 new URLClassLoader(new URL[] {f.toURI().toURL()}, null) {
65
66 @Override
67 public URL getResource(String name) {
68 return findResource(name);
69 }
70 };
71
72 final URL url = new URL("jar:" + f.toURI().toURL() + "!/");
73 final JarFile jarFile = new JarFile(f);
74 final ZipFile zipFile = ZipFile.builder()
75 .setFile(f)
76 .setCharset(charset != null ? charset : StandardCharsets.UTF_8)
77 .get();
78 final Enumeration<ZipArchiveEntry> en = zipFile.getEntriesInPhysicalOrder();
79 return new ZipFileResourceIterator(en, url, jarFile, zipFile, urlClassLoader);
80 }
81
82 private static class ZipFileResourceIterator implements Iterator<PlexusIoResource>, Closeable {
83
84 private class ZipFileResource extends PlexusIoURLResource {
85 private final JarFile jarFile;
86
87 private ZipFileResource(JarFile jarFile, ZipArchiveEntry entry) {
88 super(
89 entry.getName(),
90 entry.getTime() == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : entry.getTime(),
91 entry.isDirectory() ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize(),
92 !entry.isDirectory(),
93 entry.isDirectory(),
94 true);
95
96 this.jarFile = jarFile;
97 }
98
99 @Override
100 public InputStream getContents() throws IOException {
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 return jarFile.getInputStream(jarFile.getEntry(getName()));
116 }
117
118 @Override
119 public URL getURL() throws IOException {
120 String spec = getName();
121 if (spec.startsWith("/")) {
122
123
124
125 spec = "./" + spec;
126 return new URL(url, spec);
127 }
128 return urlClassLoader.getResource(spec);
129 }
130 }
131
132 private class ZipFileSymlinkResource extends ZipFileResource implements SymlinkDestinationSupplier {
133
134 private final ZipArchiveEntry entry;
135
136 private ZipFileSymlinkResource(JarFile jarFile, ZipArchiveEntry entry) {
137 super(jarFile, entry);
138
139 this.entry = entry;
140 }
141
142 @Override
143 public String getSymlinkDestination() throws IOException {
144 return zipFile.getUnixSymlink(entry);
145 }
146
147 @Override
148 public boolean isSymbolicLink() {
149 return true;
150 }
151 }
152
153 private final Enumeration<ZipArchiveEntry> en;
154
155 private final URL url;
156
157 private final JarFile jarFile;
158
159 private final ZipFile zipFile;
160
161 private final URLClassLoader urlClassLoader;
162
163 public ZipFileResourceIterator(
164 Enumeration<ZipArchiveEntry> en,
165 URL url,
166 JarFile jarFile,
167 ZipFile zipFile,
168 URLClassLoader urlClassLoader) {
169 this.en = en;
170 this.url = url;
171 this.jarFile = jarFile;
172 this.zipFile = zipFile;
173 this.urlClassLoader = urlClassLoader;
174 }
175
176 @Override
177 public boolean hasNext() {
178 return en.hasMoreElements();
179 }
180
181 @Override
182 public PlexusIoResource next() {
183 final ZipArchiveEntry entry = en.nextElement();
184 return entry.isUnixSymlink()
185 ? new ZipFileSymlinkResource(jarFile, entry)
186 : new ZipFileResource(jarFile, entry);
187 }
188
189 @Override
190 public void remove() {
191 throw new UnsupportedOperationException("Removing isn't implemented.");
192 }
193
194 @Override
195 public void close() throws IOException {
196 try {
197 urlClassLoader.close();
198 } finally {
199 try {
200 zipFile.close();
201 } finally {
202 jarFile.close();
203 }
204 }
205 }
206 }
207
208 @Override
209 public void setEncoding(Charset charset) {
210 this.charset = charset;
211 }
212 }