package net.vhati.modmanager.core; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.vhati.ftldat.FTLDat; import net.vhati.modmanager.core.ModDB; import net.vhati.modmanager.core.ModInfo; import net.vhati.modmanager.core.ModsScanObserver; import net.vhati.modmanager.xml.JDOMModMetadataReader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * A thread to calculate MD5 hashes of files in the background. * * As each file is hashed, a class implementing HashObserver is notified. * Note: The callback on that class needs to be thread-safe. */ public class ModsScanThread extends Thread { private static final Logger log = LogManager.getLogger(ModsScanThread.class); private List<File> fileList = new ArrayList<File>(); private ModDB newDB; private ModsScanObserver scanObserver; public ModsScanThread( File[] files, ModDB knownDB, ModsScanObserver scanObserver ) { this.fileList.addAll( Arrays.asList(files) ); this.newDB = new ModDB( knownDB ); this.scanObserver = scanObserver; } public void run() { Map<File,String> hashMap = new HashMap<File,String>(); for ( File f : fileList ) { String hash = calcFileMD5( f ); if ( hash != null ) { hashMap.put( f, hash ); scanObserver.hashCalculated( f, hash ); } } log.info( "Background hashing finished." ); // Cache info about new files. for ( File f : fileList ) { String fileHash = hashMap.get( f ); if ( fileHash != null && newDB.getModInfo( fileHash ) == null ) { ModInfo modInfo = JDOMModMetadataReader.parseModFile( f ); if ( modInfo != null ) { modInfo.setFileHash( fileHash ); newDB.addMod( modInfo ); } } } // Prune info about absent files. for ( Iterator<ModInfo> it = newDB.getCatalog().iterator(); it.hasNext(); ) { ModInfo modInfo = it.next(); if ( !hashMap.containsValue( modInfo.getFileHash() ) ) it.remove(); } scanObserver.localModDBUpdated( new ModDB( newDB ) ); log.info( "Background metadata caching finished." ); scanObserver.modsScanEnded(); } private String calcFileMD5( File f ) { String result = null; try { result = FTLDat.calcFileMD5( f ); } catch ( Exception e ) { log.error( "Error while calculating hash for file: "+ f.getPath(), e ); } return result; } }