Skip to content

Commit e1d0e6c

Browse files
authored
Merge pull request #150 from scalecube/feature/classpath-scan-manifest
Added reading from MANIFEST for ClassPathConfigSource
2 parents f11fdc7 + c07bd54 commit e1d0e6c

File tree

1 file changed

+87
-31
lines changed

1 file changed

+87
-31
lines changed

config/src/main/java/io/scalecube/config/source/ClassPathConfigSource.java

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Collection;
1818
import java.util.Collections;
1919
import java.util.Enumeration;
20+
import java.util.HashSet;
2021
import java.util.LinkedHashSet;
2122
import java.util.List;
2223
import java.util.Map;
@@ -25,13 +26,17 @@
2526
import java.util.StringJoiner;
2627
import java.util.TreeMap;
2728
import java.util.function.Predicate;
29+
import java.util.jar.Attributes;
2830
import java.util.jar.JarEntry;
2931
import java.util.jar.JarFile;
32+
import java.util.jar.Manifest;
3033
import java.util.stream.Collectors;
3134

3235
public final class ClassPathConfigSource extends FilteredPathConfigSource {
36+
3337
private static final String CLASSPATH = System.getProperty("java.class.path");
3438
private static final String PATH_SEPARATOR = System.getProperty("path.separator");
39+
private static final String CLASSPATH_ATTIBUTE_MANIFEST_SEPARATOR = " ";
3540

3641
private Map<String, ConfigProperty> loadedConfig;
3742

@@ -79,16 +84,19 @@ public Map<String, ConfigProperty> loadConfig() {
7984
.forEach(
8085
uri -> {
8186
File file = new File(uri);
82-
if (file.exists()) {
83-
try {
84-
if (file.isDirectory()) {
85-
scanDirectory(file, "", Collections.emptySet(), pathCollection);
86-
} else {
87-
scanJar(file, pathCollection);
88-
}
89-
} catch (Exception e) {
90-
throw ThrowableUtil.propagate(e);
87+
if (!file.exists()) {
88+
return;
89+
}
90+
try {
91+
if (file.isDirectory()) {
92+
Set<File> currentPath =
93+
new HashSet<>(Collections.singleton(file.getCanonicalFile()));
94+
scanDirectory(file, "", currentPath, pathCollection);
95+
} else {
96+
scanJar(file, pathCollection);
9197
}
98+
} catch (Exception e) {
99+
throw ThrowableUtil.propagate(e);
92100
}
93101
});
94102

@@ -150,7 +158,7 @@ private static Collection<URL> parseJavaClassPath() {
150158
try {
151159
urls.add(new File(entry).toURI().toURL());
152160
} catch (SecurityException e) {
153-
urls.add(new URL("file", null, new File(entry).getAbsolutePath()));
161+
throw ThrowableUtil.propagate(e);
154162
}
155163
} catch (MalformedURLException ex) {
156164
throw ThrowableUtil.propagate(ex);
@@ -160,48 +168,96 @@ private static Collection<URL> parseJavaClassPath() {
160168
}
161169

162170
private static void scanDirectory(
163-
File directory, String prefix, Set<File> ancestors, Collection<Path> collector)
171+
File directory, String prefix, Set<File> currentPath, Collection<Path> collector)
164172
throws IOException {
165-
File canonical = directory.getCanonicalFile();
166-
if (ancestors.contains(canonical)) {
167-
return;
168-
}
173+
169174
File[] files = directory.listFiles();
170175
if (files == null) {
171176
return;
172177
}
173-
Set<File> objects = new LinkedHashSet<>(ancestors);
174-
objects.add(canonical);
175-
Set<File> newAncestors = Collections.unmodifiableSet(objects);
178+
176179
for (File f : files) {
177180
String name = f.getName();
178181
if (f.isDirectory()) {
179-
scanDirectory(f, prefix + name + "/", newAncestors, collector);
182+
File deref = f.getCanonicalFile();
183+
if (currentPath.add(deref)) {
184+
scanDirectory(deref, prefix + name + "/", currentPath, collector);
185+
currentPath.remove(deref);
186+
}
180187
} else {
181-
collector.add(f.toPath());
188+
String resourceName = prefix + name;
189+
if (!resourceName.equals(JarFile.MANIFEST_NAME)) {
190+
collector.add(f.toPath());
191+
}
182192
}
183193
}
184194
}
185195

186196
private static void scanJar(File file, Collection<Path> collector) throws IOException {
187-
JarFile jarFile;
188-
try {
189-
jarFile = new JarFile(file);
190-
} catch (IOException ignore) {
191-
return;
197+
try (JarFile jarFile = new JarFile(file)) {
198+
for (File path : getClassPathFromManifest(file, jarFile.getManifest())) {
199+
if (collector.add(path.getCanonicalFile().toPath())) {
200+
scanFrom(path, collector);
201+
}
202+
}
203+
scanJarFile(jarFile, file.toPath(), collector);
192204
}
193-
try (FileSystem zipfs = FileSystems.newFileSystem(file.toPath(), null)) {
194-
Enumeration<JarEntry> entries = jarFile.entries();
205+
}
206+
207+
private static void scanJarFile(JarFile file, Path path, Collection<Path> collector)
208+
throws IOException {
209+
try (FileSystem zipfs = FileSystems.newFileSystem(path, null)) {
210+
Enumeration<JarEntry> entries = file.entries();
195211
while (entries.hasMoreElements()) {
196212
JarEntry entry = entries.nextElement();
213+
if (entry.isDirectory() || entry.getName().equals(JarFile.MANIFEST_NAME)) {
214+
continue;
215+
}
197216
collector.add(zipfs.getPath(entry.getName()));
198217
}
199-
} finally {
218+
}
219+
}
220+
221+
private static Set<File> getClassPathFromManifest(File jarFile, Manifest manifest) {
222+
Set<File> result = new LinkedHashSet<>();
223+
224+
if (manifest == null) {
225+
return result;
226+
}
227+
228+
String classpathAttribute =
229+
manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH.toString());
230+
if (classpathAttribute == null) {
231+
return result;
232+
}
233+
234+
for (String path : classpathAttribute.split(CLASSPATH_ATTIBUTE_MANIFEST_SEPARATOR)) {
235+
URL url;
200236
try {
201-
jarFile.close();
202-
} catch (IOException ignore) {
203-
// ignore
237+
url = new URL(jarFile.toURI().toURL(), path);
238+
} catch (MalformedURLException e) {
239+
throw ThrowableUtil.propagate(e);
204240
}
241+
if (url.getProtocol().equals("file")) {
242+
result.add(toFile(url));
243+
}
244+
}
245+
return result;
246+
}
247+
248+
private static void scanFrom(File file, Collection<Path> collector) throws IOException {
249+
try {
250+
if (!file.exists()) {
251+
return;
252+
}
253+
} catch (SecurityException e) {
254+
throw ThrowableUtil.propagate(e);
255+
}
256+
if (file.isDirectory()) {
257+
Set<File> currentPath = new HashSet<>(Collections.singleton(file.getCanonicalFile()));
258+
scanDirectory(file, "", currentPath, collector);
259+
} else {
260+
scanJar(file, collector);
205261
}
206262
}
207263

0 commit comments

Comments
 (0)