4545
4646import java .io .BufferedInputStream ;
4747import java .io .BufferedOutputStream ;
48- import java .io .File ;
4948import java .io .IOException ;
5049import java .io .InputStream ;
5150import java .io .InputStreamReader ;
5251import java .net .MalformedURLException ;
5352import java .net .URL ;
5453import java .nio .file .Files ;
54+ import java .nio .file .Path ;
5555import java .nio .file .Paths ;
5656import java .nio .file .StandardCopyOption ;
5757import java .security .MessageDigest ;
5858import java .util .ArrayList ;
59- import java .util .Arrays ;
6059import java .util .HashMap ;
6160import java .util .HashSet ;
6261import 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 );
0 commit comments