Package net.datacrow.drivemanager

Source Code of net.datacrow.drivemanager.DriveManager

/******************************************************************************
*                                     __                                     *
*                              <-----/@@\----->                              *
*                             <-< <  \\//  > >->                             *
*                               <-<-\ __ /->->                               *
*                               Data /  \ Crow                               *
*                                   ^    ^                                   *
*                              info@datacrow.net                             *
*                                                                            *
*                       This file is part of Data Crow.                      *
*       Data Crow is free software; you can redistribute it and/or           *
*        modify it under the terms of the GNU General Public                 *
*       License as published by the Free Software Foundation; either         *
*              version 3 of the License, or any later version.               *
*                                                                            *
*        Data Crow is distributed in the hope that it will be useful,        *
*      but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.             *
*           See the GNU General Public License for more details.             *
*                                                                            *
*        You should have received a copy of the GNU General Public           *
*  License along with this program. If not, see http://www.gnu.org/licenses  *
*                                                                            *
******************************************************************************/

package net.datacrow.drivemanager;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import net.datacrow.core.DataCrow;
import net.datacrow.core.DcRepository;
import net.datacrow.core.resources.DcResources;
import net.datacrow.settings.DcSettings;
import net.datacrow.util.Hash;
import net.datacrow.util.Utilities;

import org.apache.log4j.Logger;

/**
* The Drive Manager of Data Crow. Schedules tasks to scan drives for files,
* allows current file locations to be retrieved and checks the system for new
* mounted / inserted discs.
*/
public class DriveManager {

    public static final int _PRECISION_LOWEST = 0;
    public static final int _PRECISION_MEDIUM = 1;
    public static final int _PRECISION_HIGHEST = 2;
   
    private static Logger logger = Logger.getLogger(DriveManager.class);

    private static DriveManager instance = new DriveManager();
   
    private FileSynchronizer fs;
    private DrivePoller dp;

    private Collection<File> drives;
    private Collection<String> excludedDirs = new ArrayList<String>();
    private Map<File, DriveScanner> scanners = new HashMap<File, DriveScanner>();
   
    private Map<File, String> hashes = new HashMap<File, String>();
   
    private boolean drivesWereScanned = false;
   
    private Collection<IDriveManagerListener> pollerListeners = new ArrayList<IDriveManagerListener>();
    private Collection<IDriveManagerListener> scannerListeners = new ArrayList<IDriveManagerListener>();
    private Collection<IDriveManagerListener> synchronizerListeners = new ArrayList<IDriveManagerListener>();
   
    public static DriveManager getInstance() {
        return instance;
    }
   
    private DriveManager()  {
        clean();
    }
   
    public void startDrivePoller() throws JobAlreadyRunningException {
        if (dp != null && dp.isRunning()) {
            throw new JobAlreadyRunningException();
        } else {
            dp = dp == null ? new DrivePoller() : dp;
            dp.start();
        }
    }
   
    public void startFileSynchronizer(int precision) throws JobAlreadyRunningException {
        if (fs != null && fs.isRunning()) {
            throw new JobAlreadyRunningException();
        } else {
            hashes.clear();
            fs = fs == null ? new FileSynchronizer() : fs;
            fs.start(precision);
        }
    }   
   
    public void sendMessage(Collection<IDriveManagerListener> listeners, String msg) {
        for (IDriveManagerListener listener : listeners)
            listener.notify(msg);
    }

    public void notifyJobStopped(Collection<IDriveManagerListener> listeners) {
        for (IDriveManagerListener listener : listeners)
            listener.notifyJobStopped();
    }

    public void notifyJobStarted(Collection<IDriveManagerListener> listeners) {
        for (IDriveManagerListener listener : listeners)
            listener.notifyJobStarted();
    }
   
    public void restartScan(File drive) {
        if (getDrives().contains(drive)) {
            notifyJobStarted(getScannerListeners());
            DriveScanner scanner = scanners.get(drive);
            scanner.restart();
        }
    }
   
