Skip to content

Commit

Permalink
Feat[cc]: unified place for checking directories and parent directories
Browse files Browse the repository at this point in the history
  • Loading branch information
artdeell committed Dec 16, 2023
1 parent 1002c8a commit 8a04ffe
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.kdt.pojavlaunch.lifecycle.ContextExecutor;
import net.kdt.pojavlaunch.tasks.AsyncAssetManager;
import net.kdt.pojavlaunch.utils.*;
import net.kdt.pojavlaunch.utils.FileUtils;

public class PojavApplication extends Application {
public static final String CRASH_REPORT_TAG = "PojavCrashReport";
Expand All @@ -35,10 +36,7 @@ public void onCreate() {
File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt");
try {
// Write to file, since some devices may not able to show error
File crashHome = crashFile.getParentFile();
if(crashHome != null && !crashHome.exists() && !crashHome.mkdirs()) {
throw new IOException("Failed to create crash log home");
}
FileUtils.ensureParentDirectory(crashFile);
PrintStream crashStream = new PrintStream(crashFile);
crashStream.append("PojavLauncher crash report\n");
crashStream.append(" - Time: ").append(DateFormat.getDateTimeInstance().format(new Date())).append("\n");
Expand Down
12 changes: 4 additions & 8 deletions app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.utils.DateUtils;
import net.kdt.pojavlaunch.utils.DownloadUtils;
import net.kdt.pojavlaunch.utils.FileUtils;
import net.kdt.pojavlaunch.utils.JREUtils;
import net.kdt.pojavlaunch.utils.JSONUtils;
import net.kdt.pojavlaunch.utils.OldVersionsUtils;
Expand Down Expand Up @@ -242,7 +243,7 @@ public static void buildNotificationChannel(Context context){
}
public static void disableSplash(File dir) {
File configDir = new File(dir, "config");
if(configDir.exists() || configDir.mkdirs()) {
if(FileUtils.ensureDirectorySilently(configDir)) {
File forgeSplashFile = new File(dir, "config/splash.properties");
String forgeSplashContent = "enabled=true";
try {
Expand Down Expand Up @@ -536,9 +537,7 @@ public static void copyAssetFile(Context ctx, String fileName, String output, bo

public static void copyAssetFile(Context ctx, String fileName, String output, String outputName, boolean overwrite) throws IOException {
File parentFolder = new File(output);
if(!parentFolder.exists() && !parentFolder.mkdirs()) {
throw new IOException("Failed to create parent directory");
}
FileUtils.ensureDirectory(parentFolder);
File destinationFile = new File(output, outputName);
if(!destinationFile.exists() || overwrite){
try(InputStream inputStream = ctx.getAssets().open(fileName)) {
Expand Down Expand Up @@ -859,10 +858,7 @@ public static String read(String path) throws IOException {

public static void write(String path, String content) throws IOException {
File file = new File(path);
File parent = file.getParentFile();
if(parent != null && !parent.exists()) {
if(!parent.mkdirs()) throw new IOException("Failed to create parent directory");
}
FileUtils.ensureParentDirectory(file);
try(FileOutputStream outStream = new FileOutputStream(file)) {
IOUtils.write(content, outStream);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
import net.kdt.pojavlaunch.utils.DownloadUtils;
import net.kdt.pojavlaunch.utils.FileUtils;
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;

Expand Down Expand Up @@ -53,8 +54,7 @@ private boolean runCatching() throws IOException{
}
File versionJsonDir = new File(Tools.DIR_HOME_VERSION, versionId);
File versionJsonFile = new File(versionJsonDir, versionId+".json");
if(versionJsonDir.isFile()) throw new IOException("Version destination directory is a file!");
if(!versionJsonDir.exists() && !versionJsonDir.mkdirs()) throw new IOException("Failed to create version directory");
FileUtils.ensureDirectory(versionJsonDir);
Tools.write(versionJsonFile.getAbsolutePath(), fabricJson);
if(mCreateProfile) {
LauncherProfiles.load();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.utils.JREUtils;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
Expand Down Expand Up @@ -224,8 +223,7 @@ private static void installRuntimeNamedNoRemove(InputStream runtimeInputStream,
}

private static void uncompressTarXZ(final InputStream tarFileInputStream, final File dest) throws IOException {
if(dest.isFile()) throw new IOException("Attempting to unpack into a file");
if(!dest.exists() && !dest.mkdirs()) throw new IOException("Failed to create destination directory");
net.kdt.pojavlaunch.utils.FileUtils.ensureDirectory(dest);

byte[] buffer = new byte[8192];
TarArchiveInputStream tarIn = new TarArchiveInputStream(
Expand All @@ -240,10 +238,8 @@ private static void uncompressTarXZ(final InputStream tarFileInputStream, final
ProgressLayout.setProgress(ProgressLayout.UNPACK_RUNTIME, 100, R.string.global_unpacking, tarEntryName);

File destPath = new File(dest, tarEntry.getName());
File destParent = destPath.getParentFile();
net.kdt.pojavlaunch.utils.FileUtils.ensureParentDirectory(destPath);
if (tarEntry.isSymbolicLink()) {
if(destParent != null && !destParent.exists() && !destParent.mkdirs())
throw new IOException("Failed to create parent directory for symlink");
try {
// android.system.Os
// Libcore one support all Android versions
Expand All @@ -253,16 +249,11 @@ private static void uncompressTarXZ(final InputStream tarFileInputStream, final
}

} else if (tarEntry.isDirectory()) {
if(!destPath.exists() && !destPath.mkdirs())
throw new IOException("Failed to create directory");
net.kdt.pojavlaunch.utils.FileUtils.ensureDirectory(destPath);
} else if (!destPath.exists() || destPath.length() != tarEntry.getSize()) {
if(destParent != null && !destParent.exists() && !destParent.mkdirs())
throw new IOException("Failed to create parent directory for file");

FileOutputStream os = new FileOutputStream(destPath);
IOUtils.copyLarge(tarIn, os, buffer);
os.close();

}
tarEntry = tarIn.getNextTarEntry();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,75 +56,37 @@ public static String downloadString(String url) throws IOException {
}

public static void downloadFile(String url, File out) throws IOException {
out.getParentFile().mkdirs();
File tempOut = File.createTempFile(out.getName(), ".part", out.getParentFile());
BufferedOutputStream bos = null;
try {
OutputStream bos2 = new BufferedOutputStream(new FileOutputStream(tempOut));
try {
download(url, bos2);
tempOut.renameTo(out);
if (bos2 != null) {
bos2.close();
}
if (tempOut.exists()) {
tempOut.delete();
}
} catch (IOException th2) {
if (bos != null) {
bos.close();
}
if (tempOut.exists()) {
tempOut.delete();
}
throw th2;
}
} catch (IOException th3) {

if (bos != null) {
bos.close();
}
if (tempOut.exists()) {
tempOut.delete();
}
throw th3;
FileUtils.ensureParentDirectory(out);
try (FileOutputStream fileOutputStream = new FileOutputStream(out)) {
download(url, fileOutputStream);
}
}

public static void downloadFileMonitored(String urlInput, String nameOutput, @Nullable byte[] buffer,
public static void downloadFileMonitored(String urlInput, File outputFile, @Nullable byte[] buffer,
Tools.DownloaderFeedback monitor) throws IOException {
downloadFileMonitored(urlInput, new File(nameOutput), buffer, monitor);
}
public static void downloadFileMonitored(String urlInput,File outputFile, @Nullable byte[] buffer,
Tools.DownloaderFeedback monitor) throws IOException {
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
}
FileUtils.ensureParentDirectory(outputFile);

HttpURLConnection conn = (HttpURLConnection) new URL(urlInput).openConnection();
InputStream readStr = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(outputFile);
int cur;
int oval = 0;
int len = conn.getContentLength();
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
int current;
int overall = 0;
int length = conn.getContentLength();

if(buffer == null) buffer = new byte[65535];
if (buffer == null) buffer = new byte[65535];

while ((cur = readStr.read(buffer)) != -1) {
oval += cur;
fos.write(buffer, 0, cur);
monitor.updateProgress(oval, len);
while ((current = readStr.read(buffer)) != -1) {
overall += current;
fos.write(buffer, 0, current);
monitor.updateProgress(overall, length);
}
conn.disconnect();
}
fos.close();
conn.disconnect();

}

public static <T> T downloadStringCached(String url, String cacheName, ParseCallback<T> parseCallback) throws IOException, ParseException{
File cacheDestination = new File(Tools.DIR_CACHE, "string_cache/"+cacheName);
File cacheDestinationDir = cacheDestination.getParentFile();
if(cacheDestinationDir != null &&
!cacheDestinationDir.exists() &&
!cacheDestinationDir.mkdirs()) throw new IOException("Failed to create the cache directory");
if(cacheDestination.isFile() &&
cacheDestination.canRead() &&
System.currentTimeMillis() < (cacheDestination.lastModified() + 86400000)) {
Expand All @@ -143,14 +105,13 @@ public static <T> T downloadStringCached(String url, String cacheName, ParseCall
// string into cache
T parseResult = parseCallback.process(urlContent);

boolean tryWriteCache = false;
boolean tryWriteCache;
if(cacheDestination.exists()) {
tryWriteCache = cacheDestination.canWrite();
} else {
// if it is null, then cacheDestination is the file system root. Very bad.
// but let's shield ourselves and just never try to cache the file if that happens
if(cacheDestinationDir != null && !cacheDestinationDir.isFile()) tryWriteCache = cacheDestinationDir.canWrite();
tryWriteCache = FileUtils.ensureParentDirectorySilently(cacheDestination);
}

if(tryWriteCache) try {
Tools.write(cacheDestination.getAbsolutePath(), urlContent);
}catch(IOException e) {
Expand All @@ -159,32 +120,6 @@ public static <T> T downloadStringCached(String url, String cacheName, ParseCall
return parseResult;
}

public static void downloadFileMonitoredWithHeaders(String urlInput,File outputFile, @Nullable byte[] buffer,
Tools.DownloaderFeedback monitor, String userAgent, String cookies) throws IOException {
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
}

HttpURLConnection conn = (HttpURLConnection) new URL(urlInput).openConnection();
conn.setRequestProperty("User-Agent", userAgent);
conn.setRequestProperty("Cookies", cookies);
InputStream readStr = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(outputFile);
int cur;
int oval = 0;
int len = conn.getContentLength();

if(buffer == null) buffer = new byte[65535];

while ((cur = readStr.read(buffer)) != -1) {
oval += cur;
fos.write(buffer, 0, cur);
monitor.updateProgress(oval, len);
}
fos.close();
conn.disconnect();
}

public static <T> T ensureSha1(File outputFile, @Nullable String sha1, Callable<T> downloadFunction) throws IOException {
// Skip if needed
if(sha1 == null){
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,72 @@
package net.kdt.pojavlaunch.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class FileUtils {
/**
* Check if a file denoted by a String path exists.
* @param filePath the path to check
* @return whether it exists (same as File.exists()
*/
public static boolean exists(String filePath){
return new File(filePath).exists();
}

/**
* Get the file name from a path/URL string.
* @param pathOrUrl the path or the URL of the file
* @return the file's name
*/
public static String getFileName(String pathOrUrl) {
int lastSlashIndex = pathOrUrl.lastIndexOf('/');
if(lastSlashIndex == -1) return null;
return pathOrUrl.substring(lastSlashIndex);
}

/**
* Ensure that a directory exists, is a directory and is writable.
* @param targetFile the directory to check
* @return if the check has succeeded
*/
public static boolean ensureDirectorySilently(File targetFile) {
if(targetFile.isFile()) return false;
if(targetFile.exists()) return targetFile.canWrite();
else return targetFile.mkdirs();

}

/**
* Ensure that the parent directory of a file exists and is writable
* @param targetFile the File whose parent should be checked
* @return if the check as succeeded
*/
public static boolean ensureParentDirectorySilently(File targetFile) {
File parentFile = targetFile.getParentFile();
if(parentFile == null) return false;
return ensureDirectorySilently(parentFile);
}

/**
* Same as ensureDirectorySilently(), but throws an IOException telling why the check failed.
* @param targetFile the directory to check
* @throws IOException when the checks fail
*/
public static void ensureDirectory(File targetFile) throws IOException{
if(targetFile.isFile()) throw new IOException("Target directory is a file");
if(targetFile.exists()) {
if(!targetFile.canWrite()) throw new IOException("Target directory is not writable");
}else if(!targetFile.mkdirs()) throw new IOException("Unable to create target directory");
}

/**
* Same as ensureParentDirectorySilently(), but throws an IOException telling why the check failed.
* @param targetFile the File whose parent should be checked
* @throws IOException when the checks fail
*/
public static void ensureParentDirectory(File targetFile) throws IOException{
File parentFile = targetFile.getParentFile();
if(parentFile == null) throw new IOException("targetFile does not have a parent");
ensureDirectory(parentFile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,9 @@ public static void zipExtract(ZipFile zipFile, String dirName, File destination)
String entryName = zipEntry.getName();
if(!entryName.startsWith(dirName) || zipEntry.isDirectory()) continue;
File zipDestination = new File(destination, entryName.substring(dirNameLen));
File parent = zipDestination.getParentFile();
if(parent != null && !parent.exists())
if(!parent.mkdirs()) throw new IOException("Failed to create "+parent.getAbsolutePath());
FileUtils.ensureParentDirectory(zipDestination);
try (InputStream inputStream = zipFile.getInputStream(zipEntry);
OutputStream outputStream =
new FileOutputStream(zipDestination)) {
OutputStream outputStream = new FileOutputStream(zipDestination)) {
IOUtils.copy(inputStream, outputStream);
}
}
Expand Down

0 comments on commit 8a04ffe

Please sign in to comment.