229 lines
6.5 KiB
Java
229 lines
6.5 KiB
Java
package net.vhati.modmanager.ui;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.IOException;
|
|
import java.nio.charset.Charset;
|
|
import java.util.ArrayList;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.util.concurrent.locks.Lock;
|
|
import javax.swing.SwingUtilities;
|
|
|
|
import net.vhati.modmanager.core.AutoUpdateInfo;
|
|
import net.vhati.modmanager.core.ModDB;
|
|
import net.vhati.modmanager.core.ModFileInfo;
|
|
import net.vhati.modmanager.core.SlipstreamConfig;
|
|
import net.vhati.modmanager.json.JacksonAutoUpdateReader;
|
|
import net.vhati.modmanager.json.JacksonCatalogReader;
|
|
import net.vhati.modmanager.json.URLFetcher;
|
|
import net.vhati.modmanager.ui.ManagerFrame;
|
|
import net.vhati.modmanager.ui.table.ListState;
|
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
|
|
/**
|
|
* Performs I/O-related setup for ManagerFrame in the background.
|
|
*
|
|
* Reads cached local metadata.
|
|
* Rescans the "mods/" folder.
|
|
* Reads saved catalog, and redownloads if stale.
|
|
* Reads saved info about app updates, and redownloads if stale.
|
|
*/
|
|
public class ManagerInitThread extends Thread {
|
|
|
|
private static final Logger log = LogManager.getLogger( ManagerInitThread.class );
|
|
|
|
private final ManagerFrame frame;
|
|
private final SlipstreamConfig appConfig;
|
|
private final File modsDir;
|
|
private final File modsTableStateFile;
|
|
private final File metadataFile;
|
|
private final File catalogFile;
|
|
private final File catalogETagFile;
|
|
private final File appUpdateFile;
|
|
private final File appUpdateETagFile;
|
|
|
|
|
|
public ManagerInitThread( ManagerFrame frame, SlipstreamConfig appConfig, File modsDir, File modsTableStateFile, File metadataFile, File catalogFile, File catalogETagFile, File appUpdateFile, File appUpdateETagFile ) {
|
|
this.frame = frame;
|
|
this.appConfig = appConfig;
|
|
this.modsDir = modsDir;
|
|
this.modsTableStateFile = modsTableStateFile;
|
|
this.metadataFile = metadataFile;
|
|
this.catalogFile = catalogFile;
|
|
this.catalogETagFile = catalogETagFile;
|
|
this.appUpdateFile = appUpdateFile;
|
|
this.appUpdateETagFile = appUpdateETagFile;
|
|
}
|
|
|
|
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
init();
|
|
}
|
|
catch ( Exception e ) {
|
|
log.error( "Error during ManagerFrame init.", e );
|
|
}
|
|
}
|
|
|
|
|
|
private void init() throws InterruptedException {
|
|
if ( metadataFile.exists() ) {
|
|
// Load cached metadata first, before scanning for new info.
|
|
ModDB cachedDB = JacksonCatalogReader.parse( metadataFile );
|
|
if ( cachedDB != null ) frame.setLocalModDB( cachedDB );
|
|
}
|
|
|
|
final ListState<ModFileInfo> tableState = loadModsTableState();
|
|
|
|
Lock managerLock = frame.getLock();
|
|
managerLock.lock();
|
|
try {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() { frame.rescanMods( tableState ); }
|
|
});
|
|
|
|
// Wait until notified that "mods/" has been scanned.
|
|
while ( frame.isScanning() ) {
|
|
frame.getScanEndedCondition().await();
|
|
}
|
|
}
|
|
finally {
|
|
managerLock.unlock();
|
|
}
|
|
|
|
int catalogUpdateInterval = appConfig.getPropertyAsInt( "update_catalog", 0 );
|
|
boolean needNewCatalog = false;
|
|
|
|
if ( catalogFile.exists() ) {
|
|
// Load the catalog first, before updating.
|
|
reloadCatalog();
|
|
|
|
if ( catalogUpdateInterval > 0 ) {
|
|
// Check if the downloaded catalog is stale.
|
|
if ( isFileStale( catalogFile, catalogUpdateInterval ) ) {
|
|
log.debug( String.format( "Catalog is older than %d days.", catalogUpdateInterval ) );
|
|
needNewCatalog = true;
|
|
} else {
|
|
log.debug( "Catalog isn't stale yet." );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Catalog file doesn't exist.
|
|
needNewCatalog = true;
|
|
}
|
|
|
|
// Don't update if the user doesn't want to.
|
|
if ( catalogUpdateInterval <= 0 ) needNewCatalog = false;
|
|
|
|
if ( needNewCatalog ) {
|
|
boolean fetched = URLFetcher.refetchURL( ManagerFrame.CATALOG_URL, catalogFile, catalogETagFile );
|
|
if ( fetched && catalogFile.exists() ) {
|
|
reloadCatalog();
|
|
}
|
|
}
|
|
|
|
int appUpdateInterval = appConfig.getPropertyAsInt( "update_app", 0 );
|
|
boolean needAppUpdate = false;
|
|
|
|
if ( appUpdateFile.exists() ) {
|
|
// Load the info first, before downloading.
|
|
reloadAppUpdateInfo();
|
|
|
|
if ( appUpdateInterval > 0 ) {
|
|
// Check if the app update info is stale.
|
|
if ( isFileStale( appUpdateFile, appUpdateInterval ) ) {
|
|
log.debug( String.format( "App update info is older than %d days.", appUpdateInterval ) );
|
|
needAppUpdate = true;
|
|
} else {
|
|
log.debug( "App update info isn't stale yet." );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// App update file doesn't exist.
|
|
needAppUpdate = true;
|
|
}
|
|
|
|
// Don't update if the user doesn't want to.
|
|
if ( appUpdateInterval <= 0 ) needAppUpdate = false;
|
|
|
|
if ( needAppUpdate ) {
|
|
boolean fetched = URLFetcher.refetchURL( ManagerFrame.APP_UPDATE_URL, appUpdateFile, appUpdateETagFile );
|
|
if ( fetched && appUpdateFile.exists() ) {
|
|
reloadAppUpdateInfo();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Reads modorder.txt and returns a list of mod names in preferred order.
|
|
*/
|
|
private ListState<ModFileInfo> loadModsTableState() {
|
|
List<String> fileNames = new ArrayList<String>();
|
|
|
|
BufferedReader br = null;
|
|
try {
|
|
FileInputStream is = new FileInputStream( modsTableStateFile );
|
|
br = new BufferedReader( new InputStreamReader( is, Charset.forName( "UTF-8" ) ) );
|
|
String line;
|
|
while ( (line = br.readLine()) != null ) {
|
|
fileNames.add( line );
|
|
}
|
|
}
|
|
catch ( FileNotFoundException e ) {
|
|
}
|
|
catch ( IOException e ) {
|
|
log.error( String.format( "Error reading \"%s\".", modsTableStateFile.getName() ), e );
|
|
fileNames.clear();
|
|
}
|
|
finally {
|
|
try {if ( br != null ) br.close();}
|
|
catch ( Exception e ) {}
|
|
}
|
|
|
|
ListState<ModFileInfo> result = new ListState<ModFileInfo>();
|
|
|
|
for ( String fileName : fileNames ) {
|
|
File modFile = new File( modsDir, fileName );
|
|
ModFileInfo modFileInfo = new ModFileInfo( modFile );
|
|
result.addItem( modFileInfo );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
private void reloadCatalog() {
|
|
ModDB currentDB = JacksonCatalogReader.parse( catalogFile );
|
|
if ( currentDB != null ) frame.setCatalogModDB( currentDB );
|
|
}
|
|
|
|
private void reloadAppUpdateInfo() {
|
|
AutoUpdateInfo aui = JacksonAutoUpdateReader.parse( appUpdateFile );
|
|
if ( aui != null ) frame.setAppUpdateInfo( aui );
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns true if a file is older than N days.
|
|
*/
|
|
private boolean isFileStale( File f, int maxDays ) {
|
|
Date modifiedDate = new Date( f.lastModified() );
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.add( Calendar.DATE, maxDays * -1 );
|
|
return modifiedDate.before( cal.getTime() );
|
|
}
|
|
}
|