    public void startScanners() throws JobAlreadyRunningException {
        if (isScanActive())
            throw new JobAlreadyRunningException();
       
        initializeScanners();
        notifyJobStarted(getScannerListeners());
       
        for (File drive : getDrives()) {
            if (Utilities.isDriveTraversable(drive) && drive.canRead()) {
                scanners.get(drive).cancel();
                scanners.get(drive).start();
            } else {
                sendMessage(getScannerListeners(), DcResources.getText("msgSkippingUnreadbleDrive", drive.toString()));
            }
        }
       
        drivesWereScanned = true;
    }   
   
    public boolean drivesWereScanned() {
        return drivesWereScanned;
    }

    public void stopScanners() {
        for (DriveScanner scanner : scanners.values())
            scanner.cancel();
       
        notifyJobStopped(getScannerListeners());
    }

    public void stopDrivePoller() {
        if (dp != null) dp.cancel();
    }

    public void stopFileSynchronizer() {
        if (fs != null) fs.cancel();
    }   
   
    public void setDrives(Collection<File> drives) throws JobAlreadyRunningException {
        if (isScanActive())
            throw new JobAlreadyRunningException();
           
        this.drives = drives;
    }
   
    public Collection<String> getExcludedDirs() {
        return excludedDirs;
    }   
   
    protected String getTempFileSuffix() {
        return "_drive_report.properties";
    }
   
    protected String getTempDir() {
        return DataCrow.dataDir + "temp/";
    }   
   
    private void initializeScanners() {
        for (File drive : getDrives()) {
            try {
                if (scanners.get(drive) == null)
                    scanners.put(drive, new DriveScanner(this, drive));   
            } catch (Exception e) {
                logger.error(e, e);
            }     
        }
    }

    public Collection<IDriveManagerListener> getPollerListeners() {
        return pollerListeners;
    }

    public Collection<IDriveManagerListener> getScannerListeners() {
        return scannerListeners;
    }

    public Collection<IDriveManagerListener> getSynchronizerListeners() {
        return synchronizerListeners;
    }
   
    private void clean() {
        File file = new File(getTempDir());
        for (String filename : file.list()) {
            if (filename.endsWith(getTempFileSuffix())) {
                File tempFile = new File(getTempDir() + filename);
                if (tempFile.isFile())
                    tempFile.delete();
            }
        }
    }   
   
    public synchronized Collection<File> getDrives() {
        if (drives == null || drives.size() == 0) {
            drives = drives == null ? new ArrayList<File>() : drives;
            for (Drive drive : new Drives().getDrives())
                drives.add(drive.getPath());
        }
        return drives;
    }

    public boolean isScanActive() {
        boolean running = false;
        for (DriveScanner scanner : scanners.values())
            running |= scanner.isRunning();
       
        return running;
    }
   
    protected void notifyScanComplete(DriveScanner scanner) {
        sendMessage(getScannerListeners(),
                    DcResources.getText("msgScanHasCompletedForX", "" + scanner.getDrive()));

        scanner.cancel();
        if (!isScanActive())
            notifyJobStopped(getScannerListeners());
    }
   
    public void setExcludedDirectories(Collection<String> directories) throws JobAlreadyRunningException {
        if (isScanActive())
            throw new JobAlreadyRunningException();
       
        this.excludedDirs = directories;
    }
   
    protected boolean isDirExcluded(File directory) {
        return excludedDirs.contains(directory.toString());
    }
   
    public void exclude(String directory) {
        String dir = directory.toLowerCase();
        dir = dir.replaceAll("'\'", File.separator);
        dir = dir.replaceAll("'/'", File.separator);
        excludedDirs.add(dir);
    }   
   
    private FileInfo getFileInfo(File file, String hash, Long size) {
        hash = hash == null ? Hash.getInstance().calculateHash(file.toString()) : hash;
        size = size == null ? Utilities.getSize(file) : size;
        return new FileInfo(hash, file.toString(), size);       
    }

