Skip to content

Commit 76339db

Browse files
committed
Refactored dependency scanner
1 parent 5317e71 commit 76339db

File tree

3 files changed

+127
-97
lines changed

3 files changed

+127
-97
lines changed

src/main/java/com/falsepattern/lib/internal/asm/CoreLoadingPlugin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ public class CoreLoadingPlugin implements IFMLLoadingPlugin {
5757
}
5858
//Scan for dependencies now
5959
Share.LOG.info("Scanning for deps...");
60+
long start = System.nanoTime();
6061
DependencyLoaderImpl.scanDeps();
62+
long end = System.nanoTime();
63+
Share.LOG.info("Scanned in " + (end - start) / 1000000 + "ms");
6164
//Initializing the rest
6265
Share.LOG.info("Initializing mapping manager...");
6366
MappingManager.initialize();

src/main/java/com/falsepattern/lib/internal/impl/dependencies/DependencyLoaderImpl.java

Lines changed: 116 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,17 @@
4545

4646
import java.io.BufferedInputStream;
4747
import java.io.BufferedOutputStream;
48-
import java.io.File;
4948
import java.io.IOException;
5049
import java.io.InputStream;
5150
import java.io.InputStreamReader;
5251
import java.net.MalformedURLException;
5352
import java.net.URL;
5453
import java.nio.file.Files;
54+
import java.nio.file.Path;
5555
import java.nio.file.Paths;
5656
import java.nio.file.StandardCopyOption;
5757
import java.security.MessageDigest;
5858
import java.util.ArrayList;
59-
import java.util.Arrays;
6059
import java.util.HashMap;
6160
import java.util.HashSet;
6261
import java.util.List;
@@ -94,54 +93,71 @@ public class DependencyLoaderImpl {
9493
thread.setName("Dependency Download Thread " + counter.incrementAndGet());
9594
return thread;
9695
});
97-
private static final File libDir;
96+
private static final Path libDir;
97+
private static final Path tempDir;
9898

