You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FoxMagiskModuleManager/app/src/main/java/com/fox2code/mmm/repo/RepoData.java

125 lines
4.9 KiB
Java

package com.fox2code.mmm.repo;
import android.content.SharedPreferences;
import com.fox2code.mmm.manager.ModuleInfo;
import com.fox2code.mmm.utils.Files;
import com.fox2code.mmm.utils.PropUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class RepoData {
private final Object populateLock = new Object();
public final String url;
public final File cacheRoot;
public final SharedPreferences cachedPreferences;
public final File metaDataCache;
public final HashMap<String, RepoModule> moduleHashMap;
public long lastUpdate;
public String name;
RepoData(String url, File cacheRoot, SharedPreferences cachedPreferences) {
this.url = url;
this.cacheRoot = cacheRoot;
this.cachedPreferences = cachedPreferences;
this.metaDataCache = new File(cacheRoot, "modules.json");
this.moduleHashMap = new HashMap<>();
this.name = this.url; // Set url as default name
if (!this.cacheRoot.isDirectory()) {
this.cacheRoot.mkdirs();
} else if (this.metaDataCache.exists()) {
try {
List<RepoModule> modules = this.populate(new JSONObject(
new String(Files.read(this.metaDataCache), StandardCharsets.UTF_8)));
for (RepoModule repoModule: modules) {
if (!this.tryLoadMetadata(repoModule)) {
repoModule.moduleInfo.flags &=~ ModuleInfo.FLAG_METADATA_INVALID;
}
}
} catch (Exception e) {
this.metaDataCache.delete();
}
}
}
List<RepoModule> populate(JSONObject jsonObject) throws JSONException {
List<RepoModule> newModules = new ArrayList<>();
synchronized (this.populateLock) {
String name = jsonObject.getString("name");
long lastUpdate = jsonObject.getLong("last_update");
for (RepoModule repoModule : this.moduleHashMap.values()) {
repoModule.processed = false;
}
JSONArray array = jsonObject.getJSONArray("modules");
int len = array.length();
for (int i = 0; i < len; i++) {
JSONObject module = array.getJSONObject(i);
String moduleId = module.getString("id");
long moduleLastUpdate = module.getLong("last_update");
String moduleNotesUrl = module.getString("notes_url");
String modulePropsUrl = module.getString("prop_url");
String moduleZipUrl = module.getString("zip_url");
RepoModule repoModule = this.moduleHashMap.get(moduleId);
if (repoModule == null) {
repoModule = new RepoModule(moduleId);
this.moduleHashMap.put(moduleId, repoModule);
newModules.add(repoModule);
} else {
if (repoModule.lastUpdated < moduleLastUpdate ||
repoModule.moduleInfo.hasFlag(ModuleInfo.FLAG_METADATA_INVALID)) {
newModules.add(repoModule);
}
}
repoModule.processed = true;
repoModule.lastUpdated = moduleLastUpdate;
repoModule.notesUrl = moduleNotesUrl;
repoModule.propUrl = modulePropsUrl;
repoModule.zipUrl = moduleZipUrl;
}
// Remove no longer existing modules
Iterator<RepoModule> moduleInfoIterator = this.moduleHashMap.values().iterator();
while (moduleInfoIterator.hasNext()) {
RepoModule repoModule = moduleInfoIterator.next();
if (!repoModule.processed) {
new File(this.cacheRoot, repoModule.id + ".prop").delete();
moduleInfoIterator.remove();
}
}
// Update final metadata
this.name = name;
this.lastUpdate = lastUpdate;
}
return newModules;
}
public boolean tryLoadMetadata(RepoModule repoModule) {
File file = new File(this.cacheRoot, repoModule.id + ".prop");
if (file.exists()) {
try {
PropUtils.readProperties(repoModule.moduleInfo, file.getAbsolutePath());
repoModule.moduleInfo.flags &= ~ModuleInfo.FLAG_METADATA_INVALID;
return true;
} catch (Exception ignored) {
file.delete();
}
}
repoModule.moduleInfo.flags |= ModuleInfo.FLAG_METADATA_INVALID;
return false;
}
public String getNameOrFallback(String fallback) {
return this.name == null ||
this.name.equals(this.url) ?
fallback : this.name;
}
}