package filerogue.client; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.Adler32; import filerogue.*; /** * This class handles the scanning and uploading of a catalog to the server. */ public class CUploadCatalogOperation extends Thread implements ThreadListener { private static final Logger logger = Logger.getLogger( "global" ); volatile boolean validReceived = false; CBaseDirData cbDirs; int iUserID; Object obSleepLock = new Object(); HashMap validNames = new HashMap(); // map names to FileNameLength objects // checksum stuff Adler32 check = new Adler32(); int blockSize = 8 * 1024; // 8 KB byte[] buffer = new byte[ blockSize ]; /** * Creates a new CUploadCatalogOperation object and starts it. */ public CUploadCatalogOperation( CBaseDirData baseDirs, int userID ) { cbDirs = baseDirs; iUserID = userID; this.setPriority( NORM_PRIORITY - 1 ); this.start(); } /** * Run. Thread implementation. * Attempts to upload the catalog to the server. */ public void run() { attemptUpload(); } public void validListReceived( List fnl ) { FileNameLength fnlTemp; // fill in the lookup set for ( Iterator iter = fnl.iterator(); iter.hasNext(); ) { fnlTemp = ( FileNameLength ) iter.next(); validNames.put( fnlTemp.name, fnlTemp ); } validReceived = true; // wake the scanner/uploader thread up synchronized ( obSleepLock ) { obSleepLock.notifyAll(); } } /** * Attempt to upload the catalog to the server. */ private void attemptUpload() { if ( cbDirs.hasBeenScanned() ) { cbDirs.getCatalogData().setUserID( iUserID ); // if we're doing DRM, upload name/size listing and wait for server response to wake us up if( Version.ENABLE_DRM ) { try { Client.getInstance().getServerConnection().getConnection().sendCompressedObject( new Message( Message.MSG_FILE_LIST, cbDirs.getCatalogData().exportList() ) ); Client.getInstance().setStatus( "Uploaded preliminary listing for " + cbDirs.getCatalogData().getTotalFileCount() + " files successfully." ); } catch ( IOException ex ) { logger.log( Level.INFO, "Attempt upload: " + ex ); } // now go to sleep until woken up if ( !validReceived ) { synchronized ( obSleepLock ) { try { obSleepLock.wait(); } catch ( InterruptedException ex1 ) { } } } // now we're awake, do full checksums on valid files checkValid(); // this process also removes any files which aren't valid, now we want to trim any empty dirs cbDirs.getCatalogData().trimAllEmptyDirs(); } uploadCatalog(); } else { Client.getInstance().setStatus( "Scanning your shared folders..." ); new CDirScanner( this, cbDirs ); } } private void uploadCatalog() { Client.getInstance().setStatus( "Uploading compressed catalog data to server..." ); try { cbDirs.getCatalogData().setOwner( Client.getInstance().getLocalUser().getName() ); Client.getInstance().getServerConnection().getConnection().sendCompressedObject( new Message( Message.MSG_CATALOG_UPLOAD, cbDirs.getCatalogData() ) ); } catch ( Exception x ) { x.printStackTrace(); } Client.getInstance().setStatus( "Uploaded checked listing for " + cbDirs.getCatalogData().getTotalFileCount() + " files successfully." ); } /** * Strip invalid files from catalog, perform full checksum scans on remaining */ private void checkValid() { CatalogData cat = cbDirs.getCatalogData(); int f, rCount; long checkValue; SubDirData dir; FileData file; FileNameLength fnl; for ( int d = cat.getTotalDirCount() - 1; d >= 0; d-- ) { rCount = 0; dir = cat.getSubDir( d ); for ( f = dir.getFileCount() - 1; f >= 0; f-- ) { file = dir.getFileData( f ); fnl = ( FileNameLength )validNames.get( file.getFullName() ); if( fnl != null && fnl.length == file.getLength() ) { try { checkValue = checksum( cbDirs.getFile( file ) ); file.setDigest( checkValue ); } catch ( IOException ex ) { logger.log( Level.INFO, ex.toString() ); dir.removeFileData( f ); rCount++; } } else { dir.removeFileData( f ); rCount++; } } // dir is finished, check for trimming if ( rCount > 0 ) { dir.repack(); } } } private long checksum( File file ) throws IOException { FileInputStream fin = new FileInputStream( file ); int bytesRead = 0; check.reset(); // read it in while ( ( bytesRead = fin.read( buffer ) ) > 0 ) { check.update( buffer, 0, bytesRead ); } fin.close(); // logger.log( Level.INFO, "Checksum for: " + file.getName() + " = " + check.getValue() ); return check.getValue(); } /** * Notification that the specified thread has completed its operation. * Now we can attempt to upload the catalog to the server. */ public void completed( Thread thread, Object object ) { Client.getInstance().setStatus( "Scan complete." ); attemptUpload(); } }