99-
static {
100-
101-
var homeDir = System.getProperty("minecraft.sharedDataDir");
102-
if (homeDir == null) {
103-
homeDir = System.getenv("MINECRAFT_SHARED_DATA_DIR");
104-
if (homeDir == null) {
105-
homeDir = FileUtil.getMinecraftHome().getAbsolutePath();
99+
private static void ensureExists(Path directory) {
100+
if (!Files.exists(directory)) {
101+
try {
102+
Files.createDirectories(directory);
103+
} catch (IOException e) {
104+
LOG.fatal("Failed to create directory {}", directory);
105+
throw new RuntimeException("Failed to create directory " + directory, e);
106106
}
107107
}
108-
val modsDir = Paths.get(homeDir, "mods").toFile();
109-
val oldLibDir = new File(modsDir, "falsepattern");
110-
libDir = new File(homeDir, "falsepattern");
111-
if (!libDir.exists()) {
112-
if (!libDir.mkdirs()) {
113-
LOG.fatal("Failed to create directory {}", libDir);
114-
throw new RuntimeException("Failed to create directory " + libDir);
115-
}
108+
}
109+
110+
static {
111+
Path homeDir;
112+
String homeDirStr = System.getProperty("minecraft.sharedDataDir");
113+
if (homeDirStr == null) {
114+
homeDirStr = System.getenv("MINECRAFT_SHARED_DATA_DIR");
115+
}
116+
if (homeDirStr == null) {
117+
homeDir = FileUtil.getMinecraftHome().toPath();
118+
} else {
119+
homeDir = Paths.get(homeDirStr);
116120
}
117-
if (oldLibDir.exists()) {
121+
libDir = homeDir.resolve("falsepattern");
122+
tempDir = homeDir.resolve(Paths.get("logs", "falsepattern_tmp"));
123+
ensureExists(libDir);
124+
ensureExists(tempDir);
125+
val oldLibDir = homeDir.resolve(Paths.get("mods", "falsepattern"));
126+
if (Files.exists(oldLibDir)) {
118127
LOG.info("Migrating old library folder. From: "
119-
+ oldLibDir.getAbsolutePath()
128+
+ oldLibDir.toAbsolutePath()
120129
+ ", To: "
121-
+ libDir.getAbsolutePath());
122-
val oldFiles = oldLibDir.listFiles();
123-
if (oldFiles != null) {
124-
for (val file : oldFiles) {
130+
+ libDir.toAbsolutePath());
131+
try (val oldFiles = Files.list(oldLibDir)) {
132+
oldFiles.forEach(file -> {
125133
try {
126-
Files.move(file.toPath(),
127-
libDir.toPath().resolve(oldLibDir.toPath().relativize(file.toPath())),
134+
Files.move(file,
135+
libDir.resolve(oldLibDir.relativize(file)),
128136
StandardCopyOption.REPLACE_EXISTING);
129137
} catch (IOException e) {
130-
LOG.warn("Failed to move file " + file.getName() + " to new dir! Deleting instead.");
138+
LOG.warn("Failed to move file " + file.getFileName() + " to new dir! Deleting instead.");
131139
try {
132-
Files.deleteIfExists(file.toPath());
140+
Files.deleteIfExists(file);
133141
} catch (IOException ex) {
134-
LOG.warn("Failed to delete file " + file.getPath() + "!");
135-
file.deleteOnExit();
142+
LOG.warn("Failed to delete file " + file + "!", ex);
136143
}
137144
}
138-
}
145+
});
146+
} catch (IOException e) {
147+
LOG.warn("Failed to iterate old library directory!", e);
148+
}
149+
try {
150+
Files.deleteIfExists(oldLibDir);
151+
} catch (IOException e) {
152+
LOG.warn("Failed to delete old library directory!", e);
139153
}
154+
}
155+
var oldCacheFile = libDir.resolve(".depscan_cache");
156+
if (Files.exists(oldCacheFile)) {
140157
try {
141-
Files.deleteIfExists(oldLibDir.toPath());
158+
Files.delete(oldCacheFile);
142159
} catch (IOException e) {
143-
LOG.warn("Failed to delete old library directory!");
144-
oldLibDir.deleteOnExit();
160+
LOG.warn("Failed to delete old depscan cache file!", e);
145161
}
146162
}
147163
}
@@ -168,8 +184,8 @@ private static String digest(String algo, byte[] data) {
168184
}
169185

170186
@SneakyThrows
171-
private static String hash(String algo, File file) {
172-
byte[] data = Files.readAllBytes(file.toPath());
187+
private static String hash(String algo, Path file) {
188+
byte[] data = Files.readAllBytes(file);
173189
switch (algo) {
174190
case "md5":
175191
algo = "MD5";
@@ -187,29 +203,31 @@ private static String hash(String algo, File file) {
187203
return digest(algo, data);
188204
}
189205

190-
private static void checkedDelete(File file) {
191-
if (!file.delete()) {
206+
private static void checkedDelete(Path file) {
207+
try {
208+
Files.delete(file);
209+
} catch (IOException e) {
192210
LOG.fatal("Failed to delete file {}", file);
193-
throw new RuntimeException("Failed to delete file " + file);
211+
throw new RuntimeException("Failed to delete file " + file, e);
194212
}
195213
}
196214

197-
private static synchronized void addToClasspath(File file) {
215+
private static synchronized void addToClasspath(Path file) {
198216
try {
199217
val cl = (LaunchClassLoader) DependencyLoaderImpl.class.getClassLoader();
200-
cl.addURL(file.toURI().toURL());
201-
LOG.debug("Injected file {} into classpath!", file.getPath());
218+
cl.addURL(file.toUri().toURL());
219+
LOG.debug("Injected file {} into classpath!", file);
202220
} catch (Exception e) {
203-
throw new RuntimeException("Failed to add library to classpath: " + file.getAbsolutePath(), e);
221+
throw new RuntimeException("Failed to add library to classpath: " + file.toAbsolutePath(), e);
204222
}
205223
}
206224

207225
@SneakyThrows
208-
private static void download(InputStream is, File target) {
209-
if (target.exists()) {
226+
private static void download(InputStream is, Path target) {
227+
if (Files.exists(target)) {
210228
return;
211229
}
212-
Internet.transferAndClose(is, new BufferedOutputStream(Files.newOutputStream(target.toPath())));
230+
Internet.transferAndClose(is, new BufferedOutputStream(Files.newOutputStream(target)));
213231
}
214232

215233
public static void loadLibraries(Library... libraries) {
@@ -258,53 +276,55 @@ private static boolean scanForDepSpecs(URL source, List<URL> output) {
258276
LOG.error("Failed to open jar file {}", source.getPath());
259277
}
260278
} else {
261-
val dir = new File(fileName);
262-
if (!dir.exists() || !dir.isDirectory()) {
279+
val dir = Paths.get(fileName);
280+
if (!Files.exists(dir) || !Files.isDirectory(dir)) {
263281
LOG.warn("Skipping non-directory, nor jar source: {}", source);
264282
return false;
265283
}
266284
//Scan directory for json in META-INF, add them to the list
267-
val metaInf = new File(dir, "META-INF");
268-
if (!metaInf.exists() || !metaInf.isDirectory()) {
269-
return false;
270-
}
271-
val files = metaInf.listFiles();
272-
if (files == null) {
285+
val metaInf = dir.resolve("META-INF");
286+
if (!Files.exists(metaInf) || !Files.isDirectory(metaInf)) {
273287
return false;
274288
}
275-
for (val file : files) {
276-
if (!file.getName().endsWith(".json")) {
277-
continue;
278-
}
279-
try {
280-
output.add(file.toURI().toURL());
281-
found = true;
282-
} catch (MalformedURLException e) {
283-
LOG.error("Failed to add json source {} to dependency source list: {}", file.getName(), e);
284-
}
289+
try (val files = Files.list(metaInf)) {
290+
found = files.reduce(false, (prev,file) -> {
291+
if (!file.endsWith(".json")) {
292+
return prev;
293+
}
294+
try {
295+
output.add(file.toUri().toURL());
296+
return true;
297+
} catch (MalformedURLException e) {
298+
LOG.error("Failed to add json source {} to dependency source list: {}", file.getFileName(), e);
299+
}
300+
return prev;
301+
}, (a,b) -> a || b);
302+
} catch (IOException e) {
303+
LOG.error("Failed to open directory {}", metaInf);
285304
}
286305
}
287306
return found;
288307
}
289308

290-
private static Stream<URL> grabSourceCandidatesFromFolder(File folder) {
291-
if (!folder.exists() || !folder.isDirectory()) {
292-
LOG.warn("File does not exist or is not a directory: {}", folder);
293-
} else {
294-
val files = folder.listFiles();
295-
if (files == null) {
296-
LOG.warn("Folder is not readable: {}", folder);
297-
} else {
298-
return Arrays.stream(files).map(file -> {
299-
try {
300-
return file.toURI().toURL();
301-
} catch (MalformedURLException e) {
302-
return null;
303-
}
304-
}).filter(Objects::nonNull);
305-
}
309+
private static Stream<URL> grabSourceCandidatesFromFolder(Path folder) {
310+
if (!Files.exists(folder) || !Files.isDirectory(folder)) {
311+
return Stream.empty();
312+
}
313+
Stream<Path> paths;
314+
try (val files = Files.list(folder)) {
315+
//Lazy loading is bad here
316+
paths = files.collect(Collectors.toSet()).stream();
317+
} catch (IOException ignored) {
318+
return Stream.empty();
306319
}
307-
return Stream.empty();
320+
321+
return paths.map(file -> {
322+
try {
323+
return file.toUri().toURL();
324+
} catch (MalformedURLException e) {
325+
return null;
326+
}
327+
}).filter(Objects::nonNull);
308328
}
309329

310330
private static <A, B, C> Stream<Pair<A, B>> flatMap(Pair<A, C> pair, Function<C, Stream<B>> mapper) {
@@ -320,14 +340,14 @@ private static <A, B, C> Stream<Pair<A, B>> flatMap(Pair<A, C> pair, Function<C,
320340

321341
public static void scanDeps() {
322342
LOG.debug("Discovering dependency source candidates...");
323-
val modsDir = new File(FileUtil.getMinecraftHome(), "mods");
324-
val mods1710Dir = new File(modsDir, "1.7.10");
343+
val modsDir = FileUtil.getMinecraftHomePath().resolve("mods");
344+
val mods1710Dir = modsDir.resolve("1.7.10");
325345
long start = System.currentTimeMillis();
326346
val urlsWithoutDeps = new HashSet<String>();
327-
val depCache = new File(libDir, ".depscan_cache");
328-
if (depCache.exists()) {
347+
val depCache = tempDir.resolve(".depscan_cache");
348+
if (Files.exists(depCache)) {
329349
try {
330-
urlsWithoutDeps.addAll(Files.readAllLines(depCache.toPath()));
350+
urlsWithoutDeps.addAll(Files.readAllLines(depCache));
331351
} catch (IOException e) {
332352
LOG.error("Could not read dependency scanner cache", e);
333353
}
@@ -344,7 +364,7 @@ public static void scanDeps() {
344364
urlsWithoutDeps.add(candidate.toString());
345365
}
346366
}
347-
try (val out = Files.newBufferedWriter(depCache.toPath())) {
367+
try (val out = Files.newBufferedWriter(depCache)) {
348368
for (val noDep : urlsWithoutDeps) {
349369
out.append(noDep).append(System.lineSeparator());
350370
}
@@ -500,7 +520,7 @@ private static class DependencyLoadTask {
500520
private String artifact;
501521
private String mavenJarName;
502522
private String jarName;
503-
private File file;
523+
private Path file;
504524

505525
private void load() {
506526
try {
@@ -586,11 +606,11 @@ private void setupPaths() {
586606
mavenJarName =
587607
String.format("%s-%s%s.jar", artifactId, preferredVersion, (suffix != null) ? ("-" + suffix) : "");
588608
jarName = groupId + "-" + mavenJarName;
589-
file = new File(libDir, jarName);
609+
file = libDir.resolve(jarName);
590610
}
591611

592612
private boolean tryLoadingExistingFile() {
593-
if (!file.exists()) {
613+
if (!Files.exists(file)) {
594614
return false;
595615
}
596616
try {
@@ -694,7 +714,7 @@ private boolean tryDownloadFromMaven(String repo) {
694714
private ChecksumStatus validateChecksum(String url) throws IOException {
695715
for (val checksumType : CHECKSUM_TYPES) {
696716
val checksumURL = url + "." + checksumType;
697-
val checksumFile = new File(libDir, jarName + "." + checksumType);
717+
val checksumFile = libDir.resolve(jarName + "." + checksumType);
698718
LOG.debug("Attempting to get {} checksum...", checksumType);
699719
val success = new AtomicBoolean(false);
700720
Internet.connect(new URL(checksumURL),
@@ -715,20 +735,20 @@ private ChecksumStatus validateChecksum(String url) throws IOException {
715735
return ChecksumStatus.MISSING;
716736
}
717737

718-
private ChecksumStatus validateChecksum(File file) throws IOException {
738+
private ChecksumStatus validateChecksum(Path file) throws IOException {
719739
for (val checksumType : CHECKSUM_TYPES) {
720-
val checksumFile = new File(libDir, jarName + "." + checksumType);
740+
val checksumFile = libDir.resolve(jarName + "." + checksumType);
721741
LOG.debug("Attempting to read {} checksum from file...", checksumType);
722-
if (checksumFile.exists()) {
742+
if (Files.exists(checksumFile)) {
723743
return getChecksumStatus(file, checksumType, checksumFile);
724744
}
725745
}
726746
return ChecksumStatus.MISSING;
727747
}
728748

729-
private ChecksumStatus getChecksumStatus(File file, String checksumType, File checksumFile) throws IOException {
749+
private ChecksumStatus getChecksumStatus(Path file, String checksumType, Path checksumFile) throws IOException {
730750
val fileHash = hash(checksumType, file);
731-
val referenceHash = new String(Files.readAllBytes(checksumFile.toPath()));
751+
val referenceHash = new String(Files.readAllBytes(checksumFile));
732752
if (!fileHash.equals(referenceHash)) {
733753
LOG.error("Failed {} checksum validation for {}.", checksumType, artifactLogName);
734754
checkedDelete(file);

src/main/java/com/falsepattern/lib/util/FileUtil.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,19 @@
2626
import net.minecraft.launchwrapper.Launch;
2727

2828
import java.io.File;
29+
import java.nio.file.Path;
30+
import java.nio.file.Paths;
2931

3032
@UtilityClass
3133
@StableAPI(since = "0.8.2")
3234
public final class FileUtil {
3335
@StableAPI.Expose
3436
public static File getMinecraftHome() {
35-
return Launch.minecraftHome == null ? new File(".") : Launch.minecraftHome;
37+
return getMinecraftHomePath().toFile();
38+
}
39+
40+
@StableAPI.Expose(since = "1.0.0")
41+
public static Path getMinecraftHomePath() {
42+
return Launch.minecraftHome == null ? Paths.get("").toAbsolutePath() : Launch.minecraftHome.toPath();
3643
}
3744
}

0 commit comments

Comments
 (0)