    public void addPollerListener(IDriveManagerListener listener) {
        pollerListeners.add(listener);
    }

    public void addScannerListener(IDriveManagerListener listener) {
        scannerListeners.add(listener);
    }

    public void addSynchronizerListener(IDriveManagerListener listener) {
        synchronizerListeners.add(listener);
    }

    /**
     * Calculates the hash for the given file and stores it for future references.
     */
    private String getHash(File file) {
        String hash = hashes.get(file);
       
        if (file.length() < DcSettings.getInt(DcRepository.Settings.stHashMaxFileSizeKb))
            hash = hash == null ? Hash.getInstance().calculateHash(file.toString()) : hash;
           
        return hash;
    }
   
    /**
     * Retrieves the actual location / file for the given filename.
     * The size and the hash of the original file are used to determine its new
     * location.
     */
    public FileInfo find(FileInfo fi, int precision) {
        File file = new File(fi.getFilename());
       
        if (file.exists())
            return getFileInfo(file, fi.getHash(), fi.getSize());
       
        try {
          String name =  file.getName();
          FileInfo result = null;

          for (String propertyFile : new File(getTempDir()).list()) {
             
              if (!propertyFile.endsWith(getTempFileSuffix())) continue;
             
              File tmpFile = new File(getTempDir() + propertyFile);
              if (!tmpFile.canRead()) {
                  logger.info("Could not read drive information file: " + tmpFile + " The drive for which this file was created will be skipped!");
                  continue;
              }
             
                RandomAccessFile raf = new RandomAccessFile(tmpFile, "r");
              long length = raf.length();
             
              while (raf.getFilePointer() < length) {
                  try {
                      String line = raf.readLine();
                      int idx = line.indexOf("=");
                     
                      Long fodSize = Long.valueOf(line.substring(0, idx));
                      String fodName = line.substring(idx + 1);
                      File fod = new File(fodName);
                       
                        // make sure the file exists; might be dealing with info from an unmounted drive!
                      if (!fod.exists()) {
                          logger.info("The file as found in " + tmpFile + " does not exist and will be skipped.");
                          continue;
                      }
                     
                        boolean match = false;
                        String newHash = null;
                       
                        // low: match file name
                        if (precision == DriveManager._PRECISION_LOWEST && name.equals(fod.getName())) {
                            match = true;
                           
                        // medium: match on file size and file name
                        } else if (precision == DriveManager._PRECISION_MEDIUM &&
                                   name.equals(fod.getName()) && fodSize.equals(fi.getSize())) {
                            match = true;
                    
                        // high: match on file size and file hash
                        } else if (precision == DriveManager._PRECISION_HIGHEST) {
                        
                            if (fodSize.equals(fi.getSize())) {
                           
                                newHash = getHash(fod);
                            
                                // can happen when out of memory, when the file is not readable or when the settings
                                // do not allow for the hash to be calculated based on the file size.
                                if (newHash == null)
                                    continue;
                               
                                hashes.put(fod, newHash);
                               
                              if (newHash.equals(fi.getHash())) {
                                 match = true;
                              }
                            }
                        }
                     
                        if (match) {
                            // calculate the new hash if needed
                            newHash = getHash(fod);
                            Long filesize = Utilities.getSize(fod);
                           
                            logger.info("Match found for " + name + " (hash: " + newHash + ", filesize " + String.valueOf(filesize) + ")");
                            result = getFileInfo(fod, newHash, filesize);
                            break;
                        }
                } catch (IOException ioe) {
                    logger.error(ioe, ioe);
                }
              }
               
                try {
                    raf.close();
                } catch (IOException ioe) {
                    logger.error("Could not close RAF", ioe);
                }
               
                if (result != null)
                    return result;
          }
        } catch (Exception e) {
          logger.error(e, e);
        }
       
        return null;
    }
}
TOP

Related Classes of net.datacrow.drivemanager.DriveManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.