Package de.sosd.mediaserver.service

Source Code of de.sosd.mediaserver.service.FilesystemService

package de.sosd.mediaserver.service;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import de.sosd.mediaserver.dao.DidlDao;
import de.sosd.mediaserver.dao.FilesystemDao;
import de.sosd.mediaserver.dao.SystemDao;
import de.sosd.mediaserver.domain.db.DidlDomain;
import de.sosd.mediaserver.domain.db.FileDomain;
import de.sosd.mediaserver.domain.db.ScanFolderDomain;
import de.sosd.mediaserver.domain.db.ScanFolderState;
import de.sosd.mediaserver.domain.db.SystemDomain;
import de.sosd.mediaserver.service.dlna.DIDLService;
import de.sosd.mediaserver.util.DidlChangeMap;
import de.sosd.mediaserver.util.ScanContext;
import de.sosd.mediaserver.util.ScanFile;
import de.sosd.mediaserver.util.ScanFolder;

@Service
public class FilesystemService {

  private final static Log logger = LogFactory.getLog(FilesystemService.class);
 
  @Autowired
  private FilesystemDao fsDao;
 
  @Autowired
  private SystemDao systemDao;
 
  @Autowired
  private DidlDao didlDao;
 
  @Autowired
  private IdService idservice;
 
  @Autowired
  private DIDLService didl;
 
  @Autowired
  private MediaserverConfiguration cfg;
 
  public boolean addScanDirectory(final File directory) {
    try {
      addScanDirectoryTransactional(directory);
      return true;
    } catch (final Throwable t) {
      logger.error("error while adding directory, probably because it already exists", t);
      return false;
    }
  }
 
  @Transactional(propagation=Propagation.REQUIRED)
  public void addScanDirectoryTransactional(final File directory) {
    if (directory.isDirectory()) {
      final String id = this.idservice.getId(directory);
      if (!this.fsDao.isDirectoryPresent(id)) {
        final ScanFolderDomain scanFolder = new ScanFolderDomain(id, directory, null);
       
        final SystemDomain system = this.systemDao.getSystem(cfg.getUSN());
        system.getScanFolder().add(scanFolder);
        scanFolder.setSystem(system);
        scanFolder.setDidlRoot(this.didl.createDidlContainer(scanFolder, system.getDidlRoot()));
        this.systemDao.store(system);
        logger.info("added new scan-directory : " + scanFolder.getPath());
      }
    }
  }

  public void scanFilesystem() {
    // get list of directories due for scanning
    logger.info("scanner [start]");
    final List<ScanContext> scanContexts = createScanContexts();
    scanDirectories(scanContexts);
  }
 
  @Transactional(propagation=Propagation.REQUIRED
  private List<ScanContext> createScanContexts() {
    final List<ScanContext> scanContexts = new ArrayList<ScanContext>();
    final long currentTimeMillis = System.currentTimeMillis();
    final SystemDomain system = this.systemDao.getSystem(cfg.getUSN());
    for (final ScanFolderDomain sfd : system.getScanFolder()) {
      if (
      !ScanFolderState.SCANNING.equals(sfd.getScanState()) &&
        ((sfd.getLastScan() == null) ||
        ((sfd.getLastScan().getTime() + (sfd.getScanInterval() * 60000)) < currentTimeMillis))) {
       
        // should scan
       
        final File dir = new File(sfd.getPath());
        if (! dir.exists() || ! dir.isDirectory()) {
          // this could happen with external storage ..
          sfd.setScanState(ScanFolderState.NOT_FOUND);
          didlDao.setOnline(sfd.getId(), false);
          system.increaseUpdateId();
        } else {
          if (ScanFolderState.NOT_FOUND.equals(sfd.getScanState())) {
            didlDao.setOnline(sfd.getId(), true);
            system.increaseUpdateId();
          }
         
          sfd.setScanState(ScanFolderState.SCANNING);
          scanContexts.add(new ScanContext(sfd.getId(), dir));
        }
      }
    }   
    this.systemDao.store(system);
   
    return scanContexts;
  }
   
  @Transactional(propagation=Propagation.REQUIRED)
  private void scanDirectories(final List<ScanContext> scanContexts) {
    long changedCount = 0l;
    boolean systemChanged = false;
   
    final SystemDomain         system         = this.systemDao.getSystem(cfg.getUSN());
    final Set<Object>         itemsToPurge     = new HashSet<Object>()
    final Map<String, ScanContext>   idScanContextMap   = new HashMap<String, ScanContext>();   
    final Set<String>         foundFileIds            = new HashSet<String>();
    final DidlChangeMap   touchedDidlMap           = new DidlChangeMap();

    for (final ScanContext sc : scanContexts) {
      idScanContextMap.put(sc.getScanFolderId(), sc);
    }   
   
    // collect all Files, no Folders!
    for (final ScanContext sc : scanContexts) {
      logger.info("scanner [scan] "+sc.getScanFolder());
      List<String> knownFileIds = this.fsDao.getAllFileIds(sc.getScanFolderId());
      collectNewFiles(sc.getScanFolder(), sc.getFiles(), knownFileIds, foundFileIds);
      logger.info("scanner [found files] " + sc.getFiles().size() + " " +sc.getScanFolder());
     
     
      changedCount += sc.getFiles().size();
     
      knownFileIds.removeAll(foundFileIds);
      for (String removed : knownFileIds) {
        sc.addDeletedMediaFile(removed);
        changedCount += 1;
      }
    } 
   
    if (changedCount > 0) {
      final List<String> allDidlIds= this.didlDao.getAllDidlIds()
      for (String id : allDidlIds) {
        touchedDidlMap.addDidl(id, null);
      }
      for (final ScanFolderDomain sfd : system.getScanFolder()) {
        if (idScanContextMap.containsKey(sfd.getId())) {
          final ScanContext sc = idScanContextMap.get(sfd.getId());
          logger.info("scanner [filter] "+sc.getScanFolder());
          for (final ScanFile f : sc.getFiles()) {
            final FileDomain fd = new FileDomain(f.getId(), null, f.getFile());         
            if (this.didl.createDidl(fd, f, touchedDidlMap, sfd)) {
              sc.getMediaFiles().add(fd);
            }
          }
          logger.info("scanner [found new files] " + sc.getMediaFiles().size() + " " +sc.getScanFolder());
        }
      } 
    }
     
    // update folders
    for (final ScanFolderDomain sfd : system.getScanFolder()) {
      if (idScanContextMap.containsKey(sfd.getId())) {
        final ScanContext sc = idScanContextMap.get(sfd.getId());
        boolean changedFiles = false;
        for (final FileDomain fd : sc.getMediaFiles()) {   
          changedFiles |= sfd.addFile(fd);
          logger.info("scanner [add file] " + fd.getName() + "\t\t(" + fd.getPath() + ")");
        }       
        if (changedFiles || !sc.getDeletedMediaFiles().isEmpty()) {
          changedFiles |= updateDidl(sfd.getDidlRoot(), sfd, touchedDidlMap,sc.getDeletedMediaFiles(), itemsToPurge);
        }
        // remove scanfolder mark
        sfd.setScanState(ScanFolderState.IDLE);
        sfd.setLastScan(new Date());
       
        systemChanged |= changedFiles;
      }
    }
   
    // something changed increase updateId
    if (systemChanged) {
      logger.info("scanner [collect new stats]");
      system.increaseUpdateId();
      system.setLastDataChange(new Date());
     
      if (this.didl.foundUnsupportedFiles()) {
        logger.info("scanner [dlna-unsupported] " + this.didl.getMissingClassTypeExtensions()+ ", " + this.didl.getMissingProtocolInfoExtensions());
      }
    }   
    logger.info("scanner [update database]");
    this.systemDao.update(system, new ArrayList<Object>(itemsToPurge));
    logger.info("scanner [done]");
   
  }
  @Transactional(propagation=Propagation.REQUIRED)
  private boolean updateDidl(final DidlDomain root, final ScanFolderDomain sfd, DidlChangeMap map, final Set<String> removedItemIds, final Set<Object> itemsToPurge) {
    boolean changed = false;
    // remove files first
    for (String removedId : removedItemIds) {
      if (map.hasDidl(removedId)) {
        DidlDomain item = map.getDidl(removedId);
        changed |= removeDidl(root, map,item, itemsToPurge);
      }
    }
    return changed;
  }
  @Transactional(propagation=Propagation.REQUIRED)
  private boolean removeDidl(DidlDomain root, DidlChangeMap map,
      DidlDomain item, Set<Object> itemsToPurge) {
    if (root.getId().equals(item.getId())) {
      return false;
    }
   
    boolean changed = false;   
    DidlDomain parent;
    if (item.getParent() != null) {
      parent = map.getDidl(item.getParent().getId());
      // remove child
      final FileDomain file = item.getFile();
      changed = parent.removeChild(item);     
      didlDao.store(parent);
//      item.setFile(null);
//      item.setParent(null);
//      item.setReference(null);
//      for (DidlDomain ref : item.getReferences()) {
//        removeDidl(root, map, ref, itemsToPurge);
//      }
//      for (DidlDomain content : item.getContainerContent()) {
//        removeDidl(root, map, content, itemsToPurge);
//      }
//      item.getContainerContent().clear();
     
      if (file != null) {
        changed |= file.getParent().removeFile(file);
//        file.setParent(null);
//        file.setDidl(null);
//        storage.removeFile(file);
        logger.info("scanner [removed file] " + file.getName() + "\t(" + file.getPath() + ")")
      } else {
        logger.info("scanner [removed folder] " + item.getTitle() + "\t(" + item.getId() + ")");
      }
     
      if (parent.getContainerContent().isEmpty()) {
        changed |= removeDidl(root, map, parent, itemsToPurge);
      }
    }
    return changed;
  }

  private void collectNewFiles(final ScanFolder folder, final List<ScanFile> list, final List<String> knownFileIds, Set<String> foundFileIds) {
    if ((folder.getFile().listFiles() != null) && folder.getFile().isDirectory() && folder.getFile().canRead()) {
      for (final File f : folder.getFile().listFiles()) {
        final String id = this.idservice.getId(f);     
        if (f.isFile()) {
          foundFileIds.add(id);
          if (! knownFileIds.contains(id)) {
            ScanFile addedFile = folder.addFile(id, f);
            if (addedFile != null) {
              list.add(addedFile);
            }
          }
        } else {
          ScanFolder addedFolder = folder.addFolder(id, f);
          if (addedFolder !=  null) {
            collectNewFiles(addedFolder,list,knownFileIds,foundFileIds);
          }
        }
      }
    }
  }
}
TOP

Related Classes of de.sosd.mediaserver.service.FilesystemService